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 temporarly. */
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/* MISCELANEOUS (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 exept 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#ifdef FREECIV_TESTMATIC
1283 /* Log command to reproduce the mapseed */
1284 log_testmatic("set mapseed %d", wld.map.server.seed);
1285#else /* FREECIV_TESTMATIC */
1286 log_debug("Setting map.seed:%d", wld.map.server.seed);
1287#endif /* FREECIV_TESTMATIC */
1288 } else {
1290 }
1291
1292 rstate = fc_rand_state();
1293
1295
1296 /* Don't generate tiles with mapgen == MAPGEN_SCENARIO as we've loaded *
1297 them from file.
1298 Also, don't delete (the handcrafted!) tiny islands in a scenario */
1302
1304 /* Map can be already allocated, if we failed first map generation */
1305 if (map_is_empty()) {
1307 }
1309 /* If one mapgenerator fails, it will choose another mapgenerator */
1310 /* with a lower number to try again */
1311
1312 /* Create a temperature map */
1314
1318 }
1319
1321 /* Initialise terrain selection lists used by make_island() */
1323
1324 /* 2 or 3 players per isle? */
1327 mapgenerator4();
1328 }
1331 /* Single player per isle. */
1332 mapgenerator3();
1333 }
1335 /* "Variable" single player. */
1336 mapgenerator2();
1337 }
1338
1339 /* Free terrain selection lists used by make_island() */
1341 }
1342
1347 ? 0 : player_count()));
1348 }
1349
1353 ? player_count() / 4 : 0)));
1354 }
1355
1358 }
1359
1360 /* If hmap only generator make anything else */
1364
1366 make_land();
1368 height_map = nullptr;
1369 }
1370 if (!wld.map.server.tinyisles) {
1372 }
1373
1375
1376 /* Continent numbers must be assigned before regenerate_lakes() */
1378
1379 /* Turn small oceans into lakes. */
1380 if (wld.map.num_oceans > 0) {
1382 }
1383
1384 } else {
1386 }
1387
1388 /* Create a temperature map if it was not done before */
1391 }
1392
1393 /* Some scenarios already provide specials */
1396 }
1397
1398 if (!wld.map.server.have_huts) {
1400 }
1401
1402 /* Restore previous random state: */
1403 fc_rand_set_state(rstate);
1404
1405 /* We don't want random start positions in a scenario which already
1406 * provides them. */
1407 if (0 == map_startpos_count()) {
1408 enum map_startpos mode = MAPSTARTPOS_ALL;
1409
1410 switch (wld.map.server.generator) {
1411 case MAPGEN_FAIR:
1413 "Fair island generator failed to allocated "
1414 "start positions!");
1415 break;
1416 case MAPGEN_SCENARIO:
1417 case MAPGEN_RANDOM:
1418 case MAPGEN_FRACTURE:
1419 mode = wld.map.server.startpos;
1420 break;
1421 case MAPGEN_FRACTAL:
1423 log_verbose("Map generator chose startpos=ALL");
1424 mode = MAPSTARTPOS_ALL;
1425 } else {
1426 mode = wld.map.server.startpos;
1427 }
1428 break;
1429 case MAPGEN_ISLAND:
1430 switch (wld.map.server.startpos) {
1433 log_verbose("Map generator chose startpos=SINGLE");
1434
1436 case MAPSTARTPOS_SINGLE:
1437 mode = MAPSTARTPOS_SINGLE;
1438 break;
1439 default:
1440 log_verbose("Map generator chose startpos=2or3");
1441
1443 case MAPSTARTPOS_2or3:
1444 mode = MAPSTARTPOS_2or3;
1445 break;
1446 }
1447 break;
1448 }
1449
1450 for (;;) {
1451 bool success;
1452
1453 success = create_start_positions(mode, initial_unit);
1454 if (success) {
1455 wld.map.server.startpos = mode;
1456 break;
1457 }
1458
1459 switch (mode) {
1460 case MAPSTARTPOS_SINGLE:
1461 log_verbose("Falling back to startpos=2or3");
1462 mode = MAPSTARTPOS_2or3;
1463 continue;
1464 case MAPSTARTPOS_2or3:
1465 log_verbose("Falling back to startpos=ALL");
1466 mode = MAPSTARTPOS_ALL;
1467 break;
1468 case MAPSTARTPOS_ALL:
1469 log_verbose("Falling back to startpos=VARIABLE");
1470 mode = MAPSTARTPOS_VARIABLE;
1471 break;
1472 default:
1473 log_error(_("The server couldn't allocate starting positions."));
1474 destroy_tmap();
1475 return FALSE;
1476 }
1477 }
1478 }
1479
1480 /* Destroy temperature map */
1481 destroy_tmap();
1482
1484
1485 return TRUE;
1486}
1487
1488/**********************************************************************/
1492static void adjust_terrain_param(void)
1493{
1495 float mount_factor = (100.0 - polar - 30 * 0.8) / 10000;
1496 float factor = (100.0 - polar - wld.map.server.steepness * 0.8) / 10000;
1497
1499
1500 /* 27 % if wetness == 50 & */
1501 forest_pct = factor * (wld.map.server.wetness * 40 + 700);
1503 / (MAX_COLATITUDE * 2);
1505
1506 /* 3 - 11 % */
1507 river_pct = (100 - polar) * (3 + wld.map.server.wetness / 12) / 100;
1508
1509 /* 7 % if wetness == 50 && temperature == 50 */
1510 swamp_pct = factor * MAX(0, (wld.map.server.wetness * 12 - 150
1511 + wld.map.server.temperature * 10));
1512 desert_pct = factor * MAX(0, (wld.map.server.temperature * 15 - 250
1513 + (100 - wld.map.server.wetness) * 10));
1514}
1515
1516/**********************************************************************/
1520static bool near_safe_tiles(struct tile *ptile)
1521{
1522 square_iterate(&(wld.map), ptile, 1, tile1) {
1524 return TRUE;
1525 }
1527
1528 return FALSE;
1529}
1530
1531/**********************************************************************/
1535static void make_huts(int number)
1536{
1537 int count = 0;
1538 struct tile *ptile;
1539
1540 create_placed_map(); /* Here it means placed huts */
1541
1542 while (number > 0 && count++ < map_num_tiles() * 2) {
1543
1544 /* Add a hut. But not too close to another hut. */
1546 struct extra_type *phut = rand_extra_for_tile(ptile, EC_HUT, TRUE);
1547
1548 number--;
1549 if (phut != nullptr) {
1550 tile_add_extra(ptile, phut);
1551 }
1552 set_placed_near_pos(ptile, 3);
1553 }
1554 }
1555
1557}
1558
1559/**********************************************************************/
1563static bool is_resource_close(const struct tile *ptile)
1564{
1565 square_iterate(&(wld.map), ptile, 1, tile1) {
1566 if (tile_resource(tile1) != nullptr) {
1567 return TRUE;
1568 }
1570
1571 return FALSE;
1572}
1573
1574/**********************************************************************/
1577static void add_resources(int prob)
1578{
1579 whole_map_iterate(&(wld.map), ptile) {
1580 const struct terrain *pterrain = tile_terrain(ptile);
1581
1582 if (is_resource_close(ptile) || fc_rand (1000) >= prob) {
1583 continue;
1584 }
1585 if (!is_ocean(pterrain) || near_safe_tiles(ptile)
1587 struct extra_type *res = pick_resource(pterrain);
1588
1589 if (res != nullptr) {
1590 tile_set_resource(ptile, res);
1591 }
1592 }
1594
1596}
1597
1598/**********************************************************************/
1602 const struct gen234_state *const pstate)
1603{
1604 int xrnd, yrnd;
1605
1606 fc_assert_ret_val((pstate->e - pstate->w) > 0, nullptr);
1607 fc_assert_ret_val((pstate->e - pstate->w) < MAP_NATIVE_WIDTH, nullptr);
1608 fc_assert_ret_val((pstate->s - pstate->n) > 0, nullptr);
1609 fc_assert_ret_val((pstate->s - pstate->n) < MAP_NATIVE_HEIGHT, nullptr);
1610
1611 xrnd = pstate->w + fc_rand(pstate->e - pstate->w);
1612 yrnd = pstate->n + fc_rand(pstate->s - pstate->n);
1613
1614 return native_pos_to_tile(&(wld.map), xrnd, yrnd);
1615}
1616
1617/**********************************************************************/
1624 int temp_condition,
1625 int wet_condition)
1626{
1627 struct terrain_select *ptersel = fc_malloc(sizeof(*ptersel));
1628
1629 ptersel->weight = weight;
1630 ptersel->target = target;
1631 ptersel->prefer = prefer;
1632 ptersel->avoid = avoid;
1633 ptersel->temp_condition = temp_condition;
1634 ptersel->wet_condition = wet_condition;
1635
1636 return ptersel;
1637}
1638
1639/**********************************************************************/
1643{
1644 if (ptersel != nullptr) {
1646 }
1647}
1648
1649/**********************************************************************/
1652static void fill_island(int coast, long int *bucket,
1653 const struct terrain_select_list *tersel_list,
1654 const struct gen234_state *const pstate)
1655{
1656 int i, k, capac, total_weight = 0;
1658 long int failsafe;
1659
1660 if (*bucket <= 0 ) {
1661 return;
1662 }
1663
1664 /* Must have at least one terrain selection given in tersel_list */
1665 fc_assert_ret(ntersel != 0);
1666
1667 capac = pstate->totalmass;
1668 i = *bucket / capac;
1669 i++;
1670 *bucket -= i * capac;
1671
1672 k = i;
1673 failsafe = i * (pstate->s - pstate->n) * (pstate->e - pstate->w);
1674 if (failsafe < 0) {
1675 failsafe = -failsafe;
1676 }
1677
1679 total_weight += ptersel->weight;
1681
1682 if (total_weight <= 0) {
1683 return;
1684 }
1685
1686 while (i > 0 && (failsafe--) > 0) {
1688
1689 if (tile_continent(ptile) != pstate->isleindex || !not_placed(ptile)) {
1690 continue;
1691 }
1692
1693 struct terrain_select *ptersel
1695
1696 if (fc_rand(total_weight) > ptersel->weight) {
1697 continue;
1698 }
1699
1700 if (!tmap_is(ptile, ptersel->temp_condition)
1701 || !test_wetness(ptile, ptersel->wet_condition)) {
1702 continue;
1703 }
1704
1705 struct terrain *pterrain = pick_terrain(ptersel->target, ptersel->prefer,
1706 ptersel->avoid);
1707
1708 /* The first condition helps make terrain more contiguous,
1709 the second lets it avoid the coast: */
1710 if ((i * 3 > k * 2
1711 || fc_rand(100) < 50
1712 || is_terrain_near_tile(&(wld.map), ptile, pterrain, FALSE))
1714 || fc_rand(100) < coast)) {
1715 tile_set_terrain(ptile, pterrain);
1716 map_set_placed(ptile);
1717
1718 log_debug("[fill_island] placed terrain '%s' at (%2d,%2d)",
1719 terrain_rule_name(pterrain), TILE_XY(ptile));
1720 }
1721
1722 if (!not_placed(ptile)) {
1723 i--;
1724 }
1725 }
1726}
1727
1728/**********************************************************************/
1731static bool island_river_mouth_suitability(const struct tile *ptile,
1732 const struct extra_type *priver)
1733{
1735
1738 TC_OCEAN);
1741 TC_OCEAN);
1743
1744 return (num_card_ocean == 1 && pct_adj_ocean <= 35
1745 && num_adj_river == 0);
1746}
1747
1748/**********************************************************************/
1752static bool island_river_suitability(const struct tile *ptile,
1753 const struct extra_type *priver)
1754{
1756
1760 TC_OCEAN);
1763 TC_OCEAN);
1765
1766 return (num_card_river == 1 && num_card_ocean == 0
1767 && pct_adj_ocean < 20 && pct_adj_river < 35
1768 /* The following expression helps with straightness,
1769 * ocean avoidance, and reduces forking. */
1770 && (pct_adj_river + pct_adj_ocean * 2) < fc_rand(25) + 25);
1771}
1772
1773/**********************************************************************/
1776static void fill_island_rivers(int coast, long int *bucket,
1777 const struct gen234_state *const pstate)
1778{
1779 long int failsafe, capac, i, k;
1780 struct tile *ptile;
1781
1782 if (*bucket <= 0) {
1783 return;
1784 }
1785 if (river_type_count <= 0) {
1786 return;
1787 }
1788
1789 capac = pstate->totalmass;
1790 i = *bucket / capac;
1791 i++;
1792 *bucket -= i * capac;
1793
1794 /* Generate 75% more rivers than generator 1 */
1795 i = (i * 175) / 100;
1796
1797 k = i;
1798 failsafe = i * (pstate->s - pstate->n) * (pstate->e - pstate->w) * 5;
1799 if (failsafe < 0) {
1800 failsafe = -failsafe;
1801 }
1802
1803 while (i > 0 && failsafe-- > 0) {
1804 struct extra_type *priver;
1805
1807 if (tile_continent(ptile) != pstate->isleindex
1808 || tile_has_river(ptile)) {
1809 continue;
1810 }
1811
1813
1814 if (test_wetness(ptile, WC_DRY) && fc_rand(100) < 50) {
1815 /* Rivers don't like dry locations */
1816 continue;
1817 }
1818
1820 && (fc_rand(100) < coast || i == k))
1821 || island_river_suitability(ptile, priver)) {
1822 tile_add_extra(ptile, priver);
1823 i--;
1824 }
1825 }
1826}
1827
1828/**********************************************************************/
1832static bool is_near_land(struct tile *ptile)
1833{
1834 /* Note this function may sometimes be called on land tiles. */
1835 adjc_iterate(&(wld.map), ptile, tile1) {
1836 if (!is_ocean(tile_terrain(tile1))) {
1837 return TRUE;
1838 }
1840
1841 return FALSE;
1842}
1843
1844static long int checkmass;
1845
1846/**********************************************************************/
1850{
1851 int i = 0, xcur, ycur, nat_x, nat_y;
1852 struct tile *ptile;
1853
1854 ptile = rand_map_pos(&(wld.map));
1856
1857 /* This helps a lot for maps with high landmass */
1858 for (ycur = pstate->n, xcur = pstate->w;
1859 ycur < pstate->s && xcur < pstate->e;
1860 ycur++, xcur++) {
1861 struct tile *tile0 = native_pos_to_tile(&(wld.map), xcur, ycur);
1862 struct tile *tile1 = native_pos_to_tile(&(wld.map),
1863 xcur + nat_x - pstate->w,
1864 ycur + nat_y - pstate->n);
1865
1866 if (!tile0 || !tile1) {
1867 return FALSE;
1868 }
1869 if (hmap(tile0) != 0 && is_near_land(tile1)) {
1870 return FALSE;
1871 }
1872 }
1873
1874 for (ycur = pstate->n; ycur < pstate->s; ycur++) {
1875 for (xcur = pstate->w; xcur < pstate->e; xcur++) {
1876 struct tile *tile0 = native_pos_to_tile(&(wld.map), xcur, ycur);
1877 struct tile *tile1 = native_pos_to_tile(&(wld.map),
1878 xcur + nat_x - pstate->w,
1879 ycur + nat_y - pstate->n);
1880
1881 if (!tile0 || !tile1) {
1882 return FALSE;
1883 }
1884 if (hmap(tile0) != 0 && is_near_land(tile1)) {
1885 return FALSE;
1886 }
1887 }
1888 }
1889
1890 for (ycur = pstate->n; ycur < pstate->s; ycur++) {
1891 for (xcur = pstate->w; xcur < pstate->e; xcur++) {
1892 if (hmap(native_pos_to_tile(&(wld.map), xcur, ycur)) != 0) {
1893 struct tile *tile1 = native_pos_to_tile(&(wld.map),
1894 xcur + nat_x - pstate->w,
1895 ycur + nat_y - pstate->n);
1896
1897 checkmass--;
1898 if (checkmass <= 0) {
1899 log_error("mapgen.c: mass doesn't sum up.");
1900 return i != 0;
1901 }
1902
1905
1906 tile_set_continent(tile1, pstate->isleindex);
1907 i++;
1908 }
1909 }
1910 }
1911
1912 pstate->s += nat_y - pstate->n;
1913 pstate->e += nat_x - pstate->w;
1914 pstate->n = nat_y;
1915 pstate->w = nat_x;
1916
1917 return i != 0;
1918}
1919
1920/**********************************************************************/
1923static int count_card_adjc_elevated_tiles(struct tile *ptile)
1924{
1925 int count = 0;
1926
1927 cardinal_adjc_iterate(&(wld.map), ptile, tile1) {
1928 if (hmap(tile1) != 0) {
1929 count++;
1930 }
1932
1933 return count;
1934}
1935
1936/**********************************************************************/
1940{
1941 int i, nat_x, nat_y;
1942 long int tries = islemass * (2 + islemass / 20) + 99;
1943 bool j;
1944 struct tile *ptile
1947
1948 memset(height_map, '\0', MAP_INDEX_SIZE * sizeof(*height_map));
1950 MAP_NATIVE_WIDTH / 2, MAP_NATIVE_HEIGHT / 2)) = 1;
1951
1953 pstate->n = nat_y - 1;
1954 pstate->w = nat_x - 1;
1955 pstate->s = nat_y + 2;
1956 pstate->e = nat_x + 2;
1957 i = islemass - 1;
1958
1959 while (i > 0 && tries-->0) {
1962
1963 if ((!near_singularity(ptile) || fc_rand(50) < 25 )
1964 && hmap(ptile) == 0 && count_card_adjc_elevated_tiles(ptile) > 0) {
1965 hmap(ptile) = 1;
1966 i--;
1967 if (nat_y >= pstate->s - 1 && pstate->s < MAP_NATIVE_HEIGHT - 2) {
1968 pstate->s++;
1969 }
1970 if (nat_x >= pstate->e - 1 && pstate->e < MAP_NATIVE_WIDTH - 2) {
1971 pstate->e++;
1972 }
1973 if (nat_y <= pstate->n && pstate->n > 2) {
1974 pstate->n--;
1975 }
1976 if (nat_x <= pstate->w && pstate->w > 2) {
1977 pstate->w--;
1978 }
1979 }
1980 if (i < islemass / 10) {
1981 int xcur, ycur;
1982
1983 for (ycur = pstate->n; ycur < pstate->s; ycur++) {
1984 for (xcur = pstate->w; xcur < pstate->e; xcur++) {
1985 ptile = native_pos_to_tile(&(wld.map), xcur, ycur);
1986 if (hmap(ptile) == 0 && i > 0
1987 && count_card_adjc_elevated_tiles(ptile) == 4) {
1988 hmap(ptile) = 1;
1989 i--;
1990 }
1991 }
1992 }
1993 }
1994 }
1995
1996 if (tries <= 0) {
1997 log_error("create_island ended early with %d/%d.", islemass-i, islemass);
1998 }
1999
2000 tries = map_num_tiles() / 4; /* On a 40x60 map, there are 2400 places */
2001 while (!(j = place_island(pstate)) && (--tries) > 0) {
2002 /* Nothing */
2003 }
2004
2005 return j;
2006}
2007
2008/*************************************************************************/
2009
2010/**********************************************************************/
2013static void island_terrain_init(void)
2014{
2015 struct terrain_select *ptersel;
2016
2017 /* Forest */
2023 TT_ALL, WC_ALL);
2031
2032 /* Desert */
2035 TT_HOT, WC_DRY);
2041 TT_NHOT, WC_DRY);
2044 TT_FROZEN, WC_DRY);
2046
2047 /* Mountain */
2050 TT_ALL, WC_ALL);
2053 TT_ALL, WC_ALL);
2055
2056 /* Swamp */
2062 TT_HOT, WC_NDRY);
2065 TT_NHOT, WC_NDRY);
2067
2068 island_terrain.init = TRUE;
2069}
2070
2071/**********************************************************************/
2074static void island_terrain_free(void)
2075{
2076 if (!island_terrain.init) {
2077 return;
2078 }
2079
2084
2085 island_terrain.init = FALSE;
2086}
2087
2088/**********************************************************************/
2094static bool make_island(int islemass, int starters,
2095 struct gen234_state *pstate,
2097{
2098 /* int may be only 2 bytes ! */
2099 static long int tilefactor, balance, lastplaced;
2101 int i;
2102
2103 /* The terrain selection lists have to be initialised.
2104 * (see island_terrain_init()) */
2106
2107 if (islemass == 0) {
2108 /* This only runs to initialise static things, not to actually
2109 * create an island. */
2110 balance = 0;
2111 /* 0 = none, poles, then isles */
2112 pstate->isleindex = wld.map.num_continents + 1;
2113
2114 checkmass = pstate->totalmass;
2115
2116 /* Caveat: this should really be sent to all players */
2117 if (pstate->totalmass > 3000) {
2118 log_normal(_("High landmass - this may take a few seconds."));
2119 }
2120
2122 i = (i <= 90) ? 100 : i * 11 / 10;
2123 tilefactor = pstate->totalmass / i;
2124 riverbuck = -(long int) fc_rand(pstate->totalmass);
2125 mountbuck = -(long int) fc_rand(pstate->totalmass);
2126 desertbuck = -(long int) fc_rand(pstate->totalmass);
2127 forestbuck = -(long int) fc_rand(pstate->totalmass);
2128 swampbuck = -(long int) fc_rand(pstate->totalmass);
2129 lastplaced = pstate->totalmass;
2130 } else {
2131
2132 /* Makes the islands this big */
2134
2135 if (islemass > lastplaced + 1 + lastplaced / 50) {
2136 /* Don't create big isles we can't place */
2137 islemass = lastplaced + 1 + lastplaced / 50;
2138 }
2139
2140 /* Isle creation does not perform well for nonsquare islands */
2141 if (islemass > (MAP_NATIVE_HEIGHT - 6) * (MAP_NATIVE_HEIGHT - 6)) {
2143 }
2144
2145 if (islemass > (MAP_NATIVE_WIDTH - 2) * (MAP_NATIVE_WIDTH - 2)) {
2147 }
2148
2149 i = islemass;
2150 if (i <= 0) {
2151 return FALSE;
2152 }
2153 fc_assert_ret_val(starters >= 0, FALSE);
2154 log_verbose("island %i", pstate->isleindex);
2155
2156 /* Keep trying to place an island, and decrease the size of
2157 * the island we're trying to create until we succeed.
2158 * If we get too small, return an error. */
2159 while (!create_island(i, pstate)) {
2160 if (i < islemass * min_specific_island_size / 100) {
2161 return FALSE;
2162 }
2163 i--;
2164 }
2165 i++;
2166 lastplaced = i;
2167 if (i * 10 > islemass) {
2168 balance = i - islemass;
2169 } else {
2170 balance = 0;
2171 }
2172
2173 log_verbose("ini=%d, plc=%d, bal=%ld, tot=%ld",
2175
2176 i *= tilefactor;
2177
2178 riverbuck += river_pct * i;
2180
2181 /* Forest */
2182 forestbuck += forest_pct * i;
2184
2185 /* Desert */
2186 desertbuck += desert_pct * i;
2188
2189 /* Mountain */
2191 fill_island(20, &mountbuck, island_terrain.mountain, pstate);
2192
2193 /* Swamp */
2194 swampbuck += swamp_pct * i;
2196
2197 pstate->isleindex++;
2199 }
2200
2201 return TRUE;
2202}
2203
2204/**********************************************************************/
2208static void initworld(struct gen234_state *pstate)
2209{
2211 FALSE);
2212
2213 fc_assert(deepest_ocean != nullptr);
2215 create_placed_map(); /* Land tiles which aren't placed yet */
2216
2217 whole_map_iterate(&(wld.map), ptile) {
2219 tile_set_continent(ptile, 0);
2220 map_set_placed(ptile); /* Not a land tile */
2221 BV_CLR_ALL(ptile->extras);
2222 tile_set_owner(ptile, nullptr, nullptr);
2223 ptile->extras_owner = nullptr;
2225
2226 if (HAS_POLES) {
2227 make_polar();
2228 }
2229
2230 /* Set poles numbers. After the map is generated continents will
2231 * be renumbered. */
2232 make_island(0, 0, pstate, 0);
2233}
2234
2235/* This variable is the Default Minimum Specific Island Size,
2236 * ie the smallest size we'll typically permit our island, as a % of
2237 * the size we wanted. So if we ask for an island of size x, the island
2238 * creation will return if it would create an island smaller than
2239 * x * DMSIS / 100 */
2240#define DMSIS 10
2241
2242/**********************************************************************/
2245static void mapgenerator2(void)
2246{
2247 long int totalweight;
2248 struct gen234_state state;
2249 struct gen234_state *pstate = &state;
2250 int i;
2251 bool done = FALSE;
2252 int spares = 1;
2253 /* Constant that makes up that an island actually needs additional space */
2254
2255 /* Put 70% of land in big continents,
2256 * 20% in medium, and
2257 * 10% in small. */
2258 int bigfrac = 70, midfrac = 20, smallfrac = 10;
2259
2260 if (wld.map.server.landpercent > 85) {
2261 log_verbose("ISLAND generator: falling back to RANDOM generator");
2263
2264 return;
2265 }
2266
2267 pstate->totalmass = ((MAP_NATIVE_HEIGHT - 6 - spares) * wld.map.server.landpercent
2268 * (MAP_NATIVE_WIDTH - spares)) / 100;
2269 totalweight = 100 * player_count();
2270
2273
2274 while (!done && bigfrac > midfrac) {
2275 done = TRUE;
2276
2279 }
2280
2282
2283 /* Create one big island for each player. */
2284 for (i = player_count(); i > 0; i--) {
2285 if (!make_island(bigfrac * pstate->totalmass / totalweight,
2286 1, pstate, 95)) {
2287 /* We couldn't make an island at least 95% as big as we wanted,
2288 * and since we're trying hard to be fair, we need to start again,
2289 * with all big islands reduced slightly in size.
2290 * Take the size reduction from the big islands and add it to the
2291 * small islands to keep overall landmass unchanged.
2292 * Note that the big islands can get very small if necessary, and
2293 * the smaller islands will not exist if we can't place them
2294 * easily. */
2295 log_verbose("Island too small, trying again with all smaller "
2296 "islands.");
2297 midfrac += bigfrac * 0.01;
2298 smallfrac += bigfrac * 0.04;
2299 bigfrac *= 0.95;
2300 done = FALSE;
2301 break;
2302 }
2303 }
2304 }
2305
2306 if (bigfrac <= midfrac) {
2307 /* We could never make adequately big islands. */
2308 log_verbose("ISLAND generator: falling back to RANDOM generator");
2310
2311 /* Init world created this map, destroy it before abort */
2314 height_map = nullptr;
2315
2316 return;
2317 }
2318
2319 /* Now place smaller islands, but don't worry if they're small,
2320 * or even non-existent. One medium and one small per player. */
2321 for (i = player_count(); i > 0; i--) {
2322 make_island(midfrac * pstate->totalmass / totalweight, 0, pstate, DMSIS);
2323 }
2324 for (i = player_count(); i > 0; i--) {
2325 make_island(smallfrac * pstate->totalmass / totalweight, 0, pstate, DMSIS);
2326 }
2327
2329 make_plains();
2332 height_map = nullptr;
2333
2335 log_verbose("%ld mass left unplaced", checkmass);
2336 }
2337}
2338
2339/**********************************************************************/
2343static void mapgenerator3(void)
2344{
2345 int spares = 1;
2346 int j = 0;
2347 long int islandmass, landmass, size;
2348 long int maxmassdiv6 = 20;
2349 int bigislands;
2350 struct gen234_state state;
2351 struct gen234_state *pstate = &state;
2352
2353 if (wld.map.server.landpercent > 80) {
2354 log_verbose("ISLAND generator: falling back to FRACTAL generator due "
2355 "to landpercent > 80.");
2357 return;
2358 }
2359
2360 if (MAP_NATIVE_WIDTH < 40 || MAP_NATIVE_HEIGHT < 40) {
2361 log_verbose("ISLAND generator: falling back to FRACTAL generator due "
2362 "to unsupported map size.");
2364 return;
2365 }
2366
2367 pstate->totalmass = (((MAP_NATIVE_HEIGHT - 6 - spares) * wld.map.server.landpercent
2368 * (MAP_NATIVE_WIDTH - spares)) / 100);
2369
2371
2373 /* Subtracting the arctics */
2374 if (landmass > 3 * MAP_NATIVE_HEIGHT + player_count() * 3) {
2376 }
2377
2378 islandmass = (landmass) / (3 * bigislands);
2379 if (islandmass < 4 * maxmassdiv6) {
2380 islandmass = (landmass) / (2 * bigislands);
2381 }
2382 if (islandmass < 3 * maxmassdiv6 && player_count() * 2 < landmass) {
2384 }
2385
2386 if (islandmass < 2) {
2387 islandmass = 2;
2388 }
2389 if (islandmass > maxmassdiv6 * 6) {
2390 islandmass = maxmassdiv6 * 6; /* !PS: Let's try this */
2391 }
2392
2394
2395 while (pstate->isleindex - 2 <= bigislands && checkmass > islandmass
2396 && ++j < 500) {
2398 }
2399
2400 if (j == 500) {
2401 log_normal(_("Generator 3 didn't place all big islands."));
2402 }
2403
2404 islandmass = (islandmass * 11) / 8;
2406 if (islandmass < 2) {
2407 islandmass = 2;
2408 }
2409
2410 while (checkmass > islandmass && ++j < 1500) {
2411 if (j < 1000) {
2412 size = fc_rand((islandmass + 1) / 2 + 1) + islandmass / 2;
2413 } else {
2414 size = fc_rand((islandmass + 1) / 2 + 1);
2415 }
2416 if (size < 2) {
2417 size = 2;
2418 }
2419
2420 make_island(size, (pstate->isleindex - 2 <= player_count()) ? 1 : 0,
2421 pstate, DMSIS);
2422 }
2423
2425 make_plains();
2428 height_map = nullptr;
2429
2430 if (j == 1500) {
2431 log_normal(_("Generator 3 left %li landmass unplaced."), checkmass);
2433 log_verbose("%ld mass left unplaced", checkmass);
2434 }
2435}
2436
2437/**********************************************************************/
2440static void mapgenerator4(void)
2441{
2442 int bigweight = 70;
2443 int spares = 1;
2444 int i;
2445 long int totalweight;
2446 struct gen234_state state;
2447 struct gen234_state *pstate = &state;
2448
2449 /* No islands with mass >> sqr(min(xsize,ysize)) */
2450
2451 if (player_count() < 2 || wld.map.server.landpercent > 80) {
2452 log_verbose("ISLAND generator: falling back to startpos=SINGLE");
2454 return;
2455 }
2456
2457 if (wld.map.server.landpercent > 60) {
2458 bigweight = 30;
2459 } else if (wld.map.server.landpercent > 40) {
2460 bigweight = 50;
2461 } else {
2462 bigweight = 70;
2463 }
2464
2465 spares = (wld.map.server.landpercent - 5) / 30;
2466
2467 pstate->totalmass = (((MAP_NATIVE_HEIGHT - 6 - spares) * wld.map.server.landpercent
2468 * (MAP_NATIVE_WIDTH - spares)) / 100);
2469
2471 totalweight = (30 + bigweight) * player_count();
2472
2474
2475 i = player_count() / 2;
2476 if ((player_count() & 1) == 1) {
2477 make_island(bigweight * 3 * pstate->totalmass / totalweight, 3,
2478 pstate, DMSIS);
2479 } else {
2480 i++;
2481 }
2482 while ((--i) > 0) {
2483 make_island(bigweight * 2 * pstate->totalmass / totalweight, 2,
2484 pstate, DMSIS);
2485 }
2486 for (i = player_count(); i > 0; i--) {
2487 make_island(20 * pstate->totalmass / totalweight, 0, pstate, DMSIS);
2488 }
2489 for (i = player_count(); i > 0; i--) {
2490 make_island(10 * pstate->totalmass / totalweight, 0, pstate, DMSIS);
2491 }
2492
2494 make_plains();
2497 height_map = nullptr;
2498
2500 log_verbose("%ld mass left unplaced", checkmass);
2501 }
2502}
2503
2504#undef DMSIS
2505
2506/**********************************************************************/
2509static void river_types_init(void)
2510{
2511 river_type_count = 0;
2512
2515 && priver->generated) {
2517 }
2519}
2520
2521
2522/****************************************************************************
2523 Fair island generator types.
2524****************************************************************************/
2534
2542
2543typedef void (*fair_geometry_func)(int *x, int *y);
2548
2549/**********************************************************************/
2553static inline struct fair_tile *fair_map_new(void)
2554{
2555 return fc_calloc(MAP_INDEX_SIZE, sizeof(struct fair_tile));
2556}
2557
2558/**********************************************************************/
2561static inline void fair_map_destroy(struct fair_tile *pmap)
2562{
2563 free(pmap);
2564}
2565
2566/**********************************************************************/
2569static inline void fair_map_tile_pos(struct fair_tile *pmap,
2570 struct fair_tile *ptile, int *x, int *y)
2571{
2572 index_to_map_pos(x, y, ptile - pmap);
2573}
2574
2575/**********************************************************************/
2578static inline struct fair_tile *
2580{
2581 int nat_x, nat_y;
2582
2584
2585 /* Wrap in X and Y directions, as needed. */
2589 } else {
2590 return nullptr;
2591 }
2592 }
2596 } else {
2597 return nullptr;
2598 }
2599 }
2600
2602}
2603
2604/**********************************************************************/
2607static inline struct fair_tile *
2609 enum direction8 dir)
2610{
2611 int x, y, dx, dy;
2612
2613 fair_map_tile_pos(pmap, ptile, &x, &y);
2614 DIRSTEP(dx, dy, dir);
2615
2616 return fair_map_pos_tile(pmap, x + dx, y + dy);
2617}
2618
2619/**********************************************************************/
2623static inline bool
2625 int dist)
2626{
2627 int nat_x, nat_y;
2628
2629 index_to_native_pos(&nat_x, &nat_y, ptile - pmap);
2630
2633 return TRUE;
2634 }
2635
2636 if (MAP_IS_ISOMETRIC) {
2637 dist *= 2;
2638 }
2639
2642 return TRUE;
2643 }
2644
2645 return FALSE;
2646}
2647
2648/**********************************************************************/
2651static int fair_team_placement_closest(const void *a, const void *b)
2652{
2653 const struct iter_index *index1 = a, *index2 = b;
2654
2655 return index1->dist - index2->dist;
2656}
2657
2658/**********************************************************************/
2661static int fair_team_placement_horizontal(const void *a, const void *b)
2662{
2663 const struct iter_index *index1 = a, *index2 = b;
2664 /* Map vector to natural vector (Y axis). */
2665 int diff = (MAP_IS_ISOMETRIC
2666 ? abs(index1->dx + index1->dy) - abs(index2->dx + index2->dy)
2667 : abs(index1->dy) - abs(index2->dy));
2668
2669 return (diff != 0 ? diff : index1->dist - index2->dist);
2670}
2671
2672/**********************************************************************/
2675static int fair_team_placement_vertical(const void *a, const void *b)
2676{
2677 const struct iter_index *index1 = a, *index2 = b;
2678 /* Map vector to natural vector (X axis). */
2679 int diff = (MAP_IS_ISOMETRIC
2680 ? abs(index1->dx - index1->dy) - abs(index2->dx - index2->dy)
2681 : abs(index1->dx) - abs(index2->dx));
2682
2683 return (diff != 0 ? diff : index1->dist - index2->dist);
2684}
2685
2686/**********************************************************************/
2689static void fair_do_symmetry1(int *x, int *y)
2690{
2691 *x = -*x;
2692}
2693
2694/**********************************************************************/
2697static void fair_do_symmetry2(int *x, int *y)
2698{
2699 *y = -*y;
2700}
2701
2702/**********************************************************************/
2705static void fair_do_hex_symmetry1(int *x, int *y)
2706{
2707 *x = -(*x + *y);
2708}
2709
2710/**********************************************************************/
2713static void fair_do_hex_symmetry2(int *x, int *y)
2714{
2715 *x = -*x;
2716 *y = -*y;
2717}
2718
2719/**********************************************************************/
2722static void fair_do_iso_hex_symmetry1(int *x, int *y)
2723{
2724 *y = *x - *y;
2725}
2726
2727#define fair_do_iso_hex_symmetry2 fair_do_rotation
2728
2729/**********************************************************************/
2732static void fair_do_rotation(int *x, int *y)
2733{
2734 int z = *x;
2735
2736 *x = *y;
2737 *y = z;
2738}
2739
2740/**********************************************************************/
2743static void fair_do_hex_rotation(int *x, int *y)
2744{
2745 int z = *x + *y;
2746
2747 *x = -*y;
2748 *y = z;
2749}
2750
2751/**********************************************************************/
2754static void fair_do_iso_hex_rotation(int *x, int *y)
2755{
2756 int z = *x - *y;
2757
2758 *y = *x;
2759 *x = z;
2760}
2761
2762/**********************************************************************/
2765static void fair_do_geometry(const struct fair_geometry_data *data,
2766 int *x, int *y)
2767{
2768 int i;
2769
2770 for (i = 0; i < data->transform_num; i++) {
2771 data->transform[i](x, y);
2772 }
2773}
2774
2775/**********************************************************************/
2779{
2780 int i = 0;
2781
2783 if (fc_rand(100) < 50) {
2784 data->transform[i++] = fair_do_symmetry1;
2785 }
2786 if (fc_rand(100) < 50) {
2787 data->transform[i++] = fair_do_symmetry2;
2788 }
2789 if (fc_rand(100) < 50) {
2790 data->transform[i++] = fair_do_rotation;
2791 }
2792 } else if (!current_topo_has_flag(TF_ISO)) {
2793 int steps;
2794
2795 if (fc_rand(100) < 50) {
2797 }
2798 if (fc_rand(100) < 50) {
2800 }
2801 /* Rotations have 2 steps on hexgonal topologies. */
2802 for (steps = fc_rand(99) % 3; steps > 0; steps--) {
2803 data->transform[i++] = fair_do_hex_rotation;
2804 }
2805 } else {
2806 int steps;
2807
2808 if (fc_rand(100) < 50) {
2810 }
2811 if (fc_rand(100) < 50) {
2813 }
2814 /* Rotations have 2 steps on hexgonal topologies. */
2815 for (steps = fc_rand(99) % 3; steps > 0; steps--) {
2817 }
2818 }
2819
2820 fc_assert(i <= ARRAY_SIZE(data->transform));
2821
2822 data->transform_num = i;
2823}
2824
2825/**********************************************************************/
2831static bool fair_map_copy(struct fair_tile *ptarget, int tx, int ty,
2832 struct fair_tile *psource,
2833 const struct fair_geometry_data *data,
2834 int startpos_team_id)
2835{
2836 int sdx = MAP_NATIVE_WIDTH / 2, sdy = MAP_NATIVE_HEIGHT / 2;
2838 struct fair_tile *pstile, *pttile;
2839 int x, y;
2840
2841 /* Check. */
2842 for (pstile = psource; pstile < smax_tile; pstile++) {
2843 if (pstile->flags == FTF_NONE) {
2844 continue;
2845 }
2846
2847 /* Do translation and eventually other transformations. */
2849 x -= sdx;
2850 y -= sdy;
2851 fair_do_geometry(data, &x, &y);
2852 x += tx;
2853 y += ty;
2855 if (pttile == nullptr) {
2856 return FALSE; /* Limit of the map. */
2857 }
2858 if (pttile->flags & FTF_ASSIGNED) {
2859 if (pstile->flags & FTF_ASSIGNED
2860 || !(pttile->flags & FTF_OCEAN)
2861 || !(pstile->flags & FTF_OCEAN)) {
2862 return FALSE; /* Already assigned for another usage. */
2863 }
2864 } else if (pttile->flags & FTF_OCEAN && !(pstile->flags & FTF_OCEAN)) {
2865 return FALSE; /* We clearly want a sea tile here. */
2866 }
2867 if ((pttile->flags & FTF_NO_RESOURCE && pstile->presource != nullptr)
2868 || (pstile->flags & FTF_NO_RESOURCE && pttile->presource != nullptr)) {
2869 return FALSE; /* Resource disallowed there. */
2870 }
2871 if ((pttile->flags & FTF_NO_HUT && pstile->flags & FTF_HAS_HUT)
2872 || (pstile->flags & FTF_NO_HUT && pttile->flags & FTF_HAS_HUT)) {
2873 return FALSE; /* Resource disallowed there. */
2874 }
2875 }
2876
2877 /* Copy. */
2878 for (pstile = psource; pstile < smax_tile; pstile++) {
2879 if (pstile->flags == FTF_NONE) {
2880 continue;
2881 }
2882
2883 /* Do translation and eventually other transformations. */
2885 x -= sdx;
2886 y -= sdy;
2887 fair_do_geometry(data, &x, &y);
2888 x += tx;
2889 y += ty;
2891 fc_assert_ret_val(pttile != nullptr, FALSE);
2892 pttile->flags |= pstile->flags;
2893
2894 if (pstile->pterrain != nullptr) {
2895 pttile->pterrain = pstile->pterrain;
2896 pttile->presource = pstile->presource;
2897 pttile->extras = pstile->extras;
2898 }
2899 if (pstile->flags & FTF_STARTPOS) {
2900 pttile->startpos_team_id = startpos_team_id;
2901 }
2902 }
2903 return TRUE; /* Looks ok. */
2904}
2905
2906/**********************************************************************/
2911 struct fair_tile *psource)
2912{
2914 int i, r, x, y;
2915
2917
2918 /* Try random positions. */
2919 for (i = 0; i < 10; i++) {
2921 index_to_map_pos(&x, &y, r);
2922 if (fair_map_copy(ptarget, x, y, psource, &geometry, -1)) {
2923 return TRUE;
2924 }
2925 }
2926
2927 /* Try hard placement. */
2929 for (i = (r + 1) % MAP_INDEX_SIZE; i != r; i = (i + 1) % MAP_INDEX_SIZE) {
2930 index_to_map_pos(&x, &y, i);
2931 if (fair_map_copy(ptarget, x, y, psource, &geometry, -1)) {
2932 return TRUE;
2933 }
2934 }
2935
2936 /* Impossible placement. */
2937 return FALSE;
2938}
2939
2940/**********************************************************************/
2944static bool
2946 struct fair_tile *psource,
2947 const struct iter_index *outwards_indices,
2948 int startpos_team_id)
2949{
2951 int i, x, y;
2952
2954
2955 /* Iterate positions, beginning by a random index of the outwards
2956 * indices. */
2959 x = tx + outwards_indices[i].dx;
2960 y = ty + outwards_indices[i].dy;
2961 if (normalize_map_pos(&(wld.map), &x, &y)
2963 startpos_team_id)) {
2964 return TRUE;
2965 }
2966 }
2967
2968 /* Impossible placement. */
2969 return FALSE;
2970}
2971
2972/**********************************************************************/
2976{
2977 struct fair_tile *pftile, *pftile2;
2978 int i, j;
2979
2980 for (i = 0; i < MAP_INDEX_SIZE; i++) {
2981 pftile = pmap + i;
2982 if (pftile->flags == FTF_NONE
2983 || pftile->flags & FTF_NO_RESOURCE
2984 || fc_rand (1000) >= wld.map.server.riches) {
2985 continue;
2986 }
2987
2988 if (pftile->flags & FTF_OCEAN) {
2989 bool land_around = FALSE;
2990
2991 for (j = 0; j < MAP_NUM_VALID_DIRS; j++) {
2993 if (pftile2 != nullptr
2994 && pftile2->flags & FTF_ASSIGNED
2995 && !(pftile2->flags & FTF_OCEAN)) {
2996 land_around = TRUE;
2997 break;
2998 }
2999 }
3000 if (!land_around) {
3001 continue;
3002 }
3003 }
3004
3005 pftile->presource = pick_resource(pftile->pterrain);
3006 /* Note that 'pftile->presource' might be nullptr if there is no suitable
3007 * resource for the terrain. */
3008 if (pftile->presource != nullptr) {
3009 pftile->flags |= FTF_NO_RESOURCE;
3010 for (j = 0; j < MAP_NUM_VALID_DIRS; j++) {
3012 if (pftile2 != nullptr) {
3013 pftile2->flags |= FTF_NO_RESOURCE;
3014 }
3015 }
3016
3017 BV_SET(pftile->extras, extra_index(pftile->presource));
3018 }
3019 }
3020}
3021
3022/**********************************************************************/
3026{
3027 struct fair_tile *pftile;
3028 struct tile *pvtile = tile_virtual_new(nullptr);
3029 struct extra_type *phut;
3030 int i, j, k;
3031
3032 for (i = wld.map.server.huts * map_num_tiles() / 1000, j = 0;
3033 i > 0 && j < map_num_tiles() * 2; j++) {
3035 pftile = pmap + k;
3036 while (pftile->flags & FTF_NO_HUT) {
3037 pftile++;
3038 if (pftile - pmap == MAP_INDEX_SIZE) {
3039 pftile = pmap;
3040 }
3041 if (pftile - pmap == k) {
3042 break;
3043 }
3044 }
3045 if (pftile->flags & FTF_NO_HUT) {
3046 break; /* Cannot make huts anymore. */
3047 }
3048
3049 i--;
3050 if (pftile->pterrain == nullptr) {
3051 continue; /* Not an used tile. */
3052 }
3053
3054 pvtile->index = pftile - pmap;
3055 tile_set_terrain(pvtile, pftile->pterrain);
3056 tile_set_resource(pvtile, pftile->presource);
3057 pvtile->extras = pftile->extras;
3058
3060 if (phut != nullptr) {
3062 pftile->extras = pvtile->extras;
3063 pftile->flags |= FTF_HAS_HUT;
3065 3, ptile) {
3066 pmap[tile_index(ptile)].flags |= FTF_NO_HUT;
3068 }
3069 }
3070
3072}
3073
3074/**********************************************************************/
3078{
3079 enum {
3081 FT_FOREST,
3082 FT_DESERT,
3083 FT_HILL,
3085 FT_SWAMP,
3086 FT_COUNT
3087 };
3088 struct {
3089 int count;
3090 enum mapgen_terrain_property target;
3091 enum mapgen_terrain_property prefer;
3092 enum mapgen_terrain_property avoid;
3093 } terrain[FT_COUNT] = {
3096 { 0, MG_DRY, MG_TEMPERATE, MG_GREEN },
3100 };
3101
3102 struct fair_tile *pisland;
3103 struct fair_tile *land_tiles[1000];
3104 struct fair_tile *pftile, *pftile2, *pftile3;
3105 int fantasy;
3106 const int sea_around_island = (startpos_num > 0
3108 const int sea_around_island_sq = (startpos_num > 0
3110 int i, j, k;
3111
3113 fantasy = (size * 2) / 5;
3117 pftile->flags |= FTF_ASSIGNED;
3118 land_tiles[0] = pftile;
3119 i = 1;
3120
3121 log_debug("Generating an island with %d land tiles [fantasy=%d].",
3122 size, fantasy);
3123
3124 /* Make land. */
3125 while (i < fantasy) {
3127
3128 for (j = 0; j < MAP_NUM_VALID_DIRS; j++) {
3130 fc_assert(pftile2 != nullptr);
3132 continue;
3133 }
3134
3135 if (pftile2->flags == FTF_NONE) {
3136 pftile2->flags = FTF_ASSIGNED;
3137 land_tiles[i++] = pftile2;
3138 if (i == fantasy) {
3139 break;
3140 }
3141 }
3142 }
3143 }
3144
3145 while (i < size) {
3146 pftile = land_tiles[i - fc_rand(fantasy) - 1];
3149 fc_assert(pftile2 != nullptr);
3151 continue;
3152 }
3153
3154 if (pftile2->flags == FTF_NONE) {
3155 pftile2->flags = FTF_ASSIGNED;
3156 land_tiles[i++] = pftile2;
3157 }
3158 }
3159 fc_assert(i == size);
3160
3161 /* Add start positions. */
3162 for (i = 0; i < startpos_num;) {
3164 fc_assert(pftile->flags & FTF_ASSIGNED);
3165 if (!(pftile->flags & FTF_STARTPOS)) {
3166 pftile->flags |= FTF_STARTPOS;
3167 i++;
3168 }
3169 }
3170
3171 /* Make terrain. */
3173 terrain[FT_FOREST].count = ((forest_pct + jungle_pct) * size) / 100;
3174 terrain[FT_DESERT].count = (desert_pct * size) / 100;
3175 terrain[FT_HILL].count = (mountain_pct * size) / 150;
3176 terrain[FT_MOUNTAIN].count = (mountain_pct * size) / 300;
3177 terrain[FT_SWAMP].count = (swamp_pct * size) / 100;
3178
3179 j = FT_GRASSLAND;
3180 for (i = 0; i < size; i++) {
3181 pftile = land_tiles[i];
3182
3183 if (pftile->flags & FTF_STARTPOS) {
3185 } else {
3186 if (terrain[j].count == 0 || fc_rand(100) < 70) {
3187 do {
3188 j = fc_rand(FT_COUNT);
3189 } while (terrain[j].count == 0);
3190 }
3191 pftile->pterrain = pick_terrain(terrain[j].target, terrain[j].prefer,
3192 terrain[j].avoid);
3193 terrain[j].count--;
3194 }
3195 }
3196
3197 /* Make sea around the island. */
3198 for (i = 0; i < size; i++) {
3201 sea_around_island_sq, ptile) {
3202 pftile = pisland + tile_index(ptile);
3203
3204 if (pftile->flags == FTF_NONE) {
3205 pftile->flags = FTF_OCEAN;
3206 /* No ice around island */
3207 pftile->pterrain =
3210 if (startpos_num > 0) {
3211 pftile->flags |= FTF_ASSIGNED;
3212 }
3213 }
3215 }
3216
3217 /* Make rivers. */
3218 if (river_type_count > 0) {
3219 struct extra_type *priver;
3220 struct fair_tile *pend;
3222 * MAP_NUM_CARDINAL_DIRS) / 200);
3223 int length_max = 3, length, l;
3224 enum direction8 dir;
3225 int extra_idx;
3226 int dirs_num;
3227 bool cardinal_only;
3229 int river_around;
3230 bool finished;
3231
3232 for (i = 0; i < n; i++) {
3234 if (!terrain_has_flag(pftile->pterrain, TER_CAN_HAVE_RIVER)) {
3235 continue;
3236 }
3237
3240 if (BV_ISSET(pftile->extras, extra_idx)) {
3241 continue;
3242 }
3244
3245 river_around = 0;
3248 for (j = 0; j < MAP_NUM_VALID_DIRS; j++) {
3250 if (pftile2 == nullptr) {
3251 continue;
3252 }
3253
3254 if (pftile2->flags & FTF_OCEAN) {
3256 break;
3257 } else if (BV_ISSET(pftile2->extras, extra_idx)) {
3258 river_around++;
3261 }
3262 }
3263 }
3264 if (ocean_around
3265 || river_around > 1
3266 || (river_around == 1 && !connectable_river_around)) {
3267 continue;
3268 }
3269
3271 log_debug("Adding river at (%d, %d)",
3274 BV_SET(pftile->extras, extra_idx);
3275 continue;
3276 }
3277
3278 /* Check a river in one direction. */
3279 pend = nullptr;
3280 length = -1;
3281 dir = direction8_invalid();
3282 dirs_num = 0;
3283 for (j = 0; j < MAP_NUM_VALID_DIRS; j++) {
3285 continue;
3286 }
3287
3288 finished = FALSE;
3289 pftile2 = pftile;
3290 for (l = 2; l < length_max; l++) {
3292 if (pftile2 == nullptr
3294 break;
3295 }
3296
3297 river_around = 0;
3300 for (k = 0; k < MAP_NUM_VALID_DIRS; k++) {
3302 continue;
3303 }
3304
3306 MAP_VALID_DIRS[k]);
3307 if (pftile3 == nullptr) {
3308 continue;
3309 }
3310
3311 if (pftile3->flags & FTF_OCEAN) {
3314 }
3315 } else if (BV_ISSET(pftile3->extras, extra_idx)) {
3316 river_around++;
3319 }
3320 }
3321 }
3323 break;
3324 } else if (ocean_around || connectable_river_around) {
3325 finished = TRUE;
3326 break;
3327 }
3328 }
3329 if (finished && fc_rand(++dirs_num) == 0) {
3330 dir = MAP_VALID_DIRS[j];
3331 pend = pftile2;
3332 length = l;
3333 }
3334 }
3335 if (pend == nullptr) {
3336 continue;
3337 }
3338
3339 log_debug("Make river from (%d, %d) to (%d, %d) [dir=%s, length=%d]",
3344 direction8_name(dir),
3345 length);
3346 for (;;) {
3347 BV_SET(pftile->extras, extra_idx);
3348 length--;
3349 if (pftile == pend) {
3350 fc_assert(length == 0);
3351 break;
3352 }
3354 fc_assert(pftile != nullptr);
3355 }
3356 }
3357 }
3358
3359 if (startpos_num > 0) {
3360 /* Islands with start positions must have the same resources and the
3361 * same huts. Other ones don't matter. */
3362
3363 /* Make resources. */
3364 if (wld.map.server.riches > 0) {
3366 }
3367
3368 /* Make huts. */
3369 if (wld.map.server.huts > 0) {
3371 }
3372
3373 /* Make sure there will be no more resources and huts on assigned
3374 * tiles. */
3375 for (i = 0; i < MAP_INDEX_SIZE; i++) {
3376 pftile = pisland + i;
3377 if (pftile->flags & FTF_ASSIGNED) {
3378 pftile->flags |= (FTF_NO_RESOURCE | FTF_NO_HUT);
3379 }
3380 }
3381 }
3382
3383 return pisland;
3384}
3385
3386/**********************************************************************/
3390{
3391 struct terrain *deepest_ocean
3393 struct fair_tile *pmap, *pisland;
3395 int min_island_size = wld.map.server.tinyisles ? 1 : 2;
3396 int players_per_island = 1;
3398 int i, iter = CLIP(1, 100000 / map_num_tiles(), 10);
3399 bool done = FALSE;
3400
3403 fc_assert(0 < i);
3404 if (i == 1) {
3406 } else {
3407 teams_num++;
3409 }
3412
3413 /* Take in account the 'startpos' setting. */
3417 }
3418
3419 switch (wld.map.server.startpos) {
3420 case MAPSTARTPOS_2or3:
3421 {
3422 bool maybe2 = (0 == player_count() % 2);
3423 bool maybe3 = (0 == player_count() % 3);
3424
3428 if (i > 1) {
3429 if (0 != i % 2) {
3430 maybe2 = FALSE;
3431 }
3432 if (0 != i % 3) {
3433 maybe3 = FALSE;
3434 }
3435 }
3437 }
3438
3439 if (maybe3) {
3441 } else if (maybe2) {
3443 }
3444 }
3445 break;
3446 case MAPSTARTPOS_ALL:
3450 if (i > 1) {
3451 if (players_per_island == 1) {
3453 } else if (i != players_per_island) {
3454 /* Every team doesn't have the same number of players. Cannot
3455 * consider this option. */
3458 break;
3459 }
3460 }
3462 }
3463 break;
3465 case MAPSTARTPOS_SINGLE:
3467 break;
3468 }
3469 if (players_per_island == 1) {
3471 }
3472
3473 whole_map_iterate(&(wld.map), ptile) {
3475 tile_set_continent(ptile, 0);
3476 BV_CLR_ALL(ptile->extras);
3477 tile_set_owner(ptile, nullptr, nullptr);
3478 ptile->extras_owner = nullptr;
3480
3481 i = 0;
3482 if (HAS_POLES) {
3483 make_polar();
3484
3485 whole_map_iterate(&(wld.map), ptile) {
3486 if (tile_terrain(ptile) != deepest_ocean) {
3487 i++;
3488 }
3490 }
3491
3494 } else {
3496 / (player_count() * 100));
3497 }
3501 }
3502 islandmass2 = (playermass * 2) / 10;
3505 }
3506 islandmass3 = playermass / 10;
3509 }
3510
3511 log_verbose("Creating a map with fair island generator");
3512 log_debug("max iterations=%d", iter);
3513 log_debug("players_per_island=%d", players_per_island);
3514 log_debug("team_placement=%s",
3516 log_debug("teams_num=%d, team_players_num=%d, single_players_num=%d",
3518 log_debug("playermass=%d, islandmass1=%d, islandmass2=%d, islandmass3=%d",
3520
3521 pmap = fair_map_new();
3522
3523 while (--iter >= 0) {
3524 done = TRUE;
3525
3526 whole_map_iterate(&(wld.map), ptile) {
3527 struct fair_tile *pftile = pmap + tile_index(ptile);
3528
3529 if (tile_terrain(ptile) != deepest_ocean) {
3530 pftile->flags |= (FTF_ASSIGNED | FTF_NO_HUT);
3531 adjc_iterate(&(wld.map), ptile, atile) {
3532 struct fair_tile *aftile = pmap + tile_index(atile);
3533
3534 if (!(aftile->flags & FTF_ASSIGNED)
3536 aftile->flags |= FTF_OCEAN;
3537 }
3539 }
3540 pftile->pterrain = tile_terrain(ptile);
3541 pftile->presource = tile_resource(ptile);
3542 pftile->extras = *tile_extras(ptile);
3544
3545 /* Create main player island. */
3546 log_debug("Making main island.");
3548
3549 log_debug("Place main islands on the map.");
3550 i = 0;
3551
3553 && team_players_num > 0) {
3554 /* Do team placement. */
3556 int start_x[teams_num], start_y[teams_num];
3557 int dx = 0, dy = 0;
3558 int j, k;
3559
3560 /* Build outwards_indices. */
3562 sizeof(outwards_indices));
3563 switch (wld.map.server.team_placement) {
3566 break;
3569 for (j = 0; j < MAP_NUM_ITERATE_OUTWARDS_INDICES; j++) {
3570 /* We want square distances for comparing. */
3571 outwards_indices[j].dist =
3573 outwards_indices[j].dy);
3574 }
3577 break;
3581 break;
3585 break;
3586 }
3587
3588 /* Make start point for teams. */
3591 }
3594 }
3595 for (j = 0; j < teams_num; j++) {
3596 start_x[j] = (MAP_NATIVE_WIDTH * (2 * j + 1)) / (2 * teams_num) + dx;
3597 start_y[j] = (MAP_NATIVE_HEIGHT * (2 * j + 1)) / (2 * teams_num) + dy;
3599 start_x[j] = FC_WRAP(start_x[j], MAP_NATIVE_WIDTH);
3600 }
3603 }
3604 }
3605 /* Randomize. */
3606 array_shuffle(start_x, teams_num);
3608
3609 j = 0;
3612 int team_id;
3613 int x, y;
3614
3615 if (members_count <= 1) {
3616 continue;
3617 }
3618 team_id = team_number(pteam);
3619
3620 NATIVE_TO_MAP_POS(&x, &y, start_x[j], start_y[j]);
3621 log_verbose("Team %d (%s) will start on (%d, %d)",
3622 team_id, team_rule_name(pteam), x, y);
3623
3624 for (k = 0; k < members_count; k += players_per_island) {
3626 outwards_indices, team_id)) {
3627 log_verbose("Failed to place island number %d for team %d (%s).",
3628 k, team_id, team_rule_name(pteam));
3629 done = FALSE;
3630 break;
3631 }
3632 }
3633 if (!done) {
3634 break;
3635 }
3636 i += k;
3637 j++;
3639
3640 fc_assert(!done || i == team_players_num);
3641 }
3642
3643 if (done) {
3644 /* Place last player islands. */
3645 for (; i < player_count(); i += players_per_island) {
3647 log_verbose("Failed to place island number %d.", i);
3648 done = FALSE;
3649 break;
3650 }
3651 }
3652 fc_assert(!done || i == player_count());
3653 }
3655
3656 if (done) {
3657 log_debug("Create and place small islands on the map.");
3658 for (i = 0; i < player_count(); i++) {
3661 log_verbose("Failed to place small island2 number %d.", i);
3662 done = FALSE;
3664 break;
3665 }
3667 }
3668 }
3669 if (done) {
3670 for (i = 0; i < player_count(); i++) {
3673 log_verbose("Failed to place small island3 number %d.", i);
3674 done = FALSE;
3676 break;
3677 }
3679 }
3680 }
3681
3682 if (done) {
3683 break;
3684 }
3685
3687 pmap = fair_map_new();
3688
3689 /* Decrease land mass, for better chances. */
3690 islandmass1 = (islandmass1 * 99) / 100;
3693 }
3694 islandmass2 = (islandmass2 * 99) / 100;
3697 }
3698 islandmass3 = (islandmass3 * 99) / 100;
3701 }
3702 }
3703
3704 if (!done) {
3705 log_verbose("Failed to create map after %d iterations.", iter);
3707 return FALSE;
3708 }
3709
3710 /* Finalize the map. */
3711 for (i = 0; i < MAP_INDEX_SIZE; i++) {
3712 /* Mark all tiles as assigned, for adding resources and huts. */
3713 pmap[i].flags |= FTF_ASSIGNED;
3714 }
3715 if (wld.map.server.riches > 0) {
3717 }
3718 if (wld.map.server.huts > 0) {
3720 }
3721
3722 /* Apply the map. */
3723 log_debug("Applying the map...");
3724 whole_map_iterate(&(wld.map), ptile) {
3725 struct fair_tile *pftile = pmap + tile_index(ptile);
3726
3727 fc_assert(pftile->pterrain != nullptr);
3728 tile_set_terrain(ptile, pftile->pterrain);
3729 ptile->extras = pftile->extras;
3730 tile_set_resource(ptile, pftile->presource);
3731 if (pftile->flags & FTF_STARTPOS) {
3732 struct startpos *psp = map_startpos_new(ptile);
3733
3734 if (pftile->startpos_team_id != -1) {
3736 (pftile->startpos_team_id)), pplayer) {
3737 startpos_allow(psp, nation_of_player(pplayer));
3739 } else {
3741 }
3742 }
3744
3747
3749
3750 log_verbose("Fair island map created with success!");
3751
3752 return TRUE;
3753}
#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:82
#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:2021
int map_num_tiles(void)
Definition map.c:1152
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1843
struct tile * rand_map_pos(const struct civ_map *nmap)
Definition map.c:1228
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:1242
int map_startpos_count(void)
Definition map.c:2008
bool is_cardinal_dir(enum direction8 dir)
Definition map.c:1457
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:1787
bool normalize_map_pos(const struct civ_map *nmap, int *x, int *y)
Definition map.c:1117
#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:430
static int index_to_map_pos_y(int mindex)
Definition map.h:752
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:388
#define cardinal_adjc_iterate_end
Definition map.h:456
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:425
#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:463
#define square_iterate_end
Definition map.h:391
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:452
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:398
static int index_to_map_pos_x(int mindex)
Definition map.h:743
#define whole_map_iterate(_map, _tile)
Definition map.h:573
static const bool C_CARDINAL
Definition map.h:38
#define cardinal_adjc_dir_base_iterate_end
Definition map.h:470
#define DIR_REVERSE(dir)
Definition map.h:589
#define current_wrap_has_flag(flag)
Definition map.h:46
#define cardinal_adjc_dir_base_iterate(nmap, center_tile, dir_itr)
Definition map.h:466
#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:459
#define whole_map_iterate_end
Definition map.h:582
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:229
#define circle_iterate_end
Definition map.h:401
#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:2675
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:2245
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:2705
static int jungle_pct
Definition mapgen.c:166
#define fair_do_iso_hex_symmetry2
Definition mapgen.c:2727
static void fair_map_make_resources(struct fair_tile *pmap)
Definition mapgen.c:2975
static bool make_island(int islemass, int starters, struct gen234_state *pstate, int min_specific_island_size)
Definition mapgen.c:2094
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:2553
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:2778
static int mountain_pct
Definition mapgen.c:165
#define map_pos_is_dry(ptile)
Definition mapgen.c:175
#define DMSIS
Definition mapgen.c:2240
void(* fair_geometry_func)(int *x, int *y)
Definition mapgen.c:2543
static void fair_do_iso_hex_symmetry1(int *x, int *y)
Definition mapgen.c:2722
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:2765
static void make_land(void)
Definition mapgen.c:1053
static void initworld(struct gen234_state *pstate)
Definition mapgen.c:2208
static struct fair_tile * fair_map_island_new(int size, int startpos_num)
Definition mapgen.c:3077
static void fair_map_destroy(struct fair_tile *pmap)
Definition mapgen.c:2561
static bool fair_map_tile_border(struct fair_tile *pmap, struct fair_tile *ptile, int dist)
Definition mapgen.c:2624
static void mapgenerator4(void)
Definition mapgen.c:2440
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:2713
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:1652
#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:2569
static void adjust_terrain_param(void)
Definition mapgen.c:1492
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:1620
#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:1849
static void river_blockmark(struct river_map *privermap, struct tile *ptile)
Definition mapgen.c:672
static void make_huts(int number)
Definition mapgen.c:1535
static bool test_wetness(const struct tile *ptile, wetness_c c)
Definition mapgen.c:204
static void island_terrain_free(void)
Definition mapgen.c:2074
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:2509
static bool near_safe_tiles(struct tile *ptile)
Definition mapgen.c:1520
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:2689
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:1832
static int fair_team_placement_horizontal(const void *a, const void *b)
Definition mapgen.c:2661
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:1601
static bool is_resource_close(const struct tile *ptile)
Definition mapgen.c:1563
static void add_resources(int prob)
Definition mapgen.c:1577
static void mapgenerator3(void)
Definition mapgen.c:2343
static void fair_do_rotation(int *x, int *y)
Definition mapgen.c:2732
static bool fair_map_place_island_rand(struct fair_tile *ptarget, struct fair_tile *psource)
Definition mapgen.c:2910
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:1776
static void fair_map_make_huts(struct fair_tile *pmap)
Definition mapgen.c:3025
static int fair_team_placement_closest(const void *a, const void *b)
Definition mapgen.c:2651
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:2013
static bool island_river_mouth_suitability(const struct tile *ptile, const struct extra_type *priver)
Definition mapgen.c:1731
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:3389
static void fair_do_iso_hex_rotation(int *x, int *y)
Definition mapgen.c:2754
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:1939
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:1752
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:2945
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:2831
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:2743
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:1923
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:2697
static struct fair_tile * fair_map_pos_tile(struct fair_tile *pmap, int x, int y)
Definition mapgen.c:2579
static void tersel_free(struct terrain_select *ptersel)
Definition mapgen.c:1642
static long int checkmass
Definition mapgen.c:1844
static struct fair_tile * fair_map_tile_step(struct fair_tile *pmap, struct fair_tile *ptile, enum direction8 dir)
Definition mapgen.c:2608
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:2525
@ FTF_NONE
Definition mapgen.c:2526
@ FTF_NO_RESOURCE
Definition mapgen.c:2530
@ FTF_HAS_HUT
Definition mapgen.c:2531
@ FTF_ASSIGNED
Definition mapgen.c:2527
@ FTF_OCEAN
Definition mapgen.c:2528
@ FTF_STARTPOS
Definition mapgen.c:2529
@ FTF_NO_HUT
Definition mapgen.c:2532
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:2545
bv_extras extras
Definition mapgen.c:2539
struct terrain * pterrain
Definition mapgen.c:2537
enum fair_tile_flag flags
Definition mapgen.c:2536
int startpos_team_id
Definition mapgen.c:2540
struct extra_type * presource
Definition mapgen.c:2538
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:146
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:118
int count_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, bool cardinal_only, bool percentage, enum terrain_class tclass)
Definition terrain.c:633
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:591
Terrain_type_id terrain_index(const struct terrain *pterrain)
Definition terrain.c:138
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
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:369
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:348
#define terrain_type_iterate(_p)
Definition terrain.h:266
#define T_UNKNOWN
Definition terrain.h:62
#define is_ocean(pterrain)
Definition terrain.h:194
#define is_ocean_tile(ptile)
Definition terrain.h:196
#define TERRAIN_OCEAN_DEPTH_MINIMUM
Definition terrain.h:147
#define terrain_type_iterate_end
Definition terrain.h:272
#define TERRAIN_OCEAN_DEPTH_MAXIMUM
Definition terrain.h:148
#define terrain_has_flag(terr, flag)
Definition terrain.h:176
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:111
#define TILE_XY(ptile)
Definition tile.h:43
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:121
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
#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