Freeciv-3.2: /fast/freeciv/nightly/S3_2/server/generator/mapgen.c Source File

Freeciv-3.2

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/* should be used after having hmap_low_level initialized */
192#define map_pos_is_low(ptile) ((hmap((ptile)) < hmap_low_level))
193
194 typedef enum { MC_NONE, MC_LOW, MC_NLOW } miscellaneous_c;
195
196/**************************************************************************
197 These functions test for conditions used in rand_map_pos_characteristic
198**************************************************************************/
199
200/**********************************************************************/
203 static bool test_wetness(const struct tile *ptile, wetness_c c)
204{
205 switch (c) {
206 case WC_ALL:
207 return TRUE;
208 case WC_DRY:
209 return map_pos_is_dry(ptile);
210 case WC_NDRY:
211 return !map_pos_is_dry(ptile);
212 }
213 log_error("Invalid wetness_c %d", c);
214 return FALSE;
215}
216
217/**********************************************************************/
220 static bool test_miscellaneous(const struct tile *ptile, miscellaneous_c c)
221{
222 switch (c) {
223 case MC_NONE:
224 return TRUE;
225 case MC_LOW:
226 return map_pos_is_low(ptile);
227 case MC_NLOW:
228 return !map_pos_is_low(ptile);
229 }
230 log_error("Invalid miscellaneous_c %d", c);
231 return FALSE;
232}
233
234/**************************************************************************
235 Passed as data to rand_map_pos_filtered() by rand_map_pos_characteristic()
236**************************************************************************/
237 struct DataFilter {
238 wetness_c wc;
239 temperature_type tc;
240 miscellaneous_c mc;
241};
242
243/**********************************************************************/
247 static bool condition_filter(const struct tile *ptile, const void *data)
248{
249 const struct DataFilter *filter = data;
250
251 return not_placed(ptile)
252 && tmap_is(ptile, filter->tc)
253 && test_wetness(ptile, filter->wc)
254 && test_miscellaneous(ptile, filter->mc);
255}
256
257/**********************************************************************/
262 static struct tile *rand_map_pos_characteristic(wetness_c wc,
263 temperature_type tc,
264 miscellaneous_c mc )
265{
266 struct DataFilter filter = { .wc = wc, .tc = tc, .mc = mc };
267
268 return rand_map_pos_filtered(&(wld.map), &filter, condition_filter);
269}
270
271/**********************************************************************/
277 static bool terrain_is_too_high(struct tile *ptile,
278 int thill, int my_height)
279{
280 square_iterate(&(wld.map), ptile, 1, tile1) {
281 if (hmap(tile1) + (hmap_max_level - hmap_mountain_level) / 5 < thill) {
282 return FALSE;
283 }
284 } square_iterate_end;
285 return TRUE;
286}
287
288/**********************************************************************/
294 static void make_relief(void)
295{
296 /* Calculate the mountain level. map.server.mountains specifies the
297 * percentage of land that is turned into hills and mountains. */
298 hmap_mountain_level = (((hmap_max_level - hmap_shore_level)
299 * (100 - wld.map.server.steepness))
300 / 100 + hmap_shore_level);
301
302 whole_map_iterate(&(wld.map), ptile) {
303 if (not_placed(ptile)
304 && ((hmap_mountain_level < hmap(ptile)
305 && (fc_rand(10) > 5
306 || !terrain_is_too_high(ptile, hmap_mountain_level,
307 hmap(ptile))))
308 || area_is_too_flat(ptile, hmap_mountain_level, hmap(ptile)))) {
309 if (tmap_is(ptile, TT_HOT)) {
310 /* Prefer hills to mountains in hot regions. */
311 tile_set_terrain(ptile,
312 pick_terrain(MG_MOUNTAINOUS, fc_rand(10) < 4
313 ? MG_UNUSED : MG_GREEN, MG_UNUSED));
314 } else {
315 /* Prefer mountains hills to in cold regions. */
316 tile_set_terrain(ptile,
317 pick_terrain(MG_MOUNTAINOUS, MG_UNUSED,
318 fc_rand(10) < 8 ? MG_GREEN : MG_UNUSED));
319 }
320 map_set_placed(ptile);
321 }
322 } whole_map_iterate_end;
323}
324
325/**********************************************************************/
331 static void make_polar(void)
332{
333 struct terrain *ocean = pick_ocean(TERRAIN_OCEAN_DEPTH_MAXIMUM, TRUE);
334
335 whole_map_iterate(&(wld.map), ptile) {
336 if (tmap_is(ptile, TT_FROZEN)
337 || (tmap_is(ptile, TT_COLD)
338 && (fc_rand(10) > 7)
339 && is_temperature_type_near(ptile, TT_FROZEN))) {
340 if (ocean) {
341 tile_set_terrain(ptile, ocean);
342 } else {
343 tile_set_terrain(ptile,
344 pick_terrain(MG_FROZEN, MG_UNUSED, MG_TROPICAL));
345 }
346 }
347 } whole_map_iterate_end;
348}
349
350/**********************************************************************/
353 static bool ok_for_separate_poles(struct tile *ptile)
354{
355 if (!wld.map.server.separatepoles) {
356 return TRUE;
357 }
358 adjc_iterate(&(wld.map), ptile, tile1) {
359 if (tile_continent(tile1) > 0) {
360 return FALSE;
361 }
362 } adjc_iterate_end;
363 return TRUE;
364}
365
366/**********************************************************************/
371 static void make_polar_land(void)
372{
373 assign_continent_numbers();
374
375 whole_map_iterate(&(wld.map), ptile) {
376 if ((tile_terrain(ptile) == T_UNKNOWN
377 || !terrain_has_flag(tile_terrain(ptile), TER_FROZEN))
378 && ((tmap_is(ptile, TT_FROZEN)
379 && ok_for_separate_poles(ptile))
380 || (tmap_is(ptile, TT_COLD)
381 && fc_rand(10) > 7
382 && is_temperature_type_near(ptile, TT_FROZEN)
383 && ok_for_separate_poles(ptile)))) {
384 tile_set_terrain(ptile, T_UNKNOWN);
385 tile_set_continent(ptile, 0);
386 }
387 } whole_map_iterate_end;
388}
389
390/**********************************************************************/
393 static void place_terrain(struct tile *ptile, int diff,
394 struct terrain *pterrain, int *to_be_placed,
395 wetness_c wc,
396 temperature_type tc,
397 miscellaneous_c mc)
398{
399 if (*to_be_placed <= 0) {
400 return;
401 }
402 fc_assert_ret(not_placed(ptile));
403 tile_set_terrain(ptile, pterrain);
404 map_set_placed(ptile);
405 (*to_be_placed)--;
406
407 cardinal_adjc_iterate(&(wld.map), ptile, tile1) {
408 /* Check L_UNIT and H_UNIT against 0. */
409 int Delta = (abs(map_colatitude(tile1) - map_colatitude(ptile))
410 / MAX(L_UNIT, 1)
411 + abs(hmap(tile1) - (hmap(ptile))) / MAX(H_UNIT, 1));
412 if (not_placed(tile1)
413 && tmap_is(tile1, tc)
414 && test_wetness(tile1, wc)
415 && test_miscellaneous(tile1, mc)
416 && Delta < diff
417 && fc_rand(10) > 4) {
418 place_terrain(tile1, diff - 1 - Delta, pterrain,
419 to_be_placed, wc, tc, mc);
420 }
421 } cardinal_adjc_iterate_end;
422}
423
424/**********************************************************************/
428 static void make_plain(struct tile *ptile, int *to_be_placed )
429{
430 /* in cold place we get tundra instead */
431 if (tmap_is(ptile, TT_FROZEN)) {
432 tile_set_terrain(ptile,
433 pick_terrain(MG_FROZEN, MG_UNUSED, MG_MOUNTAINOUS));
434 } else if (tmap_is(ptile, TT_COLD)) {
435 tile_set_terrain(ptile,
436 pick_terrain(MG_COLD, MG_UNUSED, MG_MOUNTAINOUS));
437 } else {
438 tile_set_terrain(ptile,
439 pick_terrain(MG_TEMPERATE, MG_GREEN, MG_MOUNTAINOUS));
440 }
441 map_set_placed(ptile);
442 (*to_be_placed)--;
443}
444
445/**********************************************************************/
449 static void make_plains(void)
450{
451 int to_be_placed;
452
453 whole_map_iterate(&(wld.map), ptile) {
454 if (not_placed(ptile)) {
455 to_be_placed = 1;
456 make_plain(ptile, &to_be_placed);
457 }
458 } whole_map_iterate_end;
459}
460
461/**********************************************************************/
464#define PLACE_ONE_TYPE(count, alternate, ter, wc, tc, mc, weight) \
465 if ((count) > 0) { \
466 struct tile *ptile; \
467 /* Place some terrains */ \
468 if ((ptile = rand_map_pos_characteristic((wc), (tc), (mc)))) { \
469 place_terrain(ptile, (weight), (ter), &(count), (wc),(tc), (mc)); \
470 } else { \
471 /* If rand_map_pos_temperature returns FALSE we may as well stop */ \
472 /* looking for this time and go to alternate type. */ \
473 (alternate) += (count); \
474 (count) = 0; \
475 } \
476 }
477
478/**********************************************************************/
485 static void make_terrains(void)
486{
487 int total = 0;
488 int forests_count = 0;
489 int jungles_count = 0;
490 int deserts_count = 0;
491 int alt_deserts_count = 0;
492 int plains_count = 0;
493 int swamps_count = 0;
494
495 whole_map_iterate(&(wld.map), ptile) {
496 if (not_placed(ptile)) {
497 total++;
498 }
499 } whole_map_iterate_end;
500
501 forests_count = total * forest_pct / (100 - mountain_pct);
502 jungles_count = total * jungle_pct / (100 - mountain_pct);
503
504 deserts_count = total * desert_pct / (100 - mountain_pct);
505 swamps_count = total * swamp_pct / (100 - mountain_pct);
506
507 /* grassland, tundra,arctic and plains is counted in plains_count */
508 plains_count = total - forests_count - deserts_count
509 - swamps_count - jungles_count;
510
511 /* the placement loop */
512 do {
513
514 PLACE_ONE_TYPE(forests_count , plains_count,
515 pick_terrain(MG_FOLIAGE, MG_TEMPERATE, MG_TROPICAL),
516 WC_ALL, TT_NFROZEN, MC_NONE, 60);
517 PLACE_ONE_TYPE(jungles_count, forests_count,
518 pick_terrain(MG_FOLIAGE, MG_TROPICAL, MG_COLD),
519 WC_ALL, TT_TROPICAL, MC_NONE, 50);
520 PLACE_ONE_TYPE(swamps_count, forests_count,
521 pick_terrain(MG_WET, MG_UNUSED, MG_FOLIAGE),
522 WC_NDRY, TT_HOT, MC_LOW, 50);
523 PLACE_ONE_TYPE(deserts_count, alt_deserts_count,
524 pick_terrain(MG_DRY, MG_TROPICAL, MG_COLD),
525 WC_DRY, TT_NFROZEN, MC_NLOW, 80);
526 PLACE_ONE_TYPE(alt_deserts_count, plains_count,
527 pick_terrain(MG_DRY, MG_TROPICAL, MG_WET),
528 WC_ALL, TT_NFROZEN, MC_NLOW, 40);
529
530 /* make the plains and tundras */
531 if (plains_count > 0) {
532 struct tile *ptile;
533
534 /* Don't use any restriction here ! */
535 if ((ptile = rand_map_pos_characteristic(WC_ALL, TT_ALL, MC_NONE))) {
536 make_plain(ptile, &plains_count);
537 } else {
538 /* If rand_map_pos_temperature returns FALSE we may as well stop
539 * looking for plains. */
540 plains_count = 0;
541 }
542 }
543 } while (forests_count > 0 || jungles_count > 0
544 || deserts_count > 0 || alt_deserts_count > 0
545 || plains_count > 0 || swamps_count > 0 );
546}
547
548/**********************************************************************/
551 static int river_test_blocked(struct river_map *privermap,
552 struct tile *ptile,
553 struct extra_type *priver)
554{
555 if (dbv_isset(&privermap->blocked, tile_index(ptile))) {
556 return 1;
557 }
558
559 /* any un-blocked? */
560 cardinal_adjc_iterate(&(wld.map), ptile, ptile1) {
561 if (!dbv_isset(&privermap->blocked, tile_index(ptile1))) {
562 return 0;
563 }
564 } cardinal_adjc_iterate_end;
565
566 return 1; /* none non-blocked |- all blocked */
567}
568
569/**********************************************************************/
572 static int river_test_rivergrid(struct river_map *privermap,
573 struct tile *ptile,
574 struct extra_type *priver)
575{
576 return (count_river_type_tile_card(&(wld.map), ptile, priver, FALSE) > 1)
577 ? 1 : 0;
578}
579
580/**********************************************************************/
583 static int river_test_highlands(struct river_map *privermap,
584 struct tile *ptile,
585 struct extra_type *priver)
586{
587 return tile_terrain(ptile)->property[MG_MOUNTAINOUS];
588}
589
590/**********************************************************************/
593 static int river_test_adjacent_ocean(struct river_map *privermap,
594 struct tile *ptile,
595 struct extra_type *priver)
596{
597 return 100 - count_terrain_class_near_tile(&(wld.map), ptile,
598 TRUE, TRUE, TC_OCEAN);
599}
600
601/**********************************************************************/
604 static int river_test_adjacent_river(struct river_map *privermap,
605 struct tile *ptile,
606 struct extra_type *priver)
607{
608 return 100 - count_river_type_tile_card(&(wld.map), ptile, priver, TRUE);
609}
610
611/**********************************************************************/
614 static int river_test_adjacent_highlands(struct river_map *privermap,
615 struct tile *ptile,
616 struct extra_type *priver)
617{
618 int sum = 0;
619
620 adjc_iterate(&(wld.map), ptile, ptile2) {
621 sum += tile_terrain(ptile2)->property[MG_MOUNTAINOUS];
622 } adjc_iterate_end;
623
624 return sum;
625}
626
627/**********************************************************************/
630 static int river_test_swamp(struct river_map *privermap,
631 struct tile *ptile,
632 struct extra_type *priver)
633{
634 return FC_INFINITY - tile_terrain(ptile)->property[MG_WET];
635}
636
637/**********************************************************************/
640 static int river_test_adjacent_swamp(struct river_map *privermap,
641 struct tile *ptile,
642 struct extra_type *priver)
643{
644 int sum = 0;
645
646 adjc_iterate(&(wld.map), ptile, ptile2) {
647 sum += tile_terrain(ptile2)->property[MG_WET];
648 } adjc_iterate_end;
649
650 return FC_INFINITY - sum;
651}
652
653/**********************************************************************/
656 static int river_test_height_map(struct river_map *privermap,
657 struct tile *ptile,
658 struct extra_type *priver)
659{
660 return hmap(ptile);
661}
662
663/**********************************************************************/
666 static void river_blockmark(struct river_map *privermap,
667 struct tile *ptile)
668{
669 log_debug("Blockmarking (%d, %d) and adjacent tiles.", TILE_XY(ptile));
670
671 dbv_set(&privermap->blocked, tile_index(ptile));
672
673 cardinal_adjc_iterate(&(wld.map), ptile, ptile1) {
674 dbv_set(&privermap->blocked, tile_index(ptile1));
675 } cardinal_adjc_iterate_end;
676}
677
678 struct test_func {
679 int (*func)(struct river_map *privermap, struct tile *ptile, struct extra_type *priver);
680 bool fatal;
681};
682
683#define NUM_TEST_FUNCTIONS 9
684 static struct test_func test_funcs[NUM_TEST_FUNCTIONS] = {
685 {river_test_blocked, TRUE},
686 {river_test_rivergrid, TRUE},
687 {river_test_highlands, FALSE},
688 {river_test_adjacent_ocean, FALSE},
689 {river_test_adjacent_river, FALSE},
690 {river_test_adjacent_highlands, FALSE},
691 {river_test_swamp, FALSE},
692 {river_test_adjacent_swamp, FALSE},
693 {river_test_height_map, FALSE}
694};
695
696/**********************************************************************/
786 static bool make_river(struct river_map *privermap, struct tile *ptile,
787 struct extra_type *priver)
788{
789 /* Comparison value for each tile surrounding the current tile. It is
790 * the suitability to continue a river to the tile in that direction;
791 * lower is better. However rivers may only run in cardinal directions;
792 * the other directions are ignored entirely. */
793 int rd_comparison_val[8];
794
795 bool rd_direction_is_valid[8];
796 int num_valid_directions, func_num, direction;
797
798 while (TRUE) {
799 /* Mark the current tile as river. */
800 dbv_set(&privermap->ok, tile_index(ptile));
801 log_debug("The tile at (%d, %d) has been marked as river in river_map.",
802 TILE_XY(ptile));
803
804 /* Test if the river is done. */
805 /* We arbitrarily make rivers end at the poles. */
806 if (count_river_near_tile(&(wld.map), ptile, priver) > 0
807 || count_terrain_class_near_tile(&(wld.map), ptile,
808 TRUE, TRUE, TC_OCEAN) > 0
809 || (tile_terrain(ptile)->property[MG_FROZEN] > 0
810 && map_colatitude(ptile) < 0.8 * COLD_LEVEL)) {
811
812 log_debug("The river ended at (%d, %d).", TILE_XY(ptile));
813 return TRUE;
814 }
815
816 /* Else choose a direction to continue the river. */
817 log_debug("The river did not end at (%d, %d). Evaluating directions...",
818 TILE_XY(ptile));
819
820 /* Mark all available cardinal directions as available. */
821 memset(rd_direction_is_valid, 0, sizeof(rd_direction_is_valid));
822 cardinal_adjc_dir_base_iterate(&(wld.map), ptile, dir) {
823 rd_direction_is_valid[dir] = TRUE;
824 } cardinal_adjc_dir_base_iterate_end;
825
826 /* Test series that selects a direction for the river. */
827 for (func_num = 0; func_num < NUM_TEST_FUNCTIONS; func_num++) {
828 int best_val = -1;
829
830 /* first get the tile values for the function */
831 cardinal_adjc_dir_iterate(&(wld.map), ptile, ptile1, dir) {
832 if (rd_direction_is_valid[dir]) {
833 rd_comparison_val[dir] = (test_funcs[func_num].func)(privermap,
834 ptile1, priver);
835 fc_assert_action(rd_comparison_val[dir] >= 0, continue);
836 if (best_val == -1) {
837 best_val = rd_comparison_val[dir];
838 } else {
839 best_val = MIN(rd_comparison_val[dir], best_val);
840 }
841 }
842 } cardinal_adjc_dir_iterate_end;
843 fc_assert_action(best_val != -1, continue);
844
845 /* should we abort? */
846 if (best_val > 0 && test_funcs[func_num].fatal) {
847 return FALSE;
848 }
849
850 /* mark the less attractive directions as invalid */
851 cardinal_adjc_dir_base_iterate(&(wld.map), ptile, dir) {
852 if (rd_direction_is_valid[dir]) {
853 if (rd_comparison_val[dir] != best_val) {
854 rd_direction_is_valid[dir] = FALSE;
855 }
856 }
857 } cardinal_adjc_dir_base_iterate_end;
858 }
859
860 /* Directions evaluated with all functions. Now choose the best
861 direction before going to the next iteration of the while loop */
862 num_valid_directions = 0;
863 cardinal_adjc_dir_base_iterate(&(wld.map), ptile, dir) {
864 if (rd_direction_is_valid[dir]) {
865 num_valid_directions++;
866 }
867 } cardinal_adjc_dir_base_iterate_end;
868
869 if (num_valid_directions == 0) {
870 return FALSE; /* river aborted */
871 }
872
873 /* One or more valid directions: choose randomly. */
874 log_debug("mapgen.c: Had to let the random number"
875 " generator select a direction for a river.");
876 direction = fc_rand(num_valid_directions);
877 log_debug("mapgen.c: direction: %d", direction);
878
879 /* Find the direction that the random number generator selected. */
880 cardinal_adjc_dir_iterate(&(wld.map), ptile, tile1, dir) {
881 if (rd_direction_is_valid[dir]) {
882 if (direction > 0) {
883 direction--;
884 } else {
885 river_blockmark(privermap, ptile);
886 ptile = tile1;
887 break;
888 }
889 }
890 } cardinal_adjc_dir_iterate_end;
891 fc_assert_ret_val(direction == 0, FALSE);
892
893 } /* end while; (Make a river.) */
894}
895
896/**********************************************************************/
900 static void make_rivers(void)
901{
902 struct tile *ptile;
903 struct terrain *pterrain;
904 struct river_map rivermap;
905 struct extra_type *road_river = NULL;
906
907 /* Formula to make the river density similar om different sized maps. Avoids
908 too few rivers on large maps and too many rivers on small maps. */
909 int desirable_riverlength =
910 river_pct *
911 /* The size of the map (poles counted in river_pct). */
912 map_num_tiles() *
913 /* Rivers need to be on land only. */
914 wld.map.server.landpercent /
915 /* Adjustment value. Tested by me. Gives no rivers with 'set
916 rivers 0', gives a reasonable amount of rivers with default
917 settings and as many rivers as possible with 'set rivers 100'. */
918 5325;
919
920 /* The number of river tiles that have been set. */
921 int current_riverlength = 0;
922
923 /* Counts the number of iterations (should increase with 1 during
924 every iteration of the main loop in this function).
925 Is needed to stop a potentially infinite loop. */
926 int iteration_counter = 0;
927
928 if (river_type_count <= 0) {
929 /* No river type available */
930 return;
931 }
932
933 create_placed_map(); /* needed bu rand_map_characteristic */
934 set_all_ocean_tiles_placed();
935
936 dbv_init(&rivermap.blocked, MAP_INDEX_SIZE);
937 dbv_init(&rivermap.ok, MAP_INDEX_SIZE);
938
939 /* The main loop in this function. */
940 while (current_riverlength < desirable_riverlength
941 && iteration_counter < RIVERS_MAXTRIES) {
942
943 if (!(ptile = rand_map_pos_characteristic(WC_ALL, TT_NFROZEN,
944 MC_NLOW))) {
945 break; /* No more spring places */
946 }
947 pterrain = tile_terrain(ptile);
948
949 /* Check if it is suitable to start a river on the current tile.
950 */
951 if (
952 /* Don't start a river on ocean. */
953 !is_ocean(pterrain)
954
955 /* Don't start a river on river. */
956 && !tile_has_river(ptile)
957
958 /* Don't start a river on a tile is surrounded by > 1 river +
959 ocean tile. */
960 && (count_river_near_tile(&(wld.map), ptile, NULL)
961 + count_terrain_class_near_tile(&(wld.map), ptile,
962 TRUE, FALSE, TC_OCEAN) <= 1)
963
964 /* Don't start a river on a tile that is surrounded by hills or
965 mountains unless it is hard to find somewhere else to start
966 it. */
967 && (count_terrain_property_near_tile(&(wld.map), ptile, TRUE, TRUE,
968 MG_MOUNTAINOUS) < 90
969 || iteration_counter >= RIVERS_MAXTRIES / 10 * 5)
970
971 /* Don't start a river on hills unless it is hard to find
972 somewhere else to start it. */
973 && (pterrain->property[MG_MOUNTAINOUS] == 0
974 || iteration_counter >= RIVERS_MAXTRIES / 10 * 6)
975
976 /* Don't start a river on arctic unless it is hard to find
977 somewhere else to start it. */
978 && (pterrain->property[MG_FROZEN] == 0
979 || iteration_counter >= RIVERS_MAXTRIES / 10 * 8)
980
981 /* Don't start a river on desert unless it is hard to find
982 somewhere else to start it. */
983 && (pterrain->property[MG_DRY] == 0
984 || iteration_counter >= RIVERS_MAXTRIES / 10 * 9)) {
985
986 /* Reset river map before making a new river. */
987 dbv_clr_all(&rivermap.blocked);
988 dbv_clr_all(&rivermap.ok);
989
990 road_river = river_types[fc_rand(river_type_count)];
991
992 extra_type_by_cause_iterate(EC_ROAD, oriver) {
993 if (oriver != road_river) {
994 whole_map_iterate(&(wld.map), rtile) {
995 if (tile_has_extra(rtile, oriver)) {
996 dbv_set(&rivermap.blocked, tile_index(rtile));
997 }
998 } whole_map_iterate_end;
999 }
1000 } extra_type_by_cause_iterate_end;
1001
1002 log_debug("Found a suitable starting tile for a river at (%d, %d)."
1003 " Starting to make it.", TILE_XY(ptile));
1004
1005 /* Try to make a river. If it is OK, apply it to the map. */
1006 if (make_river(&rivermap, ptile, road_river)) {
1007 whole_map_iterate(&(wld.map), ptile1) {
1008 if (dbv_isset(&rivermap.ok, tile_index(ptile1))) {
1009 struct terrain *river_terrain = tile_terrain(ptile1);
1010
1011 if (!terrain_has_flag(river_terrain, TER_CAN_HAVE_RIVER)) {
1012 /* We have to change the terrain to put a river here. */
1013 river_terrain = pick_terrain_by_flag(TER_CAN_HAVE_RIVER);
1014 if (river_terrain != NULL) {
1015 tile_set_terrain(ptile1, river_terrain);
1016 }
1017 }
1018
1019 tile_add_extra(ptile1, road_river);
1020 current_riverlength++;
1021 map_set_placed(ptile1);
1022 log_debug("Applied a river to (%d, %d).", TILE_XY(ptile1));
1023 }
1024 } whole_map_iterate_end;
1025 } else {
1026 log_debug("mapgen.c: A river failed. It might have gotten stuck "
1027 "in a helix.");
1028 }
1029 } /* end if; */
1030 iteration_counter++;
1031 log_debug("current_riverlength: %d; desirable_riverlength: %d; "
1032 "iteration_counter: %d",
1033 current_riverlength, desirable_riverlength, iteration_counter);
1034 } /* end while; */
1035
1036 dbv_free(&rivermap.blocked);
1037 dbv_free(&rivermap.ok);
1038
1039 destroy_placed_map();
1040}
1041
1042/**********************************************************************/
1047 static void make_land(void)
1048{
1049 struct terrain *land_fill = NULL;
1050
1051 if (HAS_POLES) {
1052 normalize_hmap_poles();
1053 }
1054
1055 /* Pick a non-ocean terrain just once and fill all land tiles with "
1056 * that terrain. We must set some terrain (and not T_UNKNOWN) so that "
1057 * continent number assignment works. */
1058 terrain_type_iterate(pterrain) {
1059 if (!is_ocean(pterrain) && !terrain_has_flag(pterrain, TER_NOT_GENERATED)) {
1060 land_fill = pterrain;
1061 break;
1062 }
1063 } terrain_type_iterate_end;
1064
1065 fc_assert_exit_msg(NULL != land_fill,
1066 "No land terrain type could be found for the purpose "
1067 "of temporarily filling in land tiles during map "
1068 "generation. This could be an error in Freeciv, or a "
1069 "mistake in the terrain.ruleset file. Please make sure "
1070 "there is at least one land terrain type in the "
1071 "ruleset, or use a different map generator. If this "
1072 "error persists, please report it at: %s", BUG_URL);
1073
1074 hmap_shore_level = (hmap_max_level * (100 - wld.map.server.landpercent)) / 100;
1075 ini_hmap_low_level();
1076 whole_map_iterate(&(wld.map), ptile) {
1077 tile_set_terrain(ptile, T_UNKNOWN); /* set as oceans count is used */
1078 if (hmap(ptile) < hmap_shore_level) {
1079 int depth = (hmap_shore_level - hmap(ptile)) * 100 / hmap_shore_level;
1080 int ocean = 0;
1081 int land = 0;
1082
1083 /* This is to make shallow connection between continents less likely */
1084 adjc_iterate(&(wld.map), ptile, other) {
1085 if (hmap(other) < hmap_shore_level) {
1086 ocean++;
1087 } else {
1088 land++;
1089 break;
1090 }
1091 } adjc_iterate_end;
1092
1093 depth += 30 * (ocean - land) / MAX(1, (ocean + land));
1094
1095 depth = MIN(depth, TERRAIN_OCEAN_DEPTH_MAXIMUM);
1096
1097 /* Generate sea ice here, if ruleset supports it. Dummy temperature
1098 * map is sufficient for this. If ruleset doesn't support it,
1099 * use unfrozen ocean; make_polar_land() will later fill in with
1100 * land-based ice. Ice has a ragged margin. */
1101 {
1102 bool frozen = HAS_POLES
1103 && (tmap_is(ptile, TT_FROZEN)
1104 || (tmap_is(ptile, TT_COLD)
1105 && fc_rand(10) > 7
1106 && is_temperature_type_near(ptile, TT_FROZEN)));
1107 struct terrain *pterrain = pick_ocean(depth, frozen);
1108
1109 if (frozen && !pterrain) {
1110 pterrain = pick_ocean(depth, FALSE);
1111 fc_assert(pterrain);
1112 }
1113 tile_set_terrain(ptile, pterrain);
1114 }
1115 } else {
1116 /* See note above for 'land_fill'. */
1117 tile_set_terrain(ptile, land_fill);
1118 }
1119 } whole_map_iterate_end;
1120
1121 if (HAS_POLES) {
1122 renormalize_hmap_poles();
1123 }
1124
1125 /* destroy old dummy temperature map ... */
1126 destroy_tmap();
1127 /* ... and create a real temperature map (needs hmap and oceans) */
1128 create_tmap(TRUE);
1129
1130 if (HAS_POLES) { /* this is a hack to terrains set with not frizzed oceans*/
1131 make_polar_land(); /* make extra land at poles*/
1132 }
1133
1134 create_placed_map(); /* here it means land terrains to be placed */
1135 set_all_ocean_tiles_placed();
1136 if (MAPGEN_FRACTURE == wld.map.server.generator) {
1137 make_fracture_relief();
1138 } else {
1139 make_relief(); /* base relief on map */
1140 }
1141 make_terrains(); /* place all exept mountains and hill */
1142 destroy_placed_map();
1143
1144 make_rivers(); /* use a new placed_map. destroy older before call */
1145}
1146
1147/**********************************************************************/
1150 static bool is_tiny_island(struct tile *ptile)
1151{
1152 struct terrain *pterrain = tile_terrain(ptile);
1153
1154 if (is_ocean(pterrain) || pterrain->property[MG_FROZEN] > 0) {
1155 /* The arctic check is needed for iso-maps: the poles may not have
1156 * any cardinally adjacent land tiles, but that's okay. */
1157 return FALSE;
1158 }
1159
1160 adjc_iterate(&(wld.map), ptile, tile1) {
1161 /* This was originally a cardinal_adjc_iterate, which seemed to cause
1162 * two or three problems. /MSS */
1163 if (!is_ocean_tile(tile1)) {
1164 return FALSE;
1165 }
1166 } adjc_iterate_end;
1167
1168 return TRUE;
1169}
1170
1171/**********************************************************************/
1176 static void remove_tiny_islands(void)
1177{
1178 whole_map_iterate(&(wld.map), ptile) {
1179 if (is_tiny_island(ptile)) {
1180 struct terrain *shallow
1181 = most_shallow_ocean(terrain_has_flag(tile_terrain(ptile), TER_FROZEN));
1182
1183 fc_assert_ret(NULL != shallow);
1184 tile_set_terrain(ptile, shallow);
1185 extra_type_by_cause_iterate(EC_ROAD, priver) {
1186 if (tile_has_extra(ptile, priver)
1187 && road_has_flag(extra_road_get(priver), RF_RIVER)) {
1188 tile_extra_rm_apply(ptile, priver);
1189 }
1190 } extra_type_by_cause_iterate_end;
1191 tile_set_continent(ptile, 0);
1192 }
1193 } whole_map_iterate_end;
1194}
1195
1196/**********************************************************************/
1200 static void print_mapgen_map(void)
1201{
1202 int terrain_counts[terrain_count()];
1203 int total = 0, ocean = 0;
1204
1205 terrain_type_iterate(pterrain) {
1206 terrain_counts[terrain_index(pterrain)] = 0;
1207 } terrain_type_iterate_end;
1208
1209 whole_map_iterate(&(wld.map), ptile) {
1210 struct terrain *pterrain = tile_terrain(ptile);
1211
1212 terrain_counts[terrain_index(pterrain)]++;
1213 if (is_ocean(pterrain)) {
1214 ocean++;
1215 }
1216 total++;
1217 } whole_map_iterate_end;
1218
1219 log_verbose("map settings:");
1220 log_verbose(" %-20s : %5d%%", "mountain_pct", mountain_pct);
1221 log_verbose(" %-20s : %5d%%", "desert_pct", desert_pct);
1222 log_verbose(" %-20s : %5d%%", "forest_pct", forest_pct);
1223 log_verbose(" %-20s : %5d%%", "jungle_pct", jungle_pct);
1224 log_verbose(" %-20s : %5d%%", "swamp_pct", swamp_pct);
1225
1226 log_verbose("map statistics:");
1227 terrain_type_iterate(pterrain) {
1228 if (is_ocean(pterrain)) {
1229 log_verbose(" %-20s : %6d %5.1f%% (ocean: %5.1f%%)",
1230 terrain_rule_name(pterrain),
1231 terrain_counts[terrain_index(pterrain)],
1232 (float) terrain_counts[terrain_index(pterrain)] * 100
1233 / total,
1234 (float) terrain_counts[terrain_index(pterrain)] * 100
1235 / ocean);
1236 } else {
1237 log_verbose(" %-20s : %6d %5.1f%% (land: %5.1f%%)",
1238 terrain_rule_name(pterrain),
1239 terrain_counts[terrain_index(pterrain)],
1240 (float) terrain_counts[terrain_index(pterrain)] * 100
1241 / total,
1242 (float) terrain_counts[terrain_index(pterrain)] * 100
1243 / (total - ocean));
1244 }
1245 } terrain_type_iterate_end;
1246}
1247
1248/**********************************************************************/
1261 bool map_fractal_generate(bool autosize, struct unit_type *initial_unit)
1262{
1263 /* save the current random state: */
1264 RANDOM_STATE rstate;
1265 RANDOM_TYPE seed_rand;
1266
1267 /* Call fc_rand() even when result is not needed to make sure
1268 * random state proceeds equally for random seeds and explicitly
1269 * set seed. */
1270 seed_rand = fc_rand(MAX_UINT32);
1271
1272 if (wld.map.server.seed_setting == 0) {
1273 /* Create a "random" map seed. */
1274 wld.map.server.seed = seed_rand & (MAX_UINT32 >> 1);
1275#ifdef FREECIV_TESTMATIC
1276 /* Log command to reproduce the mapseed */
1277 log_testmatic("set mapseed %d", wld.map.server.seed);
1278#else /* FREECIV_TESTMATICE */
1279 log_debug("Setting map.seed:%d", wld.map.server.seed);
1280#endif /* FREECIV_TESTMATIC */
1281 } else {
1282 wld.map.server.seed = wld.map.server.seed_setting;
1283 }
1284
1285 rstate = fc_rand_state();
1286
1287 fc_srand(wld.map.server.seed);
1288
1289 /* don't generate tiles with mapgen == MAPGEN_SCENARIO as we've loaded *
1290 them from file.
1291 Also, don't delete (the handcrafted!) tiny islands in a scenario */
1292 if (wld.map.server.generator != MAPGEN_SCENARIO) {
1293 wld.map.server.have_huts = FALSE;
1294 river_types_init();
1295
1296 generator_init_topology(autosize);
1297 /* Map can be already allocated, if we failed first map generation */
1298 if (map_is_empty()) {
1299 main_map_allocate();
1300 }
1301 adjust_terrain_param();
1302 /* if one mapgenerator fails, it will choose another mapgenerator */
1303 /* with a lower number to try again */
1304
1305 /* create a temperature map */
1306 create_tmap(FALSE);
1307
1308 if (MAPGEN_FAIR == wld.map.server.generator
1309 && !map_generate_fair_islands()) {
1310 wld.map.server.generator = MAPGEN_ISLAND;
1311 }
1312
1313 if (MAPGEN_ISLAND == wld.map.server.generator) {
1314 /* initialise terrain selection lists used by make_island() */
1315 island_terrain_init();
1316
1317 /* 2 or 3 players per isle? */
1318 if (MAPSTARTPOS_2or3 == wld.map.server.startpos
1319 || MAPSTARTPOS_ALL == wld.map.server.startpos) {
1320 mapgenerator4();
1321 }
1322 if (MAPSTARTPOS_DEFAULT == wld.map.server.startpos
1323 || MAPSTARTPOS_SINGLE == wld.map.server.startpos) {
1324 /* Single player per isle. */
1325 mapgenerator3();
1326 }
1327 if (MAPSTARTPOS_VARIABLE == wld.map.server.startpos) {
1328 /* "Variable" single player. */
1329 mapgenerator2();
1330 }
1331
1332 /* free terrain selection lists used by make_island() */
1333 island_terrain_free();
1334 }
1335
1336 if (MAPGEN_FRACTAL == wld.map.server.generator) {
1337 make_pseudofractal1_hmap(1 +
1338 ((MAPSTARTPOS_DEFAULT == wld.map.server.startpos
1339 || MAPSTARTPOS_ALL == wld.map.server.startpos)
1340 ? 0 : player_count()));
1341 }
1342
1343 if (MAPGEN_RANDOM == wld.map.server.generator) {
1344 make_random_hmap(MAX(1, 1 + get_sqsize()
1345 - (MAPSTARTPOS_DEFAULT != wld.map.server.startpos
1346 ? player_count() / 4 : 0)));
1347 }
1348
1349 if (MAPGEN_FRACTURE == wld.map.server.generator) {
1350 make_fracture_map();
1351 }
1352
1353 /* if hmap only generator make anything else */
1354 if (MAPGEN_RANDOM == wld.map.server.generator
1355 || MAPGEN_FRACTAL == wld.map.server.generator
1356 || MAPGEN_FRACTURE == wld.map.server.generator) {
1357
1358 make_land();
1359 free(height_map);
1360 height_map = NULL;
1361 }
1362 if (!wld.map.server.tinyisles) {
1363 remove_tiny_islands();
1364 }
1365
1366 smooth_water_depth();
1367
1368 /* Continent numbers must be assigned before regenerate_lakes() */
1369 assign_continent_numbers();
1370
1371 /* Turn small oceans into lakes. */
1372 if (wld.map.num_oceans > 0) {
1373 regenerate_lakes();
1374 }
1375
1376 } else {
1377 assign_continent_numbers();
1378 }
1379
1380 /* create a temperature map if it was not done before */
1381 if (!temperature_is_initialized()) {
1382 create_tmap(FALSE);
1383 }
1384
1385 /* some scenarios already provide specials */
1386 if (!wld.map.server.have_resources) {
1387 add_resources(wld.map.server.riches);
1388 }
1389
1390 if (!wld.map.server.have_huts) {
1391 make_huts(wld.map.server.huts * map_num_tiles() / 1000);
1392 }
1393
1394 /* restore previous random state: */
1395 fc_rand_set_state(rstate);
1396
1397 /* We don't want random start positions in a scenario which already
1398 * provides them. */
1399 if (0 == map_startpos_count()) {
1400 enum map_startpos mode = MAPSTARTPOS_ALL;
1401
1402 switch (wld.map.server.generator) {
1403 case MAPGEN_FAIR:
1404 fc_assert_msg(FALSE,
1405 "Fair island generator failed to allocated "
1406 "start positions!");
1407 break;
1408 case MAPGEN_SCENARIO:
1409 case MAPGEN_RANDOM:
1410 case MAPGEN_FRACTURE:
1411 mode = wld.map.server.startpos;
1412 break;
1413 case MAPGEN_FRACTAL:
1414 if (wld.map.server.startpos == MAPSTARTPOS_DEFAULT) {
1415 log_verbose("Map generator chose startpos=ALL");
1416 mode = MAPSTARTPOS_ALL;
1417 } else {
1418 mode = wld.map.server.startpos;
1419 }
1420 break;
1421 case MAPGEN_ISLAND:
1422 switch (wld.map.server.startpos) {
1423 case MAPSTARTPOS_DEFAULT:
1424 case MAPSTARTPOS_VARIABLE:
1425 log_verbose("Map generator chose startpos=SINGLE");
1426
1427 fc__fallthrough;
1428 case MAPSTARTPOS_SINGLE:
1429 mode = MAPSTARTPOS_SINGLE;
1430 break;
1431 default:
1432 log_verbose("Map generator chose startpos=2or3");
1433
1434 fc__fallthrough;
1435 case MAPSTARTPOS_2or3:
1436 mode = MAPSTARTPOS_2or3;
1437 break;
1438 }
1439 break;
1440 }
1441
1442 for (;;) {
1443 bool success;
1444
1445 success = create_start_positions(mode, initial_unit);
1446 if (success) {
1447 wld.map.server.startpos = mode;
1448 break;
1449 }
1450
1451 switch (mode) {
1452 case MAPSTARTPOS_SINGLE:
1453 log_verbose("Falling back to startpos=2or3");
1454 mode = MAPSTARTPOS_2or3;
1455 continue;
1456 case MAPSTARTPOS_2or3:
1457 log_verbose("Falling back to startpos=ALL");
1458 mode = MAPSTARTPOS_ALL;
1459 break;
1460 case MAPSTARTPOS_ALL:
1461 log_verbose("Falling back to startpos=VARIABLE");
1462 mode = MAPSTARTPOS_VARIABLE;
1463 break;
1464 default:
1465 log_error(_("The server couldn't allocate starting positions."));
1466 destroy_tmap();
1467 return FALSE;
1468 }
1469 }
1470 }
1471
1472 /* destroy temperature map */
1473 destroy_tmap();
1474
1475 print_mapgen_map();
1476
1477 return TRUE;
1478}
1479
1480/**********************************************************************/
1484 static void adjust_terrain_param(void)
1485{
1486 int polar = 2 * ICE_BASE_LEVEL * wld.map.server.landpercent / MAX_COLATITUDE;
1487 float mount_factor = (100.0 - polar - 30 * 0.8) / 10000;
1488 float factor = (100.0 - polar - wld.map.server.steepness * 0.8) / 10000;
1489
1490 mountain_pct = mount_factor * wld.map.server.steepness * 90;
1491
1492 /* 27 % if wetness == 50 & */
1493 forest_pct = factor * (wld.map.server.wetness * 40 + 700);
1494 jungle_pct = forest_pct * (MAX_COLATITUDE - TROPICAL_LEVEL)
1495 / (MAX_COLATITUDE * 2);
1496 forest_pct -= jungle_pct;
1497
1498 /* 3 - 11 % */
1499 river_pct = (100 - polar) * (3 + wld.map.server.wetness / 12) / 100;
1500
1501 /* 7 % if wetness == 50 && temperature == 50 */
1502 swamp_pct = factor * MAX(0, (wld.map.server.wetness * 12 - 150
1503 + wld.map.server.temperature * 10));
1504 desert_pct = factor * MAX(0, (wld.map.server.temperature * 15 - 250
1505 + (100 - wld.map.server.wetness) * 10));
1506}
1507
1508/**********************************************************************/
1512 static bool near_safe_tiles(struct tile *ptile)
1513{
1514 square_iterate(&(wld.map), ptile, 1, tile1) {
1515 if (!terrain_has_flag(tile_terrain(tile1), TER_UNSAFE_COAST)) {
1516 return TRUE;
1517 }
1518 } square_iterate_end;
1519
1520 return FALSE;
1521}
1522
1523/**********************************************************************/
1527 static void make_huts(int number)
1528{
1529 int count = 0;
1530 struct tile *ptile;
1531
1532 create_placed_map(); /* here it means placed huts */
1533
1534 while (number > 0 && count++ < map_num_tiles() * 2) {
1535
1536 /* Add a hut. But not too close to another hut. */
1537 if ((ptile = rand_map_pos_characteristic(WC_ALL, TT_ALL, MC_NONE))) {
1538 struct extra_type *phut = rand_extra_for_tile(ptile, EC_HUT, TRUE);
1539
1540 number--;
1541 if (phut != NULL) {
1542 tile_add_extra(ptile, phut);
1543 }
1544 set_placed_near_pos(ptile, 3);
1545 }
1546 }
1547 destroy_placed_map();
1548}
1549
1550/**********************************************************************/
1554 static bool is_resource_close(const struct tile *ptile)
1555{
1556 square_iterate(&(wld.map), ptile, 1, tile1) {
1557 if (NULL != tile_resource(tile1)) {
1558 return TRUE;
1559 }
1560 } square_iterate_end;
1561
1562 return FALSE;
1563}
1564
1565/**********************************************************************/
1568 static void add_resources(int prob)
1569{
1570 whole_map_iterate(&(wld.map), ptile) {
1571 const struct terrain *pterrain = tile_terrain(ptile);
1572
1573 if (is_resource_close(ptile) || fc_rand (1000) >= prob) {
1574 continue;
1575 }
1576 if (!is_ocean(pterrain) || near_safe_tiles(ptile)
1577 || wld.map.server.ocean_resources) {
1578 struct extra_type *res = pick_resource(pterrain);
1579
1580 if (NULL != res) {
1581 tile_set_resource(ptile, res);
1582 }
1583 }
1584 } whole_map_iterate_end;
1585
1586 wld.map.server.have_resources = TRUE;
1587}
1588
1589/**********************************************************************/
1592 static struct tile *get_random_map_position_from_state(
1593 const struct gen234_state *const pstate)
1594{
1595 int xrnd, yrnd;
1596
1597 fc_assert_ret_val((pstate->e - pstate->w) > 0, NULL);
1598 fc_assert_ret_val((pstate->e - pstate->w) < wld.map.xsize, NULL);
1599 fc_assert_ret_val((pstate->s - pstate->n) > 0, NULL);
1600 fc_assert_ret_val((pstate->s - pstate->n) < wld.map.ysize, NULL);
1601
1602 xrnd = pstate->w + fc_rand(pstate->e - pstate->w);
1603 yrnd = pstate->n + fc_rand(pstate->s - pstate->n);
1604
1605 return native_pos_to_tile(&(wld.map), xrnd, yrnd);
1606}
1607
1608/**********************************************************************/
1611 static struct terrain_select *tersel_new(int weight,
1612 enum mapgen_terrain_property target,
1613 enum mapgen_terrain_property prefer,
1614 enum mapgen_terrain_property avoid,
1615 int temp_condition,
1616 int wet_condition)
1617{
1618 struct terrain_select *ptersel = fc_malloc(sizeof(*ptersel));
1619
1620 ptersel->weight = weight;
1621 ptersel->target = target;
1622 ptersel->prefer = prefer;
1623 ptersel->avoid = avoid;
1624 ptersel->temp_condition = temp_condition;
1625 ptersel->wet_condition = wet_condition;
1626
1627 return ptersel;
1628}
1629
1630/**********************************************************************/
1633 static void tersel_free(struct terrain_select *ptersel)
1634{
1635 if (ptersel != NULL) {
1636 FC_FREE(ptersel);
1637 }
1638}
1639
1640/**********************************************************************/
1643 static void fill_island(int coast, long int *bucket,
1644 const struct terrain_select_list *tersel_list,
1645 const struct gen234_state *const pstate)
1646{
1647 int i, k, capac, total_weight = 0;
1648 int ntersel = terrain_select_list_size(tersel_list);
1649 long int failsafe;
1650
1651 if (*bucket <= 0 ) {
1652 return;
1653 }
1654
1655 /* must have at least one terrain selection given in tersel_list */
1656 fc_assert_ret(ntersel != 0);
1657
1658 capac = pstate->totalmass;
1659 i = *bucket / capac;
1660 i++;
1661 *bucket -= i * capac;
1662
1663 k = i;
1664 failsafe = i * (pstate->s - pstate->n) * (pstate->e - pstate->w);
1665 if (failsafe < 0) {
1666 failsafe = -failsafe;
1667 }
1668
1669 terrain_select_list_iterate(tersel_list, ptersel) {
1670 total_weight += ptersel->weight;
1671 } terrain_select_list_iterate_end;
1672
1673 if (total_weight <= 0) {
1674 return;
1675 }
1676
1677 while (i > 0 && (failsafe--) > 0) {
1678 struct tile *ptile = get_random_map_position_from_state(pstate);
1679
1680 if (tile_continent(ptile) != pstate->isleindex || !not_placed(ptile)) {
1681 continue;
1682 }
1683
1684 struct terrain_select *ptersel
1685 = terrain_select_list_get(tersel_list, fc_rand(ntersel));
1686
1687 if (fc_rand(total_weight) > ptersel->weight) {
1688 continue;
1689 }
1690
1691 if (!tmap_is(ptile, ptersel->temp_condition)
1692 || !test_wetness(ptile, ptersel->wet_condition)) {
1693 continue;
1694 }
1695
1696 struct terrain *pterrain = pick_terrain(ptersel->target, ptersel->prefer,
1697 ptersel->avoid);
1698
1699 /* The first condition helps make terrain more contiguous,
1700 the second lets it avoid the coast: */
1701 if ((i * 3 > k * 2
1702 || fc_rand(100) < 50
1703 || is_terrain_near_tile(&(wld.map), ptile, pterrain, FALSE))
1704 && (!is_terrain_class_card_near(&(wld.map), ptile, TC_OCEAN)
1705 || fc_rand(100) < coast)) {
1706 tile_set_terrain(ptile, pterrain);
1707 map_set_placed(ptile);
1708
1709 log_debug("[fill_island] placed terrain '%s' at (%2d,%2d)",
1710 terrain_rule_name(pterrain), TILE_XY(ptile));
1711 }
1712
1713 if (!not_placed(ptile)) {
1714 i--;
1715 }
1716 }
1717}
1718
1719/**********************************************************************/
1722 static bool island_river_mouth_suitability(const struct tile *ptile,
1723 const struct extra_type *priver)
1724{
1725 int num_card_ocean, pct_adj_ocean, num_adj_river;
1726
1727 num_card_ocean = count_terrain_class_near_tile(&(wld.map), ptile,
1728 C_CARDINAL, C_NUMBER,
1729 TC_OCEAN);
1730 pct_adj_ocean = count_terrain_class_near_tile(&(wld.map), ptile,
1731 C_ADJACENT, C_PERCENT,
1732 TC_OCEAN);
1733 num_adj_river = count_river_type_tile_card(&(wld.map), ptile, priver, FALSE);
1734
1735 return (num_card_ocean == 1 && pct_adj_ocean <= 35
1736 && num_adj_river == 0);
1737}
1738
1739/**********************************************************************/
1743 static bool island_river_suitability(const struct tile *ptile,
1744 const struct extra_type *priver)
1745{
1746 int pct_adj_ocean, num_card_ocean, pct_adj_river, num_card_river;
1747
1748 num_card_river = count_river_type_tile_card(&(wld.map), ptile, priver, FALSE);
1749 num_card_ocean = count_terrain_class_near_tile(&(wld.map), ptile,
1750 C_CARDINAL, C_NUMBER,
1751 TC_OCEAN);
1752 pct_adj_ocean = count_terrain_class_near_tile(&(wld.map), ptile,
1753 C_ADJACENT, C_PERCENT,
1754 TC_OCEAN);
1755 pct_adj_river = count_river_type_near_tile(&(wld.map), ptile, priver, TRUE);
1756
1757 return (num_card_river == 1 && num_card_ocean == 0
1758 && pct_adj_ocean < 20 && pct_adj_river < 35
1759 /* The following expression helps with straightness,
1760 * ocean avoidance, and reduces forking. */
1761 && (pct_adj_river + pct_adj_ocean * 2) < fc_rand(25) + 25);
1762}
1763
1764/**********************************************************************/
1767 static void fill_island_rivers(int coast, long int *bucket,
1768 const struct gen234_state *const pstate)
1769{
1770 long int failsafe, capac, i, k;
1771 struct tile *ptile;
1772
1773 if (*bucket <= 0) {
1774 return;
1775 }
1776 if (river_type_count <= 0) {
1777 return;
1778 }
1779
1780 capac = pstate->totalmass;
1781 i = *bucket / capac;
1782 i++;
1783 *bucket -= i * capac;
1784
1785 /* Generate 75% more rivers than generator 1 */
1786 i = (i * 175) / 100;
1787
1788 k = i;
1789 failsafe = i * (pstate->s - pstate->n) * (pstate->e - pstate->w) * 5;
1790 if (failsafe < 0) {
1791 failsafe = -failsafe;
1792 }
1793
1794 while (i > 0 && failsafe-- > 0) {
1795 struct extra_type *priver;
1796
1797 ptile = get_random_map_position_from_state(pstate);
1798 if (tile_continent(ptile) != pstate->isleindex
1799 || tile_has_river(ptile)) {
1800 continue;
1801 }
1802
1803 priver = river_types[fc_rand(river_type_count)];
1804
1805 if (test_wetness(ptile, WC_DRY) && fc_rand(100) < 50) {
1806 /* rivers don't like dry locations */
1807 continue;
1808 }
1809
1810 if ((island_river_mouth_suitability(ptile, priver)
1811 && (fc_rand(100) < coast || i == k))
1812 || island_river_suitability(ptile, priver)) {
1813 tile_add_extra(ptile, priver);
1814 i--;
1815 }
1816 }
1817}
1818
1819/**********************************************************************/
1823 static bool is_near_land(struct tile *ptile)
1824{
1825 /* Note this function may sometimes be called on land tiles. */
1826 adjc_iterate(&(wld.map), ptile, tile1) {
1827 if (!is_ocean(tile_terrain(tile1))) {
1828 return TRUE;
1829 }
1830 } adjc_iterate_end;
1831
1832 return FALSE;
1833}
1834
1835 static long int checkmass;
1836
1837/**********************************************************************/
1840 static bool place_island(struct gen234_state *pstate)
1841{
1842 int i = 0, xcur, ycur, nat_x, nat_y;
1843 struct tile *ptile;
1844
1845 ptile = rand_map_pos(&(wld.map));
1846 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
1847
1848 /* this helps a lot for maps with high landmass */
1849 for (ycur = pstate->n, xcur = pstate->w;
1850 ycur < pstate->s && xcur < pstate->e;
1851 ycur++, xcur++) {
1852 struct tile *tile0 = native_pos_to_tile(&(wld.map), xcur, ycur);
1853 struct tile *tile1 = native_pos_to_tile(&(wld.map),
1854 xcur + nat_x - pstate->w,
1855 ycur + nat_y - pstate->n);
1856
1857 if (!tile0 || !tile1) {
1858 return FALSE;
1859 }
1860 if (hmap(tile0) != 0 && is_near_land(tile1)) {
1861 return FALSE;
1862 }
1863 }
1864
1865 for (ycur = pstate->n; ycur < pstate->s; ycur++) {
1866 for (xcur = pstate->w; xcur < pstate->e; xcur++) {
1867 struct tile *tile0 = native_pos_to_tile(&(wld.map), xcur, ycur);
1868 struct tile *tile1 = native_pos_to_tile(&(wld.map),
1869 xcur + nat_x - pstate->w,
1870 ycur + nat_y - pstate->n);
1871
1872 if (!tile0 || !tile1) {
1873 return FALSE;
1874 }
1875 if (hmap(tile0) != 0 && is_near_land(tile1)) {
1876 return FALSE;
1877 }
1878 }
1879 }
1880
1881 for (ycur = pstate->n; ycur < pstate->s; ycur++) {
1882 for (xcur = pstate->w; xcur < pstate->e; xcur++) {
1883 if (hmap(native_pos_to_tile(&(wld.map), xcur, ycur)) != 0) {
1884 struct tile *tile1 = native_pos_to_tile(&(wld.map),
1885 xcur + nat_x - pstate->w,
1886 ycur + nat_y - pstate->n);
1887
1888 checkmass--;
1889 if (checkmass <= 0) {
1890 log_error("mapgen.c: mass doesn't sum up.");
1891 return i != 0;
1892 }
1893
1894 tile_set_terrain(tile1, T_UNKNOWN);
1895 map_unset_placed(tile1);
1896
1897 tile_set_continent(tile1, pstate->isleindex);
1898 i++;
1899 }
1900 }
1901 }
1902
1903 pstate->s += nat_y - pstate->n;
1904 pstate->e += nat_x - pstate->w;
1905 pstate->n = nat_y;
1906 pstate->w = nat_x;
1907
1908 return i != 0;
1909}
1910
1911/**********************************************************************/
1914 static int count_card_adjc_elevated_tiles(struct tile *ptile)
1915{
1916 int count = 0;
1917
1918 cardinal_adjc_iterate(&(wld.map), ptile, tile1) {
1919 if (hmap(tile1) != 0) {
1920 count++;
1921 }
1922 } cardinal_adjc_iterate_end;
1923
1924 return count;
1925}
1926
1927/**********************************************************************/
1930 static bool create_island(int islemass, struct gen234_state *pstate)
1931{
1932 int i, nat_x, nat_y;
1933 long int tries = islemass*(2+islemass/20)+99;
1934 bool j;
1935 struct tile *ptile = native_pos_to_tile(&(wld.map),
1936 wld.map.xsize / 2, wld.map.ysize / 2);
1937
1938 memset(height_map, '\0', MAP_INDEX_SIZE * sizeof(*height_map));
1939 hmap(native_pos_to_tile(&(wld.map),
1940 wld.map.xsize / 2, wld.map.ysize / 2)) = 1;
1941
1942 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
1943 pstate->n = nat_y - 1;
1944 pstate->w = nat_x - 1;
1945 pstate->s = nat_y + 2;
1946 pstate->e = nat_x + 2;
1947 i = islemass - 1;
1948 while (i > 0 && tries-->0) {
1949 ptile = get_random_map_position_from_state(pstate);
1950 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
1951
1952 if ((!near_singularity(ptile) || fc_rand(50) < 25 )
1953 && hmap(ptile) == 0 && count_card_adjc_elevated_tiles(ptile) > 0) {
1954 hmap(ptile) = 1;
1955 i--;
1956 if (nat_y >= pstate->s - 1 && pstate->s < wld.map.ysize - 2) {
1957 pstate->s++;
1958 }
1959 if (nat_x >= pstate->e - 1 && pstate->e < wld.map.xsize - 2) {
1960 pstate->e++;
1961 }
1962 if (nat_y <= pstate-> n && pstate->n > 2) {
1963 pstate->n--;
1964 }
1965 if (nat_x <= pstate->w && pstate->w > 2) {
1966 pstate->w--;
1967 }
1968 }
1969 if (i < islemass / 10) {
1970 int xcur, ycur;
1971
1972 for (ycur = pstate->n; ycur < pstate->s; ycur++) {
1973 for (xcur = pstate->w; xcur < pstate->e; xcur++) {
1974 ptile = native_pos_to_tile(&(wld.map), xcur, ycur);
1975 if (hmap(ptile) == 0 && i > 0
1976 && count_card_adjc_elevated_tiles(ptile) == 4) {
1977 hmap(ptile) = 1;
1978 i--;
1979 }
1980 }
1981 }
1982 }
1983 }
1984 if (tries <= 0) {
1985 log_error("create_island ended early with %d/%d.", islemass-i, islemass);
1986 }
1987
1988 tries = map_num_tiles() / 4; /* on a 40x60 map, there are 2400 places */
1989 while (!(j = place_island(pstate)) && (--tries) > 0) {
1990 /* nothing */
1991 }
1992 return j;
1993}
1994
1995/*************************************************************************/
1996
1997/**********************************************************************/
2000 static void island_terrain_init(void)
2001{
2002 struct terrain_select *ptersel;
2003
2004 /* forest */
2005 island_terrain.forest = terrain_select_list_new_full(tersel_free);
2006 ptersel = tersel_new(1, MG_FOLIAGE, MG_TROPICAL, MG_DRY,
2007 TT_TROPICAL, WC_ALL);
2008 terrain_select_list_append(island_terrain.forest, ptersel);
2009 ptersel = tersel_new(3, MG_FOLIAGE, MG_TEMPERATE, MG_UNUSED,
2010 TT_ALL, WC_ALL);
2011 terrain_select_list_append(island_terrain.forest, ptersel);
2012 ptersel = tersel_new(1, MG_FOLIAGE, MG_WET, MG_FROZEN,
2013 TT_TROPICAL, WC_NDRY);
2014 terrain_select_list_append(island_terrain.forest, ptersel);
2015 ptersel = tersel_new(1, MG_FOLIAGE, MG_COLD, MG_UNUSED,
2016 TT_NFROZEN, WC_ALL);
2017 terrain_select_list_append(island_terrain.forest, ptersel);
2018
2019 /* desert */
2020 island_terrain.desert = terrain_select_list_new_full(tersel_free);
2021 ptersel = tersel_new(3, MG_DRY, MG_TROPICAL, MG_GREEN,
2022 TT_HOT, WC_DRY);
2023 terrain_select_list_append(island_terrain.desert, ptersel);
2024 ptersel = tersel_new(2, MG_DRY, MG_TEMPERATE, MG_GREEN,
2025 TT_NFROZEN, WC_DRY);
2026 terrain_select_list_append(island_terrain.desert, ptersel);
2027 ptersel = tersel_new(1, MG_COLD, MG_DRY, MG_TROPICAL,
2028 TT_NHOT, WC_DRY);
2029 terrain_select_list_append(island_terrain.desert, ptersel);
2030 ptersel = tersel_new(1, MG_FROZEN, MG_DRY, MG_UNUSED,
2031 TT_FROZEN, WC_DRY);
2032 terrain_select_list_append(island_terrain.desert, ptersel);
2033
2034 /* mountain */
2035 island_terrain.mountain = terrain_select_list_new_full(tersel_free);
2036 ptersel = tersel_new(2, MG_MOUNTAINOUS, MG_GREEN, MG_UNUSED,
2037 TT_ALL, WC_ALL);
2038 terrain_select_list_append(island_terrain.mountain, ptersel);
2039 ptersel = tersel_new(1, MG_MOUNTAINOUS, MG_UNUSED, MG_GREEN,
2040 TT_ALL, WC_ALL);
2041 terrain_select_list_append(island_terrain.mountain, ptersel);
2042
2043 /* swamp */
2044 island_terrain.swamp = terrain_select_list_new_full(tersel_free);
2045 ptersel = tersel_new(1, MG_WET, MG_TROPICAL, MG_FOLIAGE,
2046 TT_TROPICAL, WC_NDRY);
2047 terrain_select_list_append(island_terrain.swamp, ptersel);
2048 ptersel = tersel_new(2, MG_WET, MG_TEMPERATE, MG_FOLIAGE,
2049 TT_HOT, WC_NDRY);
2050 terrain_select_list_append(island_terrain.swamp, ptersel);
2051 ptersel = tersel_new(1, MG_WET, MG_COLD, MG_FOLIAGE,
2052 TT_NHOT, WC_NDRY);
2053 terrain_select_list_append(island_terrain.swamp, ptersel);
2054
2055 island_terrain.init = TRUE;
2056}
2057
2058/**********************************************************************/
2061 static void island_terrain_free(void)
2062{
2063 if (!island_terrain.init) {
2064 return;
2065 }
2066
2067 terrain_select_list_destroy(island_terrain.forest);
2068 terrain_select_list_destroy(island_terrain.desert);
2069 terrain_select_list_destroy(island_terrain.mountain);
2070 terrain_select_list_destroy(island_terrain.swamp);
2071
2072 island_terrain.init = FALSE;
2073}
2074
2075/**********************************************************************/
2081 static bool make_island(int islemass, int starters,
2082 struct gen234_state *pstate,
2083 int min_specific_island_size)
2084{
2085 /* int may be only 2 byte ! */
2086 static long int tilefactor, balance, lastplaced;
2087 static long int riverbuck, mountbuck, desertbuck, forestbuck, swampbuck;
2088 int i;
2089
2090 /* The terrain selection lists have to be initialised.
2091 * (see island_terrain_init()) */
2092 fc_assert_ret_val(island_terrain.init, FALSE);
2093
2094 if (islemass == 0) {
2095 /* this only runs to initialise static things, not to actually
2096 * create an island. */
2097 balance = 0;
2098 /* 0 = none, poles, then isles */
2099 pstate->isleindex = wld.map.num_continents + 1;
2100
2101 checkmass = pstate->totalmass;
2102
2103 /* caveat: this should really be sent to all players */
2104 if (pstate->totalmass > 3000) {
2105 log_normal(_("High landmass - this may take a few seconds."));
2106 }
2107
2108 i = river_pct + mountain_pct + desert_pct + forest_pct + swamp_pct;
2109 i = (i <= 90) ? 100 : i * 11 / 10;
2110 tilefactor = pstate->totalmass / i;
2111 riverbuck = -(long int) fc_rand(pstate->totalmass);
2112 mountbuck = -(long int) fc_rand(pstate->totalmass);
2113 desertbuck = -(long int) fc_rand(pstate->totalmass);
2114 forestbuck = -(long int) fc_rand(pstate->totalmass);
2115 swampbuck = -(long int) fc_rand(pstate->totalmass);
2116 lastplaced = pstate->totalmass;
2117 } else {
2118
2119 /* makes the islands this big */
2120 islemass = islemass - balance;
2121
2122 if (islemass > lastplaced + 1 + lastplaced / 50) {
2123 /* don't create big isles we can't place */
2124 islemass = lastplaced + 1 + lastplaced / 50;
2125 }
2126
2127 /* isle creation does not perform well for nonsquare islands */
2128 if (islemass > (wld.map.ysize - 6) * (wld.map.ysize - 6)) {
2129 islemass = (wld.map.ysize - 6) * (wld.map.ysize - 6);
2130 }
2131
2132 if (islemass > (wld.map.xsize - 2) * (wld.map.xsize - 2)) {
2133 islemass = (wld.map.xsize - 2) * (wld.map.xsize - 2);
2134 }
2135
2136 i = islemass;
2137 if (i <= 0) {
2138 return FALSE;
2139 }
2140 fc_assert_ret_val(starters >= 0, FALSE);
2141 log_verbose("island %i", pstate->isleindex);
2142
2143 /* keep trying to place an island, and decrease the size of
2144 * the island we're trying to create until we succeed.
2145 * If we get too small, return an error. */
2146 while (!create_island(i, pstate)) {
2147 if (i < islemass * min_specific_island_size / 100) {
2148 return FALSE;
2149 }
2150 i--;
2151 }
2152 i++;
2153 lastplaced = i;
2154 if (i * 10 > islemass) {
2155 balance = i - islemass;
2156 } else {
2157 balance = 0;
2158 }
2159
2160 log_verbose("ini=%d, plc=%d, bal=%ld, tot=%ld",
2161 islemass, i, balance, checkmass);
2162
2163 i *= tilefactor;
2164
2165 riverbuck += river_pct * i;
2166 fill_island_rivers(1, &riverbuck, pstate);
2167
2168 /* forest */
2169 forestbuck += forest_pct * i;
2170 fill_island(60, &forestbuck, island_terrain.forest, pstate);
2171
2172 /* desert */
2173 desertbuck += desert_pct * i;
2174 fill_island(40, &desertbuck, island_terrain.desert, pstate);
2175
2176 /* mountain */
2177 mountbuck += mountain_pct * i;
2178 fill_island(20, &mountbuck, island_terrain.mountain, pstate);
2179
2180 /* swamp */
2181 swampbuck += swamp_pct * i;
2182 fill_island(80, &swampbuck, island_terrain.swamp, pstate);
2183
2184 pstate->isleindex++;
2185 wld.map.num_continents++;
2186 }
2187 return TRUE;
2188}
2189
2190/**********************************************************************/
2194 static void initworld(struct gen234_state *pstate)
2195{
2196 struct terrain *deepest_ocean = pick_ocean(TERRAIN_OCEAN_DEPTH_MAXIMUM,
2197 FALSE);
2198
2199 fc_assert(NULL != deepest_ocean);
2200 height_map = fc_malloc(MAP_INDEX_SIZE * sizeof(*height_map));
2201 create_placed_map(); /* land tiles which aren't placed yet */
2202
2203 whole_map_iterate(&(wld.map), ptile) {
2204 tile_set_terrain(ptile, deepest_ocean);
2205 tile_set_continent(ptile, 0);
2206 map_set_placed(ptile); /* not a land tile */
2207 BV_CLR_ALL(ptile->extras);
2208 tile_set_owner(ptile, NULL, NULL);
2209 ptile->extras_owner = NULL;
2210 } whole_map_iterate_end;
2211
2212 if (HAS_POLES) {
2213 make_polar();
2214 }
2215
2216 /* Set poles numbers. After the map is generated continents will
2217 * be renumbered. */
2218 make_island(0, 0, pstate, 0);
2219}
2220
2221/* This variable is the Default Minimum Specific Island Size,
2222 * ie the smallest size we'll typically permit our island, as a % of
2223 * the size we wanted. So if we ask for an island of size x, the island
2224 * creation will return if it would create an island smaller than
2225 * x * DMSIS / 100 */
2226#define DMSIS 10
2227
2228/**********************************************************************/
2231 static void mapgenerator2(void)
2232{
2233 long int totalweight;
2234 struct gen234_state state;
2235 struct gen234_state *pstate = &state;
2236 int i;
2237 bool done = FALSE;
2238 int spares = 1;
2239 /* constant that makes up that an island actually needs additional space */
2240
2241 /* put 70% of land in big continents,
2242 * 20% in medium, and
2243 * 10% in small. */
2244 int bigfrac = 70, midfrac = 20, smallfrac = 10;
2245
2246 if (wld.map.server.landpercent > 85) {
2247 log_verbose("ISLAND generator: falling back to RANDOM generator");
2248 wld.map.server.generator = MAPGEN_RANDOM;
2249 return;
2250 }
2251
2252 pstate->totalmass = ((wld.map.ysize - 6 - spares) * wld.map.server.landpercent
2253 * (wld.map.xsize - spares)) / 100;
2254 totalweight = 100 * player_count();
2255
2256 fc_assert_action(!placed_map_is_initialized(),
2257 wld.map.server.generator = MAPGEN_RANDOM; return);
2258
2259 while (!done && bigfrac > midfrac) {
2260 done = TRUE;
2261
2262 if (placed_map_is_initialized()) {
2263 destroy_placed_map();
2264 }
2265
2266 initworld(pstate);
2267
2268 /* Create one big island for each player. */
2269 for (i = player_count(); i > 0; i--) {
2270 if (!make_island(bigfrac * pstate->totalmass / totalweight,
2271 1, pstate, 95)) {
2272 /* we couldn't make an island at least 95% as big as we wanted,
2273 * and since we're trying hard to be fair, we need to start again,
2274 * with all big islands reduced slightly in size.
2275 * Take the size reduction from the big islands and add it to the
2276 * small islands to keep overall landmass unchanged.
2277 * Note that the big islands can get very small if necessary, and
2278 * the smaller islands will not exist if we can't place them
2279 * easily. */
2280 log_verbose("Island too small, trying again with all smaller "
2281 "islands.");
2282 midfrac += bigfrac * 0.01;
2283 smallfrac += bigfrac * 0.04;
2284 bigfrac *= 0.95;
2285 done = FALSE;
2286 break;
2287 }
2288 }
2289 }
2290
2291 if (bigfrac <= midfrac) {
2292 /* We could never make adequately big islands. */
2293 log_verbose("ISLAND generator: falling back to RANDOM generator");
2294 wld.map.server.generator = MAPGEN_RANDOM;
2295
2296 /* init world created this map, destroy it before abort */
2297 destroy_placed_map();
2298 free(height_map);
2299 height_map = NULL;
2300 return;
2301 }
2302
2303 /* Now place smaller islands, but don't worry if they're small,
2304 * or even non-existent. One medium and one small per player. */
2305 for (i = player_count(); i > 0; i--) {
2306 make_island(midfrac * pstate->totalmass / totalweight, 0, pstate, DMSIS);
2307 }
2308 for (i = player_count(); i > 0; i--) {
2309 make_island(smallfrac * pstate->totalmass / totalweight, 0, pstate, DMSIS);
2310 }
2311
2312 make_plains();
2313 destroy_placed_map();
2314 free(height_map);
2315 height_map = NULL;
2316
2317 if (checkmass > wld.map.xsize + wld.map.ysize + totalweight) {
2318 log_verbose("%ld mass left unplaced", checkmass);
2319 }
2320}
2321
2322/**********************************************************************/
2326 static void mapgenerator3(void)
2327{
2328 int spares = 1;
2329 int j = 0;
2330 long int islandmass, landmass, size;
2331 long int maxmassdiv6 = 20;
2332 int bigislands;
2333 struct gen234_state state;
2334 struct gen234_state *pstate = &state;
2335
2336 if (wld.map.server.landpercent > 80) {
2337 log_verbose("ISLAND generator: falling back to FRACTAL generator due "
2338 "to landpercent > 80.");
2339 wld.map.server.generator = MAPGEN_FRACTAL;
2340 return;
2341 }
2342
2343 if (wld.map.xsize < 40 || wld.map.ysize < 40) {
2344 log_verbose("ISLAND generator: falling back to FRACTAL generator due "
2345 "to unsupported map size.");
2346 wld.map.server.generator = MAPGEN_FRACTAL;
2347 return;
2348 }
2349
2350 pstate->totalmass = (((wld.map.ysize - 6 - spares) * wld.map.server.landpercent
2351 * (wld.map.xsize - spares)) / 100);
2352
2353 bigislands = player_count();
2354
2355 landmass = (wld.map.xsize * (wld.map.ysize - 6) * wld.map.server.landpercent)/100;
2356 /* subtracting the arctics */
2357 if (landmass > 3 * wld.map.ysize + player_count() * 3) {
2358 landmass -= 3 * wld.map.ysize;
2359 }
2360
2361
2362 islandmass = (landmass)/(3 * bigislands);
2363 if (islandmass < 4 * maxmassdiv6) {
2364 islandmass = (landmass)/(2 * bigislands);
2365 }
2366 if (islandmass < 3 * maxmassdiv6 && player_count() * 2 < landmass) {
2367 islandmass = (landmass)/(bigislands);
2368 }
2369
2370 if (islandmass < 2) {
2371 islandmass = 2;
2372 }
2373 if (islandmass > maxmassdiv6 * 6) {
2374 islandmass = maxmassdiv6 * 6;/* !PS: let's try this */
2375 }
2376
2377 initworld(pstate);
2378
2379 while (pstate->isleindex - 2 <= bigislands && checkmass > islandmass
2380 && ++j < 500) {
2381 make_island(islandmass, 1, pstate, DMSIS);
2382 }
2383
2384 if (j == 500) {
2385 log_normal(_("Generator 3 didn't place all big islands."));
2386 }
2387
2388 islandmass = (islandmass * 11) / 8;
2390 if (islandmass < 2) {
2391 islandmass = 2;
2392 }
2393
2394 while (checkmass > islandmass && ++j < 1500) {
2395 if (j < 1000) {
2396 size = fc_rand((islandmass + 1) / 2 + 1) + islandmass / 2;
2397 } else {
2398 size = fc_rand((islandmass + 1) / 2 + 1);
2399 }
2400 if (size < 2) {
2401 size = 2;
2402 }
2403
2404 make_island(size, (pstate->isleindex - 2 <= player_count()) ? 1 : 0,
2405 pstate, DMSIS);
2406 }
2407
2408 make_plains();
2409 destroy_placed_map();
2410 free(height_map);
2411 height_map = NULL;
2412
2413 if (j == 1500) {
2414 log_normal(_("Generator 3 left %li landmass unplaced."), checkmass);
2415 } else if (checkmass > wld.map.xsize + wld.map.ysize) {
2416 log_verbose("%ld mass left unplaced", checkmass);
2417 }
2418}
2419
2420/**********************************************************************/
2423 static void mapgenerator4(void)
2424{
2425 int bigweight = 70;
2426 int spares = 1;
2427 int i;
2428 long int totalweight;
2429 struct gen234_state state;
2430 struct gen234_state *pstate = &state;
2431
2432
2433 /* no islands with mass >> sqr(min(xsize,ysize)) */
2434
2435 if (player_count() < 2 || wld.map.server.landpercent > 80) {
2436 log_verbose("ISLAND generator: falling back to startpos=SINGLE");
2437 wld.map.server.startpos = MAPSTARTPOS_SINGLE;
2438 return;
2439 }
2440
2441 if (wld.map.server.landpercent > 60) {
2442 bigweight = 30;
2443 } else if (wld.map.server.landpercent > 40) {
2444 bigweight = 50;
2445 } else {
2446 bigweight = 70;
2447 }
2448
2449 spares = (wld.map.server.landpercent - 5) / 30;
2450
2451 pstate->totalmass = (((wld.map.ysize - 6 - spares) * wld.map.server.landpercent
2452 * (wld.map.xsize - spares)) / 100);
2453
2455 totalweight = (30 + bigweight) * player_count();
2456
2457 initworld(pstate);
2458
2459 i = player_count() / 2;
2460 if ((player_count() & 1) == 1) {
2461 make_island(bigweight * 3 * pstate->totalmass / totalweight, 3,
2462 pstate, DMSIS);
2463 } else {
2464 i++;
2465 }
2466 while ((--i) > 0) {
2467 make_island(bigweight * 2 * pstate->totalmass / totalweight, 2,
2468 pstate, DMSIS);
2469 }
2470 for (i = player_count(); i > 0; i--) {
2471 make_island(20 * pstate->totalmass / totalweight, 0, pstate, DMSIS);
2472 }
2473 for (i = player_count(); i > 0; i--) {
2474 make_island(10 * pstate->totalmass / totalweight, 0, pstate, DMSIS);
2475 }
2476 make_plains();
2477 destroy_placed_map();
2478 free(height_map);
2479 height_map = NULL;
2480
2481 if (checkmass > wld.map.xsize + wld.map.ysize + totalweight) {
2482 log_verbose("%ld mass left unplaced", checkmass);
2483 }
2484}
2485
2486#undef DMSIS
2487
2488/**********************************************************************/
2491 static void river_types_init(void)
2492{
2493 river_type_count = 0;
2494
2495 extra_type_by_cause_iterate(EC_ROAD, priver) {
2496 if (road_has_flag(extra_road_get(priver), RF_RIVER)
2497 && priver->generated) {
2498 river_types[river_type_count++] = priver;
2499 }
2500 } extra_type_by_cause_iterate_end;
2501}
2502
2503
2504/****************************************************************************
2505 Fair island generator types.
2506****************************************************************************/
2507 enum fair_tile_flag {
2508 FTF_NONE = 0,
2509 FTF_ASSIGNED = 1 << 0,
2510 FTF_OCEAN = 1 << 1,
2511 FTF_STARTPOS = 1 << 2,
2512 FTF_NO_RESOURCE = 1 << 3,
2513 FTF_HAS_HUT = 1 << 4,
2514 FTF_NO_HUT = 1 << 5
2515};
2516
2517 struct fair_tile {
2518 enum fair_tile_flag flags;
2519 struct terrain *pterrain;
2520 struct extra_type *presource;
2521 bv_extras extras;
2522 int startpos_team_id;
2523};
2524
2525 typedef void (*fair_geometry_func)(int *x, int *y);
2526 struct fair_geometry_data {
2527 fair_geometry_func transform[4];
2528 int transform_num;
2529};
2530
2531/**********************************************************************/
2535 static inline struct fair_tile *fair_map_new(void)
2536{
2537 return fc_calloc(MAP_INDEX_SIZE, sizeof(struct fair_tile));
2538}
2539
2540/**********************************************************************/
2543 static inline void fair_map_destroy(struct fair_tile *pmap)
2544{
2545 free(pmap);
2546}
2547
2548/**********************************************************************/
2551 static inline void fair_map_tile_pos(struct fair_tile *pmap,
2552 struct fair_tile *ptile, int *x, int *y)
2553{
2554 index_to_map_pos(x, y, ptile - pmap);
2555}
2556
2557/**********************************************************************/
2560static inline struct fair_tile *
2561fair_map_pos_tile(struct fair_tile *pmap, int x, int y)
2562{
2563 int nat_x, nat_y;
2564
2565 MAP_TO_NATIVE_POS(&nat_x, &nat_y, x, y);
2566
2567 /* Wrap in X and Y directions, as needed. */
2568 if (nat_x < 0 || nat_x >= wld.map.xsize) {
2569 if (current_wrap_has_flag(WRAP_X)) {
2570 nat_x = FC_WRAP(nat_x, wld.map.xsize);
2571 } else {
2572 return NULL;
2573 }
2574 }
2575 if (nat_y < 0 || nat_y >= wld.map.ysize) {
2576 if (current_wrap_has_flag(WRAP_Y)) {
2577 nat_y = FC_WRAP(nat_y, wld.map.ysize);
2578 } else {
2579 return NULL;
2580 }
2581 }
2582
2583 return pmap + native_pos_to_index(nat_x, nat_y);
2584}
2585
2586/**********************************************************************/
2589static inline struct fair_tile *
2590fair_map_tile_step(struct fair_tile *pmap, struct fair_tile *ptile,
2591 enum direction8 dir)
2592{
2593 int x, y, dx, dy;
2594
2595 fair_map_tile_pos(pmap, ptile, &x, &y);
2596 DIRSTEP(dx, dy, dir);
2597 return fair_map_pos_tile(pmap, x + dx, y + dy);
2598}
2599
2600/**********************************************************************/
2604static inline bool
2605fair_map_tile_border(struct fair_tile *pmap, struct fair_tile *ptile,
2606 int dist)
2607{
2608 int nat_x, nat_y;
2609
2610 index_to_native_pos(&nat_x, &nat_y, ptile - pmap);
2611
2612 if (!current_wrap_has_flag(WRAP_X)
2613 && (nat_x < dist || nat_x >= wld.map.xsize - dist)) {
2614 return TRUE;
2615 }
2616
2617 if (MAP_IS_ISOMETRIC) {
2618 dist *= 2;
2619 }
2620
2621 if (!current_wrap_has_flag(WRAP_Y)
2622 && (nat_y < dist || nat_y >= wld.map.ysize - dist)) {
2623 return TRUE;
2624 }
2625
2626 return FALSE;
2627}
2628
2629/**********************************************************************/
2632 static int fair_team_placement_closest(const void *a, const void *b)
2633{
2634 const struct iter_index *index1 = a, *index2 = b;
2635
2636 return index1->dist - index2->dist;
2637}
2638
2639/**********************************************************************/
2642 static int fair_team_placement_horizontal(const void *a, const void *b)
2643{
2644 const struct iter_index *index1 = a, *index2 = b;
2645 /* Map vector to natural vector (Y axis). */
2646 int diff = (MAP_IS_ISOMETRIC
2647 ? abs(index1->dx + index1->dy) - abs(index2->dx + index2->dy)
2648 : abs(index1->dy) - abs(index2->dy));
2649
2650 return (diff != 0 ? diff : index1->dist - index2->dist);
2651}
2652
2653/**********************************************************************/
2656 static int fair_team_placement_vertical(const void *a, const void *b)
2657{
2658 const struct iter_index *index1 = a, *index2 = b;
2659 /* Map vector to natural vector (X axis). */
2660 int diff = (MAP_IS_ISOMETRIC
2661 ? abs(index1->dx - index1->dy) - abs(index2->dx - index2->dy)
2662 : abs(index1->dx) - abs(index2->dx));
2663
2664 return (diff != 0 ? diff : index1->dist - index2->dist);
2665}
2666
2667/**********************************************************************/
2670 static void fair_do_symetry1(int *x, int *y)
2671{
2672 *x = -*x;
2673}
2674
2675/**********************************************************************/
2678 static void fair_do_symetry2(int *x, int *y)
2679{
2680 *y = -*y;
2681}
2682
2683/**********************************************************************/
2686 static void fair_do_hex_symetry1(int *x, int *y)
2687{
2688 *x = -(*x + *y);
2689}
2690
2691/**********************************************************************/
2694 static void fair_do_hex_symetry2(int *x, int *y)
2695{
2696 *x = -*x;
2697 *y = -*y;
2698}
2699
2700/**********************************************************************/
2703 static void fair_do_iso_hex_symetry1(int *x, int *y)
2704{
2705 *y = *x - *y;
2706}
2707
2708#define fair_do_iso_hex_symetry2 fair_do_rotation
2709
2710/**********************************************************************/
2713 static void fair_do_rotation(int *x, int *y)
2714{
2715 int z = *x;
2716
2717 *x = *y;
2718 *y = z;
2719}
2720
2721/**********************************************************************/
2724 static void fair_do_hex_rotation(int *x, int *y)
2725{
2726 int z = *x + *y;
2727
2728 *x = -*y;
2729 *y = z;
2730}
2731
2732/**********************************************************************/
2735 static void fair_do_iso_hex_rotation(int *x, int *y)
2736{
2737 int z = *x - *y;
2738
2739 *y = *x;
2740 *x = z;
2741}
2742
2743/**********************************************************************/
2746 static void fair_do_geometry(const struct fair_geometry_data *data,
2747 int *x, int *y)
2748{
2749 int i;
2750
2751 for (i = 0; i < data->transform_num; i++) {
2752 data->transform[i](x, y);
2753 }
2754}
2755
2756/**********************************************************************/
2759 static void fair_geometry_rand(struct fair_geometry_data *data)
2760{
2761 int i = 0;
2762
2763 if (!current_topo_has_flag(TF_HEX)) {
2764 if (fc_rand(100) < 50) {
2765 data->transform[i++] = fair_do_symetry1;
2766 }
2767 if (fc_rand(100) < 50) {
2768 data->transform[i++] = fair_do_symetry2;
2769 }
2770 if (fc_rand(100) < 50) {
2771 data->transform[i++] = fair_do_rotation;
2772 }
2773 } else if (!current_topo_has_flag(TF_ISO)) {
2774 int steps;
2775
2776 if (fc_rand(100) < 50) {
2777 data->transform[i++] = fair_do_hex_symetry1;
2778 }
2779 if (fc_rand(100) < 50) {
2780 data->transform[i++] = fair_do_hex_symetry2;
2781 }
2782 /* Rotations have 2 steps on hexgonal topologies. */
2783 for (steps = fc_rand(99) % 3; steps > 0; steps--) {
2784 data->transform[i++] = fair_do_hex_rotation;
2785 }
2786 } else {
2787 int steps;
2788
2789 if (fc_rand(100) < 50) {
2790 data->transform[i++] = fair_do_iso_hex_symetry1;
2791 }
2792 if (fc_rand(100) < 50) {
2793 data->transform[i++] = fair_do_iso_hex_symetry2;
2794 }
2795 /* Rotations have 2 steps on hexgonal topologies. */
2796 for (steps = fc_rand(99) % 3; steps > 0; steps--) {
2797 data->transform[i++] = fair_do_iso_hex_rotation;
2798 }
2799 }
2800 fc_assert(i <= ARRAY_SIZE(data->transform));
2801 data->transform_num = i;
2802}
2803
2804/**********************************************************************/
2810 static bool fair_map_copy(struct fair_tile *ptarget, int tx, int ty,
2811 struct fair_tile *psource,
2812 const struct fair_geometry_data *data,
2813 int startpos_team_id)
2814{
2815 int sdx = wld.map.xsize / 2, sdy = wld.map.ysize / 2;
2816 struct fair_tile *smax_tile = psource + MAP_INDEX_SIZE;
2817 struct fair_tile *pstile, *pttile;
2818 int x, y;
2819
2820 /* Check. */
2821 for (pstile = psource; pstile < smax_tile; pstile++) {
2822 if (pstile->flags == FTF_NONE) {
2823 continue;
2824 }
2825
2826 /* Do translation and eventually other transformations. */
2827 fair_map_tile_pos(psource, pstile, &x, &y);
2828 x -= sdx;
2829 y -= sdy;
2830 fair_do_geometry(data, &x, &y);
2831 x += tx;
2832 y += ty;
2833 pttile = fair_map_pos_tile(ptarget, x, y);
2834 if (pttile == NULL) {
2835 return FALSE; /* Limit of the map. */
2836 }
2837 if (pttile->flags & FTF_ASSIGNED) {
2838 if (pstile->flags & FTF_ASSIGNED
2839 || !(pttile->flags & FTF_OCEAN)
2840 || !(pstile->flags & FTF_OCEAN)) {
2841 return FALSE; /* Already assigned for another usage. */
2842 }
2843 } else if (pttile->flags & FTF_OCEAN && !(pstile->flags & FTF_OCEAN)) {
2844 return FALSE; /* We clearly want a sea tile here. */
2845 }
2846 if ((pttile->flags & FTF_NO_RESOURCE && pstile->presource != NULL)
2847 || (pstile->flags & FTF_NO_RESOURCE && pttile->presource != NULL)) {
2848 return FALSE; /* Resource disallowed there. */
2849 }
2850 if ((pttile->flags & FTF_NO_HUT && pstile->flags & FTF_HAS_HUT)
2851 || (pstile->flags & FTF_NO_HUT && pttile->flags & FTF_HAS_HUT)) {
2852 return FALSE; /* Resource disallowed there. */
2853 }
2854 }
2855
2856 /* Copy. */
2857 for (pstile = psource; pstile < smax_tile; pstile++) {
2858 if (pstile->flags == FTF_NONE) {
2859 continue;
2860 }
2861
2862 /* Do translation and eventually other transformations. */
2863 fair_map_tile_pos(psource, pstile, &x, &y);
2864 x -= sdx;
2865 y -= sdy;
2866 fair_do_geometry(data, &x, &y);
2867 x += tx;
2868 y += ty;
2869 pttile = fair_map_pos_tile(ptarget, x, y);
2870 fc_assert_ret_val(pttile != NULL, FALSE);
2871 pttile->flags |= pstile->flags;
2872 if (pstile->pterrain != NULL) {
2873 pttile->pterrain = pstile->pterrain;
2874 pttile->presource = pstile->presource;
2875 pttile->extras = pstile->extras;
2876 }
2877 if (pstile->flags & FTF_STARTPOS) {
2878 pttile->startpos_team_id = startpos_team_id;
2879 }
2880 }
2881 return TRUE; /* Looks ok. */
2882}
2883
2884/**********************************************************************/
2888 static bool fair_map_place_island_rand(struct fair_tile *ptarget,
2889 struct fair_tile *psource)
2890{
2891 struct fair_geometry_data geometry;
2892 int i, r, x, y;
2893
2894 fair_geometry_rand(&geometry);
2895
2896 /* Try random positions. */
2897 for (i = 0; i < 10; i++) {
2898 r = fc_rand(MAP_INDEX_SIZE);
2899 index_to_map_pos(&x, &y, r);
2900 if (fair_map_copy(ptarget, x, y, psource, &geometry, -1)) {
2901 return TRUE;
2902 }
2903 }
2904
2905 /* Try hard placement. */
2906 r = fc_rand(MAP_INDEX_SIZE);
2907 for (i = (r + 1) % MAP_INDEX_SIZE; i != r; i = (i + 1) % MAP_INDEX_SIZE) {
2908 index_to_map_pos(&x, &y, i);
2909 if (fair_map_copy(ptarget, x, y, psource, &geometry, -1)) {
2910 return TRUE;
2911 }
2912 }
2913
2914 /* Impossible placement. */
2915 return FALSE;
2916}
2917
2918/**********************************************************************/
2922static bool
2923fair_map_place_island_team(struct fair_tile *ptarget, int tx, int ty,
2924 struct fair_tile *psource,
2925 const struct iter_index *outwards_indices,
2926 int startpos_team_id)
2927{
2928 struct fair_geometry_data geometry;
2929 int i, x, y;
2930
2931 fair_geometry_rand(&geometry);
2932
2933 /* Iterate positions, beginning by a random index of the outwards
2934 * indices. */
2935 for (i = fc_rand(wld.map.num_iterate_outwards_indices / 200);
2936 i < wld.map.num_iterate_outwards_indices; i++) {
2937 x = tx + outwards_indices[i].dx;
2938 y = ty + outwards_indices[i].dy;
2939 if (normalize_map_pos(&(wld.map), &x, &y)
2940 && fair_map_copy(ptarget, x, y, psource, &geometry,
2941 startpos_team_id)) {
2942 return TRUE;
2943 }
2944 }
2945
2946 /* Impossible placement. */
2947 return FALSE;
2948}
2949
2950/**********************************************************************/
2953 static void fair_map_make_resources(struct fair_tile *pmap)
2954{
2955 struct fair_tile *pftile, *pftile2;
2956 int i, j;
2957
2958 for (i = 0; i < MAP_INDEX_SIZE; i++) {
2959 pftile = pmap + i;
2960 if (pftile->flags == FTF_NONE
2961 || pftile->flags & FTF_NO_RESOURCE
2962 || fc_rand (1000) >= wld.map.server.riches) {
2963 continue;
2964 }
2965
2966 if (pftile->flags & FTF_OCEAN) {
2967 bool land_around = FALSE;
2968
2969 for (j = 0; j < wld.map.num_valid_dirs; j++) {
2970 pftile2 = fair_map_tile_step(pmap, pftile, wld.map.valid_dirs[j]);
2971 if (pftile2 != NULL
2972 && pftile2->flags & FTF_ASSIGNED
2973 && !(pftile2->flags & FTF_OCEAN)) {
2974 land_around = TRUE;
2975 break;
2976 }
2977 }
2978 if (!land_around) {
2979 continue;
2980 }
2981 }
2982
2983 pftile->presource = pick_resource(pftile->pterrain);
2984 /* Note that 'pftile->presource' might be NULL if there is no suitable
2985 * resource for the terrain. */
2986 if (pftile->presource != NULL) {
2987 pftile->flags |= FTF_NO_RESOURCE;
2988 for (j = 0; j < wld.map.num_valid_dirs; j++) {
2989 pftile2 = fair_map_tile_step(pmap, pftile, wld.map.valid_dirs[j]);
2990 if (pftile2 != NULL) {
2991 pftile2->flags |= FTF_NO_RESOURCE;
2992 }
2993 }
2994
2995 BV_SET(pftile->extras, extra_index(pftile->presource));
2996 }
2997 }
2998}
2999
3000/**********************************************************************/
3003 static void fair_map_make_huts(struct fair_tile *pmap)
3004{
3005 struct fair_tile *pftile;
3006 struct tile *pvtile = tile_virtual_new(NULL);
3007 struct extra_type *phut;
3008 int i, j, k;
3009
3010 for (i = wld.map.server.huts * map_num_tiles() / 1000, j = 0;
3011 i > 0 && j < map_num_tiles() * 2; j++) {
3012 k = fc_rand(MAP_INDEX_SIZE);
3013 pftile = pmap + k;
3014 while (pftile->flags & FTF_NO_HUT) {
3015 pftile++;
3016 if (pftile - pmap == MAP_INDEX_SIZE) {
3017 pftile = pmap;
3018 }
3019 if (pftile - pmap == k) {
3020 break;
3021 }
3022 }
3023 if (pftile->flags & FTF_NO_HUT) {
3024 break; /* Cannot make huts anymore. */
3025 }
3026
3027 i--;
3028 if (pftile->pterrain == NULL) {
3029 continue; /* Not an used tile. */
3030 }
3031
3032 pvtile->index = pftile - pmap;
3033 tile_set_terrain(pvtile, pftile->pterrain);
3034 tile_set_resource(pvtile, pftile->presource);
3035 pvtile->extras = pftile->extras;
3036
3037 phut = rand_extra_for_tile(pvtile, EC_HUT, TRUE);
3038 if (phut != NULL) {
3039 tile_add_extra(pvtile, phut);
3040 pftile->extras = pvtile->extras;
3041 pftile->flags |= FTF_HAS_HUT;
3042 square_iterate(&(wld.map), index_to_tile(&(wld.map), pftile - pmap),
3043 3, ptile) {
3044 pmap[tile_index(ptile)].flags |= FTF_NO_HUT;
3045 } square_iterate_end;
3046 }
3047 }
3048
3049 tile_virtual_destroy(pvtile);
3050}
3051
3052/**********************************************************************/
3055 static struct fair_tile *fair_map_island_new(int size, int startpos_num)
3056{
3057 enum {
3058 FT_GRASSLAND,
3059 FT_FOREST,
3060 FT_DESERT,
3061 FT_HILL,
3062 FT_MOUNTAIN,
3063 FT_SWAMP,
3064 FT_COUNT
3065 };
3066 struct {
3067 int count;
3068 enum mapgen_terrain_property target;
3069 enum mapgen_terrain_property prefer;
3070 enum mapgen_terrain_property avoid;
3071 } terrain[FT_COUNT] = {
3072 { 0, MG_TEMPERATE, MG_GREEN, MG_MOUNTAINOUS },
3073 { 0, MG_FOLIAGE, MG_TEMPERATE, MG_UNUSED },
3074 { 0, MG_DRY, MG_TEMPERATE, MG_GREEN },
3075 { 0, MG_MOUNTAINOUS, MG_GREEN, MG_UNUSED },
3076 { 0, MG_MOUNTAINOUS, MG_UNUSED, MG_GREEN },
3077 { 0, MG_WET, MG_TEMPERATE, MG_FOLIAGE },
3078 };
3079
3080 struct fair_tile *pisland;
3081 struct fair_tile *land_tiles[1000];
3082 struct fair_tile *pftile, *pftile2, *pftile3;
3083 int fantasy;
3084 const int sea_around_island = (startpos_num > 0
3085 ? CITY_MAP_DEFAULT_RADIUS : 1);
3086 const int sea_around_island_sq = (startpos_num > 0
3087 ? CITY_MAP_DEFAULT_RADIUS_SQ : 2);
3088 int i, j, k;
3089
3090 size = CLIP(startpos_num, size, ARRAY_SIZE(land_tiles));
3091 fantasy = (size * 2) / 5;
3092 pisland = fair_map_new();
3093 pftile = fair_map_pos_tile(pisland, wld.map.xsize / 2, wld.map.ysize / 2);
3094 fc_assert(!fair_map_tile_border(pisland, pftile, sea_around_island));
3095 pftile->flags |= FTF_ASSIGNED;
3096 land_tiles[0] = pftile;
3097 i = 1;
3098
3099 log_debug("Generating an island with %d land tiles [fantasy=%d].",
3100 size, fantasy);
3101
3102 /* Make land. */
3103 while (i < fantasy) {
3104 pftile = land_tiles[fc_rand(i)];
3105
3106 for (j = 0; j < wld.map.num_valid_dirs; j++) {
3107 pftile2 = fair_map_tile_step(pisland, pftile, wld.map.valid_dirs[j]);
3108 fc_assert(pftile2 != NULL);
3109 if (fair_map_tile_border(pisland, pftile2, sea_around_island)) {
3110 continue;
3111 }
3112
3113 if (pftile2->flags == FTF_NONE) {
3114 pftile2->flags = FTF_ASSIGNED;
3115 land_tiles[i++] = pftile2;
3116 if (i == fantasy) {
3117 break;
3118 }
3119 }
3120 }
3121 }
3122 while (i < size) {
3123 pftile = land_tiles[i - fc_rand(fantasy) - 1];
3124 pftile2 = fair_map_tile_step(pisland, pftile, wld.map.cardinal_dirs
3125 [fc_rand(wld.map.num_cardinal_dirs)]);
3126 fc_assert(pftile2 != NULL);
3127 if (fair_map_tile_border(pisland, pftile2, sea_around_island)) {
3128 continue;
3129 }
3130
3131 if (pftile2->flags == FTF_NONE) {
3132 pftile2->flags = FTF_ASSIGNED;
3133 land_tiles[i++] = pftile2;
3134 }
3135 }
3136 fc_assert(i == size);
3137
3138 /* Add start positions. */
3139 for (i = 0; i < startpos_num;) {
3140 pftile = land_tiles[fc_rand(size - fantasy)];
3141 fc_assert(pftile->flags & FTF_ASSIGNED);
3142 if (!(pftile->flags & FTF_STARTPOS)) {
3143 pftile->flags |= FTF_STARTPOS;
3144 i++;
3145 }
3146 }
3147
3148 /* Make terrain. */
3149 terrain[FT_GRASSLAND].count = size - startpos_num;
3150 terrain[FT_FOREST].count = ((forest_pct + jungle_pct) * size) / 100;
3151 terrain[FT_DESERT].count = (desert_pct * size) / 100;
3152 terrain[FT_HILL].count = (mountain_pct * size) / 150;
3153 terrain[FT_MOUNTAIN].count = (mountain_pct * size) / 300;
3154 terrain[FT_SWAMP].count = (swamp_pct * size) / 100;
3155
3156 j = FT_GRASSLAND;
3157 for (i = 0; i < size; i++) {
3158 pftile = land_tiles[i];
3159
3160 if (pftile->flags & FTF_STARTPOS) {
3161 pftile->pterrain = pick_terrain_by_flag(TER_STARTER);
3162 } else {
3163 if (terrain[j].count == 0 || fc_rand(100) < 70) {
3164 do {
3165 j = fc_rand(FT_COUNT);
3166 } while (terrain[j].count == 0);
3167 }
3168 pftile->pterrain = pick_terrain(terrain[j].target, terrain[j].prefer,
3169 terrain[j].avoid);
3170 terrain[j].count--;
3171 }
3172 }
3173
3174 /* Make sea around the island. */
3175 for (i = 0; i < size; i++) {
3176 circle_iterate(&(wld.map),
3177 index_to_tile(&(wld.map), land_tiles[i] - pisland),
3178 sea_around_island_sq, ptile) {
3179 pftile = pisland + tile_index(ptile);
3180
3181 if (pftile->flags == FTF_NONE) {
3182 pftile->flags = FTF_OCEAN;
3183 /* No ice around island */
3184 pftile->pterrain =
3185 pick_ocean(TERRAIN_OCEAN_DEPTH_MINIMUM
3186 + fc_rand(TERRAIN_OCEAN_DEPTH_MAXIMUM / 2), FALSE);
3187 if (startpos_num > 0) {
3188 pftile->flags |= FTF_ASSIGNED;
3189 }
3190 }
3191 } circle_iterate_end;
3192 }
3193
3194 /* Make rivers. */
3195 if (river_type_count > 0) {
3196 struct extra_type *priver;
3197 struct fair_tile *pend;
3198 int n = ((river_pct * size * wld.map.num_cardinal_dirs
3199 * wld.map.num_cardinal_dirs) / 200);
3200 int length_max = 3, length, l;
3201 enum direction8 dir;
3202 int extra_idx;
3203 int dirs_num;
3204 bool cardinal_only;
3205 bool connectable_river_around, ocean_around;
3206 int river_around;
3207 bool finished;
3208
3209 for (i = 0; i < n; i++) {
3210 pftile = land_tiles[fc_rand(size)];
3211 if (!terrain_has_flag(pftile->pterrain, TER_CAN_HAVE_RIVER)) {
3212 continue;
3213 }
3214
3215 priver = river_types[fc_rand(river_type_count)];
3216 extra_idx = extra_index(priver);
3217 if (BV_ISSET(pftile->extras, extra_idx)) {
3218 continue;
3219 }
3220 cardinal_only = is_cardinal_only_road(priver);
3221
3222 river_around = 0;
3223 connectable_river_around = FALSE;
3224 ocean_around = FALSE;
3225 for (j = 0; j < wld.map.num_valid_dirs; j++) {
3226 pftile2 = fair_map_tile_step(pisland, pftile, wld.map.valid_dirs[j]);
3227 if (pftile2 == NULL) {
3228 continue;
3229 }
3230
3231 if (pftile2->flags & FTF_OCEAN) {
3232 ocean_around = TRUE;
3233 break;
3234 } else if (BV_ISSET(pftile2->extras, extra_idx)) {
3235 river_around++;
3236 if (!cardinal_only || is_cardinal_dir(wld.map.valid_dirs[j])) {
3237 connectable_river_around = TRUE;
3238 }
3239 }
3240 }
3241 if (ocean_around
3242 || river_around > 1
3243 || (river_around == 1 && !connectable_river_around)) {
3244 continue;
3245 }
3246
3247 if (connectable_river_around) {
3248 log_debug("Adding river at (%d, %d)",
3249 index_to_map_pos_x(pftile - pisland),
3250 index_to_map_pos_y(pftile - pisland));
3251 BV_SET(pftile->extras, extra_idx);
3252 continue;
3253 }
3254
3255 /* Check a river in one direction. */
3256 pend = NULL;
3257 length = -1;
3258 dir = direction8_invalid();
3259 dirs_num = 0;
3260 for (j = 0; j < wld.map.num_valid_dirs; j++) {
3261 if (cardinal_only && !is_cardinal_dir(wld.map.valid_dirs[j])) {
3262 continue;
3263 }
3264
3265 finished = FALSE;
3266 pftile2 = pftile;
3267 for (l = 2; l < length_max; l++) {
3268 pftile2 = fair_map_tile_step(pisland, pftile2, wld.map.valid_dirs[j]);
3269 if (pftile2 == NULL
3270 || !terrain_has_flag(pftile2->pterrain, TER_CAN_HAVE_RIVER)) {
3271 break;
3272 }
3273
3274 river_around = 0;
3275 connectable_river_around = FALSE;
3276 ocean_around = FALSE;
3277 for (k = 0; k < wld.map.num_valid_dirs; k++) {
3278 if (wld.map.valid_dirs[k] == DIR_REVERSE(wld.map.valid_dirs[j])) {
3279 continue;
3280 }
3281
3282 pftile3 = fair_map_tile_step(pisland, pftile2,
3283 wld.map.valid_dirs[k]);
3284 if (pftile3 == NULL) {
3285 continue;
3286 }
3287
3288 if (pftile3->flags & FTF_OCEAN) {
3289 if (!cardinal_only || is_cardinal_dir(wld.map.valid_dirs[k])) {
3290 ocean_around = TRUE;
3291 }
3292 } else if (BV_ISSET(pftile3->extras, extra_idx)) {
3293 river_around++;
3294 if (!cardinal_only || is_cardinal_dir(wld.map.valid_dirs[k])) {
3295 connectable_river_around = TRUE;
3296 }
3297 }
3298 }
3299 if (river_around > 1 && !connectable_river_around) {
3300 break;
3301 } else if (ocean_around || connectable_river_around) {
3302 finished = TRUE;
3303 break;
3304 }
3305 }
3306 if (finished && fc_rand(++dirs_num) == 0) {
3307 dir = wld.map.valid_dirs[j];
3308 pend = pftile2;
3309 length = l;
3310 }
3311 }
3312 if (pend == NULL) {
3313 continue;
3314 }
3315
3316 log_debug("Make river from (%d, %d) to (%d, %d) [dir=%s, length=%d]",
3317 index_to_map_pos_x(pftile - pisland),
3318 index_to_map_pos_y(pftile - pisland),
3319 index_to_map_pos_x(pend - pisland),
3320 index_to_map_pos_y(pend - pisland),
3321 direction8_name(dir),
3322 length);
3323 for (;;) {
3324 BV_SET(pftile->extras, extra_idx);
3325 length--;
3326 if (pftile == pend) {
3327 fc_assert(length == 0);
3328 break;
3329 }
3330 pftile = fair_map_tile_step(pisland, pftile, dir);
3331 fc_assert(pftile != NULL);
3332 }
3333 }
3334 }
3335
3336 if (startpos_num > 0) {
3337 /* Islands with start positions must have the same resources and the
3338 * same huts. Other ones don't matter. */
3339
3340 /* Make resources. */
3341 if (wld.map.server.riches > 0) {
3342 fair_map_make_resources(pisland);
3343 }
3344
3345 /* Make huts. */
3346 if (wld.map.server.huts > 0) {
3347 fair_map_make_huts(pisland);
3348 }
3349
3350 /* Make sure there will be no more resources and huts on assigned
3351 * tiles. */
3352 for (i = 0; i < MAP_INDEX_SIZE; i++) {
3353 pftile = pisland + i;
3354 if (pftile->flags & FTF_ASSIGNED) {
3355 pftile->flags |= (FTF_NO_RESOURCE | FTF_NO_HUT);
3356 }
3357 }
3358 }
3359
3360 return pisland;
3361}
3362
3363/**********************************************************************/
3366 static bool map_generate_fair_islands(void)
3367{
3368 struct terrain *deepest_ocean
3369 = pick_ocean(TERRAIN_OCEAN_DEPTH_MAXIMUM, FALSE);
3370 struct fair_tile *pmap, *pisland;
3371 int playermass, islandmass1 , islandmass2, islandmass3;
3372 int min_island_size = wld.map.server.tinyisles ? 1 : 2;
3373 int players_per_island = 1;
3374 int teams_num = 0, team_players_num = 0, single_players_num = 0;
3375 int i, iter = CLIP(1, 100000 / map_num_tiles(), 10);
3376 bool done = FALSE;
3377
3378 teams_iterate(pteam) {
3379 i = player_list_size(team_members(pteam));
3380 fc_assert(0 < i);
3381 if (i == 1) {
3382 single_players_num++;
3383 } else {
3384 teams_num++;
3385 team_players_num += i;
3386 }
3387 } teams_iterate_end;
3388 fc_assert(team_players_num + single_players_num == player_count());
3389
3390 /* Take in account the 'startpos' setting. */
3391 if (wld.map.server.startpos == MAPSTARTPOS_DEFAULT
3392 && wld.map.server.team_placement == TEAM_PLACEMENT_CONTINENT) {
3393 wld.map.server.startpos = MAPSTARTPOS_ALL;
3394 }
3395
3396 switch (wld.map.server.startpos) {
3397 case MAPSTARTPOS_2or3:
3398 {
3399 bool maybe2 = (0 == player_count() % 2);
3400 bool maybe3 = (0 == player_count() % 3);
3401
3402 if (wld.map.server.team_placement != TEAM_PLACEMENT_DISABLED) {
3403 teams_iterate(pteam) {
3404 i = player_list_size(team_members(pteam));
3405 if (i > 1) {
3406 if (0 != i % 2) {
3407 maybe2 = FALSE;
3408 }
3409 if (0 != i % 3) {
3410 maybe3 = FALSE;
3411 }
3412 }
3413 } teams_iterate_end;
3414 }
3415
3416 if (maybe3) {
3417 players_per_island = 3;
3418 } else if (maybe2) {
3419 players_per_island = 2;
3420 }
3421 }
3422 break;
3423 case MAPSTARTPOS_ALL:
3424 if (wld.map.server.team_placement == TEAM_PLACEMENT_CONTINENT) {
3425 teams_iterate(pteam) {
3426 i = player_list_size(team_members(pteam));
3427 if (i > 1) {
3428 if (players_per_island == 1) {
3429 players_per_island = i;
3430 } else if (i != players_per_island) {
3431 /* Every team doesn't have the same number of players. Cannot
3432 * consider this option. */
3433 players_per_island = 1;
3434 wld.map.server.team_placement = TEAM_PLACEMENT_CLOSEST;
3435 break;
3436 }
3437 }
3438 } teams_iterate_end;
3439 }
3440 break;
3441 case MAPSTARTPOS_DEFAULT:
3442 case MAPSTARTPOS_SINGLE:
3443 case MAPSTARTPOS_VARIABLE:
3444 break;
3445 }
3446 if (players_per_island == 1) {
3447 wld.map.server.startpos = MAPSTARTPOS_SINGLE;
3448 }
3449
3450 whole_map_iterate(&(wld.map), ptile) {
3451 tile_set_terrain(ptile, deepest_ocean);
3452 tile_set_continent(ptile, 0);
3453 BV_CLR_ALL(ptile->extras);
3454 tile_set_owner(ptile, NULL, NULL);
3455 ptile->extras_owner = NULL;
3456 } whole_map_iterate_end;
3457
3458 i = 0;
3459 if (HAS_POLES) {
3460 make_polar();
3461
3462 whole_map_iterate(&(wld.map), ptile) {
3463 if (tile_terrain(ptile) != deepest_ocean) {
3464 i++;
3465 }
3466 } whole_map_iterate_end;
3467 }
3468
3469 if (wld.map.server.mapsize == MAPSIZE_PLAYER) {
3470 playermass = wld.map.server.tilesperplayer - i / player_count();
3471 } else {
3472 playermass = ((map_num_tiles() * wld.map.server.landpercent - i)
3473 / (player_count() * 100));
3474 }
3475 islandmass1 = (players_per_island * playermass * 7) / 10;
3476 if (islandmass1 < min_island_size) {
3477 islandmass1 = min_island_size;
3478 }
3479 islandmass2 = (playermass * 2) / 10;
3480 if (islandmass2 < min_island_size) {
3481 islandmass2 = min_island_size;
3482 }
3483 islandmass3 = playermass / 10;
3484 if (islandmass3 < min_island_size) {
3485 islandmass3 = min_island_size;
3486 }
3487
3488 log_verbose("Creating a map with fair island generator");
3489 log_debug("max iterations=%d", iter);
3490 log_debug("players_per_island=%d", players_per_island);
3491 log_debug("team_placement=%s",
3492 team_placement_name(wld.map.server.team_placement));
3493 log_debug("teams_num=%d, team_players_num=%d, single_players_num=%d",
3494 teams_num, team_players_num, single_players_num);
3495 log_debug("playermass=%d, islandmass1=%d, islandmass2=%d, islandmass3=%d",
3496 playermass, islandmass1, islandmass2, islandmass3);
3497
3498 pmap = fair_map_new();
3499
3500 while (--iter >= 0) {
3501 done = TRUE;
3502
3503 whole_map_iterate(&(wld.map), ptile) {
3504 struct fair_tile *pftile = pmap + tile_index(ptile);
3505
3506 if (tile_terrain(ptile) != deepest_ocean) {
3507 pftile->flags |= (FTF_ASSIGNED | FTF_NO_HUT);
3508 adjc_iterate(&(wld.map), ptile, atile) {
3509 struct fair_tile *aftile = pmap + tile_index(atile);
3510
3511 if (!(aftile->flags & FTF_ASSIGNED)
3512 && tile_terrain(atile) == deepest_ocean) {
3513 aftile->flags |= FTF_OCEAN;
3514 }
3515 } adjc_iterate_end;
3516 }
3517 pftile->pterrain = tile_terrain(ptile);
3518 pftile->presource = tile_resource(ptile);
3519 pftile->extras = *tile_extras(ptile);
3520 } whole_map_iterate_end;
3521
3522 /* Create main player island. */
3523 log_debug("Making main island.");
3524 pisland = fair_map_island_new(islandmass1, players_per_island);
3525
3526 log_debug("Place main islands on the map.");
3527 i = 0;
3528
3529 if (wld.map.server.team_placement != TEAM_PLACEMENT_DISABLED
3530 && team_players_num > 0) {
3531 /* Do team placement. */
3532 struct iter_index outwards_indices[wld.map.num_iterate_outwards_indices];
3533 int start_x[teams_num], start_y[teams_num];
3534 int dx = 0, dy = 0;
3535 int j, k;
3536
3537 /* Build outwards_indices. */
3538 memcpy(outwards_indices, wld.map.iterate_outwards_indices,
3539 sizeof(outwards_indices));
3540 switch (wld.map.server.team_placement) {
3541 case TEAM_PLACEMENT_DISABLED:
3542 fc_assert(wld.map.server.team_placement != TEAM_PLACEMENT_DISABLED);
3543 break;
3544 case TEAM_PLACEMENT_CLOSEST:
3545 case TEAM_PLACEMENT_CONTINENT:
3546 for (j = 0; j < wld.map.num_iterate_outwards_indices; j++) {
3547 /* We want square distances for comparing. */
3548 outwards_indices[j].dist =
3549 map_vector_to_sq_distance(outwards_indices[j].dx,
3550 outwards_indices[j].dy);
3551 }
3552 qsort(outwards_indices, wld.map.num_iterate_outwards_indices,
3553 sizeof(outwards_indices[0]), fair_team_placement_closest);
3554 break;
3555 case TEAM_PLACEMENT_HORIZONTAL:
3556 qsort(outwards_indices, wld.map.num_iterate_outwards_indices,
3557 sizeof(outwards_indices[0]), fair_team_placement_horizontal);
3558 break;
3559 case TEAM_PLACEMENT_VERTICAL:
3560 qsort(outwards_indices, wld.map.num_iterate_outwards_indices,
3561 sizeof(outwards_indices[0]), fair_team_placement_vertical);
3562 break;
3563 }
3564
3565 /* Make start point for teams. */
3566 if (current_wrap_has_flag(WRAP_X)) {
3567 dx = fc_rand(wld.map.xsize);
3568 }
3569 if (current_wrap_has_flag(WRAP_Y)) {
3570 dy = fc_rand(wld.map.ysize);
3571 }
3572 for (j = 0; j < teams_num; j++) {
3573 start_x[j] = (wld.map.xsize * (2 * j + 1)) / (2 * teams_num) + dx;
3574 start_y[j] = (wld.map.ysize * (2 * j + 1)) / (2 * teams_num) + dy;
3575 if (current_wrap_has_flag(WRAP_X)) {
3576 start_x[j] = FC_WRAP(start_x[j], wld.map.xsize);
3577 }
3578 if (current_wrap_has_flag(WRAP_Y)) {
3579 start_y[j] = FC_WRAP(start_y[j], wld.map.ysize);
3580 }
3581 }
3582 /* Randomize. */
3583 array_shuffle(start_x, teams_num);
3584 array_shuffle(start_y, teams_num);
3585
3586 j = 0;
3587 teams_iterate(pteam) {
3588 int members_count = player_list_size(team_members(pteam));
3589 int team_id;
3590 int x, y;
3591
3592 if (members_count <= 1) {
3593 continue;
3594 }
3595 team_id = team_number(pteam);
3596
3597 NATIVE_TO_MAP_POS(&x, &y, start_x[j], start_y[j]);
3598 log_verbose("Team %d (%s) will start on (%d, %d)",
3599 team_id, team_rule_name(pteam), x, y);
3600
3601 for (k = 0; k < members_count; k += players_per_island) {
3602 if (!fair_map_place_island_team(pmap, x, y, pisland,
3603 outwards_indices, team_id)) {
3604 log_verbose("Failed to place island number %d for team %d (%s).",
3605 k, team_id, team_rule_name(pteam));
3606 done = FALSE;
3607 break;
3608 }
3609 }
3610 if (!done) {
3611 break;
3612 }
3613 i += k;
3614 j++;
3615 } teams_iterate_end;
3616
3617 fc_assert(!done || i == team_players_num);
3618 }
3619
3620 if (done) {
3621 /* Place last player islands. */
3622 for (; i < player_count(); i += players_per_island) {
3623 if (!fair_map_place_island_rand(pmap, pisland)) {
3624 log_verbose("Failed to place island number %d.", i);
3625 done = FALSE;
3626 break;
3627 }
3628 }
3629 fc_assert(!done || i == player_count());
3630 }
3631 fair_map_destroy(pisland);
3632
3633 if (done) {
3634 log_debug("Create and place small islands on the map.");
3635 for (i = 0; i < player_count(); i++) {
3636 pisland = fair_map_island_new(islandmass2, 0);
3637 if (!fair_map_place_island_rand(pmap, pisland)) {
3638 log_verbose("Failed to place small island2 number %d.", i);
3639 done = FALSE;
3640 fair_map_destroy(pisland);
3641 break;
3642 }
3643 fair_map_destroy(pisland);
3644 }
3645 }
3646 if (done) {
3647 for (i = 0; i < player_count(); i++) {
3648 pisland = fair_map_island_new(islandmass3, 0);
3649 if (!fair_map_place_island_rand(pmap, pisland)) {
3650 log_verbose("Failed to place small island3 number %d.", i);
3651 done = FALSE;
3652 fair_map_destroy(pisland);
3653 break;
3654 }
3655 fair_map_destroy(pisland);
3656 }
3657 }
3658
3659 if (done) {
3660 break;
3661 }
3662
3663 fair_map_destroy(pmap);
3664 pmap = fair_map_new();
3665
3666 /* Decrease land mass, for better chances. */
3667 islandmass1 = (islandmass1 * 99) / 100;
3668 if (islandmass1 < min_island_size) {
3669 islandmass1 = min_island_size;
3670 }
3671 islandmass2 = (islandmass2 * 99) / 100;
3672 if (islandmass2 < min_island_size) {
3673 islandmass2 = min_island_size;
3674 }
3675 islandmass3 = (islandmass3 * 99) / 100;
3676 if (islandmass3 < min_island_size) {
3677 islandmass3 = min_island_size;
3678 }
3679 }
3680
3681 if (!done) {
3682 log_verbose("Failed to create map after %d iterations.", iter);
3683 wld.map.server.generator = MAPGEN_ISLAND;
3684 return FALSE;
3685 }
3686
3687 /* Finalize the map. */
3688 for (i = 0; i < MAP_INDEX_SIZE; i++) {
3689 /* Mark all tiles as assigned, for adding resources and huts. */
3690 pmap[i].flags |= FTF_ASSIGNED;
3691 }
3692 if (wld.map.server.riches > 0) {
3693 fair_map_make_resources(pmap);
3694 }
3695 if (wld.map.server.huts > 0) {
3696 fair_map_make_huts(pmap);
3697 }
3698
3699 /* Apply the map. */
3700 log_debug("Applying the map...");
3701 whole_map_iterate(&(wld.map), ptile) {
3702 struct fair_tile *pftile = pmap + tile_index(ptile);
3703
3704 fc_assert(pftile->pterrain != NULL);
3705 tile_set_terrain(ptile, pftile->pterrain);
3706 ptile->extras = pftile->extras;
3707 tile_set_resource(ptile, pftile->presource);
3708 if (pftile->flags & FTF_STARTPOS) {
3709 struct startpos *psp = map_startpos_new(ptile);
3710
3711 if (pftile->startpos_team_id != -1) {
3712 player_list_iterate(team_members(team_by_number
3713 (pftile->startpos_team_id)), pplayer) {
3714 startpos_allow(psp, nation_of_player(pplayer));
3715 } player_list_iterate_end;
3716 } else {
3717 startpos_allows_all(psp);
3718 }
3719 }
3720 } whole_map_iterate_end;
3721
3722 wld.map.server.have_resources = TRUE;
3723 wld.map.server.have_huts = TRUE;
3724
3725 fair_map_destroy(pmap);
3726
3727 log_verbose("Fair island map created with success!");
3728 return TRUE;
3729}
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:292
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:63
game.h
renormalize_hmap_poles
void renormalize_hmap_poles(void)
Definition height_map.c:80
normalize_hmap_poles
void normalize_hmap_poles(void)
Definition height_map.c:64
area_is_too_flat
bool area_is_too_flat(struct tile *ptile, int thill, int my_height)
Definition height_map.c:269
make_pseudofractal1_hmap
void make_pseudofractal1_hmap(int extra_div)
Definition height_map.c:197
make_random_hmap
void make_random_hmap(int smooth)
Definition height_map.c:100
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:1866
map_num_tiles
int map_num_tiles(void)
Definition map.c:1014
startpos_allows_all
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1696
rand_map_pos
struct tile * rand_map_pos(const struct civ_map *nmap)
Definition map.c:1088
main_map_allocate
void main_map_allocate(void)
Definition map.c:519
index_to_tile
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:456
map_vector_to_sq_distance
int map_vector_to_sq_distance(int dx, int dy)
Definition map.c:614
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:1101
map_startpos_count
int map_startpos_count(void)
Definition map.c:1853
is_cardinal_dir
bool is_cardinal_dir(enum direction8 dir)
Definition map.c:1316
native_pos_to_tile
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:443
map_is_empty
bool map_is_empty(void)
Definition map.c:149
startpos_allow
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1643
normalize_map_pos
bool normalize_map_pos(const struct civ_map *nmap, int *x, int *y)
Definition map.c:979
map.h
current_topo_has_flag
#define current_topo_has_flag(flag)
Definition map.h:48
native_pos_to_index
#define native_pos_to_index(nat_x, nat_y)
Definition map.h:154
adjc_iterate_end
#define adjc_iterate_end
Definition map.h:433
index_to_map_pos_y
static int index_to_map_pos_y(int mindex)
Definition map.h:724
MAP_INDEX_SIZE
#define MAP_INDEX_SIZE
Definition map.h:137
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:391
MAP_IS_ISOMETRIC
#define MAP_IS_ISOMETRIC
Definition map.h:42
cardinal_adjc_iterate_end
#define cardinal_adjc_iterate_end
Definition map.h:459
adjc_iterate
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:428
MAP_TO_NATIVE_POS
#define MAP_TO_NATIVE_POS(pnat_x, pnat_y, map_x, map_y)
Definition map.h:172
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:166
cardinal_adjc_dir_iterate_end
#define cardinal_adjc_dir_iterate_end
Definition map.h:466
square_iterate_end
#define square_iterate_end
Definition map.h:394
cardinal_adjc_iterate
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:455
circle_iterate
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:401
index_to_map_pos_x
static int index_to_map_pos_x(int mindex)
Definition map.h:715
whole_map_iterate
#define whole_map_iterate(_map, _tile)
Definition map.h:545
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:473
DIR_REVERSE
#define DIR_REVERSE(dir)
Definition map.h:561
current_wrap_has_flag
#define current_wrap_has_flag(flag)
Definition map.h:51
cardinal_adjc_dir_base_iterate
#define cardinal_adjc_dir_base_iterate(nmap, center_tile, dir_itr)
Definition map.h:469
index_to_native_pos
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:157
cardinal_adjc_dir_iterate
#define cardinal_adjc_dir_iterate(nmap, center_tile, itr_tile, dir_itr)
Definition map.h:462
whole_map_iterate_end
#define whole_map_iterate_end
Definition map.h:554
index_to_map_pos
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:233
circle_iterate_end
#define circle_iterate_end
Definition map.h:404
DIRSTEP
#define DIRSTEP(dest_x, dest_y, dir)
Definition map.h:240
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:449
fair_team_placement_vertical
static int fair_team_placement_vertical(const void *a, const void *b)
Definition mapgen.c:2656
make_terrains
static void make_terrains(void)
Definition mapgen.c:485
hmap_low_level
static int hmap_low_level
Definition mapgen.c:185
make_rivers
static void make_rivers(void)
Definition mapgen.c:900
mapgenerator2
static void mapgenerator2(void)
Definition mapgen.c:2231
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:683
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:2678
fair_map_make_resources
static void fair_map_make_resources(struct fair_tile *pmap)
Definition mapgen.c:2953
make_island
static bool make_island(int islemass, int starters, struct gen234_state *pstate, int min_specific_island_size)
Definition mapgen.c:2081
river_test_adjacent_swamp
static int river_test_adjacent_swamp(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:640
fair_do_iso_hex_symetry1
static void fair_do_iso_hex_symetry1(int *x, int *y)
Definition mapgen.c:2703
fair_map_new
static struct fair_tile * fair_map_new(void)
Definition mapgen.c:2535
river_test_height_map
static int river_test_height_map(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:656
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:2759
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:2226
fair_geometry_func
void(* fair_geometry_func)(int *x, int *y)
Definition mapgen.c:2525
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:2746
make_land
static void make_land(void)
Definition mapgen.c:1047
initworld
static void initworld(struct gen234_state *pstate)
Definition mapgen.c:2194
fair_map_island_new
static struct fair_tile * fair_map_island_new(int size, int startpos_num)
Definition mapgen.c:3055
fair_map_destroy
static void fair_map_destroy(struct fair_tile *pmap)
Definition mapgen.c:2543
fair_map_tile_border
static bool fair_map_tile_border(struct fair_tile *pmap, struct fair_tile *ptile, int dist)
Definition mapgen.c:2605
mapgenerator4
static void mapgenerator4(void)
Definition mapgen.c:2423
make_polar_land
static void make_polar_land(void)
Definition mapgen.c:371
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:1643
map_pos_is_low
#define map_pos_is_low(ptile)
Definition mapgen.c:192
rand_map_pos_characteristic
static struct tile * rand_map_pos_characteristic(wetness_c wc, temperature_type tc, miscellaneous_c mc)
Definition mapgen.c:262
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:2551
adjust_terrain_param
static void adjust_terrain_param(void)
Definition mapgen.c:1484
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:1611
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:220
fair_do_hex_symetry1
static void fair_do_hex_symetry1(int *x, int *y)
Definition mapgen.c:2686
river_test_adjacent_ocean
static int river_test_adjacent_ocean(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:593
print_mapgen_map
static void print_mapgen_map(void)
Definition mapgen.c:1200
forest
struct terrain_select_list * forest
Definition mapgen.c:95
place_island
static bool place_island(struct gen234_state *pstate)
Definition mapgen.c:1840
river_blockmark
static void river_blockmark(struct river_map *privermap, struct tile *ptile)
Definition mapgen.c:666
make_huts
static void make_huts(int number)
Definition mapgen.c:1527
fair_do_hex_symetry2
static void fair_do_hex_symetry2(int *x, int *y)
Definition mapgen.c:2694
test_wetness
static bool test_wetness(const struct tile *ptile, wetness_c c)
Definition mapgen.c:203
island_terrain_free
static void island_terrain_free(void)
Definition mapgen.c:2061
is_tiny_island
static bool is_tiny_island(struct tile *ptile)
Definition mapgen.c:1150
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:464
river_test_adjacent_highlands
static int river_test_adjacent_highlands(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:614
fair_do_iso_hex_symetry2
#define fair_do_iso_hex_symetry2
Definition mapgen.c:2708
river_types_init
static void river_types_init(void)
Definition mapgen.c:2491
near_safe_tiles
static bool near_safe_tiles(struct tile *ptile)
Definition mapgen.c:1512
ok_for_separate_poles
static bool ok_for_separate_poles(struct tile *ptile)
Definition mapgen.c:353
miscellaneous_c
miscellaneous_c
Definition mapgen.c:194
MC_LOW
@ MC_LOW
Definition mapgen.c:194
MC_NLOW
@ MC_NLOW
Definition mapgen.c:194
MC_NONE
@ MC_NONE
Definition mapgen.c:194
is_near_land
static bool is_near_land(struct tile *ptile)
Definition mapgen.c:1823
fair_team_placement_horizontal
static int fair_team_placement_horizontal(const void *a, const void *b)
Definition mapgen.c:2642
condition_filter
static bool condition_filter(const struct tile *ptile, const void *data)
Definition mapgen.c:247
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:1592
is_resource_close
static bool is_resource_close(const struct tile *ptile)
Definition mapgen.c:1554
add_resources
static void add_resources(int prob)
Definition mapgen.c:1568
mapgenerator3
static void mapgenerator3(void)
Definition mapgen.c:2326
fair_do_rotation
static void fair_do_rotation(int *x, int *y)
Definition mapgen.c:2713
fair_map_place_island_rand
static bool fair_map_place_island_rand(struct fair_tile *ptarget, struct fair_tile *psource)
Definition mapgen.c:2888
river_test_highlands
static int river_test_highlands(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:583
fill_island_rivers
static void fill_island_rivers(int coast, long int *bucket, const struct gen234_state *const pstate)
Definition mapgen.c:1767
fair_map_make_huts
static void fair_map_make_huts(struct fair_tile *pmap)
Definition mapgen.c:3003
fair_team_placement_closest
static int fair_team_placement_closest(const void *a, const void *b)
Definition mapgen.c:2632
make_river
static bool make_river(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:786
island_terrain_init
static void island_terrain_init(void)
Definition mapgen.c:2000
island_river_mouth_suitability
static bool island_river_mouth_suitability(const struct tile *ptile, const struct extra_type *priver)
Definition mapgen.c:1722
river_test_rivergrid
static int river_test_rivergrid(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:572
map_generate_fair_islands
static bool map_generate_fair_islands(void)
Definition mapgen.c:3366
fair_do_iso_hex_rotation
static void fair_do_iso_hex_rotation(int *x, int *y)
Definition mapgen.c:2735
river_pct
static int river_pct
Definition mapgen.c:167
make_polar
static void make_polar(void)
Definition mapgen.c:331
create_island
static bool create_island(int islemass, struct gen234_state *pstate)
Definition mapgen.c:1930
make_plain
static void make_plain(struct tile *ptile, int *to_be_placed)
Definition mapgen.c:428
island_river_suitability
static bool island_river_suitability(const struct tile *ptile, const struct extra_type *priver)
Definition mapgen.c:1743
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:2923
test_funcs
static struct test_func test_funcs[NUM_TEST_FUNCTIONS]
Definition mapgen.c:684
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:2810
desert
struct terrain_select_list * desert
Definition mapgen.c:96
make_relief
static void make_relief(void)
Definition mapgen.c:294
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:2670
river_test_adjacent_river
static int river_test_adjacent_river(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:604
fair_do_hex_rotation
static void fair_do_hex_rotation(int *x, int *y)
Definition mapgen.c:2724
remove_tiny_islands
static void remove_tiny_islands(void)
Definition mapgen.c:1176
river_test_swamp
static int river_test_swamp(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:630
count_card_adjc_elevated_tiles
static int count_card_adjc_elevated_tiles(struct tile *ptile)
Definition mapgen.c:1914
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:393
terrain_is_too_high
static bool terrain_is_too_high(struct tile *ptile, int thill, int my_height)
Definition mapgen.c:277
map_fractal_generate
bool map_fractal_generate(bool autosize, struct unit_type *initial_unit)
Definition mapgen.c:1261
fair_map_pos_tile
static struct fair_tile * fair_map_pos_tile(struct fair_tile *pmap, int x, int y)
Definition mapgen.c:2561
tersel_free
static void tersel_free(struct terrain_select *ptersel)
Definition mapgen.c:1633
checkmass
static long int checkmass
Definition mapgen.c:1835
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:2590
river_test_blocked
static int river_test_blocked(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:551
fair_tile_flag
fair_tile_flag
Definition mapgen.c:2507
FTF_NONE
@ FTF_NONE
Definition mapgen.c:2508
FTF_NO_RESOURCE
@ FTF_NO_RESOURCE
Definition mapgen.c:2512
FTF_HAS_HUT
@ FTF_HAS_HUT
Definition mapgen.c:2513
FTF_ASSIGNED
@ FTF_ASSIGNED
Definition mapgen.c:2509
FTF_OCEAN
@ FTF_OCEAN
Definition mapgen.c:2510
FTF_STARTPOS
@ FTF_STARTPOS
Definition mapgen.c:2511
FTF_NO_HUT
@ FTF_NO_HUT
Definition mapgen.c:2514
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:555
player_list_iterate_end
#define player_list_iterate_end
Definition player.h:557
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:410
is_cardinal_only_road
bool is_cardinal_only_road(const struct extra_type *pextra)
Definition road.c:483
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:356
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:383
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:334
road.h
array_shuffle
void array_shuffle(int *array, int n)
Definition shared.c:2007
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:237
DataFilter::mc
miscellaneous_c mc
Definition mapgen.c:240
DataFilter::wc
wetness_c wc
Definition mapgen.c:238
DataFilter::tc
temperature_type tc
Definition mapgen.c:239
RANDOM_STATE
Definition rand.h:50
civ_map::xsize
int xsize
Definition map_types.h:78
civ_map::seed
randseed seed
Definition map_types.h:92
civ_map::tinyisles
bool tinyisles
Definition map_types.h:100
civ_map::ysize
int ysize
Definition map_types.h:78
civ_map::num_continents
int num_continents
Definition map_types.h:81
civ_map::valid_dirs
enum direction8 valid_dirs[8]
Definition map_types.h:74
civ_map::riches
int riches
Definition map_types.h:93
civ_map::num_iterate_outwards_indices
int num_iterate_outwards_indices
Definition map_types.h:77
civ_map::num_cardinal_dirs
int num_cardinal_dirs
Definition map_types.h:75
civ_map::mapsize
enum mapsize_type mapsize
Definition map_types.h:88
civ_map::num_valid_dirs
int num_valid_dirs
Definition map_types.h:75
civ_map::startpos
enum map_startpos startpos
Definition map_types.h:99
civ_map::num_oceans
int num_oceans
Definition map_types.h:82
civ_map::have_resources
bool have_resources
Definition map_types.h:108
civ_map::server
struct civ_map::@42::@44 server
civ_map::steepness
int steepness
Definition map_types.h:105
civ_map::wetness
int wetness
Definition map_types.h:104
civ_map::tilesperplayer
int tilesperplayer
Definition map_types.h:90
civ_map::seed_setting
randseed seed_setting
Definition map_types.h:91
civ_map::iterate_outwards_indices
struct iter_index * iterate_outwards_indices
Definition map_types.h:76
civ_map::landpercent
int landpercent
Definition map_types.h:97
civ_map::team_placement
enum team_placement team_placement
Definition map_types.h:109
civ_map::cardinal_dirs
enum direction8 cardinal_dirs[8]
Definition map_types.h:74
civ_map::huts
int huts
Definition map_types.h:94
civ_map::have_huts
bool have_huts
Definition map_types.h:107
civ_map::generator
enum map_generator generator
Definition map_types.h:98
civ_map::ocean_resources
bool ocean_resources
Definition map_types.h:106
civ_map::separatepoles
bool separatepoles
Definition map_types.h:101
civ_map::temperature
int temperature
Definition map_types.h:103
dbv
Definition bitvector.h:32
extra_type
Definition extras.h:88
fair_geometry_data
Definition mapgen.c:2526
fair_geometry_data::transform
fair_geometry_func transform[4]
Definition mapgen.c:2527
fair_geometry_data::transform_num
int transform_num
Definition mapgen.c:2528
fair_tile
Definition mapgen.c:2517
fair_tile::extras
bv_extras extras
Definition mapgen.c:2521
fair_tile::pterrain
struct terrain * pterrain
Definition mapgen.c:2519
fair_tile::flags
enum fair_tile_flag flags
Definition mapgen.c:2518
fair_tile::startpos_team_id
int startpos_team_id
Definition mapgen.c:2522
fair_tile::presource
struct extra_type * presource
Definition mapgen.c:2520
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:41
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:182
terrain::property
int property[MG_COUNT]
Definition terrain.h:253
test_func
Definition mapgen.c:678
test_func::fatal
bool fatal
Definition mapgen.c:680
test_func::func
int(* func)(struct river_map *privermap, struct tile *ptile, struct extra_type *priver)
Definition mapgen.c:679
tile
Definition tile.h:50
unit_type
Definition unittype.h:500
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:373
T_UNKNOWN
#define T_UNKNOWN
Definition terrain.h:57
is_ocean
#define is_ocean(pterrain)
Definition terrain.h:301
is_ocean_tile
#define is_ocean_tile(ptile)
Definition terrain.h:303
TERRAIN_OCEAN_DEPTH_MINIMUM
#define TERRAIN_OCEAN_DEPTH_MINIMUM
Definition terrain.h:254
terrain_type_iterate_end
#define terrain_type_iterate_end
Definition terrain.h:379
TERRAIN_OCEAN_DEPTH_MAXIMUM
#define TERRAIN_OCEAN_DEPTH_MAXIMUM
Definition terrain.h:255
terrain_has_flag
#define terrain_has_flag(terr, flag)
Definition terrain.h:283
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:1033
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:88
tile_resource
#define tile_resource(_tile)
Definition tile.h:102
tile_terrain
#define tile_terrain(_tile)
Definition tile.h:110
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:120
tile_continent
#define tile_continent(_tile)
Definition tile.h:92
tile_has_extra
#define tile_has_extra(ptile, pextra)
Definition tile.h:147