Freeciv-3.3: /fast/freeciv/nightly/main/server/generator/mapgen.c Source File

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 */
57 struct gen234_state {
58 int isleindex, n, e, s, w;
59 long int totalmass;
60};
61
62/* Define one terrain selection */
63 struct terrain_select {
64 int weight;
65 enum mapgen_terrain_property target;
66 enum mapgen_terrain_property prefer;
67 enum mapgen_terrain_property avoid;
68 int temp_condition;
69 int wet_condition;
70};
71
72
73 static struct extra_type *river_types[MAX_EXTRA_TYPES];
74 static 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,
85 enum mapgen_terrain_property target,
86 enum mapgen_terrain_property prefer,
87 enum mapgen_terrain_property avoid,
88 int temp_condition,
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;
95 struct terrain_select_list *forest;
96 struct terrain_select_list *desert;
97 struct terrain_select_list *mountain;
98 struct terrain_select_list *swamp;
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,
109 int min_specific_island_size);
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. */
115 struct 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);
129static int river_test_adjacent_ocean(struct river_map *privermap,
130 struct tile *ptile,
131 struct extra_type *priver);
132static int river_test_adjacent_river(struct river_map *privermap,
133 struct tile *ptile,
134 struct extra_type *priver);
135static int river_test_adjacent_highlands(struct river_map *privermap,
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);
141static int river_test_adjacent_swamp(struct river_map *privermap,
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 */
162 static int forest_pct = 0;
163 static int desert_pct = 0;
164 static int swamp_pct = 0;
165 static int mountain_pct = 0;
166 static int jungle_pct = 0;
167 static 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)
180 typedef enum { WC_ALL = 200, WC_DRY, WC_NDRY } wetness_c;
181
182/* MISCELANEOUS (OTHER CONDITIONS) */
183
184/* Necessary condition of swamp placement */
185 static 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
195 typedef enum { MC_NONE, MC_LOW, MC_NLOW } miscellaneous_c;
196
197/**************************************************************************
198 These functions test for conditions used in rand_map_pos_characteristic()
199**************************************************************************/
200
201/**********************************************************************/
204 static 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/**********************************************************************/
222 static 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**************************************************************************/
240 struct DataFilter {
241 wetness_c wc;
242 temperature_type tc;
243 miscellaneous_c mc;
244};
245
246/**********************************************************************/
250 static 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/**********************************************************************/
265 static struct tile *rand_map_pos_characteristic(wetness_c wc,
266 temperature_type tc,
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/**********************************************************************/
280 static bool terrain_is_too_high(struct tile *ptile,
281 int thill, int my_height)
282{
283 square_iterate(&(wld.map), ptile, 1, tile1) {
284 if (hmap(tile1) + (hmap_max_level - hmap_mountain_level) / 5 < thill) {
285 return FALSE;
286 }
287 } square_iterate_end;
288
289 return TRUE;
290}
291
292/**********************************************************************/
298 static 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. */
302 hmap_mountain_level = (((hmap_max_level - hmap_shore_level)
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
310 || !terrain_is_too_high(ptile, hmap_mountain_level,
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,
316 pick_terrain(MG_MOUNTAINOUS, fc_rand(10) < 4
317 ? MG_UNUSED : MG_GREEN, MG_UNUSED));
318 } else {
319 /* Prefer mountains hills to in cold regions. */
320 tile_set_terrain(ptile,
321 pick_terrain(MG_MOUNTAINOUS, MG_UNUSED,
322 fc_rand(10) < 8 ? MG_GREEN : MG_UNUSED));
323 }
324 map_set_placed(ptile);
325 }
326 } whole_map_iterate_end;
327}
328
329/**********************************************************************/
335 static void make_polar(void)
336{
337 struct terrain *ocean = pick_ocean(TERRAIN_OCEAN_DEPTH_MAXIMUM, TRUE);
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)
343 && is_temperature_type_near(ptile, TT_FROZEN))) {
344 if (ocean) {
345 tile_set_terrain(ptile, ocean);
346 } else {
347 tile_set_terrain(ptile,
348 pick_terrain(MG_FROZEN, MG_UNUSED, MG_TROPICAL));
349 }
350 }
351 } whole_map_iterate_end;
352}
353
354/**********************************************************************/
357 static bool ok_for_separate_poles(struct tile *ptile)
358{
359 if (!wld.map.server.separatepoles) {
360 return TRUE;
361 }
362 adjc_iterate(&(wld.map), ptile, tile1) {
363 if (tile_continent(tile1) > 0) {
364 return FALSE;
365 }
366 } adjc_iterate_end;
367
368 return TRUE;
369}
370
371/**********************************************************************/
376 static void make_polar_land(void)
377{
378 assign_continent_numbers();
379
380 whole_map_iterate(&(wld.map), ptile) {
381 if ((tile_terrain(ptile) == T_UNKNOWN
382 || !terrain_has_flag(tile_terrain(ptile), TER_FROZEN))
383 && ((tmap_is(ptile, TT_FROZEN)
384 && ok_for_separate_poles(ptile))
385 || (tmap_is(ptile, TT_COLD)
386 && fc_rand(10) > 7
387 && is_temperature_type_near(ptile, TT_FROZEN)
388 && ok_for_separate_poles(ptile)))) {
389 tile_set_terrain(ptile, T_UNKNOWN);
390 tile_set_continent(ptile, 0);
391 }
392 } whole_map_iterate_end;
393}
394
395/**********************************************************************/
398 static void place_terrain(struct tile *ptile, int diff,
399 struct terrain *pterrain, int *to_be_placed,
400 wetness_c wc,
401 temperature_type tc,
402 miscellaneous_c mc)
403{
404 if (*to_be_placed <= 0) {
405 return;
406 }
407 fc_assert_ret(not_placed(ptile));
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. */
414 int Delta = (abs(map_colatitude(tile1) - map_colatitude(ptile))
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)
421 && test_miscellaneous(tile1, mc)
422 && Delta < diff
423 && fc_rand(10) > 4) {
424 place_terrain(tile1, diff - 1 - Delta, pterrain,
425 to_be_placed, wc, tc, mc);
426 }
427 } cardinal_adjc_iterate_end;
428}
429
430/**********************************************************************/
434 static 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,
439 pick_terrain(MG_FROZEN, MG_UNUSED, MG_MOUNTAINOUS));
440 } else if (tmap_is(ptile, TT_COLD)) {
441 tile_set_terrain(ptile,
442 pick_terrain(MG_COLD, MG_UNUSED, MG_MOUNTAINOUS));
443 } else {
444 tile_set_terrain(ptile,
445 pick_terrain(MG_TEMPERATE, MG_GREEN, MG_MOUNTAINOUS));
446 }
447 map_set_placed(ptile);
448 (*to_be_placed)--;
449}
450
451/**********************************************************************/
455 static 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 }
464 } whole_map_iterate_end;
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/**********************************************************************/
491 static 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 }
505 } whole_map_iterate_end;
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 */
514 plains_count = total - forests_count - deserts_count
515 - swamps_count - jungles_count;
516
517 /* The placement loop */
518 do {
519
520 PLACE_ONE_TYPE(forests_count , plains_count,
521 pick_terrain(MG_FOLIAGE, MG_TEMPERATE, MG_TROPICAL),
522 WC_ALL, TT_NFROZEN, MC_NONE, 60);
523 PLACE_ONE_TYPE(jungles_count, forests_count,
524 pick_terrain(MG_FOLIAGE, MG_TROPICAL, MG_COLD),
525 WC_ALL, TT_TROPICAL, MC_NONE, 50);
526 PLACE_ONE_TYPE(swamps_count, forests_count,
527 pick_terrain(MG_WET, MG_UNUSED, MG_FOLIAGE),
528 WC_NDRY, TT_HOT, MC_LOW, 50);
529 PLACE_ONE_TYPE(deserts_count, alt_deserts_count,
530 pick_terrain(MG_DRY, MG_TROPICAL, MG_COLD),
531 WC_DRY, TT_NFROZEN, MC_NLOW, 80);
532 PLACE_ONE_TYPE(alt_deserts_count, plains_count,
533 pick_terrain(MG_DRY, MG_TROPICAL, MG_WET),
534 WC_ALL, TT_NFROZEN, MC_NLOW, 40);
535
536 /* Make the plains and tundras */
537 if (plains_count > 0) {
538 struct tile *ptile;
539
540 /* Don't use any restriction here ! */
541 if ((ptile = rand_map_pos_characteristic(WC_ALL, TT_ALL, MC_NONE))) {
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/**********************************************************************/
557 static int river_test_blocked(struct river_map *privermap,
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 }
570 } cardinal_adjc_iterate_end;
571
572 return 1; /* None non-blocked |- all blocked */
573}
574
575/**********************************************************************/
578 static int river_test_rivergrid(struct river_map *privermap,
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/**********************************************************************/
589 static int river_test_highlands(struct river_map *privermap,
590 struct tile *ptile,
591 struct extra_type *priver)
592{
593 return tile_terrain(ptile)->property[MG_MOUNTAINOUS];
594}
595
596/**********************************************************************/
599 static int river_test_adjacent_ocean(struct river_map *privermap,
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/**********************************************************************/
610 static int river_test_adjacent_river(struct river_map *privermap,
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/**********************************************************************/
620 static int river_test_adjacent_highlands(struct river_map *privermap,
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];
628 } adjc_iterate_end;
629
630 return sum;
631}
632
633/**********************************************************************/
636 static int river_test_swamp(struct river_map *privermap,
637 struct tile *ptile,
638 struct extra_type *priver)
639{
640 return FC_INFINITY - tile_terrain(ptile)->property[MG_WET];
641}
642
643/**********************************************************************/
646 static int river_test_adjacent_swamp(struct river_map *privermap,
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];
654 } adjc_iterate_end;
655
656 return FC_INFINITY - sum;
657}
658
659/**********************************************************************/
662 static int river_test_height_map(struct river_map *privermap,
663 struct tile *ptile,
664 struct extra_type *priver)
665{
666 return hmap(ptile);
667}
668
669/**********************************************************************/
672 static void river_blockmark(struct river_map *privermap,
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));
681 } cardinal_adjc_iterate_end;
682}
683
684 struct 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
690 static struct test_func test_funcs[NUM_TEST_FUNCTIONS] = {
691 {river_test_blocked, TRUE},
692 {river_test_rivergrid, TRUE},
693 {river_test_highlands, FALSE},
694 {river_test_adjacent_ocean, FALSE},
695 {river_test_adjacent_river, FALSE},
696 {river_test_adjacent_highlands, FALSE},
697 {river_test_swamp, FALSE},
698 {river_test_adjacent_swamp, FALSE},
699 {river_test_height_map, FALSE}
700};
701
702/**********************************************************************/
792 static 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
813 || count_terrain_class_near_tile(&(wld.map), ptile,
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. */
827 memset(rd_direction_is_valid, 0, sizeof(rd_direction_is_valid));
828 cardinal_adjc_dir_base_iterate(&(wld.map), ptile, dir) {
829 rd_direction_is_valid[dir] = TRUE;
830 } cardinal_adjc_dir_base_iterate_end;
831
832 /* Test series that selects a direction for the river. */
833 for (func_num = 0; func_num < NUM_TEST_FUNCTIONS; func_num++) {
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]) {
839 rd_comparison_val[dir] = (test_funcs[func_num].func)(privermap,
840 ptile1, priver);
841 fc_assert_action(rd_comparison_val[dir] >= 0, continue);
842 if (best_val == -1) {
843 best_val = rd_comparison_val[dir];
844 } else {
845 best_val = MIN(rd_comparison_val[dir], best_val);
846 }
847 }
848 } cardinal_adjc_dir_iterate_end;
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) {
860 rd_direction_is_valid[dir] = FALSE;
861 }
862 }
863 } cardinal_adjc_dir_base_iterate_end;
864 }
865
866 /* Directions evaluated with all functions. Now choose the best
867 direction before going to the next iteration of the while loop */
868 num_valid_directions = 0;
869 cardinal_adjc_dir_base_iterate(&(wld.map), ptile, dir) {
870 if (rd_direction_is_valid[dir]) {
871 num_valid_directions++;
872 }
873 } cardinal_adjc_dir_base_iterate_end;
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 {
891 river_blockmark(privermap, ptile);
892 ptile = tile1;
893 break;
894 }
895 }
896 } cardinal_adjc_dir_iterate_end;
897 fc_assert_ret_val(direction == 0, FALSE);
898
899 } /* end while; (Make a river.) */
900}
901
902/**********************************************************************/
906 static 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. */
915 int desirable_riverlength =
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. */
920 wld.map.server.landpercent /
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() */
940 set_all_ocean_tiles_placed();
941
942 dbv_init(&rivermap.blocked, MAP_INDEX_SIZE);
943 dbv_init(&rivermap.ok, MAP_INDEX_SIZE);
944
945 /* The main loop in this function. */
946 while (current_riverlength < desirable_riverlength
947 && iteration_counter < RIVERS_MAXTRIES) {
948
949 if ((ptile = rand_map_pos_characteristic(WC_ALL, TT_NFROZEN,
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)
967 + count_terrain_class_near_tile(&(wld.map), ptile,
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. */
973 && (count_terrain_property_near_tile(&(wld.map), ptile, TRUE, TRUE,
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);
994 dbv_clr_all(&rivermap.ok);
995
996 road_river = river_types[fc_rand(river_type_count)];
997
998 extra_type_by_cause_iterate(EC_ROAD, oriver) {
999 if (oriver != road_river) {
1000 whole_map_iterate(&(wld.map), rtile) {
1001 if (tile_has_extra(rtile, oriver)) {
1002 dbv_set(&rivermap.blocked, tile_index(rtile));
1003 }
1004 } whole_map_iterate_end;
1005 }
1006 } extra_type_by_cause_iterate_end;
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)) {
1013 whole_map_iterate(&(wld.map), ptile1) {
1014 if (dbv_isset(&rivermap.ok, tile_index(ptile1))) {
1015 struct terrain *river_terrain = tile_terrain(ptile1);
1016
1017 if (!terrain_has_flag(river_terrain, TER_CAN_HAVE_RIVER)) {
1018 /* We have to change the terrain to put a river here. */
1019 river_terrain = pick_terrain_by_flag(TER_CAN_HAVE_RIVER);
1020 if (river_terrain != nullptr) {
1021 tile_set_terrain(ptile1, river_terrain);
1022 }
1023 }
1024
1025 tile_add_extra(ptile1, road_river);
1026 current_riverlength++;
1027 map_set_placed(ptile1);
1028 log_debug("Applied a river to (%d, %d).", TILE_XY(ptile1));
1029 }
1030 } whole_map_iterate_end;
1031 } else {
1032 log_debug("mapgen.c: A river failed. It might have gotten stuck "
1033 "in a helix.");
1034 }
1035 } /* end if; */
1036 iteration_counter++;
1037 log_debug("current_riverlength: %d; desirable_riverlength: %d; "
1038 "iteration_counter: %d",
1039 current_riverlength, desirable_riverlength, iteration_counter);
1040 } /* end while; */
1041
1042 dbv_free(&rivermap.blocked);
1043 dbv_free(&rivermap.ok);
1044
1045 destroy_placed_map();
1046}
1047
1048/**********************************************************************/
1053 static void make_land(void)
1054{
1055 struct terrain *land_fill = nullptr;
1056
1057 if (HAS_POLES) {
1058 normalize_hmap_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 }
1069 } terrain_type_iterate_end;
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
1080 hmap_shore_level = (hmap_max_level * (100 - wld.map.server.landpercent)) / 100;
1081 ini_hmap_low_level();
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 }
1097 } adjc_iterate_end;
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
1112 && is_temperature_type_near(ptile, TT_FROZEN)));
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'. */
1123 tile_set_terrain(ptile, land_fill);
1124 }
1125 } whole_map_iterate_end;
1126
1127 if (HAS_POLES) {
1128 renormalize_hmap_poles();
1129 }
1130
1131 /* Destroy old dummy temperature map ... */
1132 destroy_tmap();
1133 /* ... and create a real temperature map (needs hmap and oceans) */
1134 create_tmap(TRUE);
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 */
1141 set_all_ocean_tiles_placed();
1142 if (MAPGEN_FRACTURE == wld.map.server.generator) {
1143 make_fracture_relief();
1144 } else {
1145 make_relief(); /* Base relief on map */
1146 }
1147 make_terrains(); /* Place all exept mountains and hill */
1148 destroy_placed_map();
1149
1150 make_rivers(); /* Use a new placed_map. Destroy older before call */
1151}
1152
1153/**********************************************************************/
1156 static 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 }
1172 } adjc_iterate_end;
1173
1174 return TRUE;
1175}
1176
1177/**********************************************************************/
1182 static void remove_tiny_islands(void)
1183{
1184 whole_map_iterate(&(wld.map), ptile) {
1185 if (is_tiny_island(ptile)) {
1186 struct terrain *shallow
1187 = most_shallow_ocean(terrain_has_flag(tile_terrain(ptile), TER_FROZEN));
1188
1189 fc_assert_ret(shallow != nullptr);
1190
1191 tile_set_terrain(ptile, shallow);
1192 extra_type_by_cause_iterate(EC_ROAD, priver) {
1193 if (tile_has_extra(ptile, priver)
1194 && road_has_flag(extra_road_get(priver), RF_RIVER)) {
1195 tile_extra_rm_apply(ptile, priver);
1196 }
1197 } extra_type_by_cause_iterate_end;
1198 tile_set_continent(ptile, 0);
1199 }
1200 } whole_map_iterate_end;
1201}
1202
1203/**********************************************************************/
1207 static void print_mapgen_map(void)
1208{
1209 int terrain_counts[terrain_count()];
1210 int total = 0, ocean = 0;
1211
1212 terrain_type_iterate(pterrain) {
1213 terrain_counts[terrain_index(pterrain)] = 0;
1214 } terrain_type_iterate_end;
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++;
1224 } whole_map_iterate_end;
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 }
1252 } terrain_type_iterate_end;
1253}
1254
1255/**********************************************************************/
1268 bool map_fractal_generate(bool autosize, struct unit_type *initial_unit)
1269{
1270 /* Save the current random state: */
1271 RANDOM_STATE rstate;
1272 RANDOM_TYPE seed_rand;
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. */
1277 seed_rand = fc_rand(MAX_UINT32);
1278
1279 if (wld.map.server.seed_setting == 0) {
1280 /* Create a "random" map seed. */
1281 wld.map.server.seed = seed_rand & (MAX_UINT32 >> 1);
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 {
1289 wld.map.server.seed = wld.map.server.seed_setting;
1290 }
1291
1292 rstate = fc_rand_state();
1293
1294 fc_srand(wld.map.server.seed);
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 */
1299 if (wld.map.server.generator != MAPGEN_SCENARIO) {
1300 wld.map.server.have_huts = FALSE;
1301 river_types_init();
1302
1303 generator_init_topology(autosize);
1304 /* Map can be already allocated, if we failed first map generation */
1305 if (map_is_empty()) {
1306 main_map_allocate();
1307 }
1308 adjust_terrain_param();
1309 /* If one mapgenerator fails, it will choose another mapgenerator */
1310 /* with a lower number to try again */
1311
1312 /* Create a temperature map */
1313 create_tmap(FALSE);
1314
1315 if (MAPGEN_FAIR == wld.map.server.generator
1316 && !map_generate_fair_islands()) {
1317 wld.map.server.generator = MAPGEN_ISLAND;
1318 }
1319
1320 if (MAPGEN_ISLAND == wld.map.server.generator) {
1321 /* Initialise terrain selection lists used by make_island() */
1322 island_terrain_init();
1323
1324 /* 2 or 3 players per isle? */
1325 if (MAPSTARTPOS_2or3 == wld.map.server.startpos
1326 || MAPSTARTPOS_ALL == wld.map.server.startpos) {
1327 mapgenerator4();
1328 }
1329 if (MAPSTARTPOS_DEFAULT == wld.map.server.startpos
1330 || MAPSTARTPOS_SINGLE == wld.map.server.startpos) {
1331 /* Single player per isle. */
1332 mapgenerator3();
1333 }
1334 if (MAPSTARTPOS_VARIABLE == wld.map.server.startpos) {
1335 /* "Variable" single player. */
1336 mapgenerator2();
1337 }
1338
1339 /* Free terrain selection lists used by make_island() */
1340 island_terrain_free();
1341 }
1342
1343 if (MAPGEN_FRACTAL == wld.map.server.generator) {
1344 make_pseudofractal1_hmap(1 +
1345 ((MAPSTARTPOS_DEFAULT == wld.map.server.startpos
1346 || MAPSTARTPOS_ALL == wld.map.server.startpos)
1347 ? 0 : player_count()));
1348 }
1349
1350 if (MAPGEN_RANDOM == wld.map.server.generator) {
1351 make_random_hmap(MAX(1, 1 + get_sqsize()
1352 - (MAPSTARTPOS_DEFAULT != wld.map.server.startpos
1353 ? player_count() / 4 : 0)));
1354 }
1355
1356 if (MAPGEN_FRACTURE == wld.map.server.generator) {
1357 make_fracture_map();
1358 }
1359
1360 /* If hmap only generator make anything else */
1361 if (MAPGEN_RANDOM == wld.map.server.generator
1362 || MAPGEN_FRACTAL == wld.map.server.generator
1363 || MAPGEN_FRACTURE == wld.map.server.generator) {
1364
1365 height_map_to_map();
1366 make_land();
1367 free(height_map);
1368 height_map = nullptr;
1369 }
1370 if (!wld.map.server.tinyisles) {
1371 remove_tiny_islands();
1372 }
1373
1374 smooth_water_depth();
1375
1376 /* Continent numbers must be assigned before regenerate_lakes() */
1377 assign_continent_numbers();
1378
1379 /* Turn small oceans into lakes. */
1380 if (wld.map.num_oceans > 0) {
1381 regenerate_lakes();
1382 }
1383
1384 } else {
1385 assign_continent_numbers();
1386 }
1387
1388 /* Create a temperature map if it was not done before */
1389 if (!temperature_is_initialized()) {
1390 create_tmap(FALSE);
1391 }
1392
1393 /* Some scenarios already provide specials */
1394 if (!wld.map.server.have_resources) {
1395 add_resources(wld.map.server.riches);
1396 }
1397
1398 if (!wld.map.server.have_huts) {
1399 make_huts(wld.map.server.huts * map_num_tiles() / 1000);
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:
1412 fc_assert_msg(FALSE,
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:
1422 if (wld.map.server.startpos == MAPSTARTPOS_DEFAULT) {
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) {
1431 case MAPSTARTPOS_DEFAULT:
1432 case MAPSTARTPOS_VARIABLE:
1433 log_verbose("Map generator chose startpos=SINGLE");
1434
1435 fc__fallthrough;
1436 case MAPSTARTPOS_SINGLE:
1437 mode = MAPSTARTPOS_SINGLE;
1438 break;
1439 default:
1440 log_verbose("Map generator chose startpos=2or3");
1441
1442 fc__fallthrough;
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
1483 print_mapgen_map();
1484
1485 return TRUE;
1486}
1487
1488/**********************************************************************/
1492 static void adjust_terrain_param(void)
1493{
1494 int polar = 2 * ICE_BASE_LEVEL * wld.map.server.landpercent / MAX_COLATITUDE;
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
1498 mountain_pct = mount_factor * wld.map.server.steepness * 90;
1499
1500 /* 27 % if wetness == 50 & */
1501 forest_pct = factor * (wld.map.server.wetness * 40 + 700);
1502 jungle_pct = forest_pct * (MAX_COLATITUDE - TROPICAL_LEVEL)
1503 / (MAX_COLATITUDE * 2);
1504 forest_pct -= jungle_pct;
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/**********************************************************************/
1520 static bool near_safe_tiles(struct tile *ptile)
1521{
1522 square_iterate(&(wld.map), ptile, 1, tile1) {
1523 if (!terrain_has_flag(tile_terrain(tile1), TER_UNSAFE_COAST)) {
1524 return TRUE;
1525 }
1526 } square_iterate_end;
1527
1528 return FALSE;
1529}
1530
1531/**********************************************************************/
1535 static 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. */
1545 if ((ptile = rand_map_pos_characteristic(WC_ALL, TT_ALL, MC_NONE))) {
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
1556 destroy_placed_map();
1557}
1558
1559/**********************************************************************/
1563 static 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 }
1569 } square_iterate_end;
1570
1571 return FALSE;
1572}
1573
1574/**********************************************************************/
1577 static 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)
1586 || wld.map.server.ocean_resources) {
1587 struct extra_type *res = pick_resource(pterrain);
1588
1589 if (res != nullptr) {
1590 tile_set_resource(ptile, res);
1591 }
1592 }
1593 } whole_map_iterate_end;
1594
1595 wld.map.server.have_resources = TRUE;
1596}
1597
1598/**********************************************************************/
1601 static struct tile *get_random_map_position_from_state(
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/**********************************************************************/
1620 static struct terrain_select *tersel_new(int weight,
1621 enum mapgen_terrain_property target,
1622 enum mapgen_terrain_property prefer,
1623 enum mapgen_terrain_property avoid,
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/**********************************************************************/
1642 static void tersel_free(struct terrain_select *ptersel)
1643{
1644 if (ptersel != nullptr) {
1645 FC_FREE(ptersel);
1646 }
1647}
1648
1649/**********************************************************************/
1652 static 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;
1657 int ntersel = terrain_select_list_size(tersel_list);
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
1678 terrain_select_list_iterate(tersel_list, ptersel) {
1679 total_weight += ptersel->weight;
1680 } terrain_select_list_iterate_end;
1681
1682 if (total_weight <= 0) {
1683 return;
1684 }
1685
1686 while (i > 0 && (failsafe--) > 0) {
1687 struct tile *ptile = get_random_map_position_from_state(pstate);
1688
1689 if (tile_continent(ptile) != pstate->isleindex || !not_placed(ptile)) {
1690 continue;
1691 }
1692
1693 struct terrain_select *ptersel
1694 = terrain_select_list_get(tersel_list, fc_rand(ntersel));
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))
1713 && (!is_terrain_class_card_near(&(wld.map), ptile, TC_OCEAN)
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/**********************************************************************/
1731 static bool island_river_mouth_suitability(const struct tile *ptile,
1732 const struct extra_type *priver)
1733{
1734 int num_card_ocean, pct_adj_ocean, num_adj_river;
1735
1736 num_card_ocean = count_terrain_class_near_tile(&(wld.map), ptile,
1737 C_CARDINAL, C_NUMBER,
1738 TC_OCEAN);
1739 pct_adj_ocean = count_terrain_class_near_tile(&(wld.map), ptile,
1740 C_ADJACENT, C_PERCENT,
1741 TC_OCEAN);
1742 num_adj_river = count_river_type_tile_card(&(wld.map), ptile, priver, FALSE);
1743
1744 return (num_card_ocean == 1 && pct_adj_ocean <= 35
1745 && num_adj_river == 0);
1746}
1747
1748/**********************************************************************/
1752 static bool island_river_suitability(const struct tile *ptile,
1753 const struct extra_type *priver)
1754{
1755 int pct_adj_ocean, num_card_ocean, pct_adj_river, num_card_river;
1756
1757 num_card_river = count_river_type_tile_card(&(wld.map), ptile, priver, FALSE);
1758 num_card_ocean = count_terrain_class_near_tile(&(wld.map), ptile,
1759 C_CARDINAL, C_NUMBER,
1760 TC_OCEAN);
1761 pct_adj_ocean = count_terrain_class_near_tile(&(wld.map), ptile,
1762 C_ADJACENT, C_PERCENT,
1763 TC_OCEAN);
1764 pct_adj_river = count_river_type_near_tile(&(wld.map), ptile, priver, TRUE);
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/**********************************************************************/
1776 static 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
1806 ptile = get_random_map_position_from_state(pstate);
1807 if (tile_continent(ptile) != pstate->isleindex
1808 || tile_has_river(ptile)) {
1809 continue;
1810 }
1811
1812 priver = river_types[fc_rand(river_type_count)];
1813
1814 if (test_wetness(ptile, WC_DRY) && fc_rand(100) < 50) {
1815 /* Rivers don't like dry locations */
1816 continue;
1817 }
1818
1819 if ((island_river_mouth_suitability(ptile, priver)
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/**********************************************************************/
1832 static 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 }
1839 } adjc_iterate_end;
1840
1841 return FALSE;
1842}
1843
1844 static long int checkmass;
1845
1846/**********************************************************************/
1849 static bool place_island(struct gen234_state *pstate)
1850{
1851 int i = 0, xcur, ycur, nat_x, nat_y;
1852 struct tile *ptile;
1853
1854 ptile = rand_map_pos(&(wld.map));
1855 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
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
1903 tile_set_terrain(tile1, T_UNKNOWN);
1904 map_unset_placed(tile1);
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/**********************************************************************/
1923 static 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 }
1931 } cardinal_adjc_iterate_end;
1932
1933 return count;
1934}
1935
1936/**********************************************************************/
1939 static bool create_island(int islemass, struct gen234_state *pstate)
1940{
1941 int i, nat_x, nat_y;
1942 long int tries = islemass * (2 + islemass / 20) + 99;
1943 bool j;
1944 struct tile *ptile
1945 = native_pos_to_tile(&(wld.map),
1946 MAP_NATIVE_WIDTH / 2, MAP_NATIVE_HEIGHT / 2);
1947
1948 memset(height_map, '\0', MAP_INDEX_SIZE * sizeof(*height_map));
1949 hmap(native_pos_to_tile(&(wld.map),
1950 MAP_NATIVE_WIDTH / 2, MAP_NATIVE_HEIGHT / 2)) = 1;
1951
1952 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
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) {
1960 ptile = get_random_map_position_from_state(pstate);
1961 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
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/**********************************************************************/
2013 static void island_terrain_init(void)
2014{
2015 struct terrain_select *ptersel;
2016
2017 /* Forest */
2018 island_terrain.forest = terrain_select_list_new_full(tersel_free);
2019 ptersel = tersel_new(1, MG_FOLIAGE, MG_TROPICAL, MG_DRY,
2020 TT_TROPICAL, WC_ALL);
2021 terrain_select_list_append(island_terrain.forest, ptersel);
2022 ptersel = tersel_new(3, MG_FOLIAGE, MG_TEMPERATE, MG_UNUSED,
2023 TT_ALL, WC_ALL);
2024 terrain_select_list_append(island_terrain.forest, ptersel);
2025 ptersel = tersel_new(1, MG_FOLIAGE, MG_WET, MG_FROZEN,
2026 TT_TROPICAL, WC_NDRY);
2027 terrain_select_list_append(island_terrain.forest, ptersel);
2028 ptersel = tersel_new(1, MG_FOLIAGE, MG_COLD, MG_UNUSED,
2029 TT_NFROZEN, WC_ALL);
2030 terrain_select_list_append(island_terrain.forest, ptersel);
2031
2032 /* Desert */
2033 island_terrain.desert = terrain_select_list_new_full(tersel_free);
2034 ptersel = tersel_new(3, MG_DRY, MG_TROPICAL, MG_GREEN,
2035 TT_HOT, WC_DRY);
2036 terrain_select_list_append(island_terrain.desert, ptersel);
2037 ptersel = tersel_new(2, MG_DRY, MG_TEMPERATE, MG_GREEN,
2038 TT_NFROZEN, WC_DRY);
2039 terrain_select_list_append(island_terrain.desert, ptersel);
2040 ptersel = tersel_new(1, MG_COLD, MG_DRY, MG_TROPICAL,
2041 TT_NHOT, WC_DRY);
2042 terrain_select_list_append(island_terrain.desert, ptersel);
2043 ptersel = tersel_new(1, MG_FROZEN, MG_DRY, MG_UNUSED,
2044 TT_FROZEN, WC_DRY);
2045 terrain_select_list_append(island_terrain.desert, ptersel);
2046
2047 /* Mountain */
2048 island_terrain.mountain = terrain_select_list_new_full(tersel_free);
2049 ptersel = tersel_new(2, MG_MOUNTAINOUS, MG_GREEN, MG_UNUSED,
2050 TT_ALL, WC_ALL);
2051 terrain_select_list_append(island_terrain.mountain, ptersel);
2052 ptersel = tersel_new(1, MG_MOUNTAINOUS, MG_UNUSED, MG_GREEN,
2053 TT_ALL, WC_ALL);
2054 terrain_select_list_append(island_terrain.mountain, ptersel);
2055
2056 /* Swamp */
2057 island_terrain.swamp = terrain_select_list_new_full(tersel_free);
2058 ptersel = tersel_new(1, MG_WET, MG_TROPICAL, MG_FOLIAGE,
2059 TT_TROPICAL, WC_NDRY);
2060 terrain_select_list_append(island_terrain.swamp, ptersel);
2061 ptersel = tersel_new(2, MG_WET, MG_TEMPERATE, MG_FOLIAGE,
2062 TT_HOT, WC_NDRY);
2063 terrain_select_list_append(island_terrain.swamp, ptersel);
2064 ptersel = tersel_new(1, MG_WET, MG_COLD, MG_FOLIAGE,
2065 TT_NHOT, WC_NDRY);
2066 terrain_select_list_append(island_terrain.swamp, ptersel);
2067
2068 island_terrain.init = TRUE;
2069}
2070
2071/**********************************************************************/
2074 static void island_terrain_free(void)
2075{
2076 if (!island_terrain.init) {
2077 return;
2078 }
2079
2080 terrain_select_list_destroy(island_terrain.forest);
2081 terrain_select_list_destroy(island_terrain.desert);
2082 terrain_select_list_destroy(island_terrain.mountain);
2083 terrain_select_list_destroy(island_terrain.swamp);
2084
2085 island_terrain.init = FALSE;
2086}
2087
2088/**********************************************************************/
2094 static bool make_island(int islemass, int starters,
2095 struct gen234_state *pstate,
2096 int min_specific_island_size)
2097{
2098 /* int may be only 2 bytes ! */
2099 static long int tilefactor, balance, lastplaced;
2100 static long int riverbuck, mountbuck, desertbuck, forestbuck, swampbuck;
2101 int i;
2102
2103 /* The terrain selection lists have to be initialised.
2104 * (see island_terrain_init()) */
2105 fc_assert_ret_val(island_terrain.init, FALSE);
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
2121 i = river_pct + mountain_pct + desert_pct + forest_pct + swamp_pct;
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 */
2133 islemass = islemass - balance;
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)) {
2142 islemass = (MAP_NATIVE_HEIGHT - 6) * (MAP_NATIVE_HEIGHT - 6);
2143 }
2144
2145 if (islemass > (MAP_NATIVE_WIDTH - 2) * (MAP_NATIVE_WIDTH - 2)) {
2146 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",
2174 islemass, i, balance, checkmass);
2175
2176 i *= tilefactor;
2177
2178 riverbuck += river_pct * i;
2179 fill_island_rivers(1, &riverbuck, pstate);
2180
2181 /* Forest */
2182 forestbuck += forest_pct * i;
2183 fill_island(60, &forestbuck, island_terrain.forest, pstate);
2184
2185 /* Desert */
2186 desertbuck += desert_pct * i;
2187 fill_island(40, &desertbuck, island_terrain.desert, pstate);
2188
2189 /* Mountain */
2190 mountbuck += mountain_pct * i;
2191 fill_island(20, &mountbuck, island_terrain.mountain, pstate);
2192
2193 /* Swamp */
2194 swampbuck += swamp_pct * i;
2195 fill_island(80, &swampbuck, island_terrain.swamp, pstate);
2196
2197 pstate->isleindex++;
2198 wld.map.num_continents++;
2199 }
2200
2201 return TRUE;
2202}
2203
2204/**********************************************************************/
2208 static void initworld(struct gen234_state *pstate)
2209{
2210 struct terrain *deepest_ocean = pick_ocean(TERRAIN_OCEAN_DEPTH_MAXIMUM,
2211 FALSE);
2212
2213 fc_assert(deepest_ocean != nullptr);
2214 height_map = fc_malloc(MAP_INDEX_SIZE * sizeof(*height_map));
2215 create_placed_map(); /* Land tiles which aren't placed yet */
2216
2217 whole_map_iterate(&(wld.map), ptile) {
2218 tile_set_terrain(ptile, deepest_ocean);
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;
2224 } whole_map_iterate_end;
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/**********************************************************************/
2245 static 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");
2262 wld.map.server.generator = MAPGEN_RANDOM;
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
2271 fc_assert_action(!placed_map_is_initialized(),
2272 wld.map.server.generator = MAPGEN_RANDOM; return);
2273
2274 while (!done && bigfrac > midfrac) {
2275 done = TRUE;
2276
2277 if (placed_map_is_initialized()) {
2278 destroy_placed_map();
2279 }
2280
2281 initworld(pstate);
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");
2309 wld.map.server.generator = MAPGEN_RANDOM;
2310
2311 /* Init world created this map, destroy it before abort */
2312 destroy_placed_map();
2313 free(height_map);
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
2328 height_map_to_map();
2329 make_plains();
2330 destroy_placed_map();
2331 free(height_map);
2332 height_map = nullptr;
2333
2334 if (checkmass > MAP_NATIVE_WIDTH + MAP_NATIVE_HEIGHT + totalweight) {
2335 log_verbose("%ld mass left unplaced", checkmass);
2336 }
2337}
2338
2339/**********************************************************************/
2343 static 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.");
2356 wld.map.server.generator = MAPGEN_FRACTAL;
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.");
2363 wld.map.server.generator = MAPGEN_FRACTAL;
2364 return;
2365 }
2366
2367 pstate->totalmass = (((MAP_NATIVE_HEIGHT - 6 - spares) * wld.map.server.landpercent
2368 * (MAP_NATIVE_WIDTH - spares)) / 100);
2369
2370 bigislands = player_count();
2371
2372 landmass = (MAP_NATIVE_WIDTH * (MAP_NATIVE_HEIGHT - 6) * wld.map.server.landpercent) / 100;
2373 /* Subtracting the arctics */
2374 if (landmass > 3 * MAP_NATIVE_HEIGHT + player_count() * 3) {
2375 landmass -= 3 * MAP_NATIVE_HEIGHT;
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) {
2383 islandmass = (landmass) / (bigislands);
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
2393 initworld(pstate);
2394
2395 while (pstate->isleindex - 2 <= bigislands && checkmass > islandmass
2396 && ++j < 500) {
2397 make_island(islandmass, 1, pstate, DMSIS);
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
2424 height_map_to_map();
2425 make_plains();
2426 destroy_placed_map();
2427 free(height_map);
2428 height_map = nullptr;
2429
2430 if (j == 1500) {
2431 log_normal(_("Generator 3 left %li landmass unplaced."), checkmass);
2432 } else if (checkmass > MAP_NATIVE_WIDTH + MAP_NATIVE_HEIGHT) {
2433 log_verbose("%ld mass left unplaced", checkmass);
2434 }
2435}
2436
2437/**********************************************************************/
2440 static 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");
2453 wld.map.server.startpos = MAPSTARTPOS_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
2473 initworld(pstate);
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
2493 height_map_to_map();
2494 make_plains();
2495 destroy_placed_map();
2496 free(height_map);
2497 height_map = nullptr;
2498
2499 if (checkmass > MAP_NATIVE_WIDTH + MAP_NATIVE_HEIGHT + totalweight) {
2500 log_verbose("%ld mass left unplaced", checkmass);
2501 }
2502}
2503
2504#undef DMSIS
2505
2506/**********************************************************************/
2509 static void river_types_init(void)
2510{
2511 river_type_count = 0;
2512
2513 extra_type_by_cause_iterate(EC_ROAD, priver) {
2514 if (road_has_flag(extra_road_get(priver), RF_RIVER)
2515 && priver->generated) {
2516 river_types[river_type_count++] = priver;
2517 }
2518 } extra_type_by_cause_iterate_end;
2519}
2520
2521
2522/****************************************************************************
2523 Fair island generator types.
2524****************************************************************************/
2525 enum fair_tile_flag {
2526 FTF_NONE = 0,
2527 FTF_ASSIGNED = 1 << 0,
2528 FTF_OCEAN = 1 << 1,
2529 FTF_STARTPOS = 1 << 2,
2530 FTF_NO_RESOURCE = 1 << 3,
2531 FTF_HAS_HUT = 1 << 4,
2532 FTF_NO_HUT = 1 << 5
2533};
2534
2535 struct fair_tile {
2536 enum fair_tile_flag flags;
2537 struct terrain *pterrain;
2538 struct extra_type *presource;
2539 bv_extras extras;
2540 int startpos_team_id;
2541};
2542
2543 typedef void (*fair_geometry_func)(int *x, int *y);
2544 struct fair_geometry_data {
2545 fair_geometry_func transform[4];
2546 int transform_num;
2547};
2548
2549/**********************************************************************/
2553 static inline struct fair_tile *fair_map_new(void)
2554{
2555 return fc_calloc(MAP_INDEX_SIZE, sizeof(struct fair_tile));
2556}
2557
2558/**********************************************************************/
2561 static inline void fair_map_destroy(struct fair_tile *pmap)
2562{
2563 free(pmap);
2564}
2565
2566/**********************************************************************/
2569 static 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 *
2579fair_map_pos_tile(struct fair_tile *pmap, int x, int y)
2580{
2581 int nat_x, nat_y;
2582
2583 MAP_TO_NATIVE_POS(&nat_x, &nat_y, x, y);
2584
2585 /* Wrap in X and Y directions, as needed. */
2586 if (nat_x < 0 || nat_x >= MAP_NATIVE_WIDTH) {
2587 if (current_wrap_has_flag(WRAP_X)) {
2588 nat_x = FC_WRAP(nat_x, MAP_NATIVE_WIDTH);
2589 } else {
2590 return nullptr;
2591 }
2592 }
2593 if (nat_y < 0 || nat_y >= MAP_NATIVE_HEIGHT) {
2594 if (current_wrap_has_flag(WRAP_Y)) {
2595 nat_y = FC_WRAP(nat_y, MAP_NATIVE_HEIGHT);
2596 } else {
2597 return nullptr;
2598 }
2599 }
2600
2601 return pmap + native_pos_to_index(nat_x, nat_y);
2602}
2603
2604/**********************************************************************/
2607static inline struct fair_tile *
2608fair_map_tile_step(struct fair_tile *pmap, struct fair_tile *ptile,
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
2624fair_map_tile_border(struct fair_tile *pmap, struct fair_tile *ptile,
2625 int dist)
2626{
2627 int nat_x, nat_y;
2628
2629 index_to_native_pos(&nat_x, &nat_y, ptile - pmap);
2630
2631 if (!current_wrap_has_flag(WRAP_X)
2632 && (nat_x < dist || nat_x >= MAP_NATIVE_WIDTH - dist)) {
2633 return TRUE;
2634 }
2635
2636 if (MAP_IS_ISOMETRIC) {
2637 dist *= 2;
2638 }
2639
2640 if (!current_wrap_has_flag(WRAP_Y)
2641 && (nat_y < dist || nat_y >= MAP_NATIVE_HEIGHT - dist)) {
2642 return TRUE;
2643 }
2644
2645 return FALSE;
2646}
2647
2648/**********************************************************************/
2651 static 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/**********************************************************************/
2661 static 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/**********************************************************************/
2675 static 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/**********************************************************************/
2689 static void fair_do_symetry1(int *x, int *y)
2690{
2691 *x = -*x;
2692}
2693
2694/**********************************************************************/
2697 static void fair_do_symetry2(int *x, int *y)
2698{
2699 *y = -*y;
2700}
2701
2702/**********************************************************************/
2705 static void fair_do_hex_symetry1(int *x, int *y)
2706{
2707 *x = -(*x + *y);
2708}
2709
2710/**********************************************************************/
2713 static void fair_do_hex_symetry2(int *x, int *y)
2714{
2715 *x = -*x;
2716 *y = -*y;
2717}
2718
2719/**********************************************************************/
2722 static void fair_do_iso_hex_symetry1(int *x, int *y)
2723{
2724 *y = *x - *y;
2725}
2726
2727#define fair_do_iso_hex_symetry2 fair_do_rotation
2728
2729/**********************************************************************/
2732 static void fair_do_rotation(int *x, int *y)
2733{
2734 int z = *x;
2735
2736 *x = *y;
2737 *y = z;
2738}
2739
2740/**********************************************************************/
2743 static 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/**********************************************************************/
2754 static 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/**********************************************************************/
2765 static 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/**********************************************************************/
2778 static void fair_geometry_rand(struct fair_geometry_data *data)
2779{
2780 int i = 0;
2781
2782 if (!current_topo_has_flag(TF_HEX)) {
2783 if (fc_rand(100) < 50) {
2784 data->transform[i++] = fair_do_symetry1;
2785 }
2786 if (fc_rand(100) < 50) {
2787 data->transform[i++] = fair_do_symetry2;
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) {
2796 data->transform[i++] = fair_do_hex_symetry1;
2797 }
2798 if (fc_rand(100) < 50) {
2799 data->transform[i++] = fair_do_hex_symetry2;
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) {
2809 data->transform[i++] = fair_do_iso_hex_symetry1;
2810 }
2811 if (fc_rand(100) < 50) {
2812 data->transform[i++] = fair_do_iso_hex_symetry2;
2813 }
2814 /* Rotations have 2 steps on hexgonal topologies. */
2815 for (steps = fc_rand(99) % 3; steps > 0; steps--) {
2816 data->transform[i++] = fair_do_iso_hex_rotation;
2817 }
2818 }
2819
2820 fc_assert(i <= ARRAY_SIZE(data->transform));
2821
2822 data->transform_num = i;
2823}
2824
2825/**********************************************************************/
2831 static 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;
2837 struct fair_tile *smax_tile = psource + MAP_INDEX_SIZE;
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. */
2848 fair_map_tile_pos(psource, pstile, &x, &y);
2849 x -= sdx;
2850 y -= sdy;
2851 fair_do_geometry(data, &x, &y);
2852 x += tx;
2853 y += ty;
2854 pttile = fair_map_pos_tile(ptarget, x, y);
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. */
2884 fair_map_tile_pos(psource, pstile, &x, &y);
2885 x -= sdx;
2886 y -= sdy;
2887 fair_do_geometry(data, &x, &y);
2888 x += tx;
2889 y += ty;
2890 pttile = fair_map_pos_tile(ptarget, x, y);
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/**********************************************************************/
2910 static bool fair_map_place_island_rand(struct fair_tile *ptarget,
2911 struct fair_tile *psource)
2912{
2913 struct fair_geometry_data geometry;
2914 int i, r, x, y;
2915
2916 fair_geometry_rand(&geometry);
2917
2918 /* Try random positions. */
2919 for (i = 0; i < 10; i++) {
2920 r = fc_rand(MAP_INDEX_SIZE);
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. */
2928 r = fc_rand(MAP_INDEX_SIZE);
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
2945fair_map_place_island_team(struct fair_tile *ptarget, int tx, int ty,
2946 struct fair_tile *psource,
2947 const struct iter_index *outwards_indices,
2948 int startpos_team_id)
2949{
2950 struct fair_geometry_data geometry;
2951 int i, x, y;
2952
2953 fair_geometry_rand(&geometry);
2954
2955 /* Iterate positions, beginning by a random index of the outwards
2956 * indices. */
2957 for (i = fc_rand(MAP_NUM_ITERATE_OUTWARDS_INDICES / 200);
2958 i < MAP_NUM_ITERATE_OUTWARDS_INDICES; i++) {
2959 x = tx + outwards_indices[i].dx;
2960 y = ty + outwards_indices[i].dy;
2961 if (normalize_map_pos(&(wld.map), &x, &y)
2962 && fair_map_copy(ptarget, x, y, psource, &geometry,
2963 startpos_team_id)) {
2964 return TRUE;
2965 }
2966 }
2967
2968 /* Impossible placement. */
2969 return FALSE;
2970}
2971
2972/**********************************************************************/
2975 static void fair_map_make_resources(struct fair_tile *pmap)
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++) {
2992 pftile2 = fair_map_tile_step(pmap, pftile, MAP_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++) {
3011 pftile2 = fair_map_tile_step(pmap, pftile, MAP_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/**********************************************************************/
3025 static void fair_map_make_huts(struct fair_tile *pmap)
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++) {
3034 k = fc_rand(MAP_INDEX_SIZE);
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
3059 phut = rand_extra_for_tile(pvtile, EC_HUT, TRUE);
3060 if (phut != nullptr) {
3061 tile_add_extra(pvtile, phut);
3062 pftile->extras = pvtile->extras;
3063 pftile->flags |= FTF_HAS_HUT;
3064 square_iterate(&(wld.map), index_to_tile(&(wld.map), pftile - pmap),
3065 3, ptile) {
3066 pmap[tile_index(ptile)].flags |= FTF_NO_HUT;
3067 } square_iterate_end;
3068 }
3069 }
3070
3071 tile_virtual_destroy(pvtile);
3072}
3073
3074/**********************************************************************/
3077 static struct fair_tile *fair_map_island_new(int size, int startpos_num)
3078{
3079 enum {
3080 FT_GRASSLAND,
3081 FT_FOREST,
3082 FT_DESERT,
3083 FT_HILL,
3084 FT_MOUNTAIN,
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] = {
3094 { 0, MG_TEMPERATE, MG_GREEN, MG_MOUNTAINOUS },
3095 { 0, MG_FOLIAGE, MG_TEMPERATE, MG_UNUSED },
3096 { 0, MG_DRY, MG_TEMPERATE, MG_GREEN },
3097 { 0, MG_MOUNTAINOUS, MG_GREEN, MG_UNUSED },
3098 { 0, MG_MOUNTAINOUS, MG_UNUSED, MG_GREEN },
3099 { 0, MG_WET, MG_TEMPERATE, MG_FOLIAGE },
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
3107 ? CITY_MAP_DEFAULT_RADIUS : 1);
3108 const int sea_around_island_sq = (startpos_num > 0
3109 ? CITY_MAP_DEFAULT_RADIUS_SQ : 2);
3110 int i, j, k;
3111
3112 size = CLIP(startpos_num, size, ARRAY_SIZE(land_tiles));
3113 fantasy = (size * 2) / 5;
3114 pisland = fair_map_new();
3115 pftile = fair_map_pos_tile(pisland, MAP_NATIVE_WIDTH / 2, MAP_NATIVE_HEIGHT / 2);
3116 fc_assert(!fair_map_tile_border(pisland, pftile, sea_around_island));
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) {
3126 pftile = land_tiles[fc_rand(i)];
3127
3128 for (j = 0; j < MAP_NUM_VALID_DIRS; j++) {
3129 pftile2 = fair_map_tile_step(pisland, pftile, MAP_VALID_DIRS[j]);
3130 fc_assert(pftile2 != nullptr);
3131 if (fair_map_tile_border(pisland, pftile2, sea_around_island)) {
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];
3147 pftile2 = fair_map_tile_step(pisland, pftile,
3148 MAP_CARDINAL_DIRS[fc_rand(MAP_NUM_CARDINAL_DIRS)]);
3149 fc_assert(pftile2 != nullptr);
3150 if (fair_map_tile_border(pisland, pftile2, sea_around_island)) {
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;) {
3163 pftile = land_tiles[fc_rand(size - fantasy)];
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. */
3172 terrain[FT_GRASSLAND].count = size - startpos_num;
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) {
3184 pftile->pterrain = pick_terrain_by_flag(TER_STARTER);
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++) {
3199 circle_iterate(&(wld.map),
3200 index_to_tile(&(wld.map), land_tiles[i] - pisland),
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 =
3208 pick_ocean(TERRAIN_OCEAN_DEPTH_MINIMUM
3209 + fc_rand(TERRAIN_OCEAN_DEPTH_MAXIMUM / 2), FALSE);
3210 if (startpos_num > 0) {
3211 pftile->flags |= FTF_ASSIGNED;
3212 }
3213 }
3214 } circle_iterate_end;
3215 }
3216
3217 /* Make rivers. */
3218 if (river_type_count > 0) {
3219 struct extra_type *priver;
3220 struct fair_tile *pend;
3221 int n = ((river_pct * size * MAP_NUM_CARDINAL_DIRS
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;
3228 bool connectable_river_around, ocean_around;
3229 int river_around;
3230 bool finished;
3231
3232 for (i = 0; i < n; i++) {
3233 pftile = land_tiles[fc_rand(size)];
3234 if (!terrain_has_flag(pftile->pterrain, TER_CAN_HAVE_RIVER)) {
3235 continue;
3236 }
3237
3238 priver = river_types[fc_rand(river_type_count)];
3239 extra_idx = extra_index(priver);
3240 if (BV_ISSET(pftile->extras, extra_idx)) {
3241 continue;
3242 }
3243 cardinal_only = is_cardinal_only_road(priver);
3244
3245 river_around = 0;
3246 connectable_river_around = FALSE;
3247 ocean_around = FALSE;
3248 for (j = 0; j < MAP_NUM_VALID_DIRS; j++) {
3249 pftile2 = fair_map_tile_step(pisland, pftile, MAP_VALID_DIRS[j]);
3250 if (pftile2 == nullptr) {
3251 continue;
3252 }
3253
3254 if (pftile2->flags & FTF_OCEAN) {
3255 ocean_around = TRUE;
3256 break;
3257 } else if (BV_ISSET(pftile2->extras, extra_idx)) {
3258 river_around++;
3259 if (!cardinal_only || is_cardinal_dir(MAP_VALID_DIRS[j])) {
3260 connectable_river_around = TRUE;
3261 }
3262 }
3263 }
3264 if (ocean_around
3265 || river_around > 1
3266 || (river_around == 1 && !connectable_river_around)) {
3267 continue;
3268 }
3269
3270 if (connectable_river_around) {
3271 log_debug("Adding river at (%d, %d)",
3272 index_to_map_pos_x(pftile - pisland),
3273 index_to_map_pos_y(pftile - pisland));
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++) {
3284 if (cardinal_only && !is_cardinal_dir(MAP_VALID_DIRS[j])) {
3285 continue;
3286 }
3287
3288 finished = FALSE;
3289 pftile2 = pftile;
3290 for (l = 2; l < length_max; l++) {
3291 pftile2 = fair_map_tile_step(pisland, pftile2, MAP_VALID_DIRS[j]);
3292 if (pftile2 == nullptr
3293 || !terrain_has_flag(pftile2->pterrain, TER_CAN_HAVE_RIVER)) {
3294 break;
3295 }
3296
3297 river_around = 0;
3298 connectable_river_around = FALSE;
3299 ocean_around = FALSE;
3300 for (k = 0; k < MAP_NUM_VALID_DIRS; k++) {
3301 if (MAP_VALID_DIRS[k] == DIR_REVERSE(MAP_VALID_DIRS[j])) {
3302 continue;
3303 }
3304
3305 pftile3 = fair_map_tile_step(pisland, pftile2,
3306 MAP_VALID_DIRS[k]);
3307 if (pftile3 == nullptr) {
3308 continue;
3309 }
3310
3311 if (pftile3->flags & FTF_OCEAN) {
3312 if (!cardinal_only || is_cardinal_dir(MAP_VALID_DIRS[k])) {
3313 ocean_around = TRUE;
3314 }
3315 } else if (BV_ISSET(pftile3->extras, extra_idx)) {
3316 river_around++;
3317 if (!cardinal_only || is_cardinal_dir(MAP_VALID_DIRS[k])) {
3318 connectable_river_around = TRUE;
3319 }
3320 }
3321 }
3322 if (river_around > 1 && !connectable_river_around) {
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]",
3340 index_to_map_pos_x(pftile - pisland),
3341 index_to_map_pos_y(pftile - pisland),
3342 index_to_map_pos_x(pend - pisland),
3343 index_to_map_pos_y(pend - pisland),
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 }
3353 pftile = fair_map_tile_step(pisland, pftile, dir);
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) {
3365 fair_map_make_resources(pisland);
3366 }
3367
3368 /* Make huts. */
3369 if (wld.map.server.huts > 0) {
3370 fair_map_make_huts(pisland);
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/**********************************************************************/
3389 static bool map_generate_fair_islands(void)
3390{
3391 struct terrain *deepest_ocean
3392 = pick_ocean(TERRAIN_OCEAN_DEPTH_MAXIMUM, FALSE);
3393 struct fair_tile *pmap, *pisland;
3394 int playermass, islandmass1 , islandmass2, islandmass3;
3395 int min_island_size = wld.map.server.tinyisles ? 1 : 2;
3396 int players_per_island = 1;
3397 int teams_num = 0, team_players_num = 0, single_players_num = 0;
3398 int i, iter = CLIP(1, 100000 / map_num_tiles(), 10);
3399 bool done = FALSE;
3400
3401 teams_iterate(pteam) {
3402 i = player_list_size(team_members(pteam));
3403 fc_assert(0 < i);
3404 if (i == 1) {
3405 single_players_num++;
3406 } else {
3407 teams_num++;
3408 team_players_num += i;
3409 }
3410 } teams_iterate_end;
3411 fc_assert(team_players_num + single_players_num == player_count());
3412
3413 /* Take in account the 'startpos' setting. */
3414 if (wld.map.server.startpos == MAPSTARTPOS_DEFAULT
3415 && wld.map.server.team_placement == TEAM_PLACEMENT_CONTINENT) {
3416 wld.map.server.startpos = MAPSTARTPOS_ALL;
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
3425 if (wld.map.server.team_placement != TEAM_PLACEMENT_DISABLED) {
3426 teams_iterate(pteam) {
3427 i = player_list_size(team_members(pteam));
3428 if (i > 1) {
3429 if (0 != i % 2) {
3430 maybe2 = FALSE;
3431 }
3432 if (0 != i % 3) {
3433 maybe3 = FALSE;
3434 }
3435 }
3436 } teams_iterate_end;
3437 }
3438
3439 if (maybe3) {
3440 players_per_island = 3;
3441 } else if (maybe2) {
3442 players_per_island = 2;
3443 }
3444 }
3445 break;
3446 case MAPSTARTPOS_ALL:
3447 if (wld.map.server.team_placement == TEAM_PLACEMENT_CONTINENT) {
3448 teams_iterate(pteam) {
3449 i = player_list_size(team_members(pteam));
3450 if (i > 1) {
3451 if (players_per_island == 1) {
3452 players_per_island = i;
3453 } else if (i != players_per_island) {
3454 /* Every team doesn't have the same number of players. Cannot
3455 * consider this option. */
3456 players_per_island = 1;
3457 wld.map.server.team_placement = TEAM_PLACEMENT_CLOSEST;
3458 break;
3459 }
3460 }
3461 } teams_iterate_end;
3462 }
3463 break;
3464 case MAPSTARTPOS_DEFAULT:
3465 case MAPSTARTPOS_SINGLE:
3466 case MAPSTARTPOS_VARIABLE:
3467 break;
3468 }
3469 if (players_per_island == 1) {
3470 wld.map.server.startpos = MAPSTARTPOS_SINGLE;
3471 }
3472
3473 whole_map_iterate(&(wld.map), ptile) {
3474 tile_set_terrain(ptile, deepest_ocean);
3475 tile_set_continent(ptile, 0);
3476 BV_CLR_ALL(ptile->extras);
3477 tile_set_owner(ptile, nullptr, nullptr);
3478 ptile->extras_owner = nullptr;
3479 } whole_map_iterate_end;
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 }
3489 } whole_map_iterate_end;
3490 }
3491
3492 if (wld.map.server.mapsize == MAPSIZE_PLAYER) {
3493 playermass = wld.map.server.tilesperplayer - i / player_count();
3494 } else {
3495 playermass = ((map_num_tiles() * wld.map.server.landpercent - i)
3496 / (player_count() * 100));
3497 }
3498 islandmass1 = (players_per_island * playermass * 7) / 10;
3499 if (islandmass1 < min_island_size) {
3500 islandmass1 = min_island_size;
3501 }
3502 islandmass2 = (playermass * 2) / 10;
3503 if (islandmass2 < min_island_size) {
3504 islandmass2 = min_island_size;
3505 }
3506 islandmass3 = playermass / 10;
3507 if (islandmass3 < min_island_size) {
3508 islandmass3 = min_island_size;
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",
3515 team_placement_name(wld.map.server.team_placement));
3516 log_debug("teams_num=%d, team_players_num=%d, single_players_num=%d",
3517 teams_num, team_players_num, single_players_num);
3518 log_debug("playermass=%d, islandmass1=%d, islandmass2=%d, islandmass3=%d",
3519 playermass, islandmass1, islandmass2, islandmass3);
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)
3535 && tile_terrain(atile) == deepest_ocean) {
3536 aftile->flags |= FTF_OCEAN;
3537 }
3538 } adjc_iterate_end;
3539 }
3540 pftile->pterrain = tile_terrain(ptile);
3541 pftile->presource = tile_resource(ptile);
3542 pftile->extras = *tile_extras(ptile);
3543 } whole_map_iterate_end;
3544
3545 /* Create main player island. */
3546 log_debug("Making main island.");
3547 pisland = fair_map_island_new(islandmass1, players_per_island);
3548
3549 log_debug("Place main islands on the map.");
3550 i = 0;
3551
3552 if (wld.map.server.team_placement != TEAM_PLACEMENT_DISABLED
3553 && team_players_num > 0) {
3554 /* Do team placement. */
3555 struct iter_index outwards_indices[MAP_NUM_ITERATE_OUTWARDS_INDICES];
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. */
3561 memcpy(outwards_indices, MAP_ITERATE_OUTWARDS_INDICES,
3562 sizeof(outwards_indices));
3563 switch (wld.map.server.team_placement) {
3564 case TEAM_PLACEMENT_DISABLED:
3565 fc_assert(wld.map.server.team_placement != TEAM_PLACEMENT_DISABLED);
3566 break;
3567 case TEAM_PLACEMENT_CLOSEST:
3568 case TEAM_PLACEMENT_CONTINENT:
3569 for (j = 0; j < MAP_NUM_ITERATE_OUTWARDS_INDICES; j++) {
3570 /* We want square distances for comparing. */
3571 outwards_indices[j].dist =
3572 map_vector_to_sq_distance(outwards_indices[j].dx,
3573 outwards_indices[j].dy);
3574 }
3575 qsort(outwards_indices, MAP_NUM_ITERATE_OUTWARDS_INDICES,
3576 sizeof(outwards_indices[0]), fair_team_placement_closest);
3577 break;
3578 case TEAM_PLACEMENT_HORIZONTAL:
3579 qsort(outwards_indices, MAP_NUM_ITERATE_OUTWARDS_INDICES,
3580 sizeof(outwards_indices[0]), fair_team_placement_horizontal);
3581 break;
3582 case TEAM_PLACEMENT_VERTICAL:
3583 qsort(outwards_indices, MAP_NUM_ITERATE_OUTWARDS_INDICES,
3584 sizeof(outwards_indices[0]), fair_team_placement_vertical);
3585 break;
3586 }
3587
3588 /* Make start point for teams. */
3589 if (current_wrap_has_flag(WRAP_X)) {
3590 dx = fc_rand(MAP_NATIVE_WIDTH);
3591 }
3592 if (current_wrap_has_flag(WRAP_Y)) {
3593 dy = fc_rand(MAP_NATIVE_HEIGHT);
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;
3598 if (current_wrap_has_flag(WRAP_X)) {
3599 start_x[j] = FC_WRAP(start_x[j], MAP_NATIVE_WIDTH);
3600 }
3601 if (current_wrap_has_flag(WRAP_Y)) {
3602 start_y[j] = FC_WRAP(start_y[j], MAP_NATIVE_HEIGHT);
3603 }
3604 }
3605 /* Randomize. */
3606 array_shuffle(start_x, teams_num);
3607 array_shuffle(start_y, teams_num);
3608
3609 j = 0;
3610 teams_iterate(pteam) {
3611 int members_count = player_list_size(team_members(pteam));
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) {
3625 if (!fair_map_place_island_team(pmap, x, y, pisland,
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++;
3638 } teams_iterate_end;
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) {
3646 if (!fair_map_place_island_rand(pmap, pisland)) {
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 }
3654 fair_map_destroy(pisland);
3655
3656 if (done) {
3657 log_debug("Create and place small islands on the map.");
3658 for (i = 0; i < player_count(); i++) {
3659 pisland = fair_map_island_new(islandmass2, 0);
3660 if (!fair_map_place_island_rand(pmap, pisland)) {
3661 log_verbose("Failed to place small island2 number %d.", i);
3662 done = FALSE;
3663 fair_map_destroy(pisland);
3664 break;
3665 }
3666 fair_map_destroy(pisland);
3667 }
3668 }
3669 if (done) {
3670 for (i = 0; i < player_count(); i++) {
3671 pisland = fair_map_island_new(islandmass3, 0);
3672 if (!fair_map_place_island_rand(pmap, pisland)) {
3673 log_verbose("Failed to place small island3 number %d.", i);
3674 done = FALSE;
3675 fair_map_destroy(pisland);
3676 break;
3677 }
3678 fair_map_destroy(pisland);
3679 }
3680 }
3681
3682 if (done) {
3683 break;
3684 }
3685
3686 fair_map_destroy(pmap);
3687 pmap = fair_map_new();
3688
3689 /* Decrease land mass, for better chances. */
3690 islandmass1 = (islandmass1 * 99) / 100;
3691 if (islandmass1 < min_island_size) {
3692 islandmass1 = min_island_size;
3693 }
3694 islandmass2 = (islandmass2 * 99) / 100;
3695 if (islandmass2 < min_island_size) {
3696 islandmass2 = min_island_size;
3697 }
3698 islandmass3 = (islandmass3 * 99) / 100;
3699 if (islandmass3 < min_island_size) {
3700 islandmass3 = min_island_size;
3701 }
3702 }
3703
3704 if (!done) {
3705 log_verbose("Failed to create map after %d iterations.", iter);
3706 wld.map.server.generator = MAPGEN_ISLAND;
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) {
3716 fair_map_make_resources(pmap);
3717 }
3718 if (wld.map.server.huts > 0) {
3719 fair_map_make_huts(pmap);
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) {
3735 player_list_iterate(team_members(team_by_number
3736 (pftile->startpos_team_id)), pplayer) {
3737 startpos_allow(psp, nation_of_player(pplayer));
3738 } player_list_iterate_end;
3739 } else {
3740 startpos_allows_all(psp);
3741 }
3742 }
3743 } whole_map_iterate_end;
3744
3745 wld.map.server.have_resources = TRUE;
3746 wld.map.server.have_huts = TRUE;
3747
3748 fair_map_destroy(pmap);
3749
3750 log_verbose("Fair island map created with success!");
3751
3752 return TRUE;
3753}
n
#define n
Definition astring.c:77
dbv_init
void dbv_init(struct dbv *pdbv, int bits)
Definition bitvector.c:50
dbv_set
void dbv_set(struct dbv *pdbv, int bit)
Definition bitvector.c:144
dbv_isset
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
dbv_free
void dbv_free(struct dbv *pdbv)
Definition bitvector.c:95
dbv_clr_all
void dbv_clr_all(struct dbv *pdbv)
Definition bitvector.c:179
bitvector.h
BV_CLR_ALL
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
BV_SET
#define BV_SET(bv, bit)
Definition bitvector.h:81
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
CITY_MAP_DEFAULT_RADIUS_SQ
#define CITY_MAP_DEFAULT_RADIUS_SQ
Definition city.h:82
incite_cost
char * incite_cost
Definition comments.c:74
fatal
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction bool fatal
Definition dialogs_g.h:86
rand_extra_for_tile
struct extra_type * rand_extra_for_tile(struct tile *ptile, enum extra_cause cause, bool generated)
Definition extras.c:283
extra_index
#define extra_index(_e_)
Definition extras.h:183
extra_road_get
#define extra_road_get(_e_)
Definition extras.h:191
extra_type_by_cause_iterate_end
#define extra_type_by_cause_iterate_end
Definition extras.h:339
extra_type_by_cause_iterate
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
CITY_MAP_DEFAULT_RADIUS
#define CITY_MAP_DEFAULT_RADIUS
Definition fc_types.h:82
MAX_EXTRA_TYPES
#define MAX_EXTRA_TYPES
Definition fc_types.h:50
fcintl.h
_
#define _(String)
Definition fcintl.h:67
make_fracture_map
void make_fracture_map(void)
Definition fracture_map.c:55
make_fracture_relief
void make_fracture_relief(void)
Definition fracture_map.c:294
landmass
static map_landmass * landmass
Definition fracture_map.c:49
height_map
int * height_map
Definition height_map.c:29
fracture_map.h
hmap_mountain_level
int hmap_mountain_level
Definition fracture_map.h:28
MG_UNUSED
#define MG_UNUSED
Definition fracture_map.h:32
hmap_shore_level
int hmap_shore_level
Definition height_map.c:30
wld
struct world wld
Definition game.c:62
game.h
renormalize_hmap_poles
void renormalize_hmap_poles(void)
Definition height_map.c:81
height_map_to_map
void height_map_to_map(void)
Definition height_map.c:300
normalize_hmap_poles
void normalize_hmap_poles(void)
Definition height_map.c:65
area_is_too_flat
bool area_is_too_flat(struct tile *ptile, int thill, int my_height)
Definition height_map.c:271
make_pseudofractal1_hmap
void make_pseudofractal1_hmap(int extra_div)
Definition height_map.c:198
make_random_hmap
void make_random_hmap(int smooth)
Definition height_map.c:101
height_map.h
H_UNIT
#define H_UNIT
Definition height_map.h:20
hmap_max_level
#define hmap_max_level
Definition height_map.h:33
hmap
#define hmap(_tile)
Definition height_map.h:17
log.h
fc_assert_msg
#define fc_assert_msg(condition, message,...)
Definition log.h:181
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
fc_assert_exit_msg
#define fc_assert_exit_msg(condition, message,...)
Definition log.h:211
log_verbose
#define log_verbose(message,...)
Definition log.h:109
fc_assert
#define fc_assert(condition)
Definition log.h:176
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
fc_assert_action
#define fc_assert_action(condition, action)
Definition log.h:187
log_debug
#define log_debug(message,...)
Definition log.h:115
log_normal
#define log_normal(message,...)
Definition log.h:107
log_error
#define log_error(message,...)
Definition log.h:103
log_testmatic
#define log_testmatic(message,...)
Definition log.h:123
nat_x
#define nat_x
nat_y
#define nat_y
map_startpos_new
struct startpos * map_startpos_new(struct tile *ptile)
Definition map.c:1895
map_num_tiles
int map_num_tiles(void)
Definition map.c:1026
startpos_allows_all
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1717
rand_map_pos
struct tile * rand_map_pos(const struct civ_map *nmap)
Definition map.c:1102
main_map_allocate
void main_map_allocate(void)
Definition map.c:525
index_to_tile
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:462
map_vector_to_sq_distance
int map_vector_to_sq_distance(int dx, int dy)
Definition map.c:620
rand_map_pos_filtered
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:1116
map_startpos_count
int map_startpos_count(void)
Definition map.c:1882
is_cardinal_dir
bool is_cardinal_dir(enum direction8 dir)
Definition map.c:1331
native_pos_to_tile
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:449
map_is_empty
bool map_is_empty(void)
Definition map.c:148
startpos_allow
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1661
normalize_map_pos
bool normalize_map_pos(const struct civ_map *nmap, int *x, int *y)
Definition map.c:991
map.h
current_topo_has_flag
#define current_topo_has_flag(flag)
Definition map.h:43
native_pos_to_index
#define native_pos_to_index(nat_x, nat_y)
Definition map.h:147
adjc_iterate_end
#define adjc_iterate_end
Definition map.h:419
index_to_map_pos_y
static int index_to_map_pos_y(int mindex)
Definition map.h:710
C_PERCENT
static const bool C_PERCENT
Definition map.h:40
C_NUMBER
static const bool C_NUMBER
Definition map.h:39
square_iterate
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:377
cardinal_adjc_iterate_end
#define cardinal_adjc_iterate_end
Definition map.h:445
adjc_iterate
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:414
MAP_TO_NATIVE_POS
#define MAP_TO_NATIVE_POS(pnat_x, pnat_y, map_x, map_y)
Definition map.h:165
C_ADJACENT
static const bool C_ADJACENT
Definition map.h:37
NATIVE_TO_MAP_POS
#define NATIVE_TO_MAP_POS(pmap_x, pmap_y, nat_x, nat_y)
Definition map.h:159
cardinal_adjc_dir_iterate_end
#define cardinal_adjc_dir_iterate_end
Definition map.h:452
square_iterate_end
#define square_iterate_end
Definition map.h:380
cardinal_adjc_iterate
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:441
circle_iterate
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:387
index_to_map_pos_x
static int index_to_map_pos_x(int mindex)
Definition map.h:701
whole_map_iterate
#define whole_map_iterate(_map, _tile)
Definition map.h:531
C_CARDINAL
static const bool C_CARDINAL
Definition map.h:38
cardinal_adjc_dir_base_iterate_end
#define cardinal_adjc_dir_base_iterate_end
Definition map.h:459
DIR_REVERSE
#define DIR_REVERSE(dir)
Definition map.h:547
current_wrap_has_flag
#define current_wrap_has_flag(flag)
Definition map.h:46
cardinal_adjc_dir_base_iterate
#define cardinal_adjc_dir_base_iterate(nmap, center_tile, dir_itr)
Definition map.h:455
index_to_native_pos
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:150
cardinal_adjc_dir_iterate
#define cardinal_adjc_dir_iterate(nmap, center_tile, itr_tile, dir_itr)
Definition map.h:448
whole_map_iterate_end
#define whole_map_iterate_end
Definition map.h:540
index_to_map_pos
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:218
circle_iterate_end
#define circle_iterate_end
Definition map.h:390
DIRSTEP
#define DIRSTEP(dest_x, dest_y, dir)
Definition map.h:225
MAPSIZE_PLAYER
@ MAPSIZE_PLAYER
Definition map_types.h:40
MAPGEN_SCENARIO
@ MAPGEN_SCENARIO
Definition map_types.h:47
MAPGEN_FRACTURE
@ MAPGEN_FRACTURE
Definition map_types.h:52
MAPGEN_ISLAND
@ MAPGEN_ISLAND
Definition map_types.h:50
MAPGEN_FAIR
@ MAPGEN_FAIR
Definition map_types.h:51
MAPGEN_FRACTAL
@ MAPGEN_FRACTAL
Definition map_types.h:49
MAPGEN_RANDOM
@ MAPGEN_RANDOM
Definition map_types.h:48
map_startpos
map_startpos
Definition map_types.h:55
MAPSTARTPOS_VARIABLE
@ MAPSTARTPOS_VARIABLE
Definition map_types.h:60
MAPSTARTPOS_2or3
@ MAPSTARTPOS_2or3
Definition map_types.h:58
MAPSTARTPOS_ALL
@ MAPSTARTPOS_ALL
Definition map_types.h:59
MAPSTARTPOS_DEFAULT
@ MAPSTARTPOS_DEFAULT
Definition map_types.h:56
MAPSTARTPOS_SINGLE
@ MAPSTARTPOS_SINGLE
Definition map_types.h:57
make_plains
static void make_plains(void)
Definition mapgen.c:455
fair_team_placement_vertical
static int fair_team_placement_vertical(const void *a, const void *b)
Definition mapgen.c:2675
make_terrains
static void make_terrains(void)
Definition mapgen.c:491
hmap_low_level
static int hmap_low_level
Definition mapgen.c:185
make_rivers
static void make_rivers(void)
Definition mapgen.c:906
mapgenerator2
static void mapgenerator2(void)
Definition mapgen.c:2245
wetness_c
wetness_c
Definition mapgen.c:180
WC_NDRY
@ WC_NDRY
Definition mapgen.c:180
WC_ALL
@ WC_ALL
Definition mapgen.c:180
WC_DRY
@ WC_DRY
Definition mapgen.c:180
terrain_select_list_iterate_end
#define terrain_select_list_iterate_end
Definition mapgen.c:81
NUM_TEST_FUNCTIONS
#define NUM_TEST_FUNCTIONS
Definition mapgen.c:689
jungle_pct
static int jungle_pct
Definition mapgen.c:166
fair_do_symetry2
static void fair_do_symetry2(int *x, int *y)
Definition mapgen.c:2697
fair_map_make_resources
static void fair_map_make_resources(struct fair_tile *pmap)
Definition mapgen.c:2975
make_island
static bool make_island(int islemass, int starters, struct gen234_state *pstate, int min_specific_island_size)
Definition mapgen.c:2094
river_test_adjacent_swamp
static int river_test_adjacent_swamp(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:646
fair_do_iso_hex_symetry1
static void fair_do_iso_hex_symetry1(int *x, int *y)
Definition mapgen.c:2722
fair_map_new
static struct fair_tile * fair_map_new(void)
Definition mapgen.c:2553
river_test_height_map
static int river_test_height_map(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:662
mountain
struct terrain_select_list * mountain
Definition mapgen.c:97
fair_geometry_rand
static void fair_geometry_rand(struct fair_geometry_data *data)
Definition mapgen.c:2778
mountain_pct
static int mountain_pct
Definition mapgen.c:165
map_pos_is_dry
#define map_pos_is_dry(ptile)
Definition mapgen.c:175
DMSIS
#define DMSIS
Definition mapgen.c:2240
fair_geometry_func
void(* fair_geometry_func)(int *x, int *y)
Definition mapgen.c:2543
desert_pct
static int desert_pct
Definition mapgen.c:163
fair_do_geometry
static void fair_do_geometry(const struct fair_geometry_data *data, int *x, int *y)
Definition mapgen.c:2765
make_land
static void make_land(void)
Definition mapgen.c:1053
initworld
static void initworld(struct gen234_state *pstate)
Definition mapgen.c:2208
fair_map_island_new
static struct fair_tile * fair_map_island_new(int size, int startpos_num)
Definition mapgen.c:3077
fair_map_destroy
static void fair_map_destroy(struct fair_tile *pmap)
Definition mapgen.c:2561
fair_map_tile_border
static bool fair_map_tile_border(struct fair_tile *pmap, struct fair_tile *ptile, int dist)
Definition mapgen.c:2624
mapgenerator4
static void mapgenerator4(void)
Definition mapgen.c:2440
make_polar_land
static void make_polar_land(void)
Definition mapgen.c:376
forest_pct
static int forest_pct
Definition mapgen.c:162
init
bool init
Definition mapgen.c:94
RIVERS_MAXTRIES
#define RIVERS_MAXTRIES
Definition mapgen.c:111
fill_island
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
map_pos_is_low
#define map_pos_is_low(ptile)
Definition mapgen.c:193
rand_map_pos_characteristic
static struct tile * rand_map_pos_characteristic(wetness_c wc, temperature_type tc, miscellaneous_c mc)
Definition mapgen.c:265
ini_hmap_low_level
#define ini_hmap_low_level()
Definition mapgen.c:186
fair_map_tile_pos
static void fair_map_tile_pos(struct fair_tile *pmap, struct fair_tile *ptile, int *x, int *y)
Definition mapgen.c:2569
adjust_terrain_param
static void adjust_terrain_param(void)
Definition mapgen.c:1492
tersel_new
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
terrain_select_list_iterate
#define terrain_select_list_iterate(tersel_list, ptersel)
Definition mapgen.c:79
test_miscellaneous
static bool test_miscellaneous(const struct tile *ptile, miscellaneous_c c)
Definition mapgen.c:222
fair_do_hex_symetry1
static void fair_do_hex_symetry1(int *x, int *y)
Definition mapgen.c:2705
river_test_adjacent_ocean
static int river_test_adjacent_ocean(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:599
print_mapgen_map
static void print_mapgen_map(void)
Definition mapgen.c:1207
forest
struct terrain_select_list * forest
Definition mapgen.c:95
place_island
static bool place_island(struct gen234_state *pstate)
Definition mapgen.c:1849
river_blockmark
static void river_blockmark(struct river_map *privermap, struct tile *ptile)
Definition mapgen.c:672
make_huts
static void make_huts(int number)
Definition mapgen.c:1535
fair_do_hex_symetry2
static void fair_do_hex_symetry2(int *x, int *y)
Definition mapgen.c:2713
test_wetness
static bool test_wetness(const struct tile *ptile, wetness_c c)
Definition mapgen.c:204
island_terrain_free
static void island_terrain_free(void)
Definition mapgen.c:2074
is_tiny_island
static bool is_tiny_island(struct tile *ptile)
Definition mapgen.c:1156
swamp
struct terrain_select_list * swamp
Definition mapgen.c:98
river_types
static struct extra_type * river_types[MAX_EXTRA_TYPES]
Definition mapgen.c:73
river_type_count
static int river_type_count
Definition mapgen.c:74
PLACE_ONE_TYPE
#define PLACE_ONE_TYPE(count, alternate, ter, wc, tc, mc, weight)
Definition mapgen.c:470
river_test_adjacent_highlands
static int river_test_adjacent_highlands(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:620
fair_do_iso_hex_symetry2
#define fair_do_iso_hex_symetry2
Definition mapgen.c:2727
river_types_init
static void river_types_init(void)
Definition mapgen.c:2509
near_safe_tiles
static bool near_safe_tiles(struct tile *ptile)
Definition mapgen.c:1520
ok_for_separate_poles
static bool ok_for_separate_poles(struct tile *ptile)
Definition mapgen.c:357
miscellaneous_c
miscellaneous_c
Definition mapgen.c:195
MC_LOW
@ MC_LOW
Definition mapgen.c:195
MC_NLOW
@ MC_NLOW
Definition mapgen.c:195
MC_NONE
@ MC_NONE
Definition mapgen.c:195
is_near_land
static bool is_near_land(struct tile *ptile)
Definition mapgen.c:1832
fair_team_placement_horizontal
static int fair_team_placement_horizontal(const void *a, const void *b)
Definition mapgen.c:2661
condition_filter
static bool condition_filter(const struct tile *ptile, const void *data)
Definition mapgen.c:250
swamp_pct
static int swamp_pct
Definition mapgen.c:164
get_random_map_position_from_state
static struct tile * get_random_map_position_from_state(const struct gen234_state *const pstate)
Definition mapgen.c:1601
is_resource_close
static bool is_resource_close(const struct tile *ptile)
Definition mapgen.c:1563
add_resources
static void add_resources(int prob)
Definition mapgen.c:1577
mapgenerator3
static void mapgenerator3(void)
Definition mapgen.c:2343
fair_do_rotation
static void fair_do_rotation(int *x, int *y)
Definition mapgen.c:2732
fair_map_place_island_rand
static bool fair_map_place_island_rand(struct fair_tile *ptarget, struct fair_tile *psource)
Definition mapgen.c:2910
river_test_highlands
static int river_test_highlands(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:589
fill_island_rivers
static void fill_island_rivers(int coast, long int *bucket, const struct gen234_state *const pstate)
Definition mapgen.c:1776
fair_map_make_huts
static void fair_map_make_huts(struct fair_tile *pmap)
Definition mapgen.c:3025
fair_team_placement_closest
static int fair_team_placement_closest(const void *a, const void *b)
Definition mapgen.c:2651
make_river
static bool make_river(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:792
island_terrain_init
static void island_terrain_init(void)
Definition mapgen.c:2013
island_river_mouth_suitability
static bool island_river_mouth_suitability(const struct tile *ptile, const struct extra_type *priver)
Definition mapgen.c:1731
river_test_rivergrid
static int river_test_rivergrid(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:578
map_generate_fair_islands
static bool map_generate_fair_islands(void)
Definition mapgen.c:3389
fair_do_iso_hex_rotation
static void fair_do_iso_hex_rotation(int *x, int *y)
Definition mapgen.c:2754
river_pct
static int river_pct
Definition mapgen.c:167
make_polar
static void make_polar(void)
Definition mapgen.c:335
create_island
static bool create_island(int islemass, struct gen234_state *pstate)
Definition mapgen.c:1939
make_plain
static void make_plain(struct tile *ptile, int *to_be_placed)
Definition mapgen.c:434
island_river_suitability
static bool island_river_suitability(const struct tile *ptile, const struct extra_type *priver)
Definition mapgen.c:1752
fair_map_place_island_team
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
test_funcs
static struct test_func test_funcs[NUM_TEST_FUNCTIONS]
Definition mapgen.c:690
fair_map_copy
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
desert
struct terrain_select_list * desert
Definition mapgen.c:96
make_relief
static void make_relief(void)
Definition mapgen.c:298
HAS_POLES
#define HAS_POLES
Definition mapgen.c:157
island_terrain
static struct @96 island_terrain
fair_do_symetry1
static void fair_do_symetry1(int *x, int *y)
Definition mapgen.c:2689
river_test_adjacent_river
static int river_test_adjacent_river(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:610
fair_do_hex_rotation
static void fair_do_hex_rotation(int *x, int *y)
Definition mapgen.c:2743
remove_tiny_islands
static void remove_tiny_islands(void)
Definition mapgen.c:1182
river_test_swamp
static int river_test_swamp(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:636
count_card_adjc_elevated_tiles
static int count_card_adjc_elevated_tiles(struct tile *ptile)
Definition mapgen.c:1923
place_terrain
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
terrain_is_too_high
static bool terrain_is_too_high(struct tile *ptile, int thill, int my_height)
Definition mapgen.c:280
map_fractal_generate
bool map_fractal_generate(bool autosize, struct unit_type *initial_unit)
Definition mapgen.c:1268
fair_map_pos_tile
static struct fair_tile * fair_map_pos_tile(struct fair_tile *pmap, int x, int y)
Definition mapgen.c:2579
tersel_free
static void tersel_free(struct terrain_select *ptersel)
Definition mapgen.c:1642
checkmass
static long int checkmass
Definition mapgen.c:1844
fair_map_tile_step
static struct fair_tile * fair_map_tile_step(struct fair_tile *pmap, struct fair_tile *ptile, enum direction8 dir)
Definition mapgen.c:2608
river_test_blocked
static int river_test_blocked(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:557
fair_tile_flag
fair_tile_flag
Definition mapgen.c:2525
FTF_NONE
@ FTF_NONE
Definition mapgen.c:2526
FTF_NO_RESOURCE
@ FTF_NO_RESOURCE
Definition mapgen.c:2530
FTF_HAS_HUT
@ FTF_HAS_HUT
Definition mapgen.c:2531
FTF_ASSIGNED
@ FTF_ASSIGNED
Definition mapgen.c:2527
FTF_OCEAN
@ FTF_OCEAN
Definition mapgen.c:2528
FTF_STARTPOS
@ FTF_STARTPOS
Definition mapgen.c:2529
FTF_NO_HUT
@ FTF_NO_HUT
Definition mapgen.c:2532
mapgen.h
generator_init_topology
void generator_init_topology(bool autosize)
Definition mapgen_topology.c:165
get_sqsize
int get_sqsize(void)
Definition mapgen_topology.c:271
map_colatitude
int map_colatitude(const struct tile *ptile)
Definition mapgen_topology.c:38
near_singularity
bool near_singularity(const struct tile *ptile)
Definition mapgen_topology.c:53
mapgen_topology.h
L_UNIT
#define L_UNIT
Definition mapgen_topology.h:42
COLD_LEVEL
#define COLD_LEVEL
Definition mapgen_topology.h:50
ICE_BASE_LEVEL
#define ICE_BASE_LEVEL
Definition mapgen_topology.h:63
TROPICAL_LEVEL
#define TROPICAL_LEVEL
Definition mapgen_topology.h:52
MAX_COLATITUDE
#define MAX_COLATITUDE
Definition mapgen_topology.h:21
pick_resource
struct extra_type * pick_resource(const struct terrain *pterrain)
Definition mapgen_utils.c:800
set_all_ocean_tiles_placed
void set_all_ocean_tiles_placed(void)
Definition mapgen_utils.c:95
create_placed_map
void create_placed_map(void)
Definition mapgen_utils.c:48
pmap
#define pmap(_tile)
Definition mapgen_utils.c:66
map_set_placed
void map_set_placed(struct tile *ptile)
Definition mapgen_utils.c:79
destroy_placed_map
void destroy_placed_map(void)
Definition mapgen_utils.c:58
not_placed
bool not_placed(const struct tile *ptile)
Definition mapgen_utils.c:71
pick_terrain_by_flag
struct terrain * pick_terrain_by_flag(enum terrain_flag_id flag)
Definition mapgen_utils.c:682
assign_continent_numbers
void assign_continent_numbers(void)
Definition mapgen_utils.c:452
regenerate_lakes
void regenerate_lakes(void)
Definition mapgen_utils.c:350
set_placed_near_pos
void set_placed_near_pos(struct tile *ptile, int dist)
Definition mapgen_utils.c:107
smooth_water_depth
void smooth_water_depth(void)
Definition mapgen_utils.c:612
placed_map_is_initialized
bool placed_map_is_initialized(void)
Definition mapgen_utils.c:40
pick_terrain
struct terrain * pick_terrain(enum mapgen_terrain_property target, enum mapgen_terrain_property prefer, enum mapgen_terrain_property avoid)
Definition mapgen_utils.c:725
most_shallow_ocean
struct terrain * most_shallow_ocean(bool frozen)
Definition mapgen_utils.c:500
pick_ocean
struct terrain * pick_ocean(int depth, bool frozen)
Definition mapgen_utils.c:546
map_unset_placed
void map_unset_placed(struct tile *ptile)
Definition mapgen_utils.c:87
mapgen_utils.h
maphand.h
mem.h
fc_calloc
#define fc_calloc(n, esz)
Definition mem.h:38
FC_FREE
#define FC_FREE(ptr)
Definition mem.h:41
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
nation_of_player
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
nation.h
player_count
int player_count(void)
Definition player.c:817
player_list_iterate
#define player_list_iterate(playerlist, pplayer)
Definition player.h:557
player_list_iterate_end
#define player_list_iterate_end
Definition player.h:559
fc_rand_state
RANDOM_STATE fc_rand_state(void)
Definition rand.c:208
fc_srand
void fc_srand(RANDOM_TYPE seed)
Definition rand.c:161
fc_rand_set_state
void fc_rand_set_state(RANDOM_STATE state)
Definition rand.c:229
rand.h
RANDOM_TYPE
uint32_t RANDOM_TYPE
Definition rand.h:26
fc_rand
#define fc_rand(_size)
Definition rand.h:56
road_has_flag
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Definition road.c:416
is_cardinal_only_road
bool is_cardinal_only_road(const struct extra_type *pextra)
Definition road.c:489
count_river_type_tile_card
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
count_river_type_near_tile
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
count_river_near_tile
int count_river_near_tile(struct civ_map *nmap, const struct tile *ptile, const struct extra_type *priver)
Definition road.c:340
road.h
array_shuffle
void array_shuffle(int *array, int n)
Definition shared.c:2008
shared.h
MAX_UINT32
#define MAX_UINT32
Definition shared.h:81
CLIP
#define CLIP(lower, current, upper)
Definition shared.h:57
ARRAY_SIZE
#define ARRAY_SIZE(x)
Definition shared.h:85
FC_WRAP
#define FC_WRAP(value, range)
Definition shared.h:65
MIN
#define MIN(x, y)
Definition shared.h:55
FC_INFINITY
#define FC_INFINITY
Definition shared.h:36
MAX
#define MAX(x, y)
Definition shared.h:54
speclist.h
size
size_t size
Definition specvec.h:72
y
struct sprite int int y
Definition sprite_g.h:31
x
struct sprite int x
Definition sprite_g.h:31
create_start_positions
bool create_start_positions(enum map_startpos mode, struct unit_type *initial_unit)
Definition startpos.c:300
startpos.h
DataFilter
Definition mapgen.c:240
DataFilter::mc
miscellaneous_c mc
Definition mapgen.c:243
DataFilter::wc
wetness_c wc
Definition mapgen.c:241
DataFilter::tc
temperature_type tc
Definition mapgen.c:242
RANDOM_STATE
Definition rand.h:50
civ_map::seed
randseed seed
Definition map_types.h:93
civ_map::tinyisles
bool tinyisles
Definition map_types.h:101
civ_map::num_continents
int num_continents
Definition map_types.h:82
civ_map::riches
int riches
Definition map_types.h:94
civ_map::mapsize
enum mapsize_type mapsize
Definition map_types.h:89
civ_map::startpos
enum map_startpos startpos
Definition map_types.h:100
civ_map::num_oceans
int num_oceans
Definition map_types.h:83
civ_map::have_resources
bool have_resources
Definition map_types.h:109
civ_map::server
struct civ_map::@42::@44 server
civ_map::steepness
int steepness
Definition map_types.h:106
civ_map::wetness
int wetness
Definition map_types.h:105
civ_map::tilesperplayer
int tilesperplayer
Definition map_types.h:91
civ_map::seed_setting
randseed seed_setting
Definition map_types.h:92
civ_map::landpercent
int landpercent
Definition map_types.h:98
civ_map::team_placement
enum team_placement team_placement
Definition map_types.h:110
civ_map::huts
int huts
Definition map_types.h:95
civ_map::have_huts
bool have_huts
Definition map_types.h:108
civ_map::generator
enum map_generator generator
Definition map_types.h:99
civ_map::ocean_resources
bool ocean_resources
Definition map_types.h:107
civ_map::separatepoles
bool separatepoles
Definition map_types.h:102
civ_map::temperature
int temperature
Definition map_types.h:104
dbv
Definition bitvector.h:32
extra_type
Definition extras.h:88
fair_geometry_data
Definition mapgen.c:2544
fair_geometry_data::transform
fair_geometry_func transform[4]
Definition mapgen.c:2545
fair_geometry_data::transform_num
int transform_num
Definition mapgen.c:2546
fair_tile
Definition mapgen.c:2535
fair_tile::extras
bv_extras extras
Definition mapgen.c:2539
fair_tile::pterrain
struct terrain * pterrain
Definition mapgen.c:2537
fair_tile::flags
enum fair_tile_flag flags
Definition mapgen.c:2536
fair_tile::startpos_team_id
int startpos_team_id
Definition mapgen.c:2540
fair_tile::presource
struct extra_type * presource
Definition mapgen.c:2538
gen234_state
Definition mapgen.c:57
gen234_state::n
int n
Definition mapgen.c:58
gen234_state::w
int w
Definition mapgen.c:58
gen234_state::isleindex
int isleindex
Definition mapgen.c:58
gen234_state::e
int e
Definition mapgen.c:58
gen234_state::totalmass
long int totalmass
Definition mapgen.c:59
gen234_state::s
int s
Definition mapgen.c:58
iter_index
Definition city.h:109
iter_index::dist
int dist
Definition city.h:110
iter_index::dx
int dx
Definition city.h:110
iter_index::dy
int dy
Definition city.h:110
river_map
Definition mapgen.c:115
river_map::ok
struct dbv ok
Definition mapgen.c:117
river_map::blocked
struct dbv blocked
Definition mapgen.c:116
startpos
Definition map.c:40
terrain_select
Definition mapgen.c:63
terrain_select::weight
int weight
Definition mapgen.c:64
terrain_select::wet_condition
int wet_condition
Definition mapgen.c:69
terrain_select::avoid
enum mapgen_terrain_property avoid
Definition mapgen.c:67
terrain_select::temp_condition
int temp_condition
Definition mapgen.c:68
terrain_select::target
enum mapgen_terrain_property target
Definition mapgen.c:65
terrain_select::prefer
enum mapgen_terrain_property prefer
Definition mapgen.c:66
terrain
Definition terrain.h:75
terrain::property
int property[MG_COUNT]
Definition terrain.h:146
test_func
Definition mapgen.c:684
test_func::fatal
bool fatal
Definition mapgen.c:686
test_func::func
int(* func)(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:685
tile
Definition tile.h:50
unit_type
Definition unittype.h:507
world::map
struct civ_map map
Definition world_object.h:38
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
fc__fallthrough
#define fc__fallthrough
Definition support.h:119
team_by_number
struct team * team_by_number(const int team_id)
Definition team.c:400
team_rule_name
const char * team_rule_name(const struct team *pteam)
Definition team.c:410
team_number
int team_number(const struct team *pteam)
Definition team.c:391
team_members
const struct player_list * team_members(const struct team *pteam)
Definition team.c:456
teams_iterate_end
#define teams_iterate_end
Definition team.h:87
teams_iterate
#define teams_iterate(_pteam)
Definition team.h:82
temperature_is_initialized
bool temperature_is_initialized(void)
Definition temperature_map.c:77
destroy_tmap
void destroy_tmap(void)
Definition temperature_map.c:107
tmap_is
bool tmap_is(const struct tile *ptile, temperature_type tt)
Definition temperature_map.c:85
is_temperature_type_near
bool is_temperature_type_near(const struct tile *ptile, temperature_type tt)
Definition temperature_map.c:93
create_tmap
void create_tmap(bool real)
Definition temperature_map.c:119
temperature_map.h
temperature_type
int temperature_type
Definition temperature_map.h:24
TT_COLD
#define TT_COLD
Definition temperature_map.h:27
TT_NHOT
#define TT_NHOT
Definition temperature_map.h:33
TT_HOT
#define TT_HOT
Definition temperature_map.h:34
TT_FROZEN
#define TT_FROZEN
Definition temperature_map.h:26
TT_TROPICAL
#define TT_TROPICAL
Definition temperature_map.h:29
TT_ALL
#define TT_ALL
Definition temperature_map.h:32
TT_NFROZEN
#define TT_NFROZEN
Definition temperature_map.h:31
terrain_count
Terrain_type_id terrain_count(void)
Definition terrain.c:118
count_terrain_class_near_tile
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
is_terrain_class_card_near
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:591
terrain_index
Terrain_type_id terrain_index(const struct terrain *pterrain)
Definition terrain.c:138
terrain_rule_name
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
count_terrain_property_near_tile
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
is_terrain_near_tile
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
terrain_type_iterate
#define terrain_type_iterate(_p)
Definition terrain.h:266
T_UNKNOWN
#define T_UNKNOWN
Definition terrain.h:62
is_ocean
#define is_ocean(pterrain)
Definition terrain.h:194
is_ocean_tile
#define is_ocean_tile(ptile)
Definition terrain.h:196
TERRAIN_OCEAN_DEPTH_MINIMUM
#define TERRAIN_OCEAN_DEPTH_MINIMUM
Definition terrain.h:147
terrain_type_iterate_end
#define terrain_type_iterate_end
Definition terrain.h:272
TERRAIN_OCEAN_DEPTH_MAXIMUM
#define TERRAIN_OCEAN_DEPTH_MAXIMUM
Definition terrain.h:148
terrain_has_flag
#define terrain_has_flag(terr, flag)
Definition terrain.h:176
tile_add_extra
void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:955
tile_set_terrain
void tile_set_terrain(struct tile *ptile, struct terrain *pterrain)
Definition tile.c:124
tile_virtual_destroy
void tile_virtual_destroy(struct tile *vtile)
Definition tile.c:1035
tile_has_river
bool tile_has_river(const struct tile *ptile)
Definition tile.c:852
tile_set_owner
void tile_set_owner(struct tile *ptile, struct player *pplayer, struct tile *claimer)
Definition tile.c:69
tile_virtual_new
struct tile * tile_virtual_new(const struct tile *ptile)
Definition tile.c:981
tile_extra_rm_apply
bool tile_extra_rm_apply(struct tile *ptile, struct extra_type *tgt)
Definition tile.c:601
tile_set_resource
void tile_set_resource(struct tile *ptile, struct extra_type *presource)
Definition tile.c:349
tile_set_continent
void tile_set_continent(struct tile *ptile, Continent_id val)
Definition tile.c:382
tile_index
#define tile_index(_pt_)
Definition tile.h:89
tile_resource
#define tile_resource(_tile)
Definition tile.h:103
tile_terrain
#define tile_terrain(_tile)
Definition tile.h:111
TILE_XY
#define TILE_XY(ptile)
Definition tile.h:43
tile_extras
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:121
tile_continent
#define tile_continent(_tile)
Definition tile.h:93
tile_has_extra
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
MAP_ITERATE_OUTWARDS_INDICES
#define MAP_ITERATE_OUTWARDS_INDICES
Definition world_object.h:66
MAP_NATIVE_WIDTH
#define MAP_NATIVE_WIDTH
Definition world_object.h:55
MAP_NUM_VALID_DIRS
#define MAP_NUM_VALID_DIRS
Definition world_object.h:65
MAP_NUM_ITERATE_OUTWARDS_INDICES
#define MAP_NUM_ITERATE_OUTWARDS_INDICES
Definition world_object.h:67
MAP_INDEX_SIZE
#define MAP_INDEX_SIZE
Definition world_object.h:52
MAP_NUM_CARDINAL_DIRS
#define MAP_NUM_CARDINAL_DIRS
Definition world_object.h:63
MAP_IS_ISOMETRIC
#define MAP_IS_ISOMETRIC
Definition world_object.h:46
MAP_CARDINAL_DIRS
#define MAP_CARDINAL_DIRS
Definition world_object.h:62
MAP_NATIVE_HEIGHT
#define MAP_NATIVE_HEIGHT
Definition world_object.h:56
MAP_VALID_DIRS
#define MAP_VALID_DIRS
Definition world_object.h:64