Freeciv-3.3
Loading...
Searching...
No Matches
mapgen.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
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
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <time.h>
22
23/* utility */
24#include "bitvector.h"
25#include "fcintl.h"
26#include "log.h"
27#include "maphand.h" /* assign_continent_numbers(), MAP_NCONT */
28#include "mem.h"
29#include "nation.h"
30#include "rand.h"
31#include "shared.h"
32
33/* common */
34#include "game.h"
35#include "map.h"
36#include "road.h"
37
38/* server/generator */
39#include "fracture_map.h"
40#include "height_map.h"
41#include "mapgen_topology.h"
42#include "mapgen_utils.h"
43#include "startpos.h"
44#include "temperature_map.h"
45
46#include "mapgen.h"
47
48static void make_huts(int number);
49static void add_resources(int prob);
50static void mapgenerator2(void);
51static void mapgenerator3(void);
52static void mapgenerator4(void);
53static bool map_generate_fair_islands(void);
54static void adjust_terrain_param(void);
55
56/* Common variables for generator 2, 3 and 4 */
58 int isleindex, n, e, s, w;
59 long int totalmass;
60};
61
62/* Define one terrain selection */
71
72
74static int river_type_count = 0;
75
76#define SPECLIST_TAG terrain_select
77#include "speclist.h"
78/* list iterator for terrain_select */
79#define terrain_select_list_iterate(tersel_list, ptersel) \
80 TYPED_LIST_ITERATE(struct terrain_select, tersel_list, ptersel)
81#define terrain_select_list_iterate_end \
82 LIST_ITERATE_END
83
84static struct terrain_select *tersel_new(int weight,
89 int wet_condition);
90static void tersel_free(struct terrain_select *ptersel);
91
92/* Terrain selection lists for make_island() */
93static struct {
94 bool init;
99} island_terrain = { .init = FALSE };
100
101static void island_terrain_init(void);
102static void island_terrain_free(void);
103
104static void fill_island(int coast, long int *bucket,
105 const struct terrain_select_list *tersel_list,
106 const struct gen234_state *const pstate);
107static bool make_island(int islemass, int starters,
108 struct gen234_state *pstate,
110
111#define RIVERS_MAXTRIES 32767
112/* This struct includes two dynamic bitvectors. They are needed to mark
113 tiles as blocked to prevent a river from falling into itself, and for
114 storing rivers temporarily. */
115struct river_map {
116 struct dbv blocked;
117 struct dbv ok;
118};
119
120static int river_test_blocked(struct river_map *privermap,
121 struct tile *ptile,
122 struct extra_type *priver);
123static int river_test_rivergrid(struct river_map *privermap,
124 struct tile *ptile,
125 struct extra_type *priver);
126static int river_test_highlands(struct river_map *privermap,
127 struct tile *ptile,
128 struct extra_type *priver);
130 struct tile *ptile,
131 struct extra_type *priver);
133 struct tile *ptile,
134 struct extra_type *priver);
136 struct tile *ptile,
137 struct extra_type *priver);
138static int river_test_swamp(struct river_map *privermap,
139 struct tile *ptile,
140 struct extra_type *priver);
142 struct tile *ptile,
143 struct extra_type *priver);
144static int river_test_height_map(struct river_map *privermap,
145 struct tile *ptile,
146 struct extra_type *priver);
147static void river_blockmark(struct river_map *privermap,
148 struct tile *ptile);
149static bool make_river(struct river_map *privermap,
150 struct tile *ptile,
151 struct extra_type *priver);
152static void make_rivers(void);
153
154static void river_types_init(void);
155
156/* Note: Only use after calling generator_init_topology() */
157#define HAS_POLES \
158 (MIN(COLD_LEVEL, 2 * ICE_BASE_LEVEL) > MIN_REAL_COLATITUDE(wld.map))
159
160/* These are the old parameters of terrains types in %
161 TODO: they depend on the hardcoded terrains */
162static int forest_pct = 0;
163static int desert_pct = 0;
164static int swamp_pct = 0;
165static int mountain_pct = 0;
166static int jungle_pct = 0;
167static int river_pct = 0;
168
169/**********************************************************************/
172/* WETNESS */
173
174/* Necessary condition of deserts placement */
175#define map_pos_is_dry(ptile) \
176 (map_colatitude((ptile)) <= DRY_MAX_LEVEL \
177 && map_colatitude((ptile)) > DRY_MIN_LEVEL \
178 && count_terrain_class_near_tile(&(wld.map), (ptile), \
179 FALSE, TRUE, TC_OCEAN) <= 35)
180typedef enum { WC_ALL = 200, WC_DRY, WC_NDRY } wetness_c;
181
182/* MISCELLANEOUS (OTHER CONDITIONS) */
183
184/* Necessary condition of swamp placement */
185static int hmap_low_level = 0;
186#define ini_hmap_low_level() \
187{ \
188hmap_low_level = (4 * swamp_pct * \
189 (hmap_max_level - hmap_shore_level)) / 100 + hmap_shore_level; \
190}
191
192/* Should be used after having hmap_low_level initialized */
193#define map_pos_is_low(ptile) ((hmap((ptile)) < hmap_low_level))
194
196
197/**************************************************************************
198 These functions test for conditions used in rand_map_pos_characteristic()
199**************************************************************************/
200
201/**********************************************************************/
204static bool test_wetness(const struct tile *ptile, wetness_c c)
205{
206 switch (c) {
207 case WC_ALL:
208 return TRUE;
209 case WC_DRY:
210 return map_pos_is_dry(ptile);
211 case WC_NDRY:
212 return !map_pos_is_dry(ptile);
213 }
214 log_error("Invalid wetness_c %d", c);
215
216 return FALSE;
217}
218
219/**********************************************************************/
222static bool test_miscellaneous(const struct tile *ptile, miscellaneous_c c)
223{
224 switch (c) {
225 case MC_NONE:
226 return TRUE;
227 case MC_LOW:
228 return map_pos_is_low(ptile);
229 case MC_NLOW:
230 return !map_pos_is_low(ptile);
231 }
232 log_error("Invalid miscellaneous_c %d", c);
233
234 return FALSE;
235}
236
237/**************************************************************************
238 Passed as data to rand_map_pos_filtered() by rand_map_pos_characteristic()
239**************************************************************************/
245
246/**********************************************************************/
250static bool condition_filter(const struct tile *ptile, const void *data)
251{
252 const struct DataFilter *filter = data;
253
254 return not_placed(ptile)
255 && tmap_is(ptile, filter->tc)
256 && test_wetness(ptile, filter->wc)
257 && test_miscellaneous(ptile, filter->mc);
258}
259
260/**********************************************************************/
267 miscellaneous_c mc )
268{
269 struct DataFilter filter = { .wc = wc, .tc = tc, .mc = mc };
270
271 return rand_map_pos_filtered(&(wld.map), &filter, condition_filter);
272}
273
274/**********************************************************************/
280static bool terrain_is_too_high(struct tile *ptile,
281 int thill, int my_height)
282{
283 square_iterate(&(wld.map), ptile, 1, tile1) {
285 return FALSE;
286 }
288
289 return TRUE;
290}
291
292/**********************************************************************/
298static void make_relief(void)
299{
300 /* Calculate the mountain level. map.server.mountains specifies the
301 * percentage of land that is turned into hills and mountains. */
303 * (100 - wld.map.server.steepness))
304 / 100 + hmap_shore_level);
305
306 whole_map_iterate(&(wld.map), ptile) {
307 if (not_placed(ptile)
308 && ((hmap_mountain_level < hmap(ptile)
309 && (fc_rand(10) > 5
311 hmap(ptile))))
312 || area_is_too_flat(ptile, hmap_mountain_level, hmap(ptile)))) {
313 if (tmap_is(ptile, TT_HOT)) {
314 /* Prefer hills to mountains in hot regions. */
315 tile_set_terrain(ptile,
318 } else {
319 /* Prefer mountains hills to in cold regions. */
320 tile_set_terrain(ptile,
322 fc_rand(10) < 8 ? MG_GREEN : MG_UNUSED));
323 }
324 map_set_placed(ptile);
325 }
327}
328
329/**********************************************************************/
335static void make_polar(void)
336{
338
339 whole_map_iterate(&(wld.map), ptile) {
340 if (tmap_is(ptile, TT_FROZEN)
341 || (tmap_is(ptile, TT_COLD)
342 && (fc_rand(10) > 7)
344 if (ocean) {
345 tile_set_terrain(ptile, ocean);
346 } else {
347 tile_set_terrain(ptile,
349 }
350 }
352}
353
354/**********************************************************************/
357static bool ok_for_separate_poles(struct tile *ptile)
358{
360 return TRUE;
361 }
362 adjc_iterate(&(wld.map), ptile, tile1) {
363 if (tile_continent(tile1) > 0) {
364 return FALSE;
365 }
367
368 return TRUE;
369}
370
371/**********************************************************************/
376static void make_polar_land(void)
377{
379
380 whole_map_iterate(&(wld.map), ptile) {
381 if ((tile_terrain(ptile) == T_UNKNOWN
383 && ((tmap_is(ptile, TT_FROZEN)
384 && ok_for_separate_poles(ptile))
385 || (tmap_is(ptile, TT_COLD)
386 && fc_rand(10) > 7
388 && ok_for_separate_poles(ptile)))) {
390 tile_set_continent(ptile, 0);
391 }
393}
394
395/**********************************************************************/
398static void place_terrain(struct tile *ptile, int diff,
399 struct terrain *pterrain, int *to_be_placed,
400 wetness_c wc,
403{
404 if (*to_be_placed <= 0) {
405 return;
406 }
408 tile_set_terrain(ptile, pterrain);
409 map_set_placed(ptile);
410 (*to_be_placed)--;
411
412 cardinal_adjc_iterate(&(wld.map), ptile, tile1) {
413 /* Check L_UNIT and H_UNIT against 0. */
415 / MAX(L_UNIT, 1)
416 + abs(hmap(tile1) - (hmap(ptile))) / MAX(H_UNIT, 1));
417
418 if (not_placed(tile1)
419 && tmap_is(tile1, tc)
420 && test_wetness(tile1, wc)
422 && Delta < diff
423 && fc_rand(10) > 4) {
424 place_terrain(tile1, diff - 1 - Delta, pterrain,
425 to_be_placed, wc, tc, mc);
426 }
428}
429
430/**********************************************************************/
434static void make_plain(struct tile *ptile, int *to_be_placed )
435{
436 /* In cold place we get tundra instead */
437 if (tmap_is(ptile, TT_FROZEN)) {
438 tile_set_terrain(ptile,
440 } else if (tmap_is(ptile, TT_COLD)) {
441 tile_set_terrain(ptile,
443 } else {
444 tile_set_terrain(ptile,
446 }
447 map_set_placed(ptile);
448 (*to_be_placed)--;
449}
450
451/**********************************************************************/
455static void make_plains(void)
456{
457 int to_be_placed;
458
459 whole_map_iterate(&(wld.map), ptile) {
460 if (not_placed(ptile)) {
461 to_be_placed = 1;
462 make_plain(ptile, &to_be_placed);
463 }
465}
466
467/**********************************************************************/
470#define PLACE_ONE_TYPE(count, alternate, ter, wc, tc, mc, weight) \
471 if ((count) > 0) { \
472 struct tile *ptile; \
473 /* Place some terrains */ \
474 if ((ptile = rand_map_pos_characteristic((wc), (tc), (mc)))) { \
475 place_terrain(ptile, (weight), (ter), &(count), (wc),(tc), (mc)); \
476 } else { \
477 /* If rand_map_pos_temperature returns FALSE we may as well stop */ \
478 /* looking for this time and go to alternate type. */ \
479 (alternate) += (count); \
480 (count) = 0; \
481 } \
482 }
483
484/**********************************************************************/
491static void make_terrains(void)
492{
493 int total = 0;
494 int forests_count = 0;
495 int jungles_count = 0;
496 int deserts_count = 0;
497 int alt_deserts_count = 0;
498 int plains_count = 0;
499 int swamps_count = 0;
500
501 whole_map_iterate(&(wld.map), ptile) {
502 if (not_placed(ptile)) {
503 total++;
504 }
506
507 forests_count = total * forest_pct / (100 - mountain_pct);
508 jungles_count = total * jungle_pct / (100 - mountain_pct);
509
510 deserts_count = total * desert_pct / (100 - mountain_pct);
511 swamps_count = total * swamp_pct / (100 - mountain_pct);
512
513 /* Grassland, tundra,arctic and plains is counted in plains_count */
516
517 /* The placement loop */
518 do {
519
528 WC_NDRY, TT_HOT, MC_LOW, 50);
535
536 /* Make the plains and tundras */
537 if (plains_count > 0) {
538 struct tile *ptile;
539
540 /* Don't use any restriction here ! */
542 make_plain(ptile, &plains_count);
543 } else {
544 /* If rand_map_pos_temperature returns FALSE we may as well stop
545 * looking for plains. */
546 plains_count = 0;
547 }
548 }
549 } while (forests_count > 0 || jungles_count > 0
550 || deserts_count > 0 || alt_deserts_count > 0
551 || plains_count > 0 || swamps_count > 0 );
552}
553
554/**********************************************************************/
558 struct tile *ptile,
559 struct extra_type *priver)
560{
561 if (dbv_isset(&privermap->blocked, tile_index(ptile))) {
562 return 1;
563 }
564
565 /* Any un-blocked? */
566 cardinal_adjc_iterate(&(wld.map), ptile, ptile1) {
567 if (!dbv_isset(&privermap->blocked, tile_index(ptile1))) {
568 return 0;
569 }
571
572 return 1; /* None non-blocked |- all blocked */
573}
574
575/**********************************************************************/
579 struct tile *ptile,
580 struct extra_type *priver)
581{
582 return (count_river_type_tile_card(&(wld.map), ptile, priver, FALSE) > 1)
583 ? 1 : 0;
584}
585
586/**********************************************************************/
590 struct tile *ptile,
591 struct extra_type *priver)
592{
593 return tile_terrain(ptile)->property[MG_MOUNTAINOUS];
594}
595
596/**********************************************************************/
600 struct tile *ptile,
601 struct extra_type *priver)
602{
603 return 100 - count_terrain_class_near_tile(&(wld.map), ptile,
604 TRUE, TRUE, TC_OCEAN);
605}
606
607/**********************************************************************/
611 struct tile *ptile,
612 struct extra_type *priver)
613{
614 return 100 - count_river_type_tile_card(&(wld.map), ptile, priver, TRUE);
615}
616
617/**********************************************************************/
621 struct tile *ptile,
622 struct extra_type *priver)
623{
624 int sum = 0;
625
626 adjc_iterate(&(wld.map), ptile, ptile2) {
627 sum += tile_terrain(ptile2)->property[MG_MOUNTAINOUS];
629
630 return sum;
631}
632
633/**********************************************************************/
637 struct tile *ptile,
638 struct extra_type *priver)
639{
640 return FC_INFINITY - tile_terrain(ptile)->property[MG_WET];
641}
642
643/**********************************************************************/
647 struct tile *ptile,
648 struct extra_type *priver)
649{
650 int sum = 0;
651
652 adjc_iterate(&(wld.map), ptile, ptile2) {
653 sum += tile_terrain(ptile2)->property[MG_WET];
655
656 return FC_INFINITY - sum;
657}
658
659/**********************************************************************/
663 struct tile *ptile,
664 struct extra_type *priver)
665{
666 return hmap(ptile);
667}
668
669/**********************************************************************/
673 struct tile *ptile)
674{
675 log_debug("Blockmarking (%d, %d) and adjacent tiles.", TILE_XY(ptile));
676
677 dbv_set(&privermap->blocked, tile_index(ptile));
678
679 cardinal_adjc_iterate(&(wld.map), ptile, ptile1) {
680 dbv_set(&privermap->blocked, tile_index(ptile1));
682}
683
684struct test_func {
685 int (*func)(struct river_map *privermap, struct tile *ptile, struct extra_type *priver);
686 bool fatal;
687};
688
689#define NUM_TEST_FUNCTIONS 9
701
702/**********************************************************************/
792static bool make_river(struct river_map *privermap, struct tile *ptile,
793 struct extra_type *priver)
794{
795 /* Comparison value for each tile surrounding the current tile. It is
796 * the suitability to continue a river to the tile in that direction;
797 * lower is better. However rivers may only run in cardinal directions;
798 * the other directions are ignored entirely. */
799 int rd_comparison_val[8];
800
801 bool rd_direction_is_valid[8];
802 int num_valid_directions, func_num, direction;
803
804 while (TRUE) {
805 /* Mark the current tile as river. */
806 dbv_set(&privermap->ok, tile_index(ptile));
807 log_debug("The tile at (%d, %d) has been marked as river in river_map.",
808 TILE_XY(ptile));
809
810 /* Test if the river is done. */
811 /* We arbitrarily make rivers end at the poles. */
812 if (count_river_near_tile(&(wld.map), ptile, priver) > 0
814 TRUE, TRUE, TC_OCEAN) > 0
815 || (tile_terrain(ptile)->property[MG_FROZEN] > 0
816 && map_colatitude(ptile) < 0.8 * COLD_LEVEL)) {
817
818 log_debug("The river ended at (%d, %d).", TILE_XY(ptile));
819 return TRUE;
820 }
821
822 /* Else choose a direction to continue the river. */
823 log_debug("The river did not end at (%d, %d). Evaluating directions...",
824 TILE_XY(ptile));
825
826 /* Mark all available cardinal directions as available. */
828 cardinal_adjc_dir_base_iterate(&(wld.map), ptile, dir) {
831
832 /* Test series that selects a direction for the river. */
834 int best_val = -1;
835
836 /* First get the tile values for the function */
837 cardinal_adjc_dir_iterate(&(wld.map), ptile, ptile1, dir) {
838 if (rd_direction_is_valid[dir]) {
840 ptile1, priver);
841 fc_assert_action(rd_comparison_val[dir] >= 0, continue);
842 if (best_val == -1) {
844 } else {
846 }
847 }
849 fc_assert_action(best_val != -1, continue);
850
851 /* Should we abort? */
852 if (best_val > 0 && test_funcs[func_num].fatal) {
853 return FALSE;
854 }
855
856 /* Mark the less attractive directions as invalid */
857 cardinal_adjc_dir_base_iterate(&(wld.map), ptile, dir) {
858 if (rd_direction_is_valid[dir]) {
859 if (rd_comparison_val[dir] != best_val) {
861 }
862 }
864 }
865
866 /* Directions evaluated with all functions. Now choose the best
867 direction before going to the next iteration of the while loop */
869 cardinal_adjc_dir_base_iterate(&(wld.map), ptile, dir) {
870 if (rd_direction_is_valid[dir]) {
872 }
874
875 if (num_valid_directions == 0) {
876 return FALSE; /* river aborted */
877 }
878
879 /* One or more valid directions: choose randomly. */
880 log_debug("mapgen.c: Had to let the random number"
881 " generator select a direction for a river.");
882 direction = fc_rand(num_valid_directions);
883 log_debug("mapgen.c: direction: %d", direction);
884
885 /* Find the direction that the random number generator selected. */
886 cardinal_adjc_dir_iterate(&(wld.map), ptile, tile1, dir) {
887 if (rd_direction_is_valid[dir]) {
888 if (direction > 0) {
889 direction--;
890 } else {
892 ptile = tile1;
893 break;
894 }
895 }
897 fc_assert_ret_val(direction == 0, FALSE);
898
899 } /* end while; (Make a river.) */
900}
901
902/**********************************************************************/
906static void make_rivers(void)
907{
908 struct tile *ptile;
909 struct terrain *pterrain;
910 struct river_map rivermap;
911 struct extra_type *road_river = nullptr;
912
913 /* Formula to make the river density similar om different sized maps. Avoids
914 too few rivers on large maps and too many rivers on small maps. */
916 river_pct *
917 /* The size of the map (poles counted in river_pct). */
918 map_num_tiles() *
919 /* Rivers need to be on land only. */
921 /* Adjustment value. Tested by me. Gives no rivers with 'set
922 rivers 0', gives a reasonable amount of rivers with default
923 settings and as many rivers as possible with 'set rivers 100'. */
924 5325;
925
926 /* The number of river tiles that have been set. */
927 int current_riverlength = 0;
928
929 /* Counts the number of iterations (should increase with 1 during
930 every iteration of the main loop in this function).
931 Is needed to stop a potentially infinite loop. */
932 int iteration_counter = 0;
933
934 if (river_type_count <= 0) {
935 /* No river type available */
936 return;
937 }
938
939 create_placed_map(); /* Needed by rand_map_characteristic() */
941
944
945 /* The main loop in this function. */
948
950 MC_NLOW)) == nullptr) {
951 break; /* No more spring places */
952 }
953 pterrain = tile_terrain(ptile);
954
955 /* Check if it is suitable to start a river on the current tile.
956 */
957 if (
958 /* Don't start a river on ocean. */
959 !is_ocean(pterrain)
960
961 /* Don't start a river on river. */
962 && !tile_has_river(ptile)
963
964 /* Don't start a river on a tile is surrounded by > 1 river +
965 ocean tile. */
966 && (count_river_near_tile(&(wld.map), ptile, nullptr)
968 TRUE, FALSE, TC_OCEAN) <= 1)
969
970 /* Don't start a river on a tile that is surrounded by hills or
971 mountains unless it is hard to find somewhere else to start
972 it. */
974 MG_MOUNTAINOUS) < 90
975 || iteration_counter >= RIVERS_MAXTRIES / 10 * 5)
976
977 /* Don't start a river on hills unless it is hard to find
978 somewhere else to start it. */
979 && (pterrain->property[MG_MOUNTAINOUS] == 0
980 || iteration_counter >= RIVERS_MAXTRIES / 10 * 6)
981
982 /* Don't start a river on arctic unless it is hard to find
983 somewhere else to start it. */
984 && (pterrain->property[MG_FROZEN] == 0
985 || iteration_counter >= RIVERS_MAXTRIES / 10 * 8)
986
987 /* Don't start a river on desert unless it is hard to find
988 somewhere else to start it. */
989 && (pterrain->property[MG_DRY] == 0
990 || iteration_counter >= RIVERS_MAXTRIES / 10 * 9)) {
991
992 /* Reset river map before making a new river. */
993 dbv_clr_all(&rivermap.blocked);
995
997
999 if (oriver != road_river) {
1001 if (tile_has_extra(rtile, oriver)) {
1002 dbv_set(&rivermap.blocked, tile_index(rtile));
1003 }
1005 }
1007
1008 log_debug("Found a suitable starting tile for a river at (%d, %d)."
1009 " Starting to make it.", TILE_XY(ptile));
1010
1011 /* Try to make a river. If it is OK, apply it to the map. */
1012 if (make_river(&rivermap, ptile, road_river)) {
1014 if (dbv_isset(&rivermap.ok, tile_index(ptile1))) {
1016
1018 /* We have to change the terrain to put a river here. */
1020 if (river_terrain != nullptr) {
1022 }
1023 }
1024
1028 log_debug("Applied a river to (%d, %d).", TILE_XY(ptile1));
1029 }
1031 } else {
1032 log_debug("mapgen.c: A river failed. It might have gotten stuck "
1033 "in a helix.");
1034 }
1035 } /* end if; */
1037 log_debug("current_riverlength: %d; desirable_riverlength: %d; "
1038 "iteration_counter: %d",
1040 } /* end while; */
1041
1042 dbv_free(&rivermap.blocked);
1043 dbv_free(&rivermap.ok);
1044
1046}
1047
1048/**********************************************************************/
1053static void make_land(void)
1054{
1055 struct terrain *land_fill = nullptr;
1056
1057 if (HAS_POLES) {
1059 }
1060
1061 /* Pick a non-ocean terrain just once and fill all land tiles with "
1062 * that terrain. We must set some terrain (and not T_UNKNOWN) so that "
1063 * continent number assignment works. */
1064 terrain_type_iterate(pterrain) {
1065 if (!is_ocean(pterrain) && !terrain_has_flag(pterrain, TER_NOT_GENERATED)) {
1066 land_fill = pterrain;
1067 break;
1068 }
1070
1071 fc_assert_exit_msg(land_fill != nullptr,
1072 "No land terrain type could be found for the purpose "
1073 "of temporarily filling in land tiles during map "
1074 "generation. This could be an error in Freeciv, or a "
1075 "mistake in the terrain.ruleset file. Please make sure "
1076 "there is at least one land terrain type in the "
1077 "ruleset, or use a different map generator. If this "
1078 "error persists, please report it at: %s", BUG_URL);
1079
1082 whole_map_iterate(&(wld.map), ptile) {
1083 tile_set_terrain(ptile, T_UNKNOWN); /* Set as oceans count is used */
1084 if (hmap(ptile) < hmap_shore_level) {
1085 int depth = (hmap_shore_level - hmap(ptile)) * 100 / hmap_shore_level;
1086 int ocean = 0;
1087 int land = 0;
1088
1089 /* This is to make shallow connection between continents less likely */
1090 adjc_iterate(&(wld.map), ptile, other) {
1091 if (hmap(other) < hmap_shore_level) {
1092 ocean++;
1093 } else {
1094 land++;
1095 break;
1096 }
1098
1099 depth += 30 * (ocean - land) / MAX(1, (ocean + land));
1100
1101 depth = MIN(depth, TERRAIN_OCEAN_DEPTH_MAXIMUM);
1102
1103 /* Generate sea ice here, if ruleset supports it. Dummy temperature
1104 * map is sufficient for this. If ruleset doesn't support it,
1105 * use unfrozen ocean; make_polar_land() will later fill in with
1106 * land-based ice. Ice has a ragged margin. */
1107 {
1108 bool frozen = HAS_POLES
1109 && (tmap_is(ptile, TT_FROZEN)
1110 || (tmap_is(ptile, TT_COLD)
1111 && fc_rand(10) > 7
1113 struct terrain *pterrain = pick_ocean(depth, frozen);
1114
1115 if (frozen && !pterrain) {
1116 pterrain = pick_ocean(depth, FALSE);
1117 fc_assert(pterrain);
1118 }
1119 tile_set_terrain(ptile, pterrain);
1120 }
1121 } else {
1122 /* See note above for 'land_fill'. */
1124 }
1126
1127 if (HAS_POLES) {
1129 }
1130
1131 /* Destroy old dummy temperature map ... */
1132 destroy_tmap();
1133 /* ... and create a real temperature map (needs hmap and oceans) */
1135
1136 if (HAS_POLES) { /* This is a hack to terrains set with not frizzed oceans*/
1137 make_polar_land(); /* Make extra land at poles*/
1138 }
1139
1140 create_placed_map(); /* Here it means land terrains to be placed */
1144 } else {
1145 make_relief(); /* Base relief on map */
1146 }
1147 make_terrains(); /* Place all except mountains and hill */
1149
1150 make_rivers(); /* Use a new placed_map. Destroy older before call */
1151}
1152
1153/**********************************************************************/
1156static bool is_tiny_island(struct tile *ptile)
1157{
1158 struct terrain *pterrain = tile_terrain(ptile);
1159
1160 if (is_ocean(pterrain) || pterrain->property[MG_FROZEN] > 0) {
1161 /* The arctic check is needed for iso-maps: the poles may not have
1162 * any cardinally adjacent land tiles, but that's okay. */
1163 return FALSE;
1164 }
1165
1166 adjc_iterate(&(wld.map), ptile, tile1) {
1167 /* This was originally a cardinal_adjc_iterate(), which seemed to cause
1168 * two or three problems. /MSS */
1169 if (!is_ocean_tile(tile1)) {
1170 return FALSE;
1171 }
1173
1174 return TRUE;
1175}
1176
1177/**********************************************************************/
1182static void remove_tiny_islands(void)
1183{
1184 whole_map_iterate(&(wld.map), ptile) {
1185 if (is_tiny_island(ptile)) {
1186 struct terrain *shallow
1188
1189 fc_assert_ret(shallow != nullptr);
1190
1191 tile_set_terrain(ptile, shallow);
1193 if (tile_has_extra(ptile, priver)
1196 }
1198 tile_set_continent(ptile, 0);
1199 }
1201}
1202
1203/**********************************************************************/
1207static void print_mapgen_map(void)
1208{
1210 int total = 0, ocean = 0;
1211
1212 terrain_type_iterate(pterrain) {
1213 terrain_counts[terrain_index(pterrain)] = 0;
1215
1216 whole_map_iterate(&(wld.map), ptile) {
1217 struct terrain *pterrain = tile_terrain(ptile);
1218
1219 terrain_counts[terrain_index(pterrain)]++;
1220 if (is_ocean(pterrain)) {
1221 ocean++;
1222 }
1223 total++;
1225
1226 log_verbose("map settings:");
1227 log_verbose(" %-20s : %5d%%", "mountain_pct", mountain_pct);
1228 log_verbose(" %-20s : %5d%%", "desert_pct", desert_pct);
1229 log_verbose(" %-20s : %5d%%", "forest_pct", forest_pct);
1230 log_verbose(" %-20s : %5d%%", "jungle_pct", jungle_pct);
1231 log_verbose(" %-20s : %5d%%", "swamp_pct", swamp_pct);
1232
1233 log_verbose("map statistics:");
1234 terrain_type_iterate(pterrain) {
1235 if (is_ocean(pterrain)) {
1236 log_verbose(" %-20s : %6d %5.1f%% (ocean: %5.1f%%)",
1237 terrain_rule_name(pterrain),
1238 terrain_counts[terrain_index(pterrain)],
1239 (float) terrain_counts[terrain_index(pterrain)] * 100
1240 / total,
1241 (float) terrain_counts[terrain_index(pterrain)] * 100
1242 / ocean);
1243 } else {
1244 log_verbose(" %-20s : %6d %5.1f%% (land: %5.1f%%)",
1245 terrain_rule_name(pterrain),
1246 terrain_counts[terrain_index(pterrain)],
1247 (float) terrain_counts[terrain_index(pterrain)] * 100
1248 / total,
1249 (float) terrain_counts[terrain_index(pterrain)] * 100
1250 / (total - ocean));
1251 }
1253}
1254
1255/**********************************************************************/
1268bool map_fractal_generate(bool autosize, struct unit_type *initial_unit)
1269{
1270 /* Save the current random state: */
1271 RANDOM_STATE rstate;
1273
1274 /* Call fc_rand() even when result is not needed to make sure
1275 * random state proceeds equally for random seeds and explicitly
1276 * set seed. */
1278
1279 if (wld.map.server.seed_setting == 0) {
1280 /* Create a "random" map seed. */
1282 while (wld.map.server.seed == 0) {
1283 /* This makes random state different, but we don't
1284 * care as this is an extreme corner case anyway. */
1287 }
1288#ifdef FREECIV_TESTMATIC
1289 /* Log command to reproduce the mapseed */
1290 log_testmatic("set mapseed %d", wld.map.server.seed);
1291#else /* FREECIV_TESTMATIC */
1292 log_debug("Setting map.seed:%d", wld.map.server.seed);
1293#endif /* FREECIV_TESTMATIC */
1294 } else {
1296 }
1297
1298 rstate = fc_rand_state();
1299
1301
1302 /* Don't generate tiles with mapgen == MAPGEN_SCENARIO as we've loaded *
1303 them from file.
1304 Also, don't delete (the handcrafted!) tiny islands in a scenario */
1308
1310 /* Map can be already allocated, if we failed first map generation */
1311 if (map_is_empty()) {
1313 }
1315 /* If one mapgenerator fails, it will choose another mapgenerator */
1316 /* with a lower number to try again */
1317
1318 /* Create a temperature map */
1320
1324 }
1325
1327 /* Initialise terrain selection lists used by make_island() */
1329
1330 /* 2 or 3 players per isle? */
1333 mapgenerator4();
1334 }
1337 /* Single player per isle. */
1338 mapgenerator3();
1339 }
1341 /* "Variable" single player. */
1342 mapgenerator2();
1343 }
1344
1345 /* Free terrain selection lists used by make_island() */
1347 }
1348
1353 ? 0 : player_count()));
1354 }
1355
1359 ? player_count() / 4 : 0)));
1360 }
1361
1364 }
1365
1366 /* If hmap only generator make anything else */
1370
1372 make_land();
1374 height_map = nullptr;
1375 }
1376 if (!wld.map.server.tinyisles) {
1378 }
1379
1381
1382 /* Continent numbers must be assigned before regenerate_lakes() */
1384
1385 /* Turn small oceans into lakes. */
1386 if (wld.map.num_oceans > 0) {
1388 }
1389
1390 } else {
1392 }
1393
1394 /* Create a temperature map if it was not done before */
1397 }
1398
1399 /* Some scenarios already provide specials */
1402 }
1403
1404 if (!wld.map.server.have_huts) {
1406 }
1407
1408 /* Restore previous random state: */
1409 fc_rand_set_state(rstate);
1410
1411 /* We don't want random start positions in a scenario which already
1412 * provides them. */
1413 if (0 == map_startpos_count()) {
1414 enum map_startpos mode = MAPSTARTPOS_ALL;
1415
1416 switch (wld.map.server.generator) {
1417 case MAPGEN_FAIR:
1419 "Fair island generator failed to allocated "
1420 "start positions!");
1421 break;
1422 case MAPGEN_SCENARIO:
1423 case MAPGEN_RANDOM:
1424 case MAPGEN_FRACTURE:
1425 mode = wld.map.server.startpos;
1426 break;
1427 case MAPGEN_FRACTAL:
1429 log_verbose("Map generator chose startpos=ALL");
1430 mode = MAPSTARTPOS_ALL;
1431 } else {
1432 mode = wld.map.server.startpos;
1433 }
1434 break;
1435 case MAPGEN_ISLAND:
1436 switch (wld.map.server.startpos) {
1439 log_verbose("Map generator chose startpos=SINGLE");
1440
1442 case MAPSTARTPOS_SINGLE:
1443 mode = MAPSTARTPOS_SINGLE;
1444 break;
1445 default:
1446 log_verbose("Map generator chose startpos=2or3");
1447
1449 case MAPSTARTPOS_2or3:
1450 mode = MAPSTARTPOS_2or3;
1451 break;
1452 }
1453 break;
1454 }
1455
1456 for (;;) {
1457 bool success;
1458
1459 success = create_start_positions(mode, initial_unit);
1460 if (success) {
1461 wld.map.server.startpos = mode;
1462 break;
1463 }
1464
1465 switch (mode) {
1466 case MAPSTARTPOS_SINGLE:
1467 log_verbose("Falling back to startpos=2or3");
1468 mode = MAPSTARTPOS_2or3;
1469 continue;
1470 case MAPSTARTPOS_2or3:
1471 log_verbose("Falling back to startpos=ALL");
1472 mode = MAPSTARTPOS_ALL;
1473 break;
1474 case MAPSTARTPOS_ALL:
1475 log_verbose("Falling back to startpos=VARIABLE");
1476 mode = MAPSTARTPOS_VARIABLE;
1477 break;
1478 default:
1479 log_error(_("The server couldn't allocate starting positions."));
1480 destroy_tmap();
1481 return FALSE;
1482 }
1483 }
1484 }
1485
1486 /* Destroy temperature map */
1487 destroy_tmap();
1488
1490
1491 return TRUE;
1492}
1493
1494/**********************************************************************/
1498static void adjust_terrain_param(void)
1499{
1501 float mount_factor = (100.0 - polar - 30 * 0.8) / 10000;
1502 float factor = (100.0 - polar - wld.map.server.steepness * 0.8) / 10000;
1503
1505
1506 /* 27 % if wetness == 50 & */
1507 forest_pct = factor * (wld.map.server.wetness * 40 + 700);
1509 / (MAX_COLATITUDE * 2);
1511
1512 /* 3 - 11 % */
1513 river_pct = (100 - polar) * (3 + wld.map.server.wetness / 12) / 100;
1514
1515 /* 7 % if wetness == 50 && temperature == 50 */
1516 swamp_pct = factor * MAX(0, (wld.map.server.wetness * 12 - 150
1517 + wld.map.server.temperature * 10));
1518 desert_pct = factor * MAX(0, (wld.map.server.temperature * 15 - 250
1519 + (100 - wld.map.server.wetness) * 10));
1520}
1521
1522/**********************************************************************/
1526static bool near_safe_tiles(struct tile *ptile)
1527{
1528 square_iterate(&(wld.map), ptile, 1, tile1) {
1530 return TRUE;
1531 }
1533
1534 return FALSE;
1535}
1536
1537/**********************************************************************/
1541static void make_huts(int number)
1542{
1543 int count = 0;
1544 struct tile *ptile;
1545
1546 create_placed_map(); /* Here it means placed huts */
1547
1548 while (number > 0 && count++ < map_num_tiles() * 2) {
1549
1550 /* Add a hut. But not too close to another hut. */
1552 struct extra_type *phut = rand_extra_for_tile(ptile, EC_HUT, TRUE);
1553
1554 number--;
1555 if (phut != nullptr) {
1556 tile_add_extra(ptile, phut);
1557 }
1558 set_placed_near_pos(ptile, 3);
1559 }
1560 }
1561
1563}
1564
1565/**********************************************************************/
1569static bool is_resource_close(const struct tile *ptile)
1570{
1571 square_iterate(&(wld.map), ptile, 1, tile1) {
1572 if (tile_resource(tile1) != nullptr) {
1573 return TRUE;
1574 }
1576
1577 return FALSE;
1578}
1579
1580/**********************************************************************/
1583static void add_resources(int prob)
1584{
1585 whole_map_iterate(&(wld.map), ptile) {
1586 const struct terrain *pterrain = tile_terrain(ptile);
1587
1588 if (is_resource_close(ptile) || fc_rand (1000) >= prob) {
1589 continue;
1590 }
1591 if (!is_ocean(pterrain) || near_safe_tiles(ptile)
1593 struct extra_type *res = pick_resource(pterrain);
1594
1595 if (res != nullptr) {
1596 tile_set_resource(ptile, res);
1597 }
1598 }
1600
1602}
1603
1604/**********************************************************************/
1608 const struct gen234_state *const pstate)
1609{
1610 int xrnd, yrnd;
1611
1612 fc_assert_ret_val((pstate->e - pstate->w) > 0, nullptr);
1613 fc_assert_ret_val((pstate->e - pstate->w) < MAP_NATIVE_WIDTH, nullptr);
1614 fc_assert_ret_val((pstate->s - pstate->n) > 0, nullptr);
1615 fc_assert_ret_val((pstate->s - pstate->n) < MAP_NATIVE_HEIGHT, nullptr);
1616
1617 xrnd = pstate->w + fc_rand(pstate->e - pstate->w);
1618 yrnd = pstate->n + fc_rand(pstate->s - pstate->n);
1619
1620 return native_pos_to_tile(&(wld.map), xrnd, yrnd);
1621}
1622
1623/**********************************************************************/
1630 int temp_condition,
1631 int wet_condition)
1632{
1633 struct terrain_select *ptersel = fc_malloc(sizeof(*ptersel));
1634
1635 ptersel->weight = weight;
1636 ptersel->target = target;
1637 ptersel->prefer = prefer;
1638 ptersel->avoid = avoid;
1639 ptersel->temp_condition = temp_condition;
1640 ptersel->wet_condition = wet_condition;
1641
1642 return ptersel;
1643}
1644
1645/**********************************************************************/
1649{
1650 if (ptersel != nullptr) {
1652 }
1653}
1654
1655/**********************************************************************/
1658static void fill_island(int coast, long int *bucket,
1659 const struct terrain_select_list *tersel_list,
1660 const struct gen234_state *const pstate)
1661{
1662 int i, k, capac, total_weight = 0;
1664 long int failsafe;
1665
1666 if (*bucket <= 0 ) {
1667 return;
1668 }
1669
1670 /* Must have at least one terrain selection given in tersel_list */
1671 fc_assert_ret(ntersel != 0);
1672
1673 capac = pstate->totalmass;
1674 i = *bucket / capac;
1675 i++;
1676 *bucket -= i * capac;
1677
1678 k = i;
1679 failsafe = i * (pstate->s - pstate->n) * (pstate->e - pstate->w);
1680 if (failsafe < 0) {
1681 failsafe = -failsafe;
1682 }
1683
1685 total_weight += ptersel->weight;
1687
1688 if (total_weight <= 0) {
1689 return;
1690 }
1691
1692 while (i > 0 && (failsafe--) > 0) {
1694
1695 if (tile_continent(ptile) != pstate->isleindex || !not_placed(ptile)) {
1696 continue;
1697 }
1698
1699 struct terrain_select *ptersel
1701
1702 if (fc_rand(total_weight) > ptersel->weight) {
1703 continue;
1704 }
1705
1706 if (!tmap_is(ptile, ptersel->temp_condition)
1707 || !test_wetness(ptile, ptersel->wet_condition)) {
1708 continue;
1709 }
1710
1711 struct terrain *pterrain = pick_terrain(ptersel->target, ptersel->prefer,
1712 ptersel->avoid);
1713
1714 /* The first condition helps make terrain more contiguous,
1715 the second lets it avoid the coast: */
1716 if ((i * 3 > k * 2
1717 || fc_rand(100) < 50
1718 || is_terrain_near_tile(&(wld.map), ptile, pterrain, FALSE))
1720 || fc_rand(100) < coast)) {
1721 tile_set_terrain(ptile, pterrain);
1722 map_set_placed(ptile);
1723
1724 log_debug("[fill_island] placed terrain '%s' at (%2d,%2d)",
1725 terrain_rule_name(pterrain), TILE_XY(ptile));
1726 }
1727
1728 if (!not_placed(ptile)) {
1729 i--;
1730 }
1731 }
1732}
1733
1734/**********************************************************************/
1737static bool island_river_mouth_suitability(const struct tile *ptile,
1738 const struct extra_type *priver)
1739{
1741
1744 TC_OCEAN);
1747 TC_OCEAN);
1749
1750 return (num_card_ocean == 1 && pct_adj_ocean <= 35
1751 && num_adj_river == 0);
1752}
1753
1754/**********************************************************************/
1758static bool island_river_suitability(const struct tile *ptile,
1759 const struct extra_type *priver)
1760{
1762
1766 TC_OCEAN);
1769 TC_OCEAN);
1771
1772 return (num_card_river == 1 && num_card_ocean == 0
1773 && pct_adj_ocean < 20 && pct_adj_river < 35
1774 /* The following expression helps with straightness,
1775 * ocean avoidance, and reduces forking. */
1776 && (pct_adj_river + pct_adj_ocean * 2) < fc_rand(25) + 25);
1777}
1778
1779/**********************************************************************/
1782static void fill_island_rivers(int coast, long int *bucket,
1783 const struct gen234_state *const pstate)
1784{
1785 long int failsafe, capac, i, k;
1786 struct tile *ptile;
1787
1788 if (*bucket <= 0) {
1789 return;
1790 }
1791 if (river_type_count <= 0) {
1792 return;
1793 }
1794
1795 capac = pstate->totalmass;
1796 i = *bucket / capac;
1797 i++;
1798 *bucket -= i * capac;
1799
1800 /* Generate 75% more rivers than generator 1 */
1801 i = (i * 175) / 100;
1802
1803 k = i;
1804 failsafe = i * (pstate->s - pstate->n) * (pstate->e - pstate->w) * 5;
1805 if (failsafe < 0) {
1806 failsafe = -failsafe;
1807 }
1808
1809 while (i > 0 && failsafe-- > 0) {
1810 struct extra_type *priver;
1811
1813 if (tile_continent(ptile) != pstate->isleindex
1814 || tile_has_river(ptile)) {
1815 continue;
1816 }
1817
1819
1820 if (test_wetness(ptile, WC_DRY) && fc_rand(100) < 50) {
1821 /* Rivers don't like dry locations */
1822 continue;
1823 }
1824
1826 && (fc_rand(100) < coast || i == k))
1827 || island_river_suitability(ptile, priver)) {
1828 tile_add_extra(ptile, priver);
1829 i--;
1830 }
1831 }
1832}
1833
1834/**********************************************************************/
1838static bool is_near_land(struct tile *ptile)
1839{
1840 /* Note this function may sometimes be called on land tiles. */
1841 adjc_iterate(&(wld.map), ptile, tile1) {
1842 if (!is_ocean(tile_terrain(tile1))) {
1843 return TRUE;
1844 }
1846
1847 return FALSE;
1848}
1849
1850static long int checkmass;
1851
1852/**********************************************************************/
1856{
1857 int i = 0, xcur, ycur, nat_x, nat_y;
1858 struct tile *ptile;
1859
1860 ptile = rand_map_pos(&(wld.map));
1862
1863 /* This helps a lot for maps with high landmass */
1864 for (ycur = pstate->n, xcur = pstate->w;
1865 ycur < pstate->s && xcur < pstate->e;
1866 ycur++, xcur++) {
1867 struct tile *tile0 = native_pos_to_tile(&(wld.map), xcur, ycur);
1868 struct tile *tile1 = native_pos_to_tile(&(wld.map),
1869 xcur + nat_x - pstate->w,
1870 ycur + nat_y - pstate->n);
1871
1872 if (!tile0 || !tile1) {
1873 return FALSE;
1874 }
1875 if (hmap(tile0) != 0 && is_near_land(tile1)) {
1876 return FALSE;
1877 }
1878 }
1879
1880 for (ycur = pstate->n; ycur < pstate->s; ycur++) {
1881 for (xcur = pstate->w; xcur < pstate->e; xcur++) {
1882 struct tile *tile0 = native_pos_to_tile(&(wld.map), xcur, ycur);
1883 struct tile *tile1 = native_pos_to_tile(&(wld.map),
1884 xcur + nat_x - pstate->w,
1885 ycur + nat_y - pstate->n);
1886
1887 if (!tile0 || !tile1) {
1888 return FALSE;
1889 }
1890 if (hmap(tile0) != 0 && is_near_land(tile1)) {
1891 return FALSE;
1892 }
1893 }
1894 }
1895
1896 for (ycur = pstate->n; ycur < pstate->s; ycur++) {
1897 for (xcur = pstate->w; xcur < pstate->e; xcur++) {
1898 if (hmap(native_pos_to_tile(&(wld.map), xcur, ycur)) != 0) {
1899 struct tile *tile1 = native_pos_to_tile(&(wld.map),
1900 xcur + nat_x - pstate->w,
1901 ycur + nat_y - pstate->n);
1902
1903 checkmass--;
1904 if (checkmass <= 0) {
1905 log_error("mapgen.c: mass doesn't sum up.");
1906 return i != 0;
1907 }
1908
1911
1912 tile_set_continent(tile1, pstate->isleindex);
1913 i++;
1914 }
1915 }
1916 }
1917
1918 pstate->s += nat_y - pstate->n;
1919 pstate->e += nat_x - pstate->w;
1920 pstate->n = nat_y;
1921 pstate->w = nat_x;
1922
1923 return i != 0;
1924}
1925
1926/**********************************************************************/
1929static int count_card_adjc_elevated_tiles(struct tile *ptile)
1930{
1931 int count = 0;
1932
1933 cardinal_adjc_iterate(&(wld.map), ptile, tile1) {
1934 if (hmap(tile1) != 0) {
1935 count++;
1936 }
1938
1939 return count;
1940}
1941
1942/**********************************************************************/
1946{
1947 int i, nat_x, nat_y;
1948 long int tries = islemass * (2 + islemass / 20) + 99;
1949 bool j;
1950 struct tile *ptile
1953
1954 memset(height_map, '\0', MAP_INDEX_SIZE * sizeof(*height_map));
1956 MAP_NATIVE_WIDTH / 2, MAP_NATIVE_HEIGHT / 2)) = 1;
1957
1959 pstate->n = nat_y - 1;
1960 pstate->w = nat_x - 1;
1961 pstate->s = nat_y + 2;
1962 pstate->e = nat_x + 2;
1963 i = islemass - 1;
1964
1965 while (i > 0 && tries-->0) {
1968
1969 if ((!near_singularity(ptile) || fc_rand(50) < 25 )
1970 && hmap(ptile) == 0 && count_card_adjc_elevated_tiles(ptile) > 0) {
1971 hmap(ptile) = 1;
1972 i--;
1973 if (nat_y >= pstate->s - 1 && pstate->s < MAP_NATIVE_HEIGHT - 2) {
1974 pstate->s++;
1975 }
1976 if (nat_x >= pstate->e - 1 && pstate->e < MAP_NATIVE_WIDTH - 2) {
1977 pstate->e++;
1978 }
1979 if (nat_y <= pstate->n && pstate->n > 2) {
1980 pstate->n--;
1981 }
1982 if (nat_x <= pstate->w && pstate->w > 2) {
1983 pstate->w--;
1984 }
1985 }
1986 if (i < islemass / 10) {
1987 int xcur, ycur;
1988
1989 for (ycur = pstate->n; ycur < pstate->s; ycur++) {
1990 for (xcur = pstate->w; xcur < pstate->e; xcur++) {
1991 ptile = native_pos_to_tile(&(wld.map), xcur, ycur);
1992 if (hmap(ptile) == 0 && i > 0
1993 && count_card_adjc_elevated_tiles(ptile) == 4) {
1994 hmap(ptile) = 1;
1995 i--;
1996 }
1997 }
1998 }
1999 }
2000 }
2001
2002 if (tries <= 0) {
2003 log_error("create_island ended early with %d/%d.", islemass-i, islemass);
2004 }
2005
2006 tries = map_num_tiles() / 4; /* On a 40x60 map, there are 2400 places */
2007 while (!(j = place_island(pstate)) && (--tries) > 0) {
2008 /* Nothing */
2009 }
2010
2011 return j;
2012}
2013
2014/*************************************************************************/
2015
2016/**********************************************************************/
2019static void island_terrain_init(void)
2020{
2021 struct terrain_select *ptersel;
2022
2023 /* Forest */
2029 TT_ALL, WC_ALL);
2037
2038 /* Desert */
2041 TT_HOT, WC_DRY);
2047 TT_NHOT, WC_DRY);
2050 TT_FROZEN, WC_DRY);
2052
2053 /* Mountain */
2056 TT_ALL, WC_ALL);
2059 TT_ALL, WC_ALL);
2061
2062 /* Swamp */
2068 TT_HOT, WC_NDRY);
2071 TT_NHOT, WC_NDRY);
2073
2074 island_terrain.init = TRUE;
2075}
2076
2077/**********************************************************************/
2080static void island_terrain_free(void)
2081{
2082 if (!island_terrain.init) {
2083 return;
2084 }
2085
2090
2091 island_terrain.init = FALSE;
2092}
2093
2094/**********************************************************************/
2100static bool make_island(int islemass, int starters,
2101 struct gen234_state *pstate,
2103{
2104 /* int may be only 2 bytes ! */
2105 static long int tilefactor, balance, lastplaced;
2107 int i;
2108
2109 /* The terrain selection lists have to be initialised.
2110 * (see island_terrain_init()) */
2112
2113 if (islemass == 0) {
2114 /* This only runs to initialise static things, not to actually
2115 * create an island. */
2116 balance = 0;
2117 /* 0 = none, poles, then isles */
2118 pstate->isleindex = wld.map.num_continents + 1;
2119
2120 checkmass = pstate->totalmass;
2121
2122 /* Caveat: this should really be sent to all players */
2123 if (pstate->totalmass > 3000) {
2124 log_normal(_("High landmass - this may take a few seconds."));
2125 }
2126
2128 i = (i <= 90) ? 100 : i * 11 / 10;
2129 tilefactor = pstate->totalmass / i;
2130 riverbuck = -(long int) fc_rand(pstate->totalmass);
2131 mountbuck = -(long int) fc_rand(pstate->totalmass);
2132 desertbuck = -(long int) fc_rand(pstate->totalmass);
2133 forestbuck = -(long int) fc_rand(pstate->totalmass);
2134 swampbuck = -(long int) fc_rand(pstate->totalmass);
2135 lastplaced = pstate->totalmass;
2136 } else {
2137
2138 /* Makes the islands this big */
2140
2141 if (islemass > lastplaced + 1 + lastplaced / 50) {
2142 /* Don't create big isles we can't place */
2143 islemass = lastplaced + 1 + lastplaced / 50;
2144 }
2145
2146 /* Isle creation does not perform well for nonsquare islands */
2147 if (islemass > (MAP_NATIVE_HEIGHT - 6) * (MAP_NATIVE_HEIGHT - 6)) {
2149 }
2150
2151 if (islemass > (MAP_NATIVE_WIDTH - 2) * (MAP_NATIVE_WIDTH - 2)) {
2153 }
2154
2155 i = islemass;
2156 if (i <= 0) {
2157 return FALSE;
2158 }
2159 fc_assert_ret_val(starters >= 0, FALSE);
2160 log_verbose("island %i", pstate->isleindex);
2161
2162 /* Keep trying to place an island, and decrease the size of
2163 * the island we're trying to create until we succeed.
2164 * If we get too small, return an error. */
2165 while (!create_island(i, pstate)) {
2166 if (i < islemass * min_specific_island_size / 100) {
2167 return FALSE;
2168 }
2169 i--;
2170 }
2171 i++;
2172 lastplaced = i;
2173 if (i * 10 > islemass) {
2174 balance = i - islemass;
2175 } else {
2176 balance = 0;
2177 }
2178
2179 log_verbose("ini=%d, plc=%d, bal=%ld, tot=%ld",
2181
2182 i *= tilefactor;
2183
2184 riverbuck += river_pct * i;
2186
2187 /* Forest */
2188 forestbuck += forest_pct * i;
2190
2191 /* Desert */
2192 desertbuck += desert_pct * i;
2194
2195 /* Mountain */
2197 fill_island(20, &mountbuck, island_terrain.mountain, pstate);
2198
2199 /* Swamp */
2200 swampbuck += swamp_pct * i;
2202
2203 pstate->isleindex++;
2205 }
2206
2207 return TRUE;
2208}
2209
2210/**********************************************************************/
2214static void initworld(struct gen234_state *pstate)
2215{
2217 FALSE);
2218
2219 fc_assert(deepest_ocean != nullptr);
2221 create_placed_map(); /* Land tiles which aren't placed yet */
2222
2223 whole_map_iterate(&(wld.map), ptile) {
2225 tile_set_continent(ptile, 0);
2226 map_set_placed(ptile); /* Not a land tile */
2227 BV_CLR_ALL(ptile->extras);
2228 tile_set_owner(ptile, nullptr, nullptr);
2229 ptile->extras_owner = nullptr;
2231
2232 if (HAS_POLES) {
2233 make_polar();
2234 }
2235
2236 /* Set poles numbers. After the map is generated continents will
2237 * be renumbered. */
2238 make_island(0, 0, pstate, 0);
2239}
2240
2241/* This variable is the Default Minimum Specific Island Size,
2242 * ie the smallest size we'll typically permit our island, as a % of
2243 * the size we wanted. So if we ask for an island of size x, the island
2244 * creation will return if it would create an island smaller than
2245 * x * DMSIS / 100 */
2246#define DMSIS 10
2247
2248/**********************************************************************/
2251static void mapgenerator2(void)
2252{
2253 long int totalweight;
2254 struct gen234_state state;
2255 struct gen234_state *pstate = &state;
2256 int i;
2257 bool done = FALSE;
2258 int spares = 1;
2259 /* Constant that makes up that an island actually needs additional space */
2260
2261 /* Put 70% of land in big continents,
2262 * 20% in medium, and
2263 * 10% in small. */
2264 int bigfrac = 70, midfrac = 20, smallfrac = 10;
2265
2266 if (wld.map.server.landpercent > 85) {
2267 log_verbose("ISLAND generator: falling back to RANDOM generator");
2269
2270 return;
2271 }
2272
2273 pstate->totalmass = ((MAP_NATIVE_HEIGHT - 6 - spares) * wld.map.server.landpercent
2274 * (MAP_NATIVE_WIDTH - spares)) / 100;
2275 totalweight = 100 * player_count();
2276
2279
2280 while (!done && bigfrac > midfrac) {
2281 done = TRUE;
2282
2285 }
2286
2288
2289 /* Create one big island for each player. */
2290 for (i = player_count(); i > 0; i--) {
2291 if (!make_island(bigfrac * pstate->totalmass / totalweight,
2292 1, pstate, 95)) {
2293 /* We couldn't make an island at least 95% as big as we wanted,
2294 * and since we're trying hard to be fair, we need to start again,
2295 * with all big islands reduced slightly in size.
2296 * Take the size reduction from the big islands and add it to the
2297 * small islands to keep overall landmass unchanged.
2298 * Note that the big islands can get very small if necessary, and
2299 * the smaller islands will not exist if we can't place them
2300 * easily. */
2301 log_verbose("Island too small, trying again with all smaller "
2302 "islands.");
2303 midfrac += bigfrac * 0.01;
2304 smallfrac += bigfrac * 0.04;
2305 bigfrac *= 0.95;
2306 done = FALSE;
2307 break;
2308 }
2309 }
2310 }
2311
2312 if (bigfrac <= midfrac) {
2313 /* We could never make adequately big islands. */
2314 log_verbose("ISLAND generator: falling back to RANDOM generator");
2316
2317 /* Init world created this map, destroy it before abort */
2320 height_map = nullptr;
2321
2322 return;
2323 }
2324
2325 /* Now place smaller islands, but don't worry if they're small,
2326 * or even non-existent. One medium and one small per player. */
2327 for (i = player_count(); i > 0; i--) {
2328 make_island(midfrac * pstate->totalmass / totalweight, 0, pstate, DMSIS);
2329 }
2330 for (i = player_count(); i > 0; i--) {
2331 make_island(smallfrac * pstate->totalmass / totalweight, 0, pstate, DMSIS);
2332 }
2333
2335 make_plains();
2338 height_map = nullptr;
2339
2341 log_verbose("%ld mass left unplaced", checkmass);
2342 }
2343}
2344
2345/**********************************************************************/
2349static void mapgenerator3(void)
2350{
2351 int spares = 1;
2352 int j = 0;
2353 long int islandmass, landmass, size;
2354 long int maxmassdiv6 = 20;
2355 int bigislands;
2356 struct gen234_state state;
2357 struct gen234_state *pstate = &state;
2358
2359 if (wld.map.server.landpercent > 80) {
2360 log_verbose("ISLAND generator: falling back to FRACTAL generator due "
2361 "to landpercent > 80.");
2363 return;
2364 }
2365
2366 if (MAP_NATIVE_WIDTH < 40 || MAP_NATIVE_HEIGHT < 40) {
2367 log_verbose("ISLAND generator: falling back to FRACTAL generator due "
2368 "to unsupported map size.");
2370 return;
2371 }
2372
2373 pstate->totalmass = (((MAP_NATIVE_HEIGHT - 6 - spares) * wld.map.server.landpercent
2374 * (MAP_NATIVE_WIDTH - spares)) / 100);
2375
2377
2379 /* Subtracting the arctics */
2380 if (landmass > 3 * MAP_NATIVE_HEIGHT + player_count() * 3) {
2382 }
2383
2384 islandmass = (landmass) / (3 * bigislands);
2385 if (islandmass < 4 * maxmassdiv6) {
2386 islandmass = (landmass) / (2 * bigislands);
2387 }
2388 if (islandmass < 3 * maxmassdiv6 && player_count() * 2 < landmass) {
2390 }
2391
2392 if (islandmass < 2) {
2393 islandmass = 2;
2394 }
2395 if (islandmass > maxmassdiv6 * 6) {
2396 islandmass = maxmassdiv6 * 6; /* !PS: Let's try this */
2397 }
2398
2400
2401 while (pstate->isleindex - 2 <= bigislands && checkmass > islandmass
2402 && ++j < 500) {
2404 }
2405
2406 if (j == 500) {
2407 log_normal(_("Generator 3 didn't place all big islands."));
2408 }
2409
2410 islandmass = (islandmass * 11) / 8;
2412 if (islandmass < 2) {
2413 islandmass = 2;
2414 }
2415
2416 while (checkmass > islandmass && ++j < 1500) {
2417 if (j < 1000) {
2418 size = fc_rand((islandmass + 1) / 2 + 1) + islandmass / 2;
2419 } else {
2420 size = fc_rand((islandmass + 1) / 2 + 1);
2421 }
2422 if (size < 2) {
2423 size = 2;
2424 }
2425
2426 make_island(size, (pstate->isleindex - 2 <= player_count()) ? 1 : 0,
2427 pstate, DMSIS);
2428 }
2429
2431 make_plains();
2434 height_map = nullptr;
2435
2436 if (j == 1500) {
2437 log_normal(_("Generator 3 left %li landmass unplaced."), checkmass);
2439 log_verbose("%ld mass left unplaced", checkmass);
2440 }
2441}
2442
2443/**********************************************************************/
2446static void mapgenerator4(void)
2447{
2448 int bigweight = 70;
2449 int spares = 1;
2450 int i;
2451 long int totalweight;
2452 struct gen234_state state;
2453 struct gen234_state *pstate = &state;
2454
2455 /* No islands with mass >> sqr(min(xsize,ysize)) */
2456
2457 if (player_count() < 2 || wld.map.server.landpercent > 80) {
2458 log_verbose("ISLAND generator: falling back to startpos=SINGLE");
2460 return;
2461 }
2462
2463 if (wld.map.server.landpercent > 60) {
2464 bigweight = 30;
2465 } else if (wld.map.server.landpercent > 40) {
2466 bigweight = 50;
2467 } else {
2468 bigweight = 70;
2469 }
2470
2471 spares = (wld.map.server.landpercent - 5) / 30;
2472
2473 pstate->totalmass = (((MAP_NATIVE_HEIGHT - 6 - spares) * wld.map.server.landpercent
2474 * (MAP_NATIVE_WIDTH - spares)) / 100);
2475
2477 totalweight = (30 + bigweight) * player_count();
2478
2480
2481 i = player_count() / 2;
2482 if ((player_count() & 1) == 1) {
2483 make_island(bigweight * 3 * pstate->totalmass / totalweight, 3,
2484 pstate, DMSIS);
2485 } else {
2486 i++;
2487 }
2488 while ((--i) > 0) {
2489 make_island(bigweight * 2 * pstate->totalmass / totalweight, 2,
2490 pstate, DMSIS);
2491 }
2492 for (i = player_count(); i > 0; i--) {
2493 make_island(20 * pstate->totalmass / totalweight, 0, pstate, DMSIS);
2494 }
2495 for (i = player_count(); i > 0; i--) {
2496 make_island(10 * pstate->totalmass / totalweight, 0, pstate, DMSIS);
2497 }
2498
2500 make_plains();
2503 height_map = nullptr;
2504
2506 log_verbose("%ld mass left unplaced", checkmass);
2507 }
2508}
2509
2510#undef DMSIS
2511
2512/**********************************************************************/
2515static void river_types_init(void)
2516{
2517 river_type_count = 0;
2518
2521 && priver->generated) {
2523 }
2525}
2526
2527
2528/****************************************************************************
2529 Fair island generator types.
2530****************************************************************************/
2540
2548
2549typedef void (*fair_geometry_func)(int *x, int *y);
2554
2555/**********************************************************************/
2559static inline struct fair_tile *fair_map_new(void)
2560{
2561 return fc_calloc(MAP_INDEX_SIZE, sizeof(struct fair_tile));
2562}
2563
2564/**********************************************************************/
2567static inline void fair_map_destroy(struct fair_tile *pmap)
2568{
2569 free(pmap);
2570}
2571
2572/**********************************************************************/
2575static inline void fair_map_tile_pos(struct fair_tile *pmap,
2576 struct fair_tile *ptile, int *x, int *y)
2577{
2578 index_to_map_pos(x, y, ptile - pmap);
2579}
2580
2581/**********************************************************************/
2584static inline struct fair_tile *
2586{
2587 int nat_x, nat_y;
2588
2590
2591 /* Wrap in X and Y directions, as needed. */
2595 } else {
2596 return nullptr;
2597 }
2598 }
2602 } else {
2603 return nullptr;
2604 }
2605 }
2606
2608}
2609
2610/**********************************************************************/
2613static inline struct fair_tile *
2615 enum direction8 dir)
2616{
2617 int x, y, dx, dy;
2618
2619 fair_map_tile_pos(pmap, ptile, &x, &y);
2620 DIRSTEP(dx, dy, dir);
2621
2622 return fair_map_pos_tile(pmap, x + dx, y + dy);
2623}
2624
2625/**********************************************************************/
2629static inline bool
2631 int dist)
2632{
2633 int nat_x, nat_y;
2634
2635 index_to_native_pos(&nat_x, &nat_y, ptile - pmap);
2636
2639 return TRUE;
2640 }
2641
2642 if (MAP_IS_ISOMETRIC) {
2643 dist *= 2;
2644 }
2645
2648 return TRUE;
2649 }
2650
2651 return FALSE;
2652}
2653
2654/**********************************************************************/
2657static int fair_team_placement_closest(const void *a, const void *b)
2658{
2659 const struct iter_index *index1 = a, *index2 = b;
2660
2661 return index1->dist - index2->dist;
2662}
2663
2664/**********************************************************************/
2667static int fair_team_placement_horizontal(const void *a, const void *b)
2668{
2669 const struct iter_index *index1 = a, *index2 = b;
2670 /* Map vector to natural vector (Y axis). */
2671 int diff = (MAP_IS_ISOMETRIC
2672 ? abs(index1->dx + index1->dy) - abs(index2->dx + index2->dy)
2673 : abs(index1->dy) - abs(index2->dy));
2674
2675 return (diff != 0 ? diff : index1->dist - index2->dist);
2676}
2677
2678/**********************************************************************/
2681static int fair_team_placement_vertical(const void *a, const void *b)
2682{
2683 const struct iter_index *index1 = a, *index2 = b;
2684 /* Map vector to natural vector (X axis). */
2685 int diff = (MAP_IS_ISOMETRIC
2686 ? abs(index1->dx - index1->dy) - abs(index2->dx - index2->dy)
2687 : abs(index1->dx) - abs(index2->dx));
2688
2689 return (diff != 0 ? diff : index1->dist - index2->dist);
2690}
2691
2692/**********************************************************************/
2695static void fair_do_symmetry1(int *x, int *y)
2696{
2697 *x = -*x;
2698}
2699
2700/**********************************************************************/
2703static void fair_do_symmetry2(int *x, int *y)
2704{
2705 *y = -*y;
2706}
2707
2708/**********************************************************************/
2711static void fair_do_hex_symmetry1(int *x, int *y)
2712{
2713 *x = -(*x + *y);
2714}
2715
2716/**********************************************************************/
2719static void fair_do_hex_symmetry2(int *x, int *y)
2720{
2721 *x = -*x;
2722 *y = -*y;
2723}
2724
2725/**********************************************************************/
2728static void fair_do_iso_hex_symmetry1(int *x, int *y)
2729{
2730 *y = *x - *y;
2731}
2732
2733#define fair_do_iso_hex_symmetry2 fair_do_rotation
2734
2735/**********************************************************************/
2738static void fair_do_rotation(int *x, int *y)
2739{
2740 int z = *x;
2741
2742 *x = *y;
2743 *y = z;
2744}
2745
2746/**********************************************************************/
2749static void fair_do_hex_rotation(int *x, int *y)
2750{
2751 int z = *x + *y;
2752
2753 *x = -*y;
2754 *y = z;
2755}
2756
2757/**********************************************************************/
2760static void fair_do_iso_hex_rotation(int *x, int *y)
2761{
2762 int z = *x - *y;
2763
2764 *y = *x;
2765 *x = z;
2766}
2767
2768/**********************************************************************/
2771static void fair_do_geometry(const struct fair_geometry_data *data,
2772 int *x, int *y)
2773{
2774 int i;
2775
2776 for (i = 0; i < data->transform_num; i++) {
2777 data->transform[i](x, y);
2778 }
2779}
2780
2781/**********************************************************************/
2785{
2786 int i = 0;
2787
2789 if (fc_rand(100) < 50) {
2790 data->transform[i++] = fair_do_symmetry1;
2791 }
2792 if (fc_rand(100) < 50) {
2793 data->transform[i++] = fair_do_symmetry2;
2794 }
2795 if (fc_rand(100) < 50) {
2796 data->transform[i++] = fair_do_rotation;
2797 }
2798 } else if (!current_topo_has_flag(TF_ISO)) {
2799 int steps;
2800
2801 if (fc_rand(100) < 50) {
2803 }
2804 if (fc_rand(100) < 50) {
2806 }
2807 /* Rotations have 2 steps on hexgonal topologies. */
2808 for (steps = fc_rand(99) % 3; steps > 0; steps--) {
2809 data->transform[i++] = fair_do_hex_rotation;
2810 }
2811 } else {
2812 int steps;
2813
2814 if (fc_rand(100) < 50) {
2816 }
2817 if (fc_rand(100) < 50) {
2819 }
2820 /* Rotations have 2 steps on hexgonal topologies. */
2821 for (steps = fc_rand(99) % 3; steps > 0; steps--) {
2823 }
2824 }
2825
2826 fc_assert(i <= ARRAY_SIZE(data->transform));
2827
2828 data->transform_num = i;
2829}
2830
2831/**********************************************************************/
2837static bool fair_map_copy(struct fair_tile *ptarget, int tx, int ty,
2838 struct fair_tile *psource,
2839 const struct fair_geometry_data *data,
2840 int startpos_team_id)
2841{
2842 int sdx = MAP_NATIVE_WIDTH / 2, sdy = MAP_NATIVE_HEIGHT / 2;
2844 struct fair_tile *pstile, *pttile;
2845 int x, y;
2846
2847 /* Check. */
2848 for (pstile = psource; pstile < smax_tile; pstile++) {
2849 if (pstile->flags == FTF_NONE) {
2850 continue;
2851 }
2852
2853 /* Do translation and eventually other transformations. */
2855 x -= sdx;
2856 y -= sdy;
2857 fair_do_geometry(data, &x, &y);
2858 x += tx;
2859 y += ty;
2861 if (pttile == nullptr) {
2862 return FALSE; /* Limit of the map. */
2863 }
2864 if (pttile->flags & FTF_ASSIGNED) {
2865 if (pstile->flags & FTF_ASSIGNED
2866 || !(pttile->flags & FTF_OCEAN)
2867 || !(pstile->flags & FTF_OCEAN)) {
2868 return FALSE; /* Already assigned for another usage. */
2869 }
2870 } else if (pttile->flags & FTF_OCEAN && !(pstile->flags & FTF_OCEAN)) {
2871 return FALSE; /* We clearly want a sea tile here. */
2872 }
2873 if ((pttile->flags & FTF_NO_RESOURCE && pstile->presource != nullptr)
2874 || (pstile->flags & FTF_NO_RESOURCE && pttile->presource != nullptr)) {
2875 return FALSE; /* Resource disallowed there. */
2876 }
2877 if ((pttile->flags & FTF_NO_HUT && pstile->flags & FTF_HAS_HUT)
2878 || (pstile->flags & FTF_NO_HUT && pttile->flags & FTF_HAS_HUT)) {
2879 return FALSE; /* Resource disallowed there. */
2880 }
2881 }
2882
2883 /* Copy. */
2884 for (pstile = psource; pstile < smax_tile; pstile++) {
2885 if (pstile->flags == FTF_NONE) {
2886 continue;
2887 }
2888
2889 /* Do translation and eventually other transformations. */
2891 x -= sdx;
2892 y -= sdy;
2893 fair_do_geometry(data, &x, &y);
2894 x += tx;
2895 y += ty;
2897 fc_assert_ret_val(pttile != nullptr, FALSE);
2898 pttile->flags |= pstile->flags;
2899
2900 if (pstile->pterrain != nullptr) {
2901 pttile->pterrain = pstile->pterrain;
2902 pttile->presource = pstile->presource;
2903 pttile->extras = pstile->extras;
2904 }
2905 if (pstile->flags & FTF_STARTPOS) {
2906 pttile->startpos_team_id = startpos_team_id;
2907 }
2908 }
2909 return TRUE; /* Looks ok. */
2910}
2911
2912/**********************************************************************/
2917 struct fair_tile *psource)
2918{
2920 int i, r, x, y;
2921
2923
2924 /* Try random positions. */
2925 for (i = 0; i < 10; i++) {
2927 index_to_map_pos(&x, &y, r);
2928 if (fair_map_copy(ptarget, x, y, psource, &geometry, -1)) {
2929 return TRUE;
2930 }
2931 }
2932
2933 /* Try hard placement. */
2935 for (i = (r + 1) % MAP_INDEX_SIZE; i != r; i = (i + 1) % MAP_INDEX_SIZE) {
2936 index_to_map_pos(&x, &y, i);
2937 if (fair_map_copy(ptarget, x, y, psource, &geometry, -1)) {
2938 return TRUE;
2939 }
2940 }
2941
2942 /* Impossible placement. */
2943 return FALSE;
2944}
2945
2946/**********************************************************************/
2950static bool
2952 struct fair_tile *psource,
2953 const struct iter_index *outwards_indices,
2954 int startpos_team_id)
2955{
2957 int i, x, y;
2958
2960
2961 /* Iterate positions, beginning by a random index of the outwards
2962 * indices. */
2965 x = tx + outwards_indices[i].dx;
2966 y = ty + outwards_indices[i].dy;
2967 if (normalize_map_pos(&(wld.map), &x, &y)
2969 startpos_team_id)) {
2970 return TRUE;
2971 }
2972 }
2973
2974 /* Impossible placement. */
2975 return FALSE;
2976}
2977
2978/**********************************************************************/
2982{
2983 struct fair_tile *pftile, *pftile2;
2984 int i, j;
2985
2986 for (i = 0; i < MAP_INDEX_SIZE; i++) {
2987 pftile = pmap + i;
2988 if (pftile->flags == FTF_NONE
2989 || pftile->flags & FTF_NO_RESOURCE
2990 || fc_rand (1000) >= wld.map.server.riches) {
2991 continue;
2992 }
2993
2994 if (pftile->flags & FTF_OCEAN) {
2995 bool land_around = FALSE;
2996
2997 for (j = 0; j < MAP_NUM_VALID_DIRS; j++) {
2999 if (pftile2 != nullptr
3000 && pftile2->flags & FTF_ASSIGNED
3001 && !(pftile2->flags & FTF_OCEAN)) {
3002 land_around = TRUE;
3003 break;
3004 }
3005 }
3006 if (!land_around) {
3007 continue;
3008 }
3009 }
3010
3011 pftile->presource = pick_resource(pftile->pterrain);
3012 /* Note that 'pftile->presource' might be nullptr if there is no suitable
3013 * resource for the terrain. */
3014 if (pftile->presource != nullptr) {
3015 pftile->flags |= FTF_NO_RESOURCE;
3016 for (j = 0; j < MAP_NUM_VALID_DIRS; j++) {
3018 if (pftile2 != nullptr) {
3019 pftile2->flags |= FTF_NO_RESOURCE;
3020 }
3021 }
3022
3023 BV_SET(pftile->extras, extra_index(pftile->presource));
3024 }
3025 }
3026}
3027
3028/**********************************************************************/
3032{
3033 struct fair_tile *pftile;
3034 struct tile *pvtile = tile_virtual_new(nullptr);
3035 struct extra_type *phut;
3036 int i, j, k;
3037
3038 for (i = wld.map.server.huts * map_num_tiles() / 1000, j = 0;
3039 i > 0 && j < map_num_tiles() * 2; j++) {
3041 pftile = pmap + k;
3042 while (pftile->flags & FTF_NO_HUT) {
3043 pftile++;
3044 if (pftile - pmap == MAP_INDEX_SIZE) {
3045 pftile = pmap;
3046 }
3047 if (pftile - pmap == k) {
3048 break;
3049 }
3050 }
3051 if (pftile->flags & FTF_NO_HUT) {
3052 break; /* Cannot make huts anymore. */
3053 }
3054
3055 i--;
3056 if (pftile->pterrain == nullptr) {
3057 continue; /* Not an used tile. */
3058 }
3059
3060 pvtile->index = pftile - pmap;
3061 tile_set_terrain(pvtile, pftile->pterrain);
3062 tile_set_resource(pvtile, pftile->presource);
3063 pvtile->extras = pftile->extras;
3064
3066 if (phut != nullptr) {
3068 pftile->extras = pvtile->extras;
3069 pftile->flags |= FTF_HAS_HUT;
3071 3, ptile) {
3072 pmap[tile_index(ptile)].flags |= FTF_NO_HUT;
3074 }
3075 }
3076
3078}
3079
3080/**********************************************************************/
3084{
3085 enum {
3087 FT_FOREST,
3088 FT_DESERT,
3089 FT_HILL,
3091 FT_SWAMP,
3092 FT_COUNT
3093 };
3094 struct {
3095 int count;
3096 enum mapgen_terrain_property target;
3097 enum mapgen_terrain_property prefer;
3098 enum mapgen_terrain_property avoid;
3099 } terrain[FT_COUNT] = {
3102 { 0, MG_DRY, MG_TEMPERATE, MG_GREEN },
3106 };
3107
3108 struct fair_tile *pisland;
3109 struct fair_tile *land_tiles[1000];
3110 struct fair_tile *pftile, *pftile2, *pftile3;
3111 int fantasy;
3112 const int sea_around_island = (startpos_num > 0
3114 const int sea_around_island_sq = (startpos_num > 0
3116 int i, j, k;
3117
3119 fantasy = (size * 2) / 5;
3123 pftile->flags |= FTF_ASSIGNED;
3124 land_tiles[0] = pftile;
3125 i = 1;
3126
3127 log_debug("Generating an island with %d land tiles [fantasy=%d].",
3128 size, fantasy);
3129
3130 /* Make land. */
3131 while (i < fantasy) {
3133
3134 for (j = 0; j < MAP_NUM_VALID_DIRS; j++) {
3136 fc_assert(pftile2 != nullptr);
3138 continue;
3139 }
3140
3141 if (pftile2->flags == FTF_NONE) {
3142 pftile2->flags = FTF_ASSIGNED;
3143 land_tiles[i++] = pftile2;
3144 if (i == fantasy) {
3145 break;
3146 }
3147 }
3148 }
3149 }
3150
3151 while (i < size) {
3152 pftile = land_tiles[i - fc_rand(fantasy) - 1];
3155 fc_assert(pftile2 != nullptr);
3157 continue;
3158 }
3159
3160 if (pftile2->flags == FTF_NONE) {
3161 pftile2->flags = FTF_ASSIGNED;
3162 land_tiles[i++] = pftile2;
3163 }
3164 }
3165 fc_assert(i == size);
3166
3167 /* Add start positions. */
3168 for (i = 0; i < startpos_num;) {
3170 fc_assert(pftile->flags & FTF_ASSIGNED);
3171 if (!(pftile->flags & FTF_STARTPOS)) {
3172 pftile->flags |= FTF_STARTPOS;
3173 i++;
3174 }
3175 }
3176
3177 /* Make terrain. */
3179 terrain[FT_FOREST].count = ((forest_pct + jungle_pct) * size) / 100;
3180 terrain[FT_DESERT].count = (desert_pct * size) / 100;
3181 terrain[FT_HILL].count = (mountain_pct * size) / 150;
3182 terrain[FT_MOUNTAIN].count = (mountain_pct * size) / 300;
3183 terrain[FT_SWAMP].count = (swamp_pct * size) / 100;
3184
3185 j = FT_GRASSLAND;
3186 for (i = 0; i < size; i++) {
3187 pftile = land_tiles[i];
3188
3189 if (pftile->flags & FTF_STARTPOS) {
3191 } else {
3192 if (terrain[j].count == 0 || fc_rand(100) < 70) {
3193 do {
3194 j = fc_rand(FT_COUNT);
3195 } while (terrain[j].count == 0);
3196 }
3197 pftile->pterrain = pick_terrain(terrain[j].target, terrain[j].prefer,
3198 terrain[j].avoid);
3199 terrain[j].count--;
3200 }
3201 }
3202
3203 /* Make sea around the island. */
3204 for (i = 0; i < size; i++) {
3207 sea_around_island_sq, ptile) {
3208 pftile = pisland + tile_index(ptile);
3209
3210 if (pftile->flags == FTF_NONE) {
3211 pftile->flags = FTF_OCEAN;
3212 /* No ice around island */
3213 pftile->pterrain =
3216 if (startpos_num > 0) {
3217 pftile->flags |= FTF_ASSIGNED;
3218 }
3219 }
3221 }
3222
3223 /* Make rivers. */
3224 if (river_type_count > 0) {
3225 struct extra_type *priver;
3226 struct fair_tile *pend;
3228 * MAP_NUM_CARDINAL_DIRS) / 200);
3229 int length_max = 3, length, l;
3230 enum direction8 dir;
3231 int extra_idx;
3232 int dirs_num;
3233 bool cardinal_only;
3235 int river_around;
3236 bool finished;
3237
3238 for (i = 0; i < n; i++) {
3240 if (!terrain_has_flag(pftile->pterrain, TER_CAN_HAVE_RIVER)) {
3241 continue;
3242 }
3243
3246 if (BV_ISSET(pftile->extras, extra_idx)) {
3247 continue;
3248 }
3250
3251 river_around = 0;
3254 for (j = 0; j < MAP_NUM_VALID_DIRS; j++) {
3256 if (pftile2 == nullptr) {
3257 continue;
3258 }
3259
3260 if (pftile2->flags & FTF_OCEAN) {
3262 break;
3263 } else if (BV_ISSET(pftile2->extras, extra_idx)) {
3264 river_around++;
3267 }
3268 }
3269 }
3270 if (ocean_around
3271 || river_around > 1
3272 || (river_around == 1 && !connectable_river_around)) {
3273 continue;
3274 }
3275
3277 log_debug("Adding river at (%d, %d)",
3280 BV_SET(pftile->extras, extra_idx);
3281 continue;
3282 }
3283
3284 /* Check a river in one direction. */
3285 pend = nullptr;
3286 length = -1;
3287 dir = direction8_invalid();
3288 dirs_num = 0;
3289 for (j = 0; j < MAP_NUM_VALID_DIRS; j++) {
3291 continue;
3292 }
3293
3294 finished = FALSE;
3295 pftile2 = pftile;
3296 for (l = 2; l < length_max; l++) {
3298 if (pftile2 == nullptr
3300 break;
3301 }
3302
3303 river_around = 0;
3306 for (k = 0; k < MAP_NUM_VALID_DIRS; k++) {
3308 continue;
3309 }
3310
3312 MAP_VALID_DIRS[k]);
3313 if (pftile3 == nullptr) {
3314 continue;
3315 }
3316
3317 if (pftile3->flags & FTF_OCEAN) {
3320 }
3321 } else if (BV_ISSET(pftile3->extras, extra_idx)) {
3322 river_around++;
3325 }
3326 }
3327 }
3329 break;
3330 } else if (ocean_around || connectable_river_around) {
3331 finished = TRUE;
3332 break;
3333 }
3334 }
3335 if (finished && fc_rand(++dirs_num) == 0) {
3336 dir = MAP_VALID_DIRS[j];
3337 pend = pftile2;
3338 length = l;
3339 }
3340 }
3341 if (pend == nullptr) {
3342 continue;
3343 }
3344
3345 log_debug("Make river from (%d, %d) to (%d, %d) [dir=%s, length=%d]",
3350 direction8_name(dir),
3351 length);
3352 for (;;) {
3353 BV_SET(pftile->extras, extra_idx);
3354 length--;
3355 if (pftile == pend) {
3356 fc_assert(length == 0);
3357 break;
3358 }
3360 fc_assert(pftile != nullptr);
3361 }
3362 }
3363 }
3364
3365 if (startpos_num > 0) {
3366 /* Islands with start positions must have the same resources and the
3367 * same huts. Other ones don't matter. */
3368
3369 /* Make resources. */
3370 if (wld.map.server.riches > 0) {
3372 }
3373
3374 /* Make huts. */
3375 if (wld.map.server.huts > 0) {
3377 }
3378
3379 /* Make sure there will be no more resources and huts on assigned
3380 * tiles. */
3381 for (i = 0; i < MAP_INDEX_SIZE; i++) {
3382 pftile = pisland + i;
3383 if (pftile->flags & FTF_ASSIGNED) {
3384 pftile->flags |= (FTF_NO_RESOURCE | FTF_NO_HUT);
3385 }
3386 }
3387 }
3388
3389 return pisland;
3390}
3391
3392/**********************************************************************/
3396{
3397 struct terrain *deepest_ocean
3399 struct fair_tile *pmap, *pisland;
3401 int min_island_size = wld.map.server.tinyisles ? 1 : 2;
3402 int players_per_island = 1;
3404 int i, iter = CLIP(1, 100000 / map_num_tiles(), 10);
3405 bool done = FALSE;
3406
3409 fc_assert(0 < i);
3410 if (i == 1) {
3412 } else {
3413 teams_num++;
3415 }
3418
3419 /* Take in account the 'startpos' setting. */
3423 }
3424
3425 switch (wld.map.server.startpos) {
3426 case MAPSTARTPOS_2or3:
3427 {
3428 bool maybe2 = (0 == player_count() % 2);
3429 bool maybe3 = (0 == player_count() % 3);
3430
3434 if (i > 1) {
3435 if (0 != i % 2) {
3436 maybe2 = FALSE;
3437 }
3438 if (0 != i % 3) {
3439 maybe3 = FALSE;
3440 }
3441 }
3443 }
3444
3445 if (maybe3) {
3447 } else if (maybe2) {
3449 }
3450 }
3451 break;
3452 case MAPSTARTPOS_ALL:
3456 if (i > 1) {
3457 if (players_per_island == 1) {
3459 } else if (i != players_per_island) {
3460 /* Every team doesn't have the same number of players. Cannot
3461 * consider this option. */
3464 break;
3465 }
3466 }
3468 }
3469 break;
3471 case MAPSTARTPOS_SINGLE:
3473 break;
3474 }
3475 if (players_per_island == 1) {
3477 }
3478
3479 whole_map_iterate(&(wld.map), ptile) {
3481 tile_set_continent(ptile, 0);
3482 BV_CLR_ALL(ptile->extras);
3483 tile_set_owner(ptile, nullptr, nullptr);
3484 ptile->extras_owner = nullptr;
3486
3487 i = 0;
3488 if (HAS_POLES) {
3489 make_polar();
3490
3491 whole_map_iterate(&(wld.map), ptile) {
3492 if (tile_terrain(ptile) != deepest_ocean) {
3493 i++;
3494 }
3496 }
3497
3500 } else {
3502 / (player_count() * 100));
3503 }
3507 }
3508 islandmass2 = (playermass * 2) / 10;
3511 }
3512 islandmass3 = playermass / 10;
3515 }
3516
3517 log_verbose("Creating a map with fair island generator");
3518 log_debug("max iterations=%d", iter);
3519 log_debug("players_per_island=%d", players_per_island);
3520 log_debug("team_placement=%s",
3522 log_debug("teams_num=%d, team_players_num=%d, single_players_num=%d",
3524 log_debug("playermass=%d, islandmass1=%d, islandmass2=%d, islandmass3=%d",
3526
3527 pmap = fair_map_new();
3528
3529 while (--iter >= 0) {
3530 done = TRUE;
3531
3532 whole_map_iterate(&(wld.map), ptile) {
3533 struct fair_tile *pftile = pmap + tile_index(ptile);
3534
3535 if (tile_terrain(ptile) != deepest_ocean) {
3536 pftile->flags |= (FTF_ASSIGNED | FTF_NO_HUT);
3537 adjc_iterate(&(wld.map), ptile, atile) {
3538 struct fair_tile *aftile = pmap + tile_index(atile);
3539
3540 if (!(aftile->flags & FTF_ASSIGNED)
3542 aftile->flags |= FTF_OCEAN;
3543 }
3545 }
3546 pftile->pterrain = tile_terrain(ptile);
3547 pftile->presource = tile_resource(ptile);
3548 pftile->extras = *tile_extras(ptile);
3550
3551 /* Create main player island. */
3552 log_debug("Making main island.");
3554
3555 log_debug("Place main islands on the map.");
3556 i = 0;
3557
3559 && team_players_num > 0) {
3560 /* Do team placement. */
3562 int start_x[teams_num], start_y[teams_num];
3563 int dx = 0, dy = 0;
3564 int j, k;
3565
3566 /* Build outwards_indices. */
3568 sizeof(outwards_indices));
3569 switch (wld.map.server.team_placement) {
3572 break;
3575 for (j = 0; j < MAP_NUM_ITERATE_OUTWARDS_INDICES; j++) {
3576 /* We want square distances for comparing. */
3577 outwards_indices[j].dist =
3579 outwards_indices[j].dy);
3580 }
3583 break;
3587 break;
3591 break;
3592 }
3593
3594 /* Make start point for teams. */
3597 }
3600 }
3601 for (j = 0; j < teams_num; j++) {
3602 start_x[j] = (MAP_NATIVE_WIDTH * (2 * j + 1)) / (2 * teams_num) + dx;
3603 start_y[j] = (MAP_NATIVE_HEIGHT * (2 * j + 1)) / (2 * teams_num) + dy;
3605 start_x[j] = FC_WRAP(start_x[j], MAP_NATIVE_WIDTH);
3606 }
3609 }
3610 }
3611 /* Randomize. */
3612 array_shuffle(start_x, teams_num);
3614
3615 j = 0;
3618 int team_id;
3619 int x, y;
3620
3621 if (members_count <= 1) {
3622 continue;
3623 }
3624 team_id = team_number(pteam);
3625
3626 NATIVE_TO_MAP_POS(&x, &y, start_x[j], start_y[j]);
3627 log_verbose("Team %d (%s) will start on (%d, %d)",
3628 team_id, team_rule_name(pteam), x, y);
3629
3630 for (k = 0; k < members_count; k += players_per_island) {
3632 outwards_indices, team_id)) {
3633 log_verbose("Failed to place island number %d for team %d (%s).",
3634 k, team_id, team_rule_name(pteam));
3635 done = FALSE;
3636 break;
3637 }
3638 }
3639 if (!done) {
3640 break;
3641 }
3642 i += k;
3643 j++;
3645
3646 fc_assert(!done || i == team_players_num);
3647 }
3648
3649 if (done) {
3650 /* Place last player islands. */
3651 for (; i < player_count(); i += players_per_island) {
3653 log_verbose("Failed to place island number %d.", i);
3654 done = FALSE;
3655 break;
3656 }
3657 }
3658 fc_assert(!done || i == player_count());
3659 }
3661
3662 if (done) {
3663 log_debug("Create and place small islands on the map.");
3664 for (i = 0; i < player_count(); i++) {
3667 log_verbose("Failed to place small island2 number %d.", i);
3668 done = FALSE;
3670 break;
3671 }
3673 }
3674 }
3675 if (done) {
3676 for (i = 0; i < player_count(); i++) {
3679 log_verbose("Failed to place small island3 number %d.", i);
3680 done = FALSE;
3682 break;
3683 }
3685 }
3686 }
3687
3688 if (done) {
3689 break;
3690 }
3691
3693 pmap = fair_map_new();
3694
3695 /* Decrease land mass, for better chances. */
3696 islandmass1 = (islandmass1 * 99) / 100;
3699 }
3700 islandmass2 = (islandmass2 * 99) / 100;
3703 }
3704 islandmass3 = (islandmass3 * 99) / 100;
3707 }
3708 }
3709
3710 if (!done) {
3711 log_verbose("Failed to create map after %d iterations.", iter);
3713 return FALSE;
3714 }
3715
3716 /* Finalize the map. */
3717 for (i = 0; i < MAP_INDEX_SIZE; i++) {
3718 /* Mark all tiles as assigned, for adding resources and huts. */
3719 pmap[i].flags |= FTF_ASSIGNED;
3720 }
3721 if (wld.map.server.riches > 0) {
3723 }
3724 if (wld.map.server.huts > 0) {
3726 }
3727
3728 /* Apply the map. */
3729 log_debug("Applying the map...");
3730 whole_map_iterate(&(wld.map), ptile) {
3731 struct fair_tile *pftile = pmap + tile_index(ptile);
3732
3733 fc_assert(pftile->pterrain != nullptr);
3734 tile_set_terrain(ptile, pftile->pterrain);
3735 ptile->extras = pftile->extras;
3736 tile_set_resource(ptile, pftile->presource);
3737 if (pftile->flags & FTF_STARTPOS) {
3738 struct startpos *psp = map_startpos_new(ptile);
3739
3740 if (pftile->startpos_team_id != -1) {
3742 (pftile->startpos_team_id)), pplayer) {
3743 startpos_allow(psp, nation_of_player(pplayer));
3745 } else {
3747 }
3748 }
3750
3753
3755
3756 log_verbose("Fair island map created with success!");
3757
3758 return TRUE;
3759}
#define n
Definition astring.c:77
void dbv_init(struct dbv *pdbv, int bits)
Definition bitvector.c:50
void dbv_set(struct dbv *pdbv, int bit)
Definition bitvector.c:142
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
void dbv_free(struct dbv *pdbv)
Definition bitvector.c:95
void dbv_clr_all(struct dbv *pdbv)
Definition bitvector.c:174
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define CITY_MAP_DEFAULT_RADIUS_SQ
Definition city.h:79
char * incite_cost
Definition comments.c:76
struct extra_type * rand_extra_for_tile(struct tile *ptile, enum extra_cause cause, bool generated)
Definition extras.c:283
#define extra_index(_e_)
Definition extras.h:183
#define extra_road_get(_e_)
Definition extras.h:191
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
#define CITY_MAP_DEFAULT_RADIUS
Definition fc_types.h:83
#define MAX_EXTRA_TYPES
Definition fc_types.h:50
#define _(String)
Definition fcintl.h:67
void make_fracture_map(void)
void make_fracture_relief(void)
static map_landmass * landmass
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
void renormalize_hmap_poles(void)
Definition height_map.c:81
void height_map_to_map(void)
Definition height_map.c:300
void normalize_hmap_poles(void)
Definition height_map.c:65
bool area_is_too_flat(struct tile *ptile, int thill, int my_height)
Definition height_map.c:271
void make_pseudofractal1_hmap(int extra_div)
Definition height_map.c:198
void make_random_hmap(int smooth)
Definition height_map.c:101
#define H_UNIT
Definition height_map.h:20
#define hmap_max_level
Definition height_map.h:33
#define hmap(_tile)
Definition height_map.h:17
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert_exit_msg(condition, message,...)
Definition log.h:212
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
#define log_testmatic(message,...)
Definition log.h:124
#define nat_x
#define nat_y
struct startpos * map_startpos_new(struct tile *ptile)
Definition map.c:2030
int map_num_tiles(void)
Definition map.c:1161
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1852
struct tile * rand_map_pos(const struct civ_map *nmap)
Definition map.c:1237
void main_map_allocate(void)
Definition map.c:534
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
int map_vector_to_sq_distance(int dx, int dy)
Definition map.c:659
struct tile * rand_map_pos_filtered(const struct civ_map *nmap, void *data, bool(*filter)(const struct tile *ptile, const void *data))
Definition map.c:1251
int map_startpos_count(void)
Definition map.c:2017
bool is_cardinal_dir(enum direction8 dir)
Definition map.c:1466
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:458
bool map_is_empty(void)
Definition map.c:148
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1796
bool normalize_map_pos(const struct civ_map *nmap, int *x, int *y)
Definition map.c:1126
#define current_topo_has_flag(flag)
Definition map.h:43
#define native_pos_to_index(nat_x, nat_y)
Definition map.h:158
#define adjc_iterate_end
Definition map.h:439
static int index_to_map_pos_y(int mindex)
Definition map.h:772
static const bool C_PERCENT
Definition map.h:40
static const bool C_NUMBER
Definition map.h:39
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:397
#define cardinal_adjc_iterate_end
Definition map.h:465
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:434
#define MAP_TO_NATIVE_POS(pnat_x, pnat_y, map_x, map_y)
Definition map.h:176
static const bool C_ADJACENT
Definition map.h:37
#define NATIVE_TO_MAP_POS(pmap_x, pmap_y, nat_x, nat_y)
Definition map.h:170
#define cardinal_adjc_dir_iterate_end
Definition map.h:472
#define square_iterate_end
Definition map.h:400
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:461
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:407
static int index_to_map_pos_x(int mindex)
Definition map.h:759
#define whole_map_iterate(_map, _tile)
Definition map.h:582
static const bool C_CARDINAL
Definition map.h:38
#define cardinal_adjc_dir_base_iterate_end
Definition map.h:479
#define DIR_REVERSE(dir)
Definition map.h:598
#define current_wrap_has_flag(flag)
Definition map.h:46
#define cardinal_adjc_dir_base_iterate(nmap, center_tile, dir_itr)
Definition map.h:475
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:161
#define cardinal_adjc_dir_iterate(nmap, center_tile, itr_tile, dir_itr)
Definition map.h:468
#define whole_map_iterate_end
Definition map.h:591
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:229
#define circle_iterate_end
Definition map.h:410
#define DIRSTEP(dest_x, dest_y, dir)
Definition map.h:236
@ MAPSIZE_PLAYER
Definition map_types.h:40
@ MAPGEN_SCENARIO
Definition map_types.h:47
@ MAPGEN_FRACTURE
Definition map_types.h:52
@ MAPGEN_ISLAND
Definition map_types.h:50
@ MAPGEN_FAIR
Definition map_types.h:51
@ MAPGEN_FRACTAL
Definition map_types.h:49
@ MAPGEN_RANDOM
Definition map_types.h:48
map_startpos
Definition map_types.h:55
@ MAPSTARTPOS_VARIABLE
Definition map_types.h:60
@ MAPSTARTPOS_2or3
Definition map_types.h:58
@ MAPSTARTPOS_ALL
Definition map_types.h:59
@ MAPSTARTPOS_DEFAULT
Definition map_types.h:56
@ MAPSTARTPOS_SINGLE
Definition map_types.h:57
static void make_plains(void)
Definition mapgen.c:455
static int fair_team_placement_vertical(const void *a, const void *b)
Definition mapgen.c:2681
static void make_terrains(void)
Definition mapgen.c:491
static int hmap_low_level
Definition mapgen.c:185
static void make_rivers(void)
Definition mapgen.c:906
static void mapgenerator2(void)
Definition mapgen.c:2251
wetness_c
Definition mapgen.c:180
@ WC_NDRY
Definition mapgen.c:180
@ WC_ALL
Definition mapgen.c:180
@ WC_DRY
Definition mapgen.c:180
#define terrain_select_list_iterate_end
Definition mapgen.c:81
#define NUM_TEST_FUNCTIONS
Definition mapgen.c:689
static void fair_do_hex_symmetry1(int *x, int *y)
Definition mapgen.c:2711
static int jungle_pct
Definition mapgen.c:166
#define fair_do_iso_hex_symmetry2
Definition mapgen.c:2733
static void fair_map_make_resources(struct fair_tile *pmap)
Definition mapgen.c:2981
static bool make_island(int islemass, int starters, struct gen234_state *pstate, int min_specific_island_size)
Definition mapgen.c:2100
static int river_test_adjacent_swamp(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:646
static struct fair_tile * fair_map_new(void)
Definition mapgen.c:2559
static int river_test_height_map(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:662
struct terrain_select_list * mountain
Definition mapgen.c:97
static void fair_geometry_rand(struct fair_geometry_data *data)
Definition mapgen.c:2784
static int mountain_pct
Definition mapgen.c:165
#define map_pos_is_dry(ptile)
Definition mapgen.c:175
#define DMSIS
Definition mapgen.c:2246
void(* fair_geometry_func)(int *x, int *y)
Definition mapgen.c:2549
static void fair_do_iso_hex_symmetry1(int *x, int *y)
Definition mapgen.c:2728
static int desert_pct
Definition mapgen.c:163
static void fair_do_geometry(const struct fair_geometry_data *data, int *x, int *y)
Definition mapgen.c:2771
static void make_land(void)
Definition mapgen.c:1053
static void initworld(struct gen234_state *pstate)
Definition mapgen.c:2214
static struct fair_tile * fair_map_island_new(int size, int startpos_num)
Definition mapgen.c:3083
static void fair_map_destroy(struct fair_tile *pmap)
Definition mapgen.c:2567
static bool fair_map_tile_border(struct fair_tile *pmap, struct fair_tile *ptile, int dist)
Definition mapgen.c:2630
static void mapgenerator4(void)
Definition mapgen.c:2446
static void make_polar_land(void)
Definition mapgen.c:376
static int forest_pct
Definition mapgen.c:162
bool init
Definition mapgen.c:94
#define RIVERS_MAXTRIES
Definition mapgen.c:111
static void fair_do_hex_symmetry2(int *x, int *y)
Definition mapgen.c:2719
static struct @99 island_terrain
static void fill_island(int coast, long int *bucket, const struct terrain_select_list *tersel_list, const struct gen234_state *const pstate)
Definition mapgen.c:1658
#define map_pos_is_low(ptile)
Definition mapgen.c:193
static struct tile * rand_map_pos_characteristic(wetness_c wc, temperature_type tc, miscellaneous_c mc)
Definition mapgen.c:265
#define ini_hmap_low_level()
Definition mapgen.c:186
static void fair_map_tile_pos(struct fair_tile *pmap, struct fair_tile *ptile, int *x, int *y)
Definition mapgen.c:2575
static void adjust_terrain_param(void)
Definition mapgen.c:1498
static struct terrain_select * tersel_new(int weight, enum mapgen_terrain_property target, enum mapgen_terrain_property prefer, enum mapgen_terrain_property avoid, int temp_condition, int wet_condition)
Definition mapgen.c:1626
#define terrain_select_list_iterate(tersel_list, ptersel)
Definition mapgen.c:79
static bool test_miscellaneous(const struct tile *ptile, miscellaneous_c c)
Definition mapgen.c:222
static int river_test_adjacent_ocean(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:599
static void print_mapgen_map(void)
Definition mapgen.c:1207
struct terrain_select_list * forest
Definition mapgen.c:95
static bool place_island(struct gen234_state *pstate)
Definition mapgen.c:1855
static void river_blockmark(struct river_map *privermap, struct tile *ptile)
Definition mapgen.c:672
static void make_huts(int number)
Definition mapgen.c:1541
static bool test_wetness(const struct tile *ptile, wetness_c c)
Definition mapgen.c:204
static void island_terrain_free(void)
Definition mapgen.c:2080
static bool is_tiny_island(struct tile *ptile)
Definition mapgen.c:1156
struct terrain_select_list * swamp
Definition mapgen.c:98
static struct extra_type * river_types[MAX_EXTRA_TYPES]
Definition mapgen.c:73
static int river_type_count
Definition mapgen.c:74
#define PLACE_ONE_TYPE(count, alternate, ter, wc, tc, mc, weight)
Definition mapgen.c:470
static int river_test_adjacent_highlands(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:620
static void river_types_init(void)
Definition mapgen.c:2515
static bool near_safe_tiles(struct tile *ptile)
Definition mapgen.c:1526
static bool ok_for_separate_poles(struct tile *ptile)
Definition mapgen.c:357
static void fair_do_symmetry1(int *x, int *y)
Definition mapgen.c:2695
miscellaneous_c
Definition mapgen.c:195
@ MC_LOW
Definition mapgen.c:195
@ MC_NLOW
Definition mapgen.c:195
@ MC_NONE
Definition mapgen.c:195
static bool is_near_land(struct tile *ptile)
Definition mapgen.c:1838
static int fair_team_placement_horizontal(const void *a, const void *b)
Definition mapgen.c:2667
static bool condition_filter(const struct tile *ptile, const void *data)
Definition mapgen.c:250
static int swamp_pct
Definition mapgen.c:164
static struct tile * get_random_map_position_from_state(const struct gen234_state *const pstate)
Definition mapgen.c:1607
static bool is_resource_close(const struct tile *ptile)
Definition mapgen.c:1569
static void add_resources(int prob)
Definition mapgen.c:1583
static void mapgenerator3(void)
Definition mapgen.c:2349
static void fair_do_rotation(int *x, int *y)
Definition mapgen.c:2738
static bool fair_map_place_island_rand(struct fair_tile *ptarget, struct fair_tile *psource)
Definition mapgen.c:2916
static int river_test_highlands(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:589
static void fill_island_rivers(int coast, long int *bucket, const struct gen234_state *const pstate)
Definition mapgen.c:1782
static void fair_map_make_huts(struct fair_tile *pmap)
Definition mapgen.c:3031
static int fair_team_placement_closest(const void *a, const void *b)
Definition mapgen.c:2657
static bool make_river(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:792
static void island_terrain_init(void)
Definition mapgen.c:2019
static bool island_river_mouth_suitability(const struct tile *ptile, const struct extra_type *priver)
Definition mapgen.c:1737
static int river_test_rivergrid(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:578
static bool map_generate_fair_islands(void)
Definition mapgen.c:3395
static void fair_do_iso_hex_rotation(int *x, int *y)
Definition mapgen.c:2760
static int river_pct
Definition mapgen.c:167
static void make_polar(void)
Definition mapgen.c:335
static bool create_island(int islemass, struct gen234_state *pstate)
Definition mapgen.c:1945
static void make_plain(struct tile *ptile, int *to_be_placed)
Definition mapgen.c:434
static bool island_river_suitability(const struct tile *ptile, const struct extra_type *priver)
Definition mapgen.c:1758
static bool fair_map_place_island_team(struct fair_tile *ptarget, int tx, int ty, struct fair_tile *psource, const struct iter_index *outwards_indices, int startpos_team_id)
Definition mapgen.c:2951
static struct test_func test_funcs[NUM_TEST_FUNCTIONS]
Definition mapgen.c:690
static bool fair_map_copy(struct fair_tile *ptarget, int tx, int ty, struct fair_tile *psource, const struct fair_geometry_data *data, int startpos_team_id)
Definition mapgen.c:2837
struct terrain_select_list * desert
Definition mapgen.c:96
static void make_relief(void)
Definition mapgen.c:298
#define HAS_POLES
Definition mapgen.c:157
static int river_test_adjacent_river(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:610
static void fair_do_hex_rotation(int *x, int *y)
Definition mapgen.c:2749
static void remove_tiny_islands(void)
Definition mapgen.c:1182
static int river_test_swamp(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:636
static int count_card_adjc_elevated_tiles(struct tile *ptile)
Definition mapgen.c:1929
static void place_terrain(struct tile *ptile, int diff, struct terrain *pterrain, int *to_be_placed, wetness_c wc, temperature_type tc, miscellaneous_c mc)
Definition mapgen.c:398
static bool terrain_is_too_high(struct tile *ptile, int thill, int my_height)
Definition mapgen.c:280
bool map_fractal_generate(bool autosize, struct unit_type *initial_unit)
Definition mapgen.c:1268
static void fair_do_symmetry2(int *x, int *y)
Definition mapgen.c:2703
static struct fair_tile * fair_map_pos_tile(struct fair_tile *pmap, int x, int y)
Definition mapgen.c:2585
static void tersel_free(struct terrain_select *ptersel)
Definition mapgen.c:1648
static long int checkmass
Definition mapgen.c:1850
static struct fair_tile * fair_map_tile_step(struct fair_tile *pmap, struct fair_tile *ptile, enum direction8 dir)
Definition mapgen.c:2614
static int river_test_blocked(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:557
fair_tile_flag
Definition mapgen.c:2531
@ FTF_NONE
Definition mapgen.c:2532
@ FTF_NO_RESOURCE
Definition mapgen.c:2536
@ FTF_HAS_HUT
Definition mapgen.c:2537
@ FTF_ASSIGNED
Definition mapgen.c:2533
@ FTF_OCEAN
Definition mapgen.c:2534
@ FTF_STARTPOS
Definition mapgen.c:2535
@ FTF_NO_HUT
Definition mapgen.c:2538
void generator_init_topology(bool autosize)
int get_sqsize(void)
int map_colatitude(const struct tile *ptile)
bool near_singularity(const struct tile *ptile)
#define L_UNIT
#define COLD_LEVEL
#define ICE_BASE_LEVEL
#define TROPICAL_LEVEL
#define MAX_COLATITUDE
struct extra_type * pick_resource(const struct terrain *pterrain)
void set_all_ocean_tiles_placed(void)
void create_placed_map(void)
#define pmap(_tile)
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)
void regenerate_lakes(void)
void set_placed_near_pos(struct tile *ptile, int dist)
void smooth_water_depth(void)
bool placed_map_is_initialized(void)
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)
void map_unset_placed(struct tile *ptile)
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
int player_count(void)
Definition player.c:817
#define player_list_iterate(playerlist, pplayer)
Definition player.h:560
#define player_list_iterate_end
Definition player.h:562
RANDOM_STATE fc_rand_state(void)
Definition rand.c:208
void fc_srand(RANDOM_TYPE seed)
Definition rand.c:161
void fc_rand_set_state(RANDOM_STATE state)
Definition rand.c:229
uint32_t RANDOM_TYPE
Definition rand.h:26
#define fc_rand(_size)
Definition rand.h:56
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Definition road.c:416
bool is_cardinal_only_road(const struct extra_type *pextra)
Definition road.c:489
int count_river_type_tile_card(struct civ_map *nmap, const struct tile *ptile, const struct extra_type *priver, bool percentage)
Definition road.c:362
int count_river_type_near_tile(struct civ_map *nmap, const struct tile *ptile, const struct extra_type *priver, bool percentage)
Definition road.c:389
int count_river_near_tile(struct civ_map *nmap, const struct tile *ptile, const struct extra_type *priver)
Definition road.c:340
void array_shuffle(int *array, int n)
Definition shared.c:2011
#define MAX_UINT32
Definition shared.h:81
#define CLIP(lower, current, upper)
Definition shared.h:57
#define ARRAY_SIZE(x)
Definition shared.h:85
#define FC_WRAP(value, range)
Definition shared.h:65
#define MIN(x, y)
Definition shared.h:55
#define FC_INFINITY
Definition shared.h:36
#define MAX(x, y)
Definition shared.h:54
size_t size
Definition specvec.h:72
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
bool create_start_positions(enum map_startpos mode, struct unit_type *initial_unit)
Definition startpos.c:300
miscellaneous_c mc
Definition mapgen.c:243
wetness_c wc
Definition mapgen.c:241
temperature_type tc
Definition mapgen.c:242
randseed seed
Definition map_types.h:105
bool tinyisles
Definition map_types.h:113
int riches
Definition map_types.h:106
Continent_id num_continents
Definition map_types.h:83
enum mapsize_type mapsize
Definition map_types.h:101
enum map_startpos startpos
Definition map_types.h:112
bool have_resources
Definition map_types.h:121
int steepness
Definition map_types.h:118
int wetness
Definition map_types.h:117
int tilesperplayer
Definition map_types.h:103
randseed seed_setting
Definition map_types.h:104
int landpercent
Definition map_types.h:110
enum team_placement team_placement
Definition map_types.h:122
struct civ_map::@44::@46 server
int huts
Definition map_types.h:107
bool have_huts
Definition map_types.h:120
enum map_generator generator
Definition map_types.h:111
bool ocean_resources
Definition map_types.h:119
bool separatepoles
Definition map_types.h:114
Continent_id num_oceans
Definition map_types.h:84
int temperature
Definition map_types.h:116
fair_geometry_func transform[4]
Definition mapgen.c:2551
bv_extras extras
Definition mapgen.c:2545
struct terrain * pterrain
Definition mapgen.c:2543
enum fair_tile_flag flags
Definition mapgen.c:2542
int startpos_team_id
Definition mapgen.c:2546
struct extra_type * presource
Definition mapgen.c:2544
int isleindex
Definition mapgen.c:58
long int totalmass
Definition mapgen.c:59
int dist
Definition city.h:107
int dx
Definition city.h:107
int dy
Definition city.h:107
struct dbv ok
Definition mapgen.c:117
struct dbv blocked
Definition mapgen.c:116
Definition map.c:40
int wet_condition
Definition mapgen.c:69
enum mapgen_terrain_property avoid
Definition mapgen.c:67
int temp_condition
Definition mapgen.c:68
enum mapgen_terrain_property target
Definition mapgen.c:65
enum mapgen_terrain_property prefer
Definition mapgen.c:66
int property[MG_COUNT]
Definition terrain.h:147
bool fatal
Definition mapgen.c:686
int(* func)(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:685
Definition tile.h:50
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define fc__fallthrough
Definition support.h:119
struct team * team_by_number(const int team_id)
Definition team.c:400
const char * team_rule_name(const struct team *pteam)
Definition team.c:410
int team_number(const struct team *pteam)
Definition team.c:391
const struct player_list * team_members(const struct team *pteam)
Definition team.c:456
#define teams_iterate_end
Definition team.h:87
#define teams_iterate(_pteam)
Definition team.h:82
bool temperature_is_initialized(void)
void destroy_tmap(void)
bool tmap_is(const struct tile *ptile, temperature_type tt)
bool is_temperature_type_near(const struct tile *ptile, temperature_type tt)
void create_tmap(bool real)
int temperature_type
#define TT_COLD
#define TT_NHOT
#define TT_HOT
#define TT_FROZEN
#define TT_TROPICAL
#define TT_ALL
#define TT_NFROZEN
Terrain_type_id terrain_count(void)
Definition terrain.c:117
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:632
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:590
Terrain_type_id terrain_index(const struct terrain *pterrain)
Definition terrain.c:137
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:246
int count_terrain_property_near_tile(const struct civ_map *nmap, const struct tile *ptile, bool cardinal_only, bool percentage, enum mapgen_terrain_property prop)
Definition terrain.c:368
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:347
#define terrain_type_iterate(_p)
Definition terrain.h:267
#define T_UNKNOWN
Definition terrain.h:62
#define is_ocean(pterrain)
Definition terrain.h:195
#define is_ocean_tile(ptile)
Definition terrain.h:197
#define TERRAIN_OCEAN_DEPTH_MINIMUM
Definition terrain.h:148
#define terrain_type_iterate_end
Definition terrain.h:273
#define TERRAIN_OCEAN_DEPTH_MAXIMUM
Definition terrain.h:149
#define terrain_has_flag(terr, flag)
Definition terrain.h:177
void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:955
void tile_set_terrain(struct tile *ptile, struct terrain *pterrain)
Definition tile.c:124
void tile_virtual_destroy(struct tile *vtile)
Definition tile.c:1035
bool tile_has_river(const struct tile *ptile)
Definition tile.c:852
void tile_set_owner(struct tile *ptile, struct player *pplayer, struct tile *claimer)
Definition tile.c:69
struct tile * tile_virtual_new(const struct tile *ptile)
Definition tile.c:981
bool tile_extra_rm_apply(struct tile *ptile, struct extra_type *tgt)
Definition tile.c:601
void tile_set_resource(struct tile *ptile, struct extra_type *presource)
Definition tile.c:349
void tile_set_continent(struct tile *ptile, Continent_id val)
Definition tile.c:382
#define tile_index(_pt_)
Definition tile.h:89
#define tile_resource(_tile)
Definition tile.h:103
#define tile_terrain(_tile)
Definition tile.h:115
#define TILE_XY(ptile)
Definition tile.h:43
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:125
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#define MAP_ITERATE_OUTWARDS_INDICES
#define MAP_NATIVE_WIDTH
#define MAP_NUM_VALID_DIRS
#define MAP_NUM_ITERATE_OUTWARDS_INDICES
#define MAP_INDEX_SIZE
#define MAP_NUM_CARDINAL_DIRS
#define MAP_IS_ISOMETRIC
#define MAP_CARDINAL_DIRS
#define MAP_NATIVE_HEIGHT
#define MAP_VALID_DIRS