Freeciv-3.3
Loading...
Searching...
No Matches
map.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/* utility */
19#include "fcintl.h"
20#include "iterator.h"
21#include "log.h"
22#include "mem.h"
23#include "rand.h"
24#include "shared.h"
25#include "support.h"
26
27/* common */
28#include "ai.h"
29#include "city.h"
30#include "game.h"
31#include "movement.h"
32#include "nation.h"
33#include "packets.h"
34#include "road.h"
35#include "unit.h"
36#include "unitlist.h"
37
38#include "map.h"
39
40struct startpos {
41 struct tile *location;
42 bool exclude;
44};
45
46static struct startpos *startpos_new(struct tile *ptile);
47static void startpos_destroy(struct startpos *psp);
48
49/* struct startpos_hash and related functions. */
50#define SPECHASH_TAG startpos
51#define SPECHASH_IKEY_TYPE struct tile *
52#define SPECHASH_IDATA_TYPE struct startpos *
53#define SPECHASH_IDATA_FREE startpos_destroy
54#include "spechash.h"
55
56/* Srart position iterator. */
59 const struct startpos *psp;
60 /* 'struct nation_iter' really. See startpos_iter_sizeof(). */
62};
63
64#define STARTPOS_ITER(p) ((struct startpos_iter *) (p))
65
66
67/* These are initialized from the terrain ruleset */
69
70/* Used to compute neighboring tiles.
71 *
72 * Using
73 * x1 = x + DIR_DX[dir];
74 * y1 = y + DIR_DY[dir];
75 * will give you the tile as shown below.
76 * -------
77 * |0|1|2|
78 * |-+-+-|
79 * |3| |4|
80 * |-+-+-|
81 * |5|6|7|
82 * -------
83 * Note that you must normalize x1 and y1 yourself.
84 */
85const int DIR_DX[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };
86const int DIR_DY[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };
87
88static bool dir_cardinality[9]; /* Including invalid one */
89static bool dir_validity[9]; /* Including invalid one */
90
91static bool is_valid_dir_calculate(enum direction8 dir);
92static bool is_cardinal_dir_calculate(enum direction8 dir);
93
94static bool restrict_infra(const struct player *pplayer, const struct tile *t1,
95 const struct tile *t2);
96
97/*******************************************************************/
101 int *pcount)
102{
104 int count = 0;
105
107
109 if (tile_has_extra(ptile, pextra)) {
110 struct tile *missingset = tile_virtual_new(ptile);
111 bool dependency = FALSE;
112
115 if (tile_has_extra(ptile, pdependant)) {
116 if (!are_reqs_active(&(const struct req_context) {
117 .tile = missingset,
118 },
119 nullptr, &pdependant->reqs, RPT_POSSIBLE)) {
121 break;
122 }
123 }
125
127
128 if (!dependency) {
129 BV_SET(pspresent, extra_index(pextra));
130 count++;
131 }
132 }
134
135 if (pcount) {
136 *pcount = count;
137 }
138
139 return pspresent;
140}
141
142/*******************************************************************/
148bool map_is_empty(void)
149{
150 return wld.map.tiles == nullptr;
151}
152
153/*******************************************************************/
156void map_init(struct civ_map *imap, bool server_side)
157{
158 imap->topology_id = MAP_DEFAULT_TOPO;
159 imap->wrap_id = MAP_DEFAULT_WRAP;
160 imap->altitude_info = FALSE;
161 imap->num_continents = 0;
162 imap->num_oceans = 0;
163 imap->tiles = nullptr;
164 imap->startpos_table = nullptr;
165 imap->iterate_outwards_indices = nullptr;
166
167 /* The [xy]size values are set in map_init_topology(). It is initialized
168 * to a non-zero value because some places erroneously use these values
169 * before they're initialized. */
172
173 imap->north_latitude = MAP_DEFAULT_NORTH_LATITUDE;
174 imap->south_latitude = MAP_DEFAULT_SOUTH_LATITUDE;
175
176 imap->continent_sizes = nullptr;
177 imap->ocean_sizes = nullptr;
178
179 if (server_side) {
180 imap->server.mapsize = MAP_DEFAULT_MAPSIZE;
181 imap->server.size = MAP_DEFAULT_SIZE;
182 imap->server.tilesperplayer = MAP_DEFAULT_TILESPERPLAYER;
183 imap->server.seed_setting = MAP_DEFAULT_SEED;
184 imap->server.seed = MAP_DEFAULT_SEED;
185 imap->server.riches = MAP_DEFAULT_RICHES;
186 imap->server.huts = MAP_DEFAULT_HUTS;
187 imap->server.huts_absolute = -1;
188 imap->server.animals = MAP_DEFAULT_ANIMALS;
189 imap->server.landpercent = MAP_DEFAULT_LANDMASS;
190 imap->server.wetness = MAP_DEFAULT_WETNESS;
191 imap->server.steepness = MAP_DEFAULT_STEEPNESS;
192 imap->server.generator = MAP_DEFAULT_GENERATOR;
193 imap->server.startpos = MAP_DEFAULT_STARTPOS;
194 imap->server.tinyisles = MAP_DEFAULT_TINYISLES;
195 imap->server.separatepoles = MAP_DEFAULT_SEPARATE_POLES;
196 imap->server.temperature = MAP_DEFAULT_TEMPERATURE;
197 imap->server.have_huts = FALSE;
198 imap->server.have_resources = FALSE;
199 imap->server.team_placement = MAP_DEFAULT_TEAM_PLACEMENT;
200
201 imap->server.island_surrounders = nullptr;
202 imap->server.lake_surrounders = nullptr;
203 } else {
204 imap->client.adj_matrix = fc_malloc(sizeof(*imap->client.adj_matrix));
205 *imap->client.adj_matrix = fc_malloc(sizeof(**imap->client.adj_matrix));
206 }
207}
208
209/*******************************************************************/
212static void generate_map_indices(void)
213{
214 int i = 0, nat_x, nat_y, tiles;
217
218 /* These caluclations are done via tricky native math. We need to make
219 * sure that when "exploring" positions in the iterate_outward() we
220 * hit each position within the distance exactly once.
221 *
222 * To do this we pick a center position (at the center of the map, for
223 * convenience). Then we iterate over all of the positions around it,
224 * accounting for wrapping, in native coordinates. Note that some of
225 * the positions iterated over before will not even be real; the point
226 * is to use the native math so as to get the right behavior under
227 * different wrapping conditions.
228 *
229 * Thus the "center" position below is just an arbitrary point. We choose
230 * the center of the map to make the min/max values (below) simpler. */
235
236 /* If we wrap in a particular direction (X or Y), we only need to explore a
237 * half of a map-width in that direction before we hit the wrap point.
238 * If not, we need to explore the full width since we have to account
239 * for the worst-case where we start at one edge of the map. Of course
240 * if we try to explore too far the extra steps will just be skipped by the
241 * normalize check later on. So the purpose at this point is just to
242 * get the right set of positions, relative to the start position, that
243 * may be needed for the iteration.
244 *
245 * If the map does wrap, we go map.Nsize / 2 in each direction.
246 * This gives a min value of 0 and a max value of Nsize-1, because of the
247 * center position chosen above. This also avoids any off-by-one errors.
248 *
249 * If the map doesn't wrap, we go map.Nsize-1 in each direction. In this
250 * case we're not concerned with going too far and wrapping around, so we
251 * just have to make sure we go far enough if we're at one edge of the
252 * map. */
257
259 ? (MAP_NATIVE_WIDTH - 1)
262 ? (MAP_NATIVE_HEIGHT - 1)
264 tiles = (nat_max_x - nat_min_x + 1) * (nat_max_y - nat_min_y + 1);
265
268 fc_malloc(tiles * sizeof(*wld.map.iterate_outwards_indices));
269
270 for (nat_x = nat_min_x; nat_x <= nat_max_x; nat_x++) {
271 for (nat_y = nat_min_y; nat_y <= nat_max_y; nat_y++) {
272 int map_x, map_y, dx, dy;
273
274 /* Now for each position, we find the vector (in map coordinates) from
275 * the center position to that position. Then we calculate the
276 * distance between the two points. Wrapping is ignored at this
277 * point since the use of native positions means we should always have
278 * the shortest vector. */
280 dx = map_x - map_center_x;
281 dy = map_y - map_center_y;
282
287 i++;
288 }
289 }
290
291 fc_assert(i == tiles);
292
295
296#if 0
297 for (i = 0; i < tiles; i++) {
298 log_debug("%5d : (%3d,%3d) : %d", i,
302 }
303#endif /* FALSE */
304
306}
307
308/*******************************************************************/
316{
317 enum direction8 dir;
318
319 /* Sanity check for iso topologies */
321
322 /* The size and ratio must satisfy the minimum and maximum *linear*
323 * restrictions on width */
330
331 nmap->num_valid_dirs = nmap->num_cardinal_dirs = 0;
332
333 /* Values for direction8_invalid() */
335 dir_validity[8] = FALSE;
337
338 /* Values for actual directions */
339 for (dir = 0; dir < 8; dir++) {
340 if (is_valid_dir_calculate(dir)) {
341 nmap->valid_dirs[nmap->num_valid_dirs] = dir;
342 nmap->num_valid_dirs++;
343 dir_validity[dir] = TRUE;
344 } else {
345 dir_validity[dir] = FALSE;
346 }
347 if (is_cardinal_dir_calculate(dir)) {
348 nmap->cardinal_dirs[nmap->num_cardinal_dirs] = dir;
349 nmap->num_cardinal_dirs++;
350 dir_cardinality[dir] = TRUE;
351 } else {
352 dir_cardinality[dir] = FALSE;
353 }
354 }
355 fc_assert(nmap->num_valid_dirs > 0 && nmap->num_valid_dirs <= 8);
356 fc_assert(nmap->num_cardinal_dirs > 0
357 && nmap->num_cardinal_dirs <= nmap->num_valid_dirs);
358}
359
360/*******************************************************************/
363static void tile_init(struct tile *ptile)
364{
365 ptile->continent = 0;
366
367 BV_CLR_ALL(ptile->extras);
368 ptile->resource = nullptr;
369 ptile->terrain = T_UNKNOWN;
370 ptile->units = unit_list_new();
371 ptile->owner = nullptr; /* Not claimed by any player. */
372 ptile->extras_owner = nullptr;
373 ptile->placing = nullptr;
374 ptile->claimer = nullptr;
375 ptile->worked = nullptr; /* No city working here. */
376 ptile->altitude = 0;
377 ptile->spec_sprite = nullptr;
378}
379
380/*******************************************************************/
384struct tile *mapstep(const struct civ_map *nmap,
385 const struct tile *ptile, enum direction8 dir)
386{
387 int dx, dy, tile_x, tile_y;
388
389 if (!is_valid_dir(dir)) {
390 return nullptr;
391 }
392
394 DIRSTEP(dx, dy, dir);
395
396 tile_x += dx;
397 tile_y += dy;
398
399 return map_pos_to_tile(&(wld.map), tile_x, tile_y);
400}
401
402/*******************************************************************/
410static inline struct tile *base_native_pos_to_tile(const struct civ_map *nmap,
411 int nat_x, int nat_y)
412{
413 /* Wrap in X and Y directions, as needed. */
414 /* If the position is out of range in a non-wrapping direction, it is
415 * unreal. */
419 return nullptr;
420 }
424 return nullptr;
425 }
426
427 /* We already checked legality of native pos above, don't repeat */
429}
430
431/*******************************************************************/
434struct tile *map_pos_to_tile(const struct civ_map *nmap, int map_x, int map_y)
435{
436 /* Instead of introducing new variables for native coordinates,
437 * update the map coordinate variables = registers already in use.
438 * This is one of the most performance-critical functions we have,
439 * so taking measures like this makes sense. */
440#define nat_x map_x
441#define nat_y map_y
442
443 if (nmap->tiles == nullptr) {
444 return nullptr;
445 }
446
447 /* Normalization is best done in native coordinates. */
450
451#undef nat_x
452#undef nat_y
453}
454
455/*******************************************************************/
458struct tile *native_pos_to_tile(const struct civ_map *nmap,
459 int nat_x, int nat_y)
460{
461 if (nmap->tiles == nullptr) {
462 return nullptr;
463 }
464
466}
467
468/*******************************************************************/
471struct tile *index_to_tile(const struct civ_map *imap, int mindex)
472{
473 if (imap->tiles == nullptr) {
474 return nullptr;
475 }
476
477 if (mindex >= 0 && mindex < MAP_INDEX_SIZE) {
478 return imap->tiles + mindex;
479 } else {
480 /* Unwrapped index coordinates are impossible, so the best we can do is
481 * return nullptr. */
482 return nullptr;
483 }
484}
485
486/*******************************************************************/
489static void tile_free(struct tile *ptile)
490{
491 unit_list_destroy(ptile->units);
492
493 if (ptile->spec_sprite) {
494 free(ptile->spec_sprite);
495 ptile->spec_sprite = nullptr;
496 }
497
498 if (ptile->label) {
499 FC_FREE(ptile->label);
500 ptile->label = nullptr;
501 }
502}
503
504/*******************************************************************/
509{
510 log_debug("map_allocate (was %p) (%d,%d)",
511 (void *) amap->tiles, amap->xsize, amap->ysize);
512
513 fc_assert_ret(amap->tiles == nullptr);
514 amap->tiles = fc_calloc(MAP_INDEX_SIZE, sizeof(*amap->tiles));
515
516 /* Note this use of whole_map_iterate may be a bit sketchy, since the
517 * tile values (ptile->index, etc.) haven't been set yet. It might be
518 * better to do a manual loop here. */
519 whole_map_iterate(amap, ptile) {
520 ptile->index = ptile - amap->tiles;
521 CHECK_INDEX(tile_index(ptile));
522 tile_init(ptile);
524
525 if (amap->startpos_table != nullptr) {
526 startpos_hash_destroy(amap->startpos_table);
527 }
528 amap->startpos_table = startpos_hash_new();
529}
530
531/*******************************************************************/
541
542/*******************************************************************/
545void map_free(struct civ_map *fmap, bool server_side)
546{
547 if (fmap->tiles) {
548 /* It is possible that map_init() was called but not map_allocate() */
549
550 whole_map_iterate(fmap, ptile) {
551 tile_free(ptile);
553
554 free(fmap->tiles);
555 fmap->tiles = nullptr;
556
557 if (fmap->startpos_table) {
558 startpos_hash_destroy(fmap->startpos_table);
559 fmap->startpos_table = nullptr;
560 }
561
562 FC_FREE(fmap->iterate_outwards_indices);
563 }
564 if (fmap->continent_sizes) {
565 FC_FREE(fmap->continent_sizes);
566 }
567 if (fmap->ocean_sizes) {
568 FC_FREE(fmap->ocean_sizes);
569 }
570
571 if (server_side) {
572 if (fmap->server.island_surrounders) {
573 FC_FREE(fmap->server.island_surrounders);
574 }
575 if (fmap->server.lake_surrounders) {
576 FC_FREE(fmap->server.lake_surrounders);
577 }
578 } else {
579 if (fmap->client.adj_matrix) {
580 int i;
581
582 for (i = 0; i <= fmap->num_continents; i++) {
583 if (fmap->client.adj_matrix[i]) {
584 free(fmap->client.adj_matrix[i]);
585 }
586 }
587
588 FC_FREE(fmap->client.adj_matrix);
589 }
590 }
591
592 /* For any code that tries accessing sizes, surrounders etc. */
593 fmap->num_continents = fmap->num_oceans = 0;
594}
595
596/*******************************************************************/
600{
601 map_free(&(wld.map), is_server());
603}
604
605/*******************************************************************/
609static int map_vector_to_distance(int dx, int dy)
610{
612 /* Hex: all directions are cardinal so the distance is equivalent to
613 * the real distance. */
614 return map_vector_to_real_distance(dx, dy);
615 } else {
616 return abs(dx) + abs(dy);
617 }
618}
619
620/*******************************************************************/
624{
625 const int absdx = abs(dx), absdy = abs(dy);
626
629 /* Iso-hex: you can't move NE or SW. */
630 if ((dx < 0 && dy > 0)
631 || (dx > 0 && dy < 0)) {
632 /* Diagonal moves in this direction aren't allowed, so it will take
633 * the full number of moves. */
634 return absdx + absdy;
635 } else {
636 /* Diagonal moves in this direction *are* allowed. */
637 return MAX(absdx, absdy);
638 }
639 } else {
640 /* Hex: you can't move SE or NW. */
641 if ((dx > 0 && dy > 0)
642 || (dx < 0 && dy < 0)) {
643 /* Diagonal moves in this direction aren't allowed, so it will take
644 * the full number of moves. */
645 return absdx + absdy;
646 } else {
647 /* Diagonal moves in this direction *are* allowed. */
648 return MAX(absdx, absdy);
649 }
650 }
651 } else {
652 return MAX(absdx, absdy);
653 }
654}
655
656/*******************************************************************/
659int map_vector_to_sq_distance(int dx, int dy)
660{
662 /* Hex: The square distance is just the square of the real distance; we
663 * don't worry about pythagorean calculations. */
664 int dist = map_vector_to_real_distance(dx, dy);
665
666 return dist * dist;
667 } else {
668 return dx * dx + dy * dy;
669 }
670}
671
672/*******************************************************************/
675int real_map_distance(const struct tile *tile0, const struct tile *tile1)
676{
677 int dx, dy;
678
679 map_distance_vector(&dx, &dy, tile0, tile1);
680 return map_vector_to_real_distance(dx, dy);
681}
682
683/*******************************************************************/
686int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
687{
688 /* We assume map_distance_vector gives us the vector with the
689 minimum squared distance. Right now this is true. */
690 int dx, dy;
691
692 map_distance_vector(&dx, &dy, tile0, tile1);
693 return map_vector_to_sq_distance(dx, dy);
694}
695
696/*******************************************************************/
699int map_distance(const struct tile *tile0, const struct tile *tile1)
700{
701 /* We assume map_distance_vector gives us the vector with the
702 minimum map distance. Right now this is true. */
703 int dx, dy;
704
705 map_distance_vector(&dx, &dy, tile0, tile1);
706 return map_vector_to_distance(dx, dy);
707}
708
709/*******************************************************************/
712bool is_safe_ocean(const struct civ_map *nmap, const struct tile *ptile)
713{
714 adjc_iterate(nmap, ptile, adjc_tile) {
717 return TRUE;
718 }
720
721 return FALSE;
722}
723
724/*******************************************************************/
729bool can_reclaim_ocean(const struct civ_map *nmap,
730 const struct tile *ptile)
731{
733 FALSE, TRUE,
734 TC_OCEAN);
735
736 return land_tiles >= terrain_control.ocean_reclaim_requirement_pct;
737}
738
739/*******************************************************************/
744bool can_channel_land(const struct civ_map *nmap,
745 const struct tile *ptile)
746{
749
750 return ocean_tiles >= terrain_control.land_channel_requirement_pct;
751}
752
753/*******************************************************************/
758bool can_thaw_terrain(const struct civ_map *nmap,
759 const struct tile *ptile)
760{
762 FALSE, TRUE,
763 TER_FROZEN);
764
765 return unfrozen_tiles >= terrain_control.terrain_thaw_requirement_pct;
766}
767
768/*******************************************************************/
773bool can_freeze_terrain(const struct civ_map *nmap,
774 const struct tile *ptile)
775{
777 FALSE, TRUE,
778 TER_FROZEN);
779
780 return frozen_tiles >= terrain_control.terrain_freeze_requirement_pct;
781}
782
783/*******************************************************************/
788 const struct tile *ptile,
789 const struct terrain *pterrain)
790{
791 bool ret = TRUE;
792
793 if (is_ocean(tile_terrain(ptile))
794 && !is_ocean(pterrain) && !can_reclaim_ocean(nmap, ptile)) {
795 ret = FALSE;
796 } else if (!is_ocean(tile_terrain(ptile))
797 && is_ocean(pterrain) && !can_channel_land(nmap, ptile)) {
798 ret = FALSE;
799 }
800
801 if (ret) {
803 && !terrain_has_flag(pterrain, TER_FROZEN)
804 && !can_thaw_terrain(nmap, ptile)) {
805 ret = FALSE;
806 } else if (!terrain_has_flag(tile_terrain(ptile), TER_FROZEN)
807 && terrain_has_flag(pterrain, TER_FROZEN)
808 && !can_freeze_terrain(nmap, ptile)) {
809 ret = FALSE;
810 }
811 }
812
813 return ret;
814}
815
816/**********************************************************************/
820{
821 fc_assert_ret_val(id > 0, -1);
823 return wld.map.continent_sizes[id];
824}
825
826/**********************************************************************/
831{
832 fc_assert_ret_val(id > 0, -1);
834 return wld.map.ocean_sizes[id];
835}
836
837/**********************************************************************/
843{
844 fc_assert_ret_val(id > 0, +1);
846 if (is_server()) {
848 } else {
849 Continent_id ocean, surrounder = 0;
850
851 for (ocean = 1; ocean <= wld.map.num_oceans; ocean++) {
852 if (wld.map.client.adj_matrix[id][ocean] > 0) {
853 if (surrounder == 0) {
854 surrounder = ocean;
855 } else if (surrounder != ocean) {
856 /* More than one adjacent ocean */
857 return +1;
858 }
859 }
860 }
861
862 if (surrounder == 0 && is_whole_continent_known(id)) {
863 return +1;
864 } else {
865 return -surrounder;
866 }
867 }
868}
869
870/**********************************************************************/
876{
877 fc_assert_ret_val(id < 0, -1);
879 if (is_server()) {
881 } else {
882 Continent_id cont, surrounder = 0;
883
884 for (cont = 1; cont <= wld.map.num_continents; cont++) {
885 if (wld.map.client.adj_matrix[cont][-id] > 0) {
886 if (surrounder == 0) {
887 surrounder = cont;
888 } else if (surrounder != cont) {
889 /* More than one adjacent continent */
890 return -1;
891 }
892 }
893 }
894
895 if (surrounder == 0 && is_whole_ocean_known(-id)) {
896 return -1;
897 } else {
898 return surrounder;
899 }
900 }
901}
902
903/*******************************************************************/
913 const struct unit *punit,
914 const struct unit_type *punittype,
915 const struct player *pplayer,
916 const struct tile *t1, const struct tile *t2)
917{
918 const struct unit_class *pclass = utype_class(punittype);
919 int cost;
920 signed char cardinal_move = -1;
921 bool ri;
922
923 /* Try to exit early for detectable conditions */
925 /* Units without UCF_TERRAIN_SPEED have a constant cost. */
926 return SINGLE_MOVE;
927
928 } else if (!is_native_tile_to_class(pclass, t2)) {
929 if (tile_city(t2) == nullptr) {
930 /* Loading to transport. */
931
932 /* UTYF_IGTER units get move benefit. */
935 } else {
936 /* Entering port. (Could be "Conquer City") */
937
938 /* UTYF_IGTER units get move benefit. */
941 }
942
943 } else if (!is_native_tile_to_class(pclass, t1)) {
944 if (tile_city(t1) == nullptr) {
945 /* Disembarking from transport. */
946
947 /* UTYF_IGTER units get move benefit. */
950 } else {
951 /* Leaving port. */
952
953 /* UTYF_IGTER units get move benefit. */
956 }
957 }
958
959 cost = tile_terrain(t2)->movement_cost * SINGLE_MOVE;
960 ri = restrict_infra(pplayer, t1, t2);
961
962 extra_type_list_iterate(pclass->cache.bonus_roads, pextra) {
963 struct road_type *proad = extra_road_get(pextra);
964
965 /* We check the destination tile first, as that's
966 * the end of move that determines the cost.
967 * If can avoid inner loop about integrating roads
968 * completely if the destination road has too high cost. */
969
970 if (cost > proad->move_cost
972 && tile_has_extra(t2, pextra)) {
973 extra_type_list_iterate(proad->integrators, iextra) {
974 /* We have no unrestricted infra related check here,
975 * destination road is the one that counts. */
976 if (tile_has_extra(t1, iextra)
978 if (proad->move_mode == RMM_FAST_ALWAYS) {
979 cost = proad->move_cost;
980 } else {
981 if (cardinal_move < 0) {
983 || is_move_cardinal(nmap, t1, t2)) ? 1 : 0;
984 }
985 if (cardinal_move > 0) {
986 cost = proad->move_cost;
987 } else {
988 switch (proad->move_mode) {
989 case RMM_CARDINAL:
990 break;
991 case RMM_RELAXED:
992 if (cost > proad->move_cost * 2) {
994 if (tile_has_extra(between, pextra)
995 || (pextra != iextra && tile_has_extra(between, iextra))) {
996 /* 'pextra != iextra' is there just to avoid
997 * tile_has_extra() in by far more common case
998 * that 'pextra == iextra' */
999 /* TODO: Should we restrict this more?
1000 * Should we check against enemy cities on between tile?
1001 * Should we check against non-native terrain on between tile?
1002 */
1003 cost = proad->move_cost * 2;
1004 }
1006 }
1007 break;
1008 case RMM_FAST_ALWAYS:
1009
1010 /* Already handled above */
1011 fc_assert(proad->move_mode != RMM_FAST_ALWAYS);
1012
1013 cost = proad->move_cost;
1014 break;
1015 }
1016 }
1017 }
1018 }
1020 }
1022
1023 /* UTYF_IGTER units have a maximum move cost per step. */
1026 }
1027
1028 if (terrain_control.pythagorean_diagonal) {
1029 if (cardinal_move < 0) {
1031 || is_move_cardinal(nmap, t1, t2)) ? 1 : 0;
1032 }
1033 if (cardinal_move == 0) {
1034 return cost * 181 >> 7; /* == (int) (cost * 1.41421356f) if cost < 99 */
1035 }
1036 }
1037
1038 return cost;
1039}
1040
1041/*******************************************************************/
1047static bool restrict_infra(const struct player *pplayer, const struct tile *t1,
1048 const struct tile *t2)
1049{
1050 struct player *plr1 = tile_owner(t1), *plr2 = tile_owner(t2);
1051
1052 if (!pplayer || !game.info.restrictinfra) {
1053 return FALSE;
1054 }
1055
1056 if ((plr1 && pplayers_at_war(plr1, pplayer))
1057 || (plr2 && pplayers_at_war(plr2, pplayer))) {
1058 return TRUE;
1059 }
1060
1061 return FALSE;
1062}
1063
1064/*******************************************************************/
1067bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
1068{
1069 return real_map_distance(tile0, tile1) == 1;
1070}
1071
1072/*******************************************************************/
1076bool same_pos(const struct tile *tile1, const struct tile *tile2)
1077{
1078 fc_assert_ret_val(tile1 != nullptr && tile2 != nullptr, FALSE);
1079
1080 /* In case of virtual tile, tile1 can be different from tile2,
1081 * but they have same index */
1082 return (tile1->index == tile2->index);
1083}
1084
1085/*******************************************************************/
1088bool is_real_map_pos(const struct civ_map *nmap, int x, int y)
1089{
1090 return normalize_map_pos(nmap, &x, &y);
1091}
1092
1093/*******************************************************************/
1099bool is_normal_map_pos(int x, int y)
1100{
1101 int nat_x, nat_y;
1102
1104
1105 return nat_x >= 0 && nat_x < MAP_NATIVE_WIDTH
1106 && nat_y >= 0 && nat_y < MAP_NATIVE_HEIGHT;
1107}
1108
1109/*******************************************************************/
1117bool normalize_map_pos(const struct civ_map *nmap, int *x, int *y)
1118{
1119 struct tile *ptile = map_pos_to_tile(nmap, *x, *y);
1120
1121 if (ptile != nullptr) {
1122 index_to_map_pos(x, y, tile_index(ptile));
1123 return TRUE;
1124 } else {
1125 return FALSE;
1126 }
1127}
1128
1129/*******************************************************************/
1133struct tile *nearest_real_tile(const struct civ_map *nmap, int x, int y)
1134{
1135 int nat_x, nat_y;
1136
1139 nat_x = CLIP(0, nat_x, MAP_NATIVE_WIDTH - 1);
1140 }
1142 nat_y = CLIP(0, nat_y, MAP_NATIVE_HEIGHT - 1);
1143 }
1145
1146 return map_pos_to_tile(nmap, x, y);
1147}
1148
1149/*******************************************************************/
1153{
1155}
1156
1157/*******************************************************************/
1162void base_map_distance_vector(int *dx, int *dy,
1163 int x0dv, int y0dv, int x1dv, int y1dv)
1164{
1166 /* Wrapping is done in native coordinates. */
1169
1170 /* Find the "native" distance vector. This corresponds closely to the
1171 * map distance vector but is easier to wrap. */
1172 *dx = x1dv - x0dv;
1173 *dy = y1dv - y0dv;
1175 /* Wrap dx to be in [-map.xsize / 2, map.xsize / 2). */
1176 *dx = FC_WRAP(*dx + MAP_NATIVE_WIDTH / 2, MAP_NATIVE_WIDTH)
1177 - MAP_NATIVE_WIDTH / 2;
1178 }
1180 /* Wrap dy to be in [-map.ysize / 2, map.ysize / 2). */
1182 - MAP_NATIVE_HEIGHT / 2;
1183 }
1184
1185 /* Convert the native delta vector back to a pair of map positions. */
1186 x1dv = x0dv + *dx;
1187 y1dv = y0dv + *dy;
1190 }
1191
1192 /* Find the final (map) vector. */
1193 *dx = x1dv - x0dv;
1194 *dy = y1dv - y0dv;
1195}
1196
1197/*******************************************************************/
1213void map_distance_vector(int *dx, int *dy,
1214 const struct tile *tile0,
1215 const struct tile *tile1)
1216{
1217 int tx0, ty0, tx1, ty1;
1218
1222}
1223
1224/*******************************************************************/
1228struct tile *rand_map_pos(const struct civ_map *nmap)
1229{
1232
1234}
1235
1236/*******************************************************************/
1242struct tile *rand_map_pos_filtered(const struct civ_map *nmap, void *data,
1243 bool (*filter)(const struct tile *ptile,
1244 const void *data))
1245{
1246 struct tile *ptile;
1247 int tries = 0;
1249
1250 /* First do a few quick checks to find a spot. The limit on number of
1251 * tries could use some tweaking. */
1252 do {
1253 ptile = nmap->tiles + fc_rand(MAP_INDEX_SIZE);
1254 } while (filter != nullptr && !filter(ptile, data) && ++tries < max_tries);
1255
1256 /* If that fails, count all available spots and pick one.
1257 * Slow but reliable. */
1258 if (filter == nullptr) {
1259 ptile = nullptr;
1260 } else if (tries == max_tries) {
1261 int count = 0, *positions;
1262
1263 positions = fc_calloc(MAP_INDEX_SIZE, sizeof(*positions));
1264
1266 if (filter(check_tile, data)) {
1267 positions[count] = tile_index(check_tile);
1268 count++;
1269 }
1271
1272 if (count == 0) {
1273 ptile = nullptr;
1274 } else {
1275 ptile = wld.map.tiles + positions[fc_rand(count)];
1276 }
1277
1278 FC_FREE(positions);
1279 }
1280
1281 return ptile;
1282}
1283
1284/*******************************************************************/
1287const char *dir_get_name(enum direction8 dir)
1288{
1289 /* A switch statement is used so the ordering can be changed easily */
1290 switch (dir) {
1291 case DIR8_NORTH:
1292 return "N";
1293 case DIR8_NORTHEAST:
1294 return "NE";
1295 case DIR8_EAST:
1296 return "E";
1297 case DIR8_SOUTHEAST:
1298 return "SE";
1299 case DIR8_SOUTH:
1300 return "S";
1301 case DIR8_SOUTHWEST:
1302 return "SW";
1303 case DIR8_WEST:
1304 return "W";
1305 case DIR8_NORTHWEST:
1306 return "NW";
1307 default:
1308 return "[Undef]";
1309 }
1310}
1311
1312/*******************************************************************/
1316{
1317 /* A switch statement is used so the ordering can be changed easily */
1318 switch (dir) {
1319 case DIR8_NORTH:
1320 return DIR8_NORTHEAST;
1321 case DIR8_NORTHEAST:
1322 return DIR8_EAST;
1323 case DIR8_EAST:
1324 return DIR8_SOUTHEAST;
1325 case DIR8_SOUTHEAST:
1326 return DIR8_SOUTH;
1327 case DIR8_SOUTH:
1328 return DIR8_SOUTHWEST;
1329 case DIR8_SOUTHWEST:
1330 return DIR8_WEST;
1331 case DIR8_WEST:
1332 return DIR8_NORTHWEST;
1333 case DIR8_NORTHWEST:
1334 return DIR8_NORTH;
1335 default:
1337 return -1;
1338 }
1339}
1340
1341/*******************************************************************/
1345{
1346 /* A switch statement is used so the ordering can be changed easily */
1347 switch (dir) {
1348 case DIR8_NORTH:
1349 return DIR8_NORTHWEST;
1350 case DIR8_NORTHEAST:
1351 return DIR8_NORTH;
1352 case DIR8_EAST:
1353 return DIR8_NORTHEAST;
1354 case DIR8_SOUTHEAST:
1355 return DIR8_EAST;
1356 case DIR8_SOUTH:
1357 return DIR8_SOUTHEAST;
1358 case DIR8_SOUTHWEST:
1359 return DIR8_SOUTH;
1360 case DIR8_WEST:
1361 return DIR8_SOUTHWEST;
1362 case DIR8_NORTHWEST:
1363 return DIR8_WEST;
1364 default:
1366 return -1;
1367 }
1368}
1369
1370/*******************************************************************/
1375{
1376 switch (dir) {
1377 case DIR8_SOUTHEAST:
1378 case DIR8_NORTHWEST:
1379 /* These directions are invalid in hex topologies. */
1381 case DIR8_NORTHEAST:
1382 case DIR8_SOUTHWEST:
1383 /* These directions are invalid in iso-hex topologies. */
1385 case DIR8_NORTH:
1386 case DIR8_EAST:
1387 case DIR8_SOUTH:
1388 case DIR8_WEST:
1389 return TRUE;
1390 default:
1391 return FALSE;
1392 }
1393}
1394
1395/*******************************************************************/
1402{
1404
1405 return dir_validity[dir];
1406}
1407
1408/*******************************************************************/
1415{
1416 if (!direction8_is_valid(dir)) {
1417 /* Isn't even in range of direction8. */
1418 return FALSE;
1419 }
1420
1421 return is_valid_dir(dir);
1422}
1423
1424/*******************************************************************/
1432{
1433 switch (dir) {
1434 case DIR8_NORTH:
1435 case DIR8_SOUTH:
1436 case DIR8_EAST:
1437 case DIR8_WEST:
1438 return TRUE;
1439 case DIR8_SOUTHEAST:
1440 case DIR8_NORTHWEST:
1441 /* These directions are cardinal in iso-hex topologies. */
1443 case DIR8_NORTHEAST:
1444 case DIR8_SOUTHWEST:
1445 /* These directions are cardinal in hexagonal topologies. */
1447 }
1448 return FALSE;
1449}
1450
1451/*******************************************************************/
1458{
1460
1461 return dir_cardinality[dir];
1462}
1463
1464/*******************************************************************/
1470 const struct tile *start_tile,
1471 const struct tile *end_tile,
1472 enum direction8 *dir)
1473{
1474 adjc_dir_iterate(nmap, start_tile, test_tile, test_dir) {
1475 if (same_pos(end_tile, test_tile)) {
1476 *dir = test_dir;
1477 return TRUE;
1478 }
1480
1481 return FALSE;
1482}
1483
1484/*******************************************************************/
1489 const struct tile *start_tile,
1490 const struct tile *end_tile)
1491{
1492 enum direction8 dir;
1493
1494 if (base_get_direction_for_step(nmap, start_tile, end_tile, &dir)) {
1495 return dir;
1496 }
1497
1499
1500 return -1;
1501}
1502
1503/*******************************************************************/
1507bool is_move_cardinal(const struct civ_map *nmap,
1508 const struct tile *start_tile,
1509 const struct tile *end_tile)
1510{
1512 if (same_pos(end_tile, test_tile)) {
1513 return TRUE;
1514 }
1516
1517 return FALSE;
1518}
1519
1520/************************************************************************/
1538static double map_relative_southness(const struct tile *ptile)
1539{
1540 int tile_x, tile_y;
1541 double x, y, toroid_rel_colatitude;
1542 bool toroid_flipped;
1543
1544 /* TODO: What should the fallback value be?
1545 * Since this is not public API, it shouldn't matter anyway. */
1546 fc_assert_ret_val(ptile != nullptr, 0.5);
1547
1550 /* Compute natural coordinates relative to world size.
1551 * x and y are in the range [0.0, 1.0] */
1552 x = (double)ntl_x / (MAP_NATURAL_WIDTH - 1);
1553 y = (double)ntl_y / (MAP_NATURAL_HEIGHT - 1);
1555
1557 /* In an Earth-like topology, north and south are at the top and
1558 * bottom of the map.
1559 * This is equivalent to a Mercator projection. */
1560 return y;
1561 }
1562
1564 /* In a Uranus-like topology, north and south are at the left and
1565 * right side of the map.
1566 * This isn't really the way Uranus is; it's the way Earth would look
1567 * if you tilted your head sideways. It's still a Mercator
1568 * projection. */
1569 return x;
1570 }
1571
1572 /* Otherwise we have a torus topology. We set it up as an approximation
1573 * of a sphere with two circular polar zones and a square equatorial
1574 * zone. In this case north and south are not constant directions on the
1575 * map because we have to use a more complicated (custom) projection.
1576 *
1577 * Generators 2 and 5 work best if the center of the map is free.
1578 * So we want to set up the map with the poles (N,S) along the sides and
1579 * the equator (/,\‍) in between.
1580 *
1581 * ........
1582 * :\ NN /:
1583 * : \ / :
1584 * :S \/ S:
1585 * :S /\ S:
1586 * : / \ :
1587 * :/ NN \:
1588 * ''''''''
1589 */
1590
1591 /* First we will fold the map into fourths:
1592 *
1593 * ....
1594 * :\ N
1595 * : \
1596 * :S \
1597 *
1598 * and renormalize x and y to go from 0.0 to 1.0 again.
1599 */
1600 x = 2.0 * (x > 0.5 ? 1.0 - x : x);
1601 y = 2.0 * (y > 0.5 ? 1.0 - y : y);
1602
1603 /* Now flip it along the X direction to get this:
1604 *
1605 * ....
1606 * :N /
1607 * : /
1608 * :/ S
1609 */
1610 x = 1.0 - x;
1611
1612 /* To simplify the following computation, we can fold along the
1613 * diagonal. This leaves us with 1/8 of the map
1614 *
1615 * .....
1616 * :P /
1617 * : /
1618 * :/
1619 *
1620 * where P is the polar regions and / is the equator.
1621 * We must remember which hemisphere we are on for later. */
1622 if (x + y > 1.0) {
1623 /* This actually reflects the bottom-right half about the center point,
1624 * rather than about the diagonal, but that makes no difference. */
1625 x = 1.0 - x;
1626 y = 1.0 - y;
1628 } else {
1630 }
1631
1632 /* toroid_rel_colatitude is 0.0 at the poles and 1.0 at the equator.
1633 * This projection makes poles with a shape of a quarter-circle along
1634 * "P" and the equator as a straight line along "/".
1635 *
1636 * The formula is
1637 * lerp(1.5 (x^2 + y^2), (x+y)^2, x+y)
1638 * where
1639 * lerp(a,b,t) = a * (1-t) + b * t
1640 * is the linear interpolation between a and b, with
1641 * lerp(a,b,0) = a and lerp(a,b,1) = b
1642 *
1643 * I.e. the colatitude is computed as a linear interpolation between
1644 * - a = 1.5 (x^2 + y^2), proportional to the squared pythagorean
1645 * distance from the pole, which gives circular lines of latitude; and
1646 * - b = (x+y)^2, the squared manhattan distance from the pole, which
1647 * gives straight, diagonal lines of latitude parallel to the equator.
1648 *
1649 * These are interpolated with t = (x+y), the manhattan distance, which
1650 * ranges from 0 at the pole to 1 at the equator. So near the pole, the
1651 * (squared) pythagorean distance wins out, giving mostly circular lines,
1652 * and near the equator, the (squared) manhattan distance wins out,
1653 * giving mostly straight lines.
1654 *
1655 * Note that the colatitude growing with the square of the distance from
1656 * the pole keeps areas relatively the same as on non-toroidal maps:
1657 * On non-torus maps, the area closer to a pole than a given tile, and
1658 * the colatitude at that tile, both grow linearly with distance from the
1659 * pole. On torus maps, since the poles are singular points rather than
1660 * entire map edges, the area closer to a pole than a given tile grows
1661 * with the square of the distance to the pole - and so the colatitude
1662 * at that tile must also grow with the square in order to keep the size
1663 * of areas in a given range of colatitude relatively the same.
1664 *
1665 * See OSDN#43665, as well as the original discussion (via newsreader) at
1666 * news://news.gmane.io/gmane.games.freeciv.devel/42648 */
1667 toroid_rel_colatitude = (1.5 * (x * x * y + x * y * y)
1668 - 0.5 * (x * x * x + y * y * y)
1669 + 1.5 * (x * x + y * y));
1670
1671 /* Finally, convert from colatitude to latitude and add hemisphere
1672 * information back in:
1673 * - if we did not flip along the diagonal before, we are in the
1674 * northern hemisphere, with relative latitude in [0.0,0.5]
1675 * - if we _did_ flip, we are in the southern hemisphere, with
1676 * relative latitude in [0.5,1.0]
1677 */
1678 return ((toroid_flipped
1679 ? 2.0 - (toroid_rel_colatitude)
1681 / 2.0);
1682}
1683
1684/************************************************************************/
1692int map_signed_latitude(const struct tile *ptile)
1693{
1694 int north_latitude, south_latitude;
1695 double southness;
1696
1697 north_latitude = MAP_NORTH_LATITUDE(wld.map);
1698 south_latitude = MAP_SOUTH_LATITUDE(wld.map);
1699
1700 if (north_latitude == south_latitude) {
1701 /* Single-latitude / all-temperate map; no need to examine tile. */
1702 return south_latitude;
1703 }
1704
1705 fc_assert_ret_val(ptile != nullptr, (north_latitude + south_latitude) / 2);
1706
1708
1709 /* Linear interpolation between northernmost and southernmost latitude.
1710 * Truncate / round towards zero so northern and southern hemisphere
1711 * are symmetrical when south_latitude = -north_latitude. */
1712 return north_latitude * (1.0 - southness) + south_latitude * southness;
1713}
1714
1715/*******************************************************************/
1723bool is_singular_tile(const struct tile *ptile, int dist)
1724{
1725 int tile_x, tile_y;
1726
1729 /* Iso-natural coordinates are doubled in scale. */
1730 dist *= MAP_IS_ISOMETRIC ? 2 : 1;
1731
1732 return ((!current_wrap_has_flag(WRAP_X)
1737}
1738
1739/*******************************************************************/
1742static struct startpos *startpos_new(struct tile *ptile)
1743{
1744 struct startpos *psp = fc_malloc(sizeof(*psp));
1745
1746 psp->location = ptile;
1747 psp->exclude = FALSE;
1748 psp->nations = nation_hash_new();
1749
1750 return psp;
1751}
1752
1753/*******************************************************************/
1756static void startpos_destroy(struct startpos *psp)
1757{
1758 fc_assert_ret(psp != nullptr);
1759
1761 free(psp);
1762}
1763
1764/*******************************************************************/
1768{
1769 return map_startpos_get(index_to_tile(&(wld.map), id));
1770}
1771
1772/*******************************************************************/
1776int startpos_number(const struct startpos *psp)
1777{
1778 fc_assert_ret_val(psp != nullptr, -1);
1779
1780 return tile_index(psp->location);
1781}
1782
1783/*******************************************************************/
1787bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
1788{
1789 fc_assert_ret_val(psp != nullptr, FALSE);
1790 fc_assert_ret_val(pnation != nullptr, FALSE);
1791
1792 if (0 == nation_hash_size(psp->nations) || !psp->exclude) {
1793 psp->exclude = FALSE; /* Disable "excluding" mode. */
1794 return nation_hash_insert(psp->nations, pnation, nullptr);
1795 } else {
1796 return nation_hash_remove(psp->nations, pnation);
1797 }
1798}
1799
1800/*******************************************************************/
1804bool startpos_disallow(struct startpos *psp, struct nation_type *pnation)
1805{
1806 fc_assert_ret_val(psp != nullptr, FALSE);
1807 fc_assert_ret_val(pnation != nullptr, FALSE);
1808
1809 if (0 == nation_hash_size(psp->nations) || psp->exclude) {
1810 psp->exclude = TRUE; /* Enable "excluding" mode. */
1811 return nation_hash_remove(psp->nations, pnation);
1812 } else {
1813 return nation_hash_insert(psp->nations, pnation, nullptr);
1814 }
1815}
1816
1817/*******************************************************************/
1820struct tile *startpos_tile(const struct startpos *psp)
1821{
1822 fc_assert_ret_val(psp != nullptr, nullptr);
1823
1824 return psp->location;
1825}
1826
1827/*******************************************************************/
1830bool startpos_nation_allowed(const struct startpos *psp,
1831 const struct nation_type *pnation)
1832{
1833 fc_assert_ret_val(psp != nullptr, FALSE);
1834 fc_assert_ret_val(pnation != nullptr, FALSE);
1835
1836 return XOR(psp->exclude, nation_hash_lookup(psp->nations, pnation,
1837 nullptr));
1838}
1839
1840/*******************************************************************/
1843bool startpos_allows_all(const struct startpos *psp)
1844{
1845 fc_assert_ret_val(psp != nullptr, FALSE);
1846
1847 return (0 == nation_hash_size(psp->nations));
1848}
1849
1850/*******************************************************************/
1854bool startpos_pack(const struct startpos *psp,
1855 struct packet_edit_startpos_full *packet)
1856{
1857 fc_assert_ret_val(psp != nullptr, FALSE);
1858 fc_assert_ret_val(packet != nullptr, FALSE);
1859
1860 packet->id = startpos_number(psp);
1861 packet->exclude = psp->exclude;
1862 BV_CLR_ALL(packet->nations);
1863
1864 nation_hash_iterate(psp->nations, pnation) {
1865 BV_SET(packet->nations, nation_number(pnation));
1867
1868 return TRUE;
1869}
1870
1871/*******************************************************************/
1875bool startpos_unpack(struct startpos *psp,
1876 const struct packet_edit_startpos_full *packet)
1877{
1878 fc_assert_ret_val(psp != nullptr, FALSE);
1879 fc_assert_ret_val(packet != nullptr, FALSE);
1880
1881 psp->exclude = packet->exclude;
1882
1884 if (!BV_ISSET_ANY(packet->nations)) {
1885 return TRUE;
1886 }
1887 nations_iterate(pnation) {
1888 if (BV_ISSET(packet->nations, nation_number(pnation))) {
1889 nation_hash_insert(psp->nations, pnation, nullptr);
1890 }
1892
1893 return TRUE;
1894}
1895
1896/*******************************************************************/
1903bool startpos_is_excluding(const struct startpos *psp)
1904{
1905 fc_assert_ret_val(psp != nullptr, FALSE);
1906
1907 return psp->exclude;
1908}
1909
1910/*******************************************************************/
1916const struct nation_hash *startpos_raw_nations(const struct startpos *psp)
1917{
1918 fc_assert_ret_val(psp != nullptr, nullptr);
1919
1920 return psp->nations;
1921}
1922
1923/*******************************************************************/
1930{
1931 return MAX(sizeof(struct startpos_iter) + nation_iter_sizeof()
1932 - sizeof(struct iterator), nation_hash_iter_sizeof());
1933}
1934
1935/*******************************************************************/
1942{
1944
1945 do {
1946 iterator_next(&iter->nation_iter);
1947 } while (iterator_valid(&iter->nation_iter)
1948 || !nation_hash_lookup(iter->psp->nations,
1949 iterator_get(&iter->nation_iter),
1950 nullptr));
1951}
1952
1953/*******************************************************************/
1961{
1963
1964 return iterator_get(&iter->nation_iter);
1965}
1966
1967/*******************************************************************/
1971{
1973
1974 return iterator_valid(&iter->nation_iter);
1975}
1976
1977/*******************************************************************/
1981 const struct startpos *psp)
1982{
1983 if (psp == nullptr) {
1985 }
1986
1987 if (startpos_allows_all(psp)) {
1988 return nation_iter_init((struct nation_iter *) iter);
1989 }
1990
1991 if (!psp->exclude) {
1993 psp->nations);
1994 }
1995
1996 iter->vtable.next = startpos_exclude_iter_next;
1997 iter->vtable.get = startpos_exclude_iter_get;
1998 iter->vtable.valid = startpos_exclude_iter_valid;
1999 iter->psp = psp;
2000 (void) nation_iter_init((struct nation_iter *) &iter->nation_iter);
2001
2002 return ITERATOR(iter);
2003}
2004
2005/*******************************************************************/
2009{
2010 if (wld.map.startpos_table != nullptr) {
2012 } else {
2013 return 0;
2014 }
2015}
2016
2017/*******************************************************************/
2021struct startpos *map_startpos_new(struct tile *ptile)
2022{
2023 struct startpos *psp;
2024
2025 fc_assert_ret_val(ptile != nullptr, nullptr);
2026 fc_assert_ret_val(wld.map.startpos_table != nullptr, nullptr);
2027
2028 psp = startpos_new(ptile);
2030
2031 return psp;
2032}
2033
2034/*******************************************************************/
2038struct startpos *map_startpos_get(const struct tile *ptile)
2039{
2040 struct startpos *psp;
2041
2042 fc_assert_ret_val(ptile != nullptr, nullptr);
2043 fc_assert_ret_val(wld.map.startpos_table != nullptr, nullptr);
2044
2046
2047 return psp;
2048}
2049
2050/*******************************************************************/
2054bool map_startpos_remove(struct tile *ptile)
2055{
2056 fc_assert_ret_val(ptile != nullptr, FALSE);
2058
2060}
2061
2062/*******************************************************************/
2067{
2069}
2070
2071/*******************************************************************/
2080
2081/*******************************************************************/
2088
2089/*******************************************************************/
2093{
2094 return direction8_max() - dir;
2095}
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:387
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define BV_ISSET_ANY(vec)
Definition bitvector.h:117
void generate_city_map_indices(void)
Definition city.c:527
int compare_iter_index(const void *a, const void *b)
Definition city.c:343
char * incite_cost
Definition comments.c:76
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 * punit
Definition dialogs_g.h:74
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 cost
Definition dialogs_g.h:74
int int id
Definition editgui_g.h:28
bool is_native_extra_to_uclass(const struct extra_type *pextra, const struct unit_class *pclass)
Definition extras.c:857
#define extra_type_iterate(_p)
Definition extras.h:315
#define extra_type_list_iterate(extralist, pextra)
Definition extras.h:165
#define extra_type_iterate_end
Definition extras.h:321
#define extra_type_by_rmcause_iterate_end
Definition extras.h:358
#define extra_index(_e_)
Definition extras.h:183
#define extra_type_by_rmcause_iterate(_rmcause, _extra)
Definition extras.h:353
#define extra_type_list_iterate_end
Definition extras.h:167
#define extra_road_get(_e_)
Definition extras.h:191
static bool is_server(void)
@ RPT_POSSIBLE
Definition fc_types.h:532
signed short Continent_id
Definition fc_types.h:231
struct civ_game game
Definition game.c:61
struct world wld
Definition game.c:62
struct iterator * invalid_iter_init(struct iterator *it)
Definition iterator.c:51
static void * iterator_get(const struct iterator *it)
Definition iterator.h:53
static bool iterator_valid(const struct iterator *it)
Definition iterator.h:61
#define ITERATOR(p)
Definition iterator.h:37
static void iterator_next(struct iterator *it)
Definition iterator.h:42
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_debug(message,...)
Definition log.h:116
bv_extras get_tile_infrastructure_set(const struct tile *ptile, int *pcount)
Definition map.c:100
bool can_channel_land(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:744
struct startpos * map_startpos_get(const struct tile *ptile)
Definition map.c:2038
bool is_normal_map_pos(int x, int y)
Definition map.c:1099
int get_continent_size(Continent_id id)
Definition map.c:819
const int DIR_DY[8]
Definition map.c:86
int startpos_number(const struct startpos *psp)
Definition map.c:1776
bool can_reclaim_ocean(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:729
bool startpos_disallow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1804
void main_map_free(void)
Definition map.c:599
#define nat_x
static int map_vector_to_distance(int dx, int dy)
Definition map.c:609
enum direction8 opposite_direction(enum direction8 dir)
Definition map.c:2092
#define nat_y
bool is_move_cardinal(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile)
Definition map.c:1507
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:686
bool can_freeze_terrain(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:773
struct startpos * map_startpos_new(struct tile *ptile)
Definition map.c:2021
bool can_thaw_terrain(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:758
int tile_move_cost_ptrs(const struct civ_map *nmap, const struct unit *punit, const struct unit_type *punittype, const struct player *pplayer, const struct tile *t1, const struct tile *t2)
Definition map.c:912
static void tile_free(struct tile *ptile)
Definition map.c:489
bool startpos_nation_allowed(const struct startpos *psp, const struct nation_type *pnation)
Definition map.c:1830
#define STARTPOS_ITER(p)
Definition map.c:64
int map_num_tiles(void)
Definition map.c:1152
int get_direction_for_step(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile)
Definition map.c:1488
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1820
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1843
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1916
const int DIR_DX[8]
Definition map.c:85
struct tile * rand_map_pos(const struct civ_map *nmap)
Definition map.c:1228
static bool restrict_infra(const struct player *pplayer, const struct tile *t1, const struct tile *t2)
Definition map.c:1047
static struct tile * base_native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:410
static void generate_map_indices(void)
Definition map.c:212
const char * dir_get_name(enum direction8 dir)
Definition map.c:1287
enum direction8 dir_ccw(enum direction8 dir)
Definition map.c:1344
struct iterator * map_startpos_iter_init(struct map_startpos_iter *iter)
Definition map.c:2075
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:1067
void map_allocate(struct civ_map *amap)
Definition map.c:508
void map_init_topology(struct civ_map *nmap)
Definition map.c:315
void main_map_allocate(void)
Definition map.c:534
static bool dir_validity[9]
Definition map.c:89
bool is_safe_ocean(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:712
static struct startpos * startpos_new(struct tile *ptile)
Definition map.c:1742
static double map_relative_southness(const struct tile *ptile)
Definition map.c:1538
bool startpos_pack(const struct startpos *psp, struct packet_edit_startpos_full *packet)
Definition map.c:1854
static bool is_valid_dir_calculate(enum direction8 dir)
Definition map.c:1374
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
int map_signed_latitude(const struct tile *ptile)
Definition map.c:1692
static bool is_cardinal_dir_calculate(enum direction8 dir)
Definition map.c:1431
struct tile * map_pos_to_tile(const struct civ_map *nmap, int map_x, int map_y)
Definition map.c:434
int map_vector_to_sq_distance(int dx, int dy)
Definition map.c:659
bool map_startpos_remove(struct tile *ptile)
Definition map.c:2054
struct tile * rand_map_pos_filtered(const struct civ_map *nmap, void *data, bool(*filter)(const struct tile *ptile, const void *data))
Definition map.c:1242
int map_startpos_count(void)
Definition map.c:2008
size_t startpos_iter_sizeof(void)
Definition map.c:1929
bool is_cardinal_dir(enum direction8 dir)
Definition map.c:1457
static void tile_init(struct tile *ptile)
Definition map.c:363
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:1076
bool map_untrusted_dir_is_valid(enum direction8 dir)
Definition map.c:1414
bool terrain_surroundings_allow_change(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain)
Definition map.c:787
int real_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:675
bool startpos_unpack(struct startpos *psp, const struct packet_edit_startpos_full *packet)
Definition map.c:1875
int get_ocean_size(Continent_id id)
Definition map.c:830
bool is_valid_dir(enum direction8 dir)
Definition map.c:1401
void base_map_distance_vector(int *dx, int *dy, int x0dv, int y0dv, int x1dv, int y1dv)
Definition map.c:1162
enum direction8 dir_cw(enum direction8 dir)
Definition map.c:1315
int get_island_surrounder(Continent_id id)
Definition map.c:842
enum direction8 rand_direction(void)
Definition map.c:2084
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:384
static void startpos_destroy(struct startpos *psp)
Definition map.c:1756
void map_free(struct civ_map *fmap, bool server_side)
Definition map.c:545
struct terrain_misc terrain_control
Definition map.c:68
static void * startpos_exclude_iter_get(const struct iterator *startpos_iter)
Definition map.c:1960
struct tile * nearest_real_tile(const struct civ_map *nmap, int x, int y)
Definition map.c:1133
bool base_get_direction_for_step(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile, enum direction8 *dir)
Definition map.c:1469
static void startpos_exclude_iter_next(struct iterator *startpos_iter)
Definition map.c:1941
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:458
void map_distance_vector(int *dx, int *dy, const struct tile *tile0, const struct tile *tile1)
Definition map.c:1213
int get_lake_surrounder(Continent_id id)
Definition map.c:875
static bool dir_cardinality[9]
Definition map.c:88
void map_init(struct civ_map *imap, bool server_side)
Definition map.c:156
bool startpos_is_excluding(const struct startpos *psp)
Definition map.c:1903
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:699
struct startpos * map_startpos_by_number(int id)
Definition map.c:1767
bool map_is_empty(void)
Definition map.c:148
size_t map_startpos_iter_sizeof(void)
Definition map.c:2066
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1787
bool normalize_map_pos(const struct civ_map *nmap, int *x, int *y)
Definition map.c:1117
static bool startpos_exclude_iter_valid(const struct iterator *startpos_iter)
Definition map.c:1970
struct iterator * startpos_iter_init(struct startpos_iter *iter, const struct startpos *psp)
Definition map.c:1980
bool is_real_map_pos(const struct civ_map *nmap, int x, int y)
Definition map.c:1088
bool is_singular_tile(const struct tile *ptile, int dist)
Definition map.c:1723
int map_vector_to_real_distance(int dx, int dy)
Definition map.c:623
#define MAP_MAX_SIZE
Definition map.h:652
#define current_topo_has_flag(flag)
Definition map.h:43
#define MAP_DEFAULT_SIZE
Definition map.h:650
#define MAP_MAX_LINEAR_SIZE
Definition map.h:668
#define adjc_dir_iterate(nmap, center_tile, itr_tile, dir_itr)
Definition map.h:435
#define MAP_DEFAULT_HUTS
Definition map.h:632
#define adjc_iterate_end
Definition map.h:430
#define do_in_natural_pos(ntl_x, ntl_y, map_x, map_y)
Definition map.h:214
#define MAP_DEFAULT_LINEAR_SIZE
Definition map.h:667
#define MAP_DEFAULT_STARTPOS
Definition map.h:708
#define MAP_DEFAULT_ANIMALS
Definition map.h:636
#define MAP_DEFAULT_TEAM_PLACEMENT
Definition map.h:726
#define MAP_DEFAULT_TOPO
Definition map.h:682
#define MAP_DEFAULT_SEED
Definition map.h:686
#define CHECK_INDEX(mindex)
Definition map.h:153
#define cardinal_between_iterate(nmap, tile1, tile2, between)
Definition map.h:474
#define MAP_DEFAULT_MAPSIZE
Definition map.h:640
#define MAP_MIN_LINEAR_SIZE
Definition map.h:669
#define MAP_DEFAULT_LANDMASS
Definition map.h:690
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:425
#define MAP_SOUTH_LATITUDE(_nmap)
Definition map.h:611
#define MAP_TO_NATIVE_POS(pnat_x, pnat_y, map_x, map_y)
Definition map.h:176
#define ALL_DIRECTIONS_CARDINAL()
Definition map.h:48
#define NATIVE_TO_MAP_POS(pmap_x, pmap_y, nat_x, nat_y)
Definition map.h:170
#define is_whole_continent_known(cont)
Definition map.h:78
#define cardinal_adjc_dir_iterate_end
Definition map.h:463
#define MAP_DEFAULT_WRAP
Definition map.h:683
#define MAP_MIN_SIZE
Definition map.h:651
#define MAP_DEFAULT_NORTH_LATITUDE
Definition map.h:606
#define MAP_DEFAULT_SEPARATE_POLES
Definition map.h:714
#define MAP_DEFAULT_RICHES
Definition map.h:694
#define MAP_DEFAULT_TINYISLES
Definition map.h:710
#define whole_map_iterate(_map, _tile)
Definition map.h:573
#define MAP_NORTH_LATITUDE(_nmap)
Definition map.h:610
#define MAP_DEFAULT_TILESPERPLAYER
Definition map.h:662
#define adjc_dir_iterate_end
Definition map.h:439
#define MAP_DEFAULT_TEMPERATURE
Definition map.h:722
#define cardinal_between_iterate_end
Definition map.h:479
#define MAP_DEFAULT_SOUTH_LATITUDE
Definition map.h:607
#define current_wrap_has_flag(flag)
Definition map.h:46
#define MAP_DEFAULT_GENERATOR
Definition map.h:706
#define is_whole_ocean_known(ocean)
Definition map.h:82
#define do_in_natural_pos_end
Definition map.h:221
#define MAP_DEFAULT_WETNESS
Definition map.h:702
#define native_pos_to_index_nocheck(nat_x, nat_y)
Definition map.h:156
#define cardinal_adjc_dir_iterate(nmap, center_tile, itr_tile, dir_itr)
Definition map.h:459
#define whole_map_iterate_end
Definition map.h:582
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:229
#define MAP_DEFAULT_STEEPNESS
Definition map.h:698
#define DIRSTEP(dest_x, dest_y, dir)
Definition map.h:236
#define terrain_misc
Definition map_types.h:29
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
#define SINGLE_MOVE
Definition movement.h:26
static bool is_native_tile_to_class(const struct unit_class *punitclass, const struct tile *ptile)
Definition movement.h:84
#define MOVE_COST_IGTER
Definition movement.h:27
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:486
struct iterator * nation_iter_init(struct nation_iter *it)
Definition nation.c:557
size_t nation_iter_sizeof(void)
Definition nation.c:524
#define nation_hash_iterate(nationhash, pnation)
Definition nation.h:93
#define nations_iterate_end
Definition nation.h:336
#define nations_iterate(NAME_pnation)
Definition nation.h:333
#define nation_hash_iterate_end
Definition nation.h:95
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1388
#define fc_rand(_size)
Definition rand.h:56
bool are_reqs_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Definition road.c:416
#define CLIP(lower, current, upper)
Definition shared.h:57
#define FC_WRAP(value, range)
Definition shared.h:65
#define MAX(x, y)
Definition shared.h:54
#define XOR(p, q)
Definition shared.h:71
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
struct packet_game_info info
Definition game.h:89
struct startpos_hash * startpos_table
Definition map_types.h:96
struct tile * tiles
Definition map_types.h:95
Continent_id num_continents
Definition map_types.h:83
int num_iterate_outwards_indices
Definition map_types.h:78
struct civ_map::@44::@47 client
Continent_id * island_surrounders
Definition map_types.h:132
Continent_id * lake_surrounders
Definition map_types.h:133
struct iter_index * iterate_outwards_indices
Definition map_types.h:77
struct civ_map::@44::@46 server
int * continent_sizes
Definition map_types.h:92
int * ocean_sizes
Definition map_types.h:93
Continent_id num_oceans
Definition map_types.h:84
int ** adj_matrix
Definition map_types.h:153
int dist
Definition city.h:107
int dx
Definition city.h:107
int dy
Definition city.h:107
bv_startpos_nations nations
const struct startpos * psp
Definition map.c:59
struct iterator vtable
Definition map.c:58
Definition map.c:40
bool exclude
Definition map.c:42
struct tile * location
Definition map.c:41
struct nation_hash * nations
Definition map.c:43
Definition tile.h:50
char * spec_sprite
Definition tile.h:67
char * label
Definition tile.h:66
int altitude
Definition tile.h:65
bv_extras extras
Definition tile.h:55
struct extra_type * resource
Definition tile.h:56
struct unit_list * units
Definition tile.h:58
struct player * extras_owner
Definition tile.h:63
struct terrain * terrain
Definition tile.h:57
struct extra_type * placing
Definition tile.h:61
struct city * worked
Definition tile.h:59
struct player * owner
Definition tile.h:60
Continent_id continent
Definition tile.h:54
struct tile * claimer
Definition tile.h:64
Definition unit.h:140
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
int count_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, bool cardinal_only, bool percentage, enum terrain_class tclass)
Definition terrain.c:633
int count_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, bool cardinal_only, bool percentage, enum terrain_flag_id flag)
Definition terrain.c:478
#define T_UNKNOWN
Definition terrain.h:62
#define is_ocean(pterrain)
Definition terrain.h:194
#define terrain_has_flag(terr, flag)
Definition terrain.h:176
void tile_virtual_destroy(struct tile *vtile)
Definition tile.c:1035
void tile_remove_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:965
struct tile * tile_virtual_new(const struct tile *ptile)
Definition tile.c:981
void * tile_hash_key(const struct tile *ptile)
Definition tile.c:1085
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_index(_pt_)
Definition tile.h:89
#define ACTIVITY_FACTOR
Definition tile.h:166
#define tile_terrain(_tile)
Definition tile.h:111
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
#define tile_owner(_tile)
Definition tile.h:97
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:773
#define utype_class(_t_)
Definition unittype.h:756
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
#define MAP_NATIVE_WIDTH
#define MAP_NUM_VALID_DIRS
#define MAP_INDEX_SIZE
#define MAP_IS_ISOMETRIC
#define MAP_NATURAL_HEIGHT
#define MAP_NATURAL_WIDTH
#define MAP_NATIVE_HEIGHT
#define MAP_VALID_DIRS