Freeciv-3.1: /fast/freeciv/nightly/S3_1/server/generator/mapgen.c Source File

Freeciv-3.1

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