Freeciv-3.4
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/*******************************************************************/
736bool can_reclaim_ocean(const struct civ_map *nmap,
737 const struct tile *ptile)
738{
740 float pct = terrain_control.ocean_reclaim_requirement_pct/100.0;
744
746}
747
748/*******************************************************************/
753bool can_channel_land(const struct civ_map *nmap,
754 const struct tile *ptile)
755{
758
759 return ocean_tiles >= terrain_control.land_channel_requirement_pct;
760}
761
762/*******************************************************************/
767bool can_thaw_terrain(const struct civ_map *nmap,
768 const struct tile *ptile)
769{
771 FALSE, TRUE,
772 TER_FROZEN);
773
774 return unfrozen_tiles >= terrain_control.terrain_thaw_requirement_pct;
775}
776
777/*******************************************************************/
782bool can_freeze_terrain(const struct civ_map *nmap,
783 const struct tile *ptile)
784{
786 FALSE, TRUE,
787 TER_FROZEN);
788
789 return frozen_tiles >= terrain_control.terrain_freeze_requirement_pct;
790}
791
792/*******************************************************************/
797 const struct tile *ptile,
798 const struct terrain *pterrain)
799{
800 bool ret = TRUE;
801
802 if (is_ocean(tile_terrain(ptile))
803 && !is_ocean(pterrain) && !can_reclaim_ocean(nmap, ptile)) {
804 ret = FALSE;
805 } else if (!is_ocean(tile_terrain(ptile))
806 && is_ocean(pterrain) && !can_channel_land(nmap, ptile)) {
807 ret = FALSE;
808 }
809
810 if (ret) {
812 && !terrain_has_flag(pterrain, TER_FROZEN)
813 && !can_thaw_terrain(nmap, ptile)) {
814 ret = FALSE;
815 } else if (!terrain_has_flag(tile_terrain(ptile), TER_FROZEN)
816 && terrain_has_flag(pterrain, TER_FROZEN)
817 && !can_freeze_terrain(nmap, ptile)) {
818 ret = FALSE;
819 }
820 }
821
822 return ret;
823}
824
825/**********************************************************************/
829{
830 fc_assert_ret_val(id > 0, -1);
832 return wld.map.continent_sizes[id];
833}
834
835/**********************************************************************/
840{
841 fc_assert_ret_val(id > 0, -1);
843 return wld.map.ocean_sizes[id];
844}
845
846/**********************************************************************/
852{
853 fc_assert_ret_val(id > 0, +1);
855 if (is_server()) {
857 } else {
858 Continent_id ocean, surrounder = 0;
859
860 for (ocean = 1; ocean <= wld.map.num_oceans; ocean++) {
861 if (wld.map.client.adj_matrix[id][ocean] > 0) {
862 if (surrounder == 0) {
863 surrounder = ocean;
864 } else if (surrounder != ocean) {
865 /* More than one adjacent ocean */
866 return +1;
867 }
868 }
869 }
870
871 if (surrounder == 0 && is_whole_continent_known(id)) {
872 return +1;
873 } else {
874 return -surrounder;
875 }
876 }
877}
878
879/**********************************************************************/
885{
886 fc_assert_ret_val(id < 0, -1);
888 if (is_server()) {
890 } else {
891 Continent_id cont, surrounder = 0;
892
893 for (cont = 1; cont <= wld.map.num_continents; cont++) {
894 if (wld.map.client.adj_matrix[cont][-id] > 0) {
895 if (surrounder == 0) {
896 surrounder = cont;
897 } else if (surrounder != cont) {
898 /* More than one adjacent continent */
899 return -1;
900 }
901 }
902 }
903
904 if (surrounder == 0 && is_whole_ocean_known(-id)) {
905 return -1;
906 } else {
907 return surrounder;
908 }
909 }
910}
911
912/*******************************************************************/
922 const struct unit *punit,
923 const struct unit_type *punittype,
924 const struct player *pplayer,
925 const struct tile *t1, const struct tile *t2)
926{
927 const struct unit_class *pclass = utype_class(punittype);
928 int cost;
929 signed char cardinal_move = -1;
930 bool ri;
931
932 /* Try to exit early for detectable conditions */
934 /* Units without UCF_TERRAIN_SPEED have a constant cost. */
935 return SINGLE_MOVE;
936
937 } else if (!is_native_tile_to_class(pclass, t2)) {
938 if (tile_city(t2) == nullptr) {
939 /* Loading to transport. */
940
941 /* UTYF_IGTER units get move benefit. */
944 } else {
945 /* Entering port. (Could be "Conquer City") */
946
947 /* UTYF_IGTER units get move benefit. */
950 }
951
952 } else if (!is_native_tile_to_class(pclass, t1)) {
953 if (tile_city(t1) == nullptr) {
954 /* Disembarking from transport. */
955
956 /* UTYF_IGTER units get move benefit. */
959 } else {
960 /* Leaving port. */
961
962 /* UTYF_IGTER units get move benefit. */
965 }
966 }
967
968 cost = tile_terrain(t2)->movement_cost * SINGLE_MOVE;
969 ri = restrict_infra(pplayer, t1, t2);
970
971 extra_type_list_iterate(pclass->cache.bonus_roads, pextra) {
972 struct road_type *proad = extra_road_get(pextra);
973
974 /* We check the destination tile first, as that's
975 * the end of move that determines the cost.
976 * If can avoid inner loop about integrating roads
977 * completely if the destination road has too high cost. */
978
979 if (cost > proad->move_cost
981 && tile_has_extra(t2, pextra)) {
982 extra_type_list_iterate(proad->integrators, iextra) {
983 /* We have no unrestricted infra related check here,
984 * destination road is the one that counts. */
985 if (tile_has_extra(t1, iextra)
987 if (proad->move_mode == RMM_FAST_ALWAYS) {
988 cost = proad->move_cost;
989 } else {
990 if (cardinal_move < 0) {
992 || is_move_cardinal(nmap, t1, t2)) ? 1 : 0;
993 }
994 if (cardinal_move > 0) {
995 cost = proad->move_cost;
996 } else {
997 switch (proad->move_mode) {
998 case RMM_CARDINAL:
999 break;
1000 case RMM_RELAXED:
1001 if (cost > proad->move_cost * 2) {
1003 if (tile_has_extra(between, pextra)
1004 || (pextra != iextra && tile_has_extra(between, iextra))) {
1005 /* 'pextra != iextra' is there just to avoid
1006 * tile_has_extra() in by far more common case
1007 * that 'pextra == iextra' */
1008 /* TODO: Should we restrict this more?
1009 * Should we check against enemy cities on between tile?
1010 * Should we check against non-native terrain on between tile?
1011 */
1012 cost = proad->move_cost * 2;
1013 }
1015 }
1016 break;
1017 case RMM_FAST_ALWAYS:
1018
1019 /* Already handled above */
1020 fc_assert(proad->move_mode != RMM_FAST_ALWAYS);
1021
1022 cost = proad->move_cost;
1023 break;
1024 }
1025 }
1026 }
1027 }
1029 }
1031
1032 /* UTYF_IGTER units have a maximum move cost per step. */
1035 }
1036
1037 if (terrain_control.pythagorean_diagonal) {
1038 if (cardinal_move < 0) {
1040 || is_move_cardinal(nmap, t1, t2)) ? 1 : 0;
1041 }
1042 if (cardinal_move == 0) {
1043 return cost * 181 >> 7; /* == (int) (cost * 1.41421356f) if cost < 99 */
1044 }
1045 }
1046
1047 return cost;
1048}
1049
1050/*******************************************************************/
1056static bool restrict_infra(const struct player *pplayer, const struct tile *t1,
1057 const struct tile *t2)
1058{
1059 struct player *plr1 = tile_owner(t1), *plr2 = tile_owner(t2);
1060
1061 if (!pplayer || !game.info.restrictinfra) {
1062 return FALSE;
1063 }
1064
1065 if ((plr1 && pplayers_at_war(plr1, pplayer))
1066 || (plr2 && pplayers_at_war(plr2, pplayer))) {
1067 return TRUE;
1068 }
1069
1070 return FALSE;
1071}
1072
1073/*******************************************************************/
1076bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
1077{
1078 return real_map_distance(tile0, tile1) == 1;
1079}
1080
1081/*******************************************************************/
1085bool same_pos(const struct tile *tile1, const struct tile *tile2)
1086{
1087 fc_assert_ret_val(tile1 != nullptr && tile2 != nullptr, FALSE);
1088
1089 /* In case of virtual tile, tile1 can be different from tile2,
1090 * but they have same index */
1091 return (tile1->index == tile2->index);
1092}
1093
1094/*******************************************************************/
1097bool is_real_map_pos(const struct civ_map *nmap, int x, int y)
1098{
1099 return normalize_map_pos(nmap, &x, &y);
1100}
1101
1102/*******************************************************************/
1108bool is_normal_map_pos(int x, int y)
1109{
1110 int nat_x, nat_y;
1111
1113
1114 return nat_x >= 0 && nat_x < MAP_NATIVE_WIDTH
1115 && nat_y >= 0 && nat_y < MAP_NATIVE_HEIGHT;
1116}
1117
1118/*******************************************************************/
1126bool normalize_map_pos(const struct civ_map *nmap, int *x, int *y)
1127{
1128 struct tile *ptile = map_pos_to_tile(nmap, *x, *y);
1129
1130 if (ptile != nullptr) {
1131 index_to_map_pos(x, y, tile_index(ptile));
1132 return TRUE;
1133 } else {
1134 return FALSE;
1135 }
1136}
1137
1138/*******************************************************************/
1142struct tile *nearest_real_tile(const struct civ_map *nmap, int x, int y)
1143{
1144 int nat_x, nat_y;
1145
1148 nat_x = CLIP(0, nat_x, MAP_NATIVE_WIDTH - 1);
1149 }
1151 nat_y = CLIP(0, nat_y, MAP_NATIVE_HEIGHT - 1);
1152 }
1154
1155 return map_pos_to_tile(nmap, x, y);
1156}
1157
1158/*******************************************************************/
1162{
1164}
1165
1166/*******************************************************************/
1171void base_map_distance_vector(int *dx, int *dy,
1172 int x0dv, int y0dv, int x1dv, int y1dv)
1173{
1175 /* Wrapping is done in native coordinates. */
1178
1179 /* Find the "native" distance vector. This corresponds closely to the
1180 * map distance vector but is easier to wrap. */
1181 *dx = x1dv - x0dv;
1182 *dy = y1dv - y0dv;
1184 /* Wrap dx to be in [-map.xsize / 2, map.xsize / 2). */
1185 *dx = FC_WRAP(*dx + MAP_NATIVE_WIDTH / 2, MAP_NATIVE_WIDTH)
1186 - MAP_NATIVE_WIDTH / 2;
1187 }
1189 /* Wrap dy to be in [-map.ysize / 2, map.ysize / 2). */
1191 - MAP_NATIVE_HEIGHT / 2;
1192 }
1193
1194 /* Convert the native delta vector back to a pair of map positions. */
1195 x1dv = x0dv + *dx;
1196 y1dv = y0dv + *dy;
1199 }
1200
1201 /* Find the final (map) vector. */
1202 *dx = x1dv - x0dv;
1203 *dy = y1dv - y0dv;
1204}
1205
1206/*******************************************************************/
1222void map_distance_vector(int *dx, int *dy,
1223 const struct tile *tile0,
1224 const struct tile *tile1)
1225{
1226 int tx0, ty0, tx1, ty1;
1227
1231}
1232
1233/*******************************************************************/
1237struct tile *rand_map_pos(const struct civ_map *nmap)
1238{
1241
1243}
1244
1245/*******************************************************************/
1251struct tile *rand_map_pos_filtered(const struct civ_map *nmap, void *data,
1252 bool (*filter)(const struct tile *ptile,
1253 const void *data))
1254{
1255 struct tile *ptile;
1256 int tries = 0;
1258
1259 /* First do a few quick checks to find a spot. The limit on number of
1260 * tries could use some tweaking. */
1261 do {
1262 ptile = nmap->tiles + fc_rand(MAP_INDEX_SIZE);
1263 } while (filter != nullptr && !filter(ptile, data) && ++tries < max_tries);
1264
1265 /* If that fails, count all available spots and pick one.
1266 * Slow but reliable. */
1267 if (filter == nullptr) {
1268 ptile = nullptr;
1269 } else if (tries == max_tries) {
1270 int count = 0, *positions;
1271
1272 positions = fc_calloc(MAP_INDEX_SIZE, sizeof(*positions));
1273
1275 if (filter(check_tile, data)) {
1276 positions[count] = tile_index(check_tile);
1277 count++;
1278 }
1280
1281 if (count == 0) {
1282 ptile = nullptr;
1283 } else {
1284 ptile = wld.map.tiles + positions[fc_rand(count)];
1285 }
1286
1287 FC_FREE(positions);
1288 }
1289
1290 return ptile;
1291}
1292
1293/*******************************************************************/
1296const char *dir_get_name(enum direction8 dir)
1297{
1298 /* A switch statement is used so the ordering can be changed easily */
1299 switch (dir) {
1300 case DIR8_NORTH:
1301 return "N";
1302 case DIR8_NORTHEAST:
1303 return "NE";
1304 case DIR8_EAST:
1305 return "E";
1306 case DIR8_SOUTHEAST:
1307 return "SE";
1308 case DIR8_SOUTH:
1309 return "S";
1310 case DIR8_SOUTHWEST:
1311 return "SW";
1312 case DIR8_WEST:
1313 return "W";
1314 case DIR8_NORTHWEST:
1315 return "NW";
1316 default:
1317 return "[Undef]";
1318 }
1319}
1320
1321/*******************************************************************/
1325{
1326 /* A switch statement is used so the ordering can be changed easily */
1327 switch (dir) {
1328 case DIR8_NORTH:
1329 return DIR8_NORTHEAST;
1330 case DIR8_NORTHEAST:
1331 return DIR8_EAST;
1332 case DIR8_EAST:
1333 return DIR8_SOUTHEAST;
1334 case DIR8_SOUTHEAST:
1335 return DIR8_SOUTH;
1336 case DIR8_SOUTH:
1337 return DIR8_SOUTHWEST;
1338 case DIR8_SOUTHWEST:
1339 return DIR8_WEST;
1340 case DIR8_WEST:
1341 return DIR8_NORTHWEST;
1342 case DIR8_NORTHWEST:
1343 return DIR8_NORTH;
1344 default:
1346 return -1;
1347 }
1348}
1349
1350/*******************************************************************/
1354{
1355 /* A switch statement is used so the ordering can be changed easily */
1356 switch (dir) {
1357 case DIR8_NORTH:
1358 return DIR8_NORTHWEST;
1359 case DIR8_NORTHEAST:
1360 return DIR8_NORTH;
1361 case DIR8_EAST:
1362 return DIR8_NORTHEAST;
1363 case DIR8_SOUTHEAST:
1364 return DIR8_EAST;
1365 case DIR8_SOUTH:
1366 return DIR8_SOUTHEAST;
1367 case DIR8_SOUTHWEST:
1368 return DIR8_SOUTH;
1369 case DIR8_WEST:
1370 return DIR8_SOUTHWEST;
1371 case DIR8_NORTHWEST:
1372 return DIR8_WEST;
1373 default:
1375 return -1;
1376 }
1377}
1378
1379/*******************************************************************/
1384{
1385 switch (dir) {
1386 case DIR8_SOUTHEAST:
1387 case DIR8_NORTHWEST:
1388 /* These directions are invalid in hex topologies. */
1390 case DIR8_NORTHEAST:
1391 case DIR8_SOUTHWEST:
1392 /* These directions are invalid in iso-hex topologies. */
1394 case DIR8_NORTH:
1395 case DIR8_EAST:
1396 case DIR8_SOUTH:
1397 case DIR8_WEST:
1398 return TRUE;
1399 default:
1400 return FALSE;
1401 }
1402}
1403
1404/*******************************************************************/
1411{
1413
1414 return dir_validity[dir];
1415}
1416
1417/*******************************************************************/
1424{
1425 if (!direction8_is_valid(dir)) {
1426 /* Isn't even in range of direction8. */
1427 return FALSE;
1428 }
1429
1430 return is_valid_dir(dir);
1431}
1432
1433/*******************************************************************/
1441{
1442 switch (dir) {
1443 case DIR8_NORTH:
1444 case DIR8_SOUTH:
1445 case DIR8_EAST:
1446 case DIR8_WEST:
1447 return TRUE;
1448 case DIR8_SOUTHEAST:
1449 case DIR8_NORTHWEST:
1450 /* These directions are cardinal in iso-hex topologies. */
1452 case DIR8_NORTHEAST:
1453 case DIR8_SOUTHWEST:
1454 /* These directions are cardinal in hexagonal topologies. */
1456 }
1457 return FALSE;
1458}
1459
1460/*******************************************************************/
1467{
1469
1470 return dir_cardinality[dir];
1471}
1472
1473/*******************************************************************/
1479 const struct tile *start_tile,
1480 const struct tile *end_tile,
1481 enum direction8 *dir)
1482{
1483 adjc_dir_iterate(nmap, start_tile, test_tile, test_dir) {
1484 if (same_pos(end_tile, test_tile)) {
1485 *dir = test_dir;
1486 return TRUE;
1487 }
1489
1490 return FALSE;
1491}
1492
1493/*******************************************************************/
1498 const struct tile *start_tile,
1499 const struct tile *end_tile)
1500{
1501 enum direction8 dir;
1502
1503 if (base_get_direction_for_step(nmap, start_tile, end_tile, &dir)) {
1504 return dir;
1505 }
1506
1508
1509 return -1;
1510}
1511
1512/*******************************************************************/
1516bool is_move_cardinal(const struct civ_map *nmap,
1517 const struct tile *start_tile,
1518 const struct tile *end_tile)
1519{
1521 if (same_pos(end_tile, test_tile)) {
1522 return TRUE;
1523 }
1525
1526 return FALSE;
1527}
1528
1529/************************************************************************/
1547static double map_relative_southness(const struct tile *ptile)
1548{
1549 int tile_x, tile_y;
1550 double x, y, toroid_rel_colatitude;
1551 bool toroid_flipped;
1552
1553 /* TODO: What should the fallback value be?
1554 * Since this is not public API, it shouldn't matter anyway. */
1555 fc_assert_ret_val(ptile != nullptr, 0.5);
1556
1559 /* Compute natural coordinates relative to world size.
1560 * x and y are in the range [0.0, 1.0] */
1561 x = (double)ntl_x / (MAP_NATURAL_WIDTH - 1);
1562 y = (double)ntl_y / (MAP_NATURAL_HEIGHT - 1);
1564
1566 /* In an Earth-like topology, north and south are at the top and
1567 * bottom of the map.
1568 * This is equivalent to a Mercator projection. */
1569 return y;
1570 }
1571
1573 /* In a Uranus-like topology, north and south are at the left and
1574 * right side of the map.
1575 * This isn't really the way Uranus is; it's the way Earth would look
1576 * if you tilted your head sideways. It's still a Mercator
1577 * projection. */
1578 return x;
1579 }
1580
1581 /* Otherwise we have a torus topology. We set it up as an approximation
1582 * of a sphere with two circular polar zones and a square equatorial
1583 * zone. In this case north and south are not constant directions on the
1584 * map because we have to use a more complicated (custom) projection.
1585 *
1586 * Generators 2 and 5 work best if the center of the map is free.
1587 * So we want to set up the map with the poles (N,S) along the sides and
1588 * the equator (/,\‍) in between.
1589 *
1590 * ........
1591 * :\ NN /:
1592 * : \ / :
1593 * :S \/ S:
1594 * :S /\ S:
1595 * : / \ :
1596 * :/ NN \:
1597 * ''''''''
1598 */
1599
1600 /* First we will fold the map into fourths:
1601 *
1602 * ....
1603 * :\ N
1604 * : \
1605 * :S \
1606 *
1607 * and renormalize x and y to go from 0.0 to 1.0 again.
1608 */
1609 x = 2.0 * (x > 0.5 ? 1.0 - x : x);
1610 y = 2.0 * (y > 0.5 ? 1.0 - y : y);
1611
1612 /* Now flip it along the X direction to get this:
1613 *
1614 * ....
1615 * :N /
1616 * : /
1617 * :/ S
1618 */
1619 x = 1.0 - x;
1620
1621 /* To simplify the following computation, we can fold along the
1622 * diagonal. This leaves us with 1/8 of the map
1623 *
1624 * .....
1625 * :P /
1626 * : /
1627 * :/
1628 *
1629 * where P is the polar regions and / is the equator.
1630 * We must remember which hemisphere we are on for later. */
1631 if (x + y > 1.0) {
1632 /* This actually reflects the bottom-right half about the center point,
1633 * rather than about the diagonal, but that makes no difference. */
1634 x = 1.0 - x;
1635 y = 1.0 - y;
1637 } else {
1639 }
1640
1641 /* toroid_rel_colatitude is 0.0 at the poles and 1.0 at the equator.
1642 * This projection makes poles with a shape of a quarter-circle along
1643 * "P" and the equator as a straight line along "/".
1644 *
1645 * The formula is
1646 * lerp(1.5 (x^2 + y^2), (x+y)^2, x+y)
1647 * where
1648 * lerp(a,b,t) = a * (1-t) + b * t
1649 * is the linear interpolation between a and b, with
1650 * lerp(a,b,0) = a and lerp(a,b,1) = b
1651 *
1652 * I.e. the colatitude is computed as a linear interpolation between
1653 * - a = 1.5 (x^2 + y^2), proportional to the squared pythagorean
1654 * distance from the pole, which gives circular lines of latitude; and
1655 * - b = (x+y)^2, the squared manhattan distance from the pole, which
1656 * gives straight, diagonal lines of latitude parallel to the equator.
1657 *
1658 * These are interpolated with t = (x+y), the manhattan distance, which
1659 * ranges from 0 at the pole to 1 at the equator. So near the pole, the
1660 * (squared) pythagorean distance wins out, giving mostly circular lines,
1661 * and near the equator, the (squared) manhattan distance wins out,
1662 * giving mostly straight lines.
1663 *
1664 * Note that the colatitude growing with the square of the distance from
1665 * the pole keeps areas relatively the same as on non-toroidal maps:
1666 * On non-torus maps, the area closer to a pole than a given tile, and
1667 * the colatitude at that tile, both grow linearly with distance from the
1668 * pole. On torus maps, since the poles are singular points rather than
1669 * entire map edges, the area closer to a pole than a given tile grows
1670 * with the square of the distance to the pole - and so the colatitude
1671 * at that tile must also grow with the square in order to keep the size
1672 * of areas in a given range of colatitude relatively the same.
1673 *
1674 * See OSDN#43665, as well as the original discussion (via newsreader) at
1675 * news://news.gmane.io/gmane.games.freeciv.devel/42648 */
1676 toroid_rel_colatitude = (1.5 * (x * x * y + x * y * y)
1677 - 0.5 * (x * x * x + y * y * y)
1678 + 1.5 * (x * x + y * y));
1679
1680 /* Finally, convert from colatitude to latitude and add hemisphere
1681 * information back in:
1682 * - if we did not flip along the diagonal before, we are in the
1683 * northern hemisphere, with relative latitude in [0.0,0.5]
1684 * - if we _did_ flip, we are in the southern hemisphere, with
1685 * relative latitude in [0.5,1.0]
1686 */
1687 return ((toroid_flipped
1688 ? 2.0 - (toroid_rel_colatitude)
1690 / 2.0);
1691}
1692
1693/************************************************************************/
1701int map_signed_latitude(const struct tile *ptile)
1702{
1703 int north_latitude, south_latitude;
1704 double southness;
1705
1706 north_latitude = MAP_NORTH_LATITUDE(wld.map);
1707 south_latitude = MAP_SOUTH_LATITUDE(wld.map);
1708
1709 if (north_latitude == south_latitude) {
1710 /* Single-latitude / all-temperate map; no need to examine tile. */
1711 return south_latitude;
1712 }
1713
1714 fc_assert_ret_val(ptile != nullptr, (north_latitude + south_latitude) / 2);
1715
1717
1718 /* Linear interpolation between northernmost and southernmost latitude.
1719 * Truncate / round towards zero so northern and southern hemisphere
1720 * are symmetrical when south_latitude = -north_latitude. */
1721 return north_latitude * (1.0 - southness) + south_latitude * southness;
1722}
1723
1724/*******************************************************************/
1732bool is_singular_tile(const struct tile *ptile, int dist)
1733{
1734 int tile_x, tile_y;
1735
1738 /* Iso-natural coordinates are doubled in scale. */
1739 dist *= MAP_IS_ISOMETRIC ? 2 : 1;
1740
1741 return ((!current_wrap_has_flag(WRAP_X)
1746}
1747
1748/*******************************************************************/
1751static struct startpos *startpos_new(struct tile *ptile)
1752{
1753 struct startpos *psp = fc_malloc(sizeof(*psp));
1754
1755 psp->location = ptile;
1756 psp->exclude = FALSE;
1757 psp->nations = nation_hash_new();
1758
1759 return psp;
1760}
1761
1762/*******************************************************************/
1765static void startpos_destroy(struct startpos *psp)
1766{
1767 fc_assert_ret(psp != nullptr);
1768
1770 free(psp);
1771}
1772
1773/*******************************************************************/
1777{
1778 return map_startpos_get(index_to_tile(&(wld.map), id));
1779}
1780
1781/*******************************************************************/
1785int startpos_number(const struct startpos *psp)
1786{
1787 fc_assert_ret_val(psp != nullptr, -1);
1788
1789 return tile_index(psp->location);
1790}
1791
1792/*******************************************************************/
1796bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
1797{
1798 fc_assert_ret_val(psp != nullptr, FALSE);
1799 fc_assert_ret_val(pnation != nullptr, FALSE);
1800
1801 if (0 == nation_hash_size(psp->nations) || !psp->exclude) {
1802 psp->exclude = FALSE; /* Disable "excluding" mode. */
1803 return nation_hash_insert(psp->nations, pnation, nullptr);
1804 } else {
1805 return nation_hash_remove(psp->nations, pnation);
1806 }
1807}
1808
1809/*******************************************************************/
1813bool startpos_disallow(struct startpos *psp, struct nation_type *pnation)
1814{
1815 fc_assert_ret_val(psp != nullptr, FALSE);
1816 fc_assert_ret_val(pnation != nullptr, FALSE);
1817
1818 if (0 == nation_hash_size(psp->nations) || psp->exclude) {
1819 psp->exclude = TRUE; /* Enable "excluding" mode. */
1820 return nation_hash_remove(psp->nations, pnation);
1821 } else {
1822 return nation_hash_insert(psp->nations, pnation, nullptr);
1823 }
1824}
1825
1826/*******************************************************************/
1829struct tile *startpos_tile(const struct startpos *psp)
1830{
1831 fc_assert_ret_val(psp != nullptr, nullptr);
1832
1833 return psp->location;
1834}
1835
1836/*******************************************************************/
1839bool startpos_nation_allowed(const struct startpos *psp,
1840 const struct nation_type *pnation)
1841{
1842 fc_assert_ret_val(psp != nullptr, FALSE);
1843 fc_assert_ret_val(pnation != nullptr, FALSE);
1844
1845 return XOR(psp->exclude, nation_hash_lookup(psp->nations, pnation,
1846 nullptr));
1847}
1848
1849/*******************************************************************/
1852bool startpos_allows_all(const struct startpos *psp)
1853{
1854 fc_assert_ret_val(psp != nullptr, FALSE);
1855
1856 return (0 == nation_hash_size(psp->nations));
1857}
1858
1859/*******************************************************************/
1863bool startpos_pack(const struct startpos *psp,
1864 struct packet_edit_startpos_full *packet)
1865{
1866 fc_assert_ret_val(psp != nullptr, FALSE);
1867 fc_assert_ret_val(packet != nullptr, FALSE);
1868
1869 packet->id = startpos_number(psp);
1870 packet->exclude = psp->exclude;
1871 BV_CLR_ALL(packet->nations);
1872
1873 nation_hash_iterate(psp->nations, pnation) {
1874 BV_SET(packet->nations, nation_number(pnation));
1876
1877 return TRUE;
1878}
1879
1880/*******************************************************************/
1884bool startpos_unpack(struct startpos *psp,
1885 const struct packet_edit_startpos_full *packet)
1886{
1887 fc_assert_ret_val(psp != nullptr, FALSE);
1888 fc_assert_ret_val(packet != nullptr, FALSE);
1889
1890 psp->exclude = packet->exclude;
1891
1893 if (!BV_ISSET_ANY(packet->nations)) {
1894 return TRUE;
1895 }
1896 nations_iterate(pnation) {
1897 if (BV_ISSET(packet->nations, nation_number(pnation))) {
1898 nation_hash_insert(psp->nations, pnation, nullptr);
1899 }
1901
1902 return TRUE;
1903}
1904
1905/*******************************************************************/
1912bool startpos_is_excluding(const struct startpos *psp)
1913{
1914 fc_assert_ret_val(psp != nullptr, FALSE);
1915
1916 return psp->exclude;
1917}
1918
1919/*******************************************************************/
1925const struct nation_hash *startpos_raw_nations(const struct startpos *psp)
1926{
1927 fc_assert_ret_val(psp != nullptr, nullptr);
1928
1929 return psp->nations;
1930}
1931
1932/*******************************************************************/
1939{
1940 return MAX(sizeof(struct startpos_iter) + nation_iter_sizeof()
1941 - sizeof(struct iterator), nation_hash_iter_sizeof());
1942}
1943
1944/*******************************************************************/
1951{
1953
1954 do {
1955 iterator_next(&iter->nation_iter);
1956 } while (iterator_valid(&iter->nation_iter)
1957 || !nation_hash_lookup(iter->psp->nations,
1958 iterator_get(&iter->nation_iter),
1959 nullptr));
1960}
1961
1962/*******************************************************************/
1970{
1972
1973 return iterator_get(&iter->nation_iter);
1974}
1975
1976/*******************************************************************/
1980{
1982
1983 return iterator_valid(&iter->nation_iter);
1984}
1985
1986/*******************************************************************/
1990 const struct startpos *psp)
1991{
1992 if (psp == nullptr) {
1994 }
1995
1996 if (startpos_allows_all(psp)) {
1997 return nation_iter_init((struct nation_iter *) iter);
1998 }
1999
2000 if (!psp->exclude) {
2002 psp->nations);
2003 }
2004
2005 iter->vtable.next = startpos_exclude_iter_next;
2006 iter->vtable.get = startpos_exclude_iter_get;
2007 iter->vtable.valid = startpos_exclude_iter_valid;
2008 iter->psp = psp;
2009 (void) nation_iter_init((struct nation_iter *) &iter->nation_iter);
2010
2011 return ITERATOR(iter);
2012}
2013
2014/*******************************************************************/
2018{
2019 if (wld.map.startpos_table != nullptr) {
2021 } else {
2022 return 0;
2023 }
2024}
2025
2026/*******************************************************************/
2030struct startpos *map_startpos_new(struct tile *ptile)
2031{
2032 struct startpos *psp;
2033
2034 fc_assert_ret_val(ptile != nullptr, nullptr);
2035 fc_assert_ret_val(wld.map.startpos_table != nullptr, nullptr);
2036
2037 psp = startpos_new(ptile);
2039
2040 return psp;
2041}
2042
2043/*******************************************************************/
2047struct startpos *map_startpos_get(const struct tile *ptile)
2048{
2049 struct startpos *psp;
2050
2051 fc_assert_ret_val(ptile != nullptr, nullptr);
2052 fc_assert_ret_val(wld.map.startpos_table != nullptr, nullptr);
2053
2055
2056 return psp;
2057}
2058
2059/*******************************************************************/
2063bool map_startpos_remove(struct tile *ptile)
2064{
2065 fc_assert_ret_val(ptile != nullptr, FALSE);
2067
2069}
2070
2071/*******************************************************************/
2076{
2078}
2079
2080/*******************************************************************/
2089
2090/*******************************************************************/
2097
2098/*******************************************************************/
2102{
2103 return direction8_max() - dir;
2104}
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:390
#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:77
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:515
signed short Continent_id
Definition fc_types.h:233
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
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:753
struct startpos * map_startpos_get(const struct tile *ptile)
Definition map.c:2047
bool is_normal_map_pos(int x, int y)
Definition map.c:1108
int get_continent_size(Continent_id id)
Definition map.c:828
const int DIR_DY[8]
Definition map.c:86
int startpos_number(const struct startpos *psp)
Definition map.c:1785
bool can_reclaim_ocean(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:736
bool startpos_disallow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1813
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:2101
#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:1516
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:782
struct startpos * map_startpos_new(struct tile *ptile)
Definition map.c:2030
bool can_thaw_terrain(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:767
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:921
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:1839
#define STARTPOS_ITER(p)
Definition map.c:64
int map_num_tiles(void)
Definition map.c:1161
int get_direction_for_step(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile)
Definition map.c:1497
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1829
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1852
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1925
const int DIR_DX[8]
Definition map.c:85
struct tile * rand_map_pos(const struct civ_map *nmap)
Definition map.c:1237
static bool restrict_infra(const struct player *pplayer, const struct tile *t1, const struct tile *t2)
Definition map.c:1056
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:1296
enum direction8 dir_ccw(enum direction8 dir)
Definition map.c:1353
struct iterator * map_startpos_iter_init(struct map_startpos_iter *iter)
Definition map.c:2084
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:1076
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:1751
static double map_relative_southness(const struct tile *ptile)
Definition map.c:1547
bool startpos_pack(const struct startpos *psp, struct packet_edit_startpos_full *packet)
Definition map.c:1863
static bool is_valid_dir_calculate(enum direction8 dir)
Definition map.c:1383
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:1701
static bool is_cardinal_dir_calculate(enum direction8 dir)
Definition map.c:1440
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:2063
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:1251
int map_startpos_count(void)
Definition map.c:2017
size_t startpos_iter_sizeof(void)
Definition map.c:1938
bool is_cardinal_dir(enum direction8 dir)
Definition map.c:1466
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:1085
bool map_untrusted_dir_is_valid(enum direction8 dir)
Definition map.c:1423
bool terrain_surroundings_allow_change(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain)
Definition map.c:796
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:1884
int get_ocean_size(Continent_id id)
Definition map.c:839
bool is_valid_dir(enum direction8 dir)
Definition map.c:1410
void base_map_distance_vector(int *dx, int *dy, int x0dv, int y0dv, int x1dv, int y1dv)
Definition map.c:1171
enum direction8 dir_cw(enum direction8 dir)
Definition map.c:1324
int get_island_surrounder(Continent_id id)
Definition map.c:851
enum direction8 rand_direction(void)
Definition map.c:2093
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:1765
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:1969
struct tile * nearest_real_tile(const struct civ_map *nmap, int x, int y)
Definition map.c:1142
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:1478
static void startpos_exclude_iter_next(struct iterator *startpos_iter)
Definition map.c:1950
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:1222
int get_lake_surrounder(Continent_id id)
Definition map.c:884
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:1912
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:1776
bool map_is_empty(void)
Definition map.c:148
size_t map_startpos_iter_sizeof(void)
Definition map.c:2075
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1796
bool normalize_map_pos(const struct civ_map *nmap, int *x, int *y)
Definition map.c:1126
static bool startpos_exclude_iter_valid(const struct iterator *startpos_iter)
Definition map.c:1979
struct iterator * startpos_iter_init(struct startpos_iter *iter, const struct startpos *psp)
Definition map.c:1989
bool is_real_map_pos(const struct civ_map *nmap, int x, int y)
Definition map.c:1097
bool is_singular_tile(const struct tile *ptile, int dist)
Definition map.c:1732
int map_vector_to_real_distance(int dx, int dy)
Definition map.c:623
#define MAP_MAX_SIZE
Definition map.h:661
#define current_topo_has_flag(flag)
Definition map.h:43
#define MAP_DEFAULT_SIZE
Definition map.h:659
#define MAP_MAX_LINEAR_SIZE
Definition map.h:677
#define adjc_dir_iterate(nmap, center_tile, itr_tile, dir_itr)
Definition map.h:444
#define MAP_DEFAULT_HUTS
Definition map.h:641
#define adjc_iterate_end
Definition map.h:439
#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:676
#define MAP_DEFAULT_STARTPOS
Definition map.h:717
#define MAP_DEFAULT_ANIMALS
Definition map.h:645
#define MAP_DEFAULT_TEAM_PLACEMENT
Definition map.h:735
#define MAP_DEFAULT_TOPO
Definition map.h:691
#define MAP_DEFAULT_SEED
Definition map.h:695
#define CHECK_INDEX(mindex)
Definition map.h:153
#define cardinal_between_iterate(nmap, tile1, tile2, between)
Definition map.h:483
#define MAP_DEFAULT_MAPSIZE
Definition map.h:649
#define MAP_MIN_LINEAR_SIZE
Definition map.h:678
#define MAP_DEFAULT_LANDMASS
Definition map.h:699
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:434
#define MAP_SOUTH_LATITUDE(_nmap)
Definition map.h:620
#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:472
#define MAP_DEFAULT_WRAP
Definition map.h:692
#define MAP_MIN_SIZE
Definition map.h:660
#define MAP_DEFAULT_NORTH_LATITUDE
Definition map.h:615
#define MAP_DEFAULT_SEPARATE_POLES
Definition map.h:723
#define MAP_DEFAULT_RICHES
Definition map.h:703
#define MAP_DEFAULT_TINYISLES
Definition map.h:719
#define whole_map_iterate(_map, _tile)
Definition map.h:582
#define MAP_NORTH_LATITUDE(_nmap)
Definition map.h:619
#define MAP_DEFAULT_TILESPERPLAYER
Definition map.h:671
#define adjc_dir_iterate_end
Definition map.h:448
#define MAP_DEFAULT_TEMPERATURE
Definition map.h:731
#define cardinal_between_iterate_end
Definition map.h:488
#define MAP_DEFAULT_SOUTH_LATITUDE
Definition map.h:616
#define current_wrap_has_flag(flag)
Definition map.h:46
#define MAP_DEFAULT_GENERATOR
Definition map.h:715
#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:711
#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:468
#define whole_map_iterate_end
Definition map.h:591
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:229
#define MAP_DEFAULT_STEEPNESS
Definition map.h:707
#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:88
#define MOVE_COST_IGTER
Definition movement.h:27
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:484
struct iterator * nation_iter_init(struct nation_iter *it)
Definition nation.c:553
size_t nation_iter_sizeof(void)
Definition nation.c:520
#define nation_hash_iterate(nationhash, pnation)
Definition nation.h:93
#define nations_iterate_end
Definition nation.h:364
#define nations_iterate(NAME_pnation)
Definition nation.h:361
#define nation_hash_iterate_end
Definition nation.h:95
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1376
#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:108
int dx
Definition city.h:108
int dy
Definition city.h:108
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:636
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:481
#define T_UNKNOWN
Definition terrain.h:62
#define is_ocean(pterrain)
Definition terrain.h:195
#define terrain_has_flag(terr, flag)
Definition terrain.h:177
void tile_virtual_destroy(struct tile *vtile)
Definition tile.c:1036
void tile_remove_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:966
struct tile * tile_virtual_new(const struct tile *ptile)
Definition tile.c:982
void * tile_hash_key(const struct tile *ptile)
Definition tile.c:1086
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:170
#define tile_terrain(_tile)
Definition tile.h:115
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#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