Stop sharing requirement_unit_state_ereq().
[freeciv.git] / common / map.c
blob0a3ac3eae22fd103863022767f16a615cef325e0
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
17 #include <string.h> /* strlen */
19 /* utility */
20 #include "fcintl.h"
21 #include "iterator.h"
22 #include "log.h"
23 #include "mem.h"
24 #include "rand.h"
25 #include "shared.h"
26 #include "support.h"
28 /* common */
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"
38 #include "map.h"
40 struct startpos {
41 struct tile *location;
42 bool exclude;
43 struct nation_hash *nations;
46 static struct startpos *startpos_new(struct tile *ptile);
47 static void startpos_destroy(struct startpos *psp);
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"
56 /* Srart position iterator. */
57 struct startpos_iter {
58 struct iterator vtable;
59 const struct startpos *psp;
60 /* 'struct nation_iter' really. See startpos_iter_sizeof(). */
61 struct iterator nation_iter;
64 #define STARTPOS_ITER(p) ((struct startpos_iter *) (p))
67 /* these are initialized from the terrain ruleset */
68 struct terrain_misc terrain_control;
70 /* used to compute neighboring tiles.
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.
85 const int DIR_DX[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };
86 const int DIR_DY[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };
88 static bool dir_cardinality[9]; /* Including invalid one */
89 static bool dir_validity[9]; /* Including invalid one */
91 static bool is_valid_dir_calculate(enum direction8 dir);
92 static bool is_cardinal_dir_calculate(enum direction8 dir);
94 static bool restrict_infra(const struct player *pplayer, const struct tile *t1,
95 const struct tile *t2);
97 /****************************************************************************
98 Return a bitfield of the extras on the tile that are infrastructure.
99 ****************************************************************************/
100 bv_extras get_tile_infrastructure_set(const struct tile *ptile,
101 int *pcount)
103 bv_extras pspresent;
104 int count = 0;
106 BV_CLR_ALL(pspresent);
108 extra_type_iterate(pextra) {
109 if (is_extra_removed_by(pextra, ERM_PILLAGE) && tile_has_extra(ptile, pextra)) {
110 struct tile *missingset = tile_virtual_new(ptile);
111 bool dependency = FALSE;
113 tile_remove_extra(missingset, pextra);
114 extra_type_iterate(pdependant) {
115 if (tile_has_extra(ptile, pdependant)) {
116 if (!are_reqs_active(NULL, NULL, NULL, NULL, missingset,
117 NULL, NULL, NULL, NULL, NULL,
118 &pdependant->reqs, RPT_POSSIBLE)) {
119 dependency = TRUE;
120 break;
123 } extra_type_iterate_end;
125 tile_virtual_destroy(missingset);
127 if (!dependency) {
128 BV_SET(pspresent, extra_index(pextra));
129 count++;
132 } extra_type_iterate_end;
134 if (pcount) {
135 *pcount = count;
138 return pspresent;
141 /***************************************************************
142 Returns TRUE if we are at a stage of the game where the map
143 has not yet been generated/loaded.
144 (To be precise, returns TRUE if map_allocate() has not yet been
145 called.)
146 ***************************************************************/
147 bool map_is_empty(void)
149 return wld.map.tiles == NULL;
152 /***************************************************************
153 Put some sensible values into the map structure
154 ***************************************************************/
155 void map_init(struct civ_map *imap, bool server_side)
157 imap->topology_id = MAP_DEFAULT_TOPO;
158 imap->num_continents = 0;
159 imap->num_oceans = 0;
160 imap->tiles = NULL;
161 imap->startpos_table = NULL;
162 imap->iterate_outwards_indices = NULL;
164 /* The [xy]size values are set in map_init_topology. It is initialized
165 * to a non-zero value because some places erronously use these values
166 * before they're initialized. */
167 imap->xsize = MAP_DEFAULT_LINEAR_SIZE;
168 imap->ysize = MAP_DEFAULT_LINEAR_SIZE;
170 if (server_side) {
171 imap->server.mapsize = MAP_DEFAULT_MAPSIZE;
172 imap->server.size = MAP_DEFAULT_SIZE;
173 imap->server.tilesperplayer = MAP_DEFAULT_TILESPERPLAYER;
174 imap->server.seed_setting = MAP_DEFAULT_SEED;
175 imap->server.seed = MAP_DEFAULT_SEED;
176 imap->server.riches = MAP_DEFAULT_RICHES;
177 imap->server.huts = MAP_DEFAULT_HUTS;
178 imap->server.huts_absolute = -1;
179 imap->server.animals = MAP_DEFAULT_ANIMALS;
180 imap->server.landpercent = MAP_DEFAULT_LANDMASS;
181 imap->server.wetness = MAP_DEFAULT_WETNESS;
182 imap->server.steepness = MAP_DEFAULT_STEEPNESS;
183 imap->server.generator = MAP_DEFAULT_GENERATOR;
184 imap->server.startpos = MAP_DEFAULT_STARTPOS;
185 imap->server.tinyisles = MAP_DEFAULT_TINYISLES;
186 imap->server.separatepoles = MAP_DEFAULT_SEPARATE_POLES;
187 imap->server.single_pole = MAP_DEFAULT_SINGLE_POLE;
188 imap->server.alltemperate = MAP_DEFAULT_ALLTEMPERATE;
189 imap->server.temperature = MAP_DEFAULT_TEMPERATURE;
190 imap->server.have_huts = FALSE;
191 imap->server.have_resources = FALSE;
192 imap->server.team_placement = MAP_DEFAULT_TEAM_PLACEMENT;
196 /**************************************************************************
197 Fill the iterate_outwards_indices array. This may depend on the topology.
198 ***************************************************************************/
199 static void generate_map_indices(void)
201 int i = 0, nat_x, nat_y, tiles;
202 int nat_center_x, nat_center_y, nat_min_x, nat_min_y, nat_max_x, nat_max_y;
203 int map_center_x, map_center_y;
205 /* These caluclations are done via tricky native math. We need to make
206 * sure that when "exploring" positions in the iterate_outward we hit each
207 * position within the distance exactly once.
209 * To do this we pick a center position (at the center of the map, for
210 * convenience). Then we iterate over all of the positions around it,
211 * accounting for wrapping, in native coordinates. Note that some of the
212 * positions iterated over before will not even be real; the point is to
213 * use the native math so as to get the right behavior under different
214 * wrapping conditions.
216 * Thus the "center" position below is just an arbitrary point. We choose
217 * the center of the map to make the min/max values (below) simpler. */
218 nat_center_x = wld.map.xsize / 2;
219 nat_center_y = wld.map.ysize / 2;
220 NATIVE_TO_MAP_POS(&map_center_x, &map_center_y,
221 nat_center_x, nat_center_y);
223 /* If we wrap in a particular direction (X or Y) we only need to explore a
224 * half of a map-width in that direction before we hit the wrap point. If
225 * not we need to explore the full width since we have to account for the
226 * worst-case where we start at one edge of the map. Of course if we try
227 * to explore too far the extra steps will just be skipped by the
228 * normalize check later on. So the purpose at this point is just to
229 * get the right set of positions, relative to the start position, that
230 * may be needed for the iteration.
232 * If the map does wrap, we go map.Nsize / 2 in each direction. This
233 * gives a min value of 0 and a max value of Nsize-1, because of the
234 * center position chosen above. This also avoids any off-by-one errors.
236 * If the map doesn't wrap, we go map.Nsize-1 in each direction. In this
237 * case we're not concerned with going too far and wrapping around, so we
238 * just have to make sure we go far enough if we're at one edge of the
239 * map. */
240 nat_min_x = (current_topo_has_flag(TF_WRAPX) ? 0 : (nat_center_x - wld.map.xsize + 1));
241 nat_min_y = (current_topo_has_flag(TF_WRAPY) ? 0 : (nat_center_y - wld.map.ysize + 1));
243 nat_max_x = (current_topo_has_flag(TF_WRAPX)
244 ? (wld.map.xsize - 1)
245 : (nat_center_x + wld.map.xsize - 1));
246 nat_max_y = (current_topo_has_flag(TF_WRAPY)
247 ? (wld.map.ysize - 1)
248 : (nat_center_y + wld.map.ysize - 1));
249 tiles = (nat_max_x - nat_min_x + 1) * (nat_max_y - nat_min_y + 1);
251 fc_assert(NULL == wld.map.iterate_outwards_indices);
252 wld.map.iterate_outwards_indices =
253 fc_malloc(tiles * sizeof(*wld.map.iterate_outwards_indices));
255 for (nat_x = nat_min_x; nat_x <= nat_max_x; nat_x++) {
256 for (nat_y = nat_min_y; nat_y <= nat_max_y; nat_y++) {
257 int map_x, map_y, dx, dy;
259 /* Now for each position, we find the vector (in map coordinates) from
260 * the center position to that position. Then we calculate the
261 * distance between the two points. Wrapping is ignored at this
262 * point since the use of native positions means we should always have
263 * the shortest vector. */
264 NATIVE_TO_MAP_POS(&map_x, &map_y, nat_x, nat_y);
265 dx = map_x - map_center_x;
266 dy = map_y - map_center_y;
268 wld.map.iterate_outwards_indices[i].dx = dx;
269 wld.map.iterate_outwards_indices[i].dy = dy;
270 wld.map.iterate_outwards_indices[i].dist =
271 map_vector_to_real_distance(dx, dy);
272 i++;
275 fc_assert(i == tiles);
277 qsort(wld.map.iterate_outwards_indices, tiles,
278 sizeof(*wld.map.iterate_outwards_indices), compare_iter_index);
280 #if 0
281 for (i = 0; i < tiles; i++) {
282 log_debug("%5d : (%3d,%3d) : %d", i,
283 wld.map.iterate_outwards_indices[i].dx,
284 wld.map.iterate_outwards_indices[i].dy,
285 wld.map.iterate_outwards_indices[i].dist);
287 #endif
289 wld.map.num_iterate_outwards_indices = tiles;
292 /****************************************************************************
293 map_init_topology needs to be called after map.topology_id is changed.
295 map.xsize and map.ysize must be set before calling map_init_topology().
296 This is done by the map generator code (server), when loading a savegame
297 or a scenario with map (server), and packhand code (client).
298 ****************************************************************************/
299 void map_init_topology(void)
301 enum direction8 dir;
303 /* sanity check for iso topologies*/
304 fc_assert(!MAP_IS_ISOMETRIC || (wld.map.ysize % 2) == 0);
306 /* The size and ratio must satisfy the minimum and maximum *linear*
307 * restrictions on width */
308 fc_assert(wld.map.xsize >= MAP_MIN_LINEAR_SIZE);
309 fc_assert(wld.map.ysize >= MAP_MIN_LINEAR_SIZE);
310 fc_assert(wld.map.xsize <= MAP_MAX_LINEAR_SIZE);
311 fc_assert(wld.map.ysize <= MAP_MAX_LINEAR_SIZE);
312 fc_assert(map_num_tiles() >= MAP_MIN_SIZE * 1000);
313 fc_assert(map_num_tiles() <= MAP_MAX_SIZE * 1000);
315 wld.map.num_valid_dirs = wld.map.num_cardinal_dirs = 0;
317 /* Values for direction8_invalid() */
318 fc_assert(direction8_invalid() == 8);
319 dir_validity[8] = FALSE;
320 dir_cardinality[8] = FALSE;
322 /* Values for actual directions */
323 for (dir = 0; dir < 8; dir++) {
324 if (is_valid_dir_calculate(dir)) {
325 wld.map.valid_dirs[wld.map.num_valid_dirs] = dir;
326 wld.map.num_valid_dirs++;
327 dir_validity[dir] = TRUE;
328 } else {
329 dir_validity[dir] = FALSE;
331 if (is_cardinal_dir_calculate(dir)) {
332 wld.map.cardinal_dirs[wld.map.num_cardinal_dirs] = dir;
333 wld.map.num_cardinal_dirs++;
334 dir_cardinality[dir] = TRUE;
335 } else {
336 dir_cardinality[dir] = FALSE;
339 fc_assert(wld.map.num_valid_dirs > 0 && wld.map.num_valid_dirs <= 8);
340 fc_assert(wld.map.num_cardinal_dirs > 0
341 && wld.map.num_cardinal_dirs <= wld.map.num_valid_dirs);
344 /***************************************************************
345 Initialize tile structure
346 ***************************************************************/
347 static void tile_init(struct tile *ptile)
349 ptile->continent = 0;
351 BV_CLR_ALL(ptile->extras);
352 ptile->resource = NULL;
353 ptile->terrain = T_UNKNOWN;
354 ptile->units = unit_list_new();
355 ptile->owner = NULL; /* Not claimed by any player. */
356 ptile->extras_owner = NULL;
357 ptile->claimer = NULL;
358 ptile->worked = NULL; /* No city working here. */
359 ptile->spec_sprite = NULL;
362 /****************************************************************************
363 Step from the given tile in the given direction. The new tile is returned,
364 or NULL if the direction is invalid or leads off the map.
365 ****************************************************************************/
366 struct tile *mapstep(const struct tile *ptile, enum direction8 dir)
368 int dx, dy, tile_x, tile_y;
370 if (!is_valid_dir(dir)) {
371 return NULL;
374 index_to_map_pos(&tile_x, &tile_y, tile_index(ptile));
375 DIRSTEP(dx, dy, dir);
377 tile_x += dx;
378 tile_y += dy;
380 return map_pos_to_tile(tile_x, tile_y);
383 /****************************************************************************
384 Return the tile for the given native position, with wrapping.
386 This is a backend function used by map_pos_to_tile and native_pos_to_tile.
387 It is called extremely often so it is made inline.
388 ****************************************************************************/
389 static inline struct tile *base_native_pos_to_tile(int nat_x, int nat_y)
391 /* Wrap in X and Y directions, as needed. */
392 /* If the position is out of range in a non-wrapping direction, it is
393 * unreal. */
394 if (current_topo_has_flag(TF_WRAPX)) {
395 nat_x = FC_WRAP(nat_x, wld.map.xsize);
396 } else if (nat_x < 0 || nat_x >= wld.map.xsize) {
397 return NULL;
399 if (current_topo_has_flag(TF_WRAPY)) {
400 nat_y = FC_WRAP(nat_y, wld.map.ysize);
401 } else if (nat_y < 0 || nat_y >= wld.map.ysize) {
402 return NULL;
405 /* We already checked legality of native pos above, don't repeat */
406 return wld.map.tiles + native_pos_to_index_nocheck(nat_x, nat_y);
409 /****************************************************************************
410 Return the tile for the given cartesian (map) position.
411 ****************************************************************************/
412 struct tile *map_pos_to_tile(int map_x, int map_y)
414 /* Instead of introducing new variables for native coordinates,
415 * update the map coordinate variables = registers already in use.
416 * This is one of the most performance-critical functions we have,
417 * so taking measures like this makes sense. */
418 #define nat_x map_x
419 #define nat_y map_y
421 if (!wld.map.tiles) {
422 return NULL;
425 /* Normalization is best done in native coordinates. */
426 MAP_TO_NATIVE_POS(&nat_x, &nat_y, map_x, map_y);
427 return base_native_pos_to_tile(nat_x, nat_y);
429 #undef nat_x
430 #undef nat_y
433 /****************************************************************************
434 Return the tile for the given native position.
435 ****************************************************************************/
436 struct tile *native_pos_to_tile(int nat_x, int nat_y)
438 if (!wld.map.tiles) {
439 return NULL;
442 return base_native_pos_to_tile(nat_x, nat_y);
445 /****************************************************************************
446 Return the tile for the given index position.
447 ****************************************************************************/
448 struct tile *index_to_tile(struct civ_map *imap, int mindex)
450 if (!imap->tiles) {
451 return NULL;
454 if (mindex >= 0 && mindex < MAP_INDEX_SIZE) {
455 return imap->tiles + mindex;
456 } else {
457 /* Unwrapped index coordinates are impossible, so the best we can do is
458 * return NULL. */
459 return NULL;
463 /***************************************************************
464 Free memory associated with one tile.
465 ***************************************************************/
466 static void tile_free(struct tile *ptile)
468 unit_list_destroy(ptile->units);
470 if (ptile->spec_sprite) {
471 free(ptile->spec_sprite);
472 ptile->spec_sprite = NULL;
475 if (ptile->label) {
476 FC_FREE(ptile->label);
477 ptile->label = NULL;
481 /**************************************************************************
482 Allocate space for map, and initialise the tiles.
483 Uses current map.xsize and map.ysize.
484 **************************************************************************/
485 void map_allocate(struct civ_map *amap)
487 log_debug("map_allocate (was %p) (%d,%d)",
488 (void *) amap->tiles, amap->xsize, amap->ysize);
490 fc_assert_ret(NULL == amap->tiles);
491 amap->tiles = fc_calloc(MAP_INDEX_SIZE, sizeof(*amap->tiles));
493 /* Note this use of whole_map_iterate may be a bit sketchy, since the
494 * tile values (ptile->index, etc.) haven't been set yet. It might be
495 * better to do a manual loop here. */
496 whole_map_iterate(amap, ptile) {
497 ptile->index = ptile - amap->tiles;
498 CHECK_INDEX(tile_index(ptile));
499 tile_init(ptile);
500 } whole_map_iterate_end;
502 if (amap->startpos_table != NULL) {
503 startpos_hash_destroy(amap->startpos_table);
505 amap->startpos_table = startpos_hash_new();
508 /***************************************************************
509 Allocate main map and related global structures.
510 ***************************************************************/
511 void main_map_allocate(void)
513 map_allocate(&(wld.map));
514 generate_city_map_indices();
515 generate_map_indices();
518 /***************************************************************
519 Frees the allocated memory of the map.
520 ***************************************************************/
521 void map_free(struct civ_map *fmap)
523 if (fmap->tiles) {
524 /* it is possible that map_init was called but not map_allocate */
526 whole_map_iterate(fmap, ptile) {
527 tile_free(ptile);
528 } whole_map_iterate_end;
530 free(fmap->tiles);
531 fmap->tiles = NULL;
533 if (fmap->startpos_table) {
534 startpos_hash_destroy(fmap->startpos_table);
535 fmap->startpos_table = NULL;
538 FC_FREE(fmap->iterate_outwards_indices);
542 /****************************************************************************
543 Return the "distance" (which is really the Manhattan distance, and should
544 rarely be used) for a given vector.
545 ****************************************************************************/
546 static int map_vector_to_distance(int dx, int dy)
548 if (current_topo_has_flag(TF_HEX)) {
549 /* Hex: all directions are cardinal so the distance is equivalent to
550 * the real distance. */
551 return map_vector_to_real_distance(dx, dy);
552 } else {
553 return abs(dx) + abs(dy);
557 /****************************************************************************
558 Return the "real" distance for a given vector.
559 ****************************************************************************/
560 int map_vector_to_real_distance(int dx, int dy)
562 const int absdx = abs(dx), absdy = abs(dy);
564 if (current_topo_has_flag(TF_HEX)) {
565 if (current_topo_has_flag(TF_ISO)) {
566 /* Iso-hex: you can't move NE or SW. */
567 if ((dx < 0 && dy > 0)
568 || (dx > 0 && dy < 0)) {
569 /* Diagonal moves in this direction aren't allowed, so it will take
570 * the full number of moves. */
571 return absdx + absdy;
572 } else {
573 /* Diagonal moves in this direction *are* allowed. */
574 return MAX(absdx, absdy);
576 } else {
577 /* Hex: you can't move SE or NW. */
578 if ((dx > 0 && dy > 0)
579 || (dx < 0 && dy < 0)) {
580 /* Diagonal moves in this direction aren't allowed, so it will take
581 * the full number of moves. */
582 return absdx + absdy;
583 } else {
584 /* Diagonal moves in this direction *are* allowed. */
585 return MAX(absdx, absdy);
588 } else {
589 return MAX(absdx, absdy);
593 /****************************************************************************
594 Return the sq_distance for a given vector.
595 ****************************************************************************/
596 int map_vector_to_sq_distance(int dx, int dy)
598 if (current_topo_has_flag(TF_HEX)) {
599 /* Hex: The square distance is just the square of the real distance; we
600 * don't worry about pythagorean calculations. */
601 int dist = map_vector_to_real_distance(dx, dy);
603 return dist * dist;
604 } else {
605 return dx * dx + dy * dy;
609 /***************************************************************
610 Return real distance between two tiles.
611 ***************************************************************/
612 int real_map_distance(const struct tile *tile0, const struct tile *tile1)
614 int dx, dy;
616 map_distance_vector(&dx, &dy, tile0, tile1);
617 return map_vector_to_real_distance(dx, dy);
620 /***************************************************************
621 Return squared distance between two tiles.
622 ***************************************************************/
623 int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
625 /* We assume map_distance_vector gives us the vector with the
626 minimum squared distance. Right now this is true. */
627 int dx, dy;
629 map_distance_vector(&dx, &dy, tile0, tile1);
630 return map_vector_to_sq_distance(dx, dy);
633 /***************************************************************
634 Return Manhattan distance between two tiles.
635 ***************************************************************/
636 int map_distance(const struct tile *tile0, const struct tile *tile1)
638 /* We assume map_distance_vector gives us the vector with the
639 minimum map distance. Right now this is true. */
640 int dx, dy;
642 map_distance_vector(&dx, &dy, tile0, tile1);
643 return map_vector_to_distance(dx, dy);
646 /****************************************************************************
647 Return TRUE if this ocean terrain is adjacent to a safe coastline.
648 ****************************************************************************/
649 bool is_safe_ocean(const struct tile *ptile)
651 adjc_iterate(ptile, adjc_tile) {
652 if (tile_terrain(adjc_tile) != T_UNKNOWN
653 && !terrain_has_flag(tile_terrain(adjc_tile), TER_UNSAFE_COAST)) {
654 return TRUE;
656 } adjc_iterate_end;
657 return FALSE;
660 /***************************************************************
661 Can tile be irrigated by given unit? Unit can be NULL to check if
662 any settler type unit of any player can irrigate.
663 ***************************************************************/
664 bool can_be_irrigated(const struct tile *ptile,
665 const struct unit *punit)
667 struct terrain* pterrain = tile_terrain(ptile);
669 if (T_UNKNOWN == pterrain) {
670 return FALSE;
673 return get_tile_bonus(ptile, punit, EFT_IRRIG_POSSIBLE) > 0;
676 /**************************************************************************
677 This function returns true if the tile at the given location can be
678 "reclaimed" from ocean into land. This is the case only when there are
679 a sufficient number of adjacent tiles that are not ocean.
680 **************************************************************************/
681 bool can_reclaim_ocean(const struct tile *ptile)
683 int land_tiles = 100 - count_terrain_class_near_tile(ptile, FALSE, TRUE,
684 TC_OCEAN);
686 return land_tiles >= terrain_control.ocean_reclaim_requirement_pct;
689 /**************************************************************************
690 This function returns true if the tile at the given location can be
691 "channeled" from land into ocean. This is the case only when there are
692 a sufficient number of adjacent tiles that are ocean.
693 **************************************************************************/
694 bool can_channel_land(const struct tile *ptile)
696 int ocean_tiles = count_terrain_class_near_tile(ptile, FALSE, TRUE, TC_OCEAN);
698 return ocean_tiles >= terrain_control.land_channel_requirement_pct;
701 /**************************************************************************
702 Returns true if the tile at the given location can be thawed from
703 terrain with a 'Frozen' flag to terrain without. This requires a
704 sufficient number of adjacent unfrozen tiles.
705 **************************************************************************/
706 bool can_thaw_terrain(const struct tile *ptile)
708 int unfrozen_tiles = 100 - count_terrain_flag_near_tile(ptile, FALSE, TRUE,
709 TER_FROZEN);
711 return unfrozen_tiles >= terrain_control.terrain_thaw_requirement_pct;
714 /**************************************************************************
715 Returns true if the tile at the given location can be turned from
716 terrain without a 'Frozen' flag to terrain with. This requires a
717 sufficient number of adjacent frozen tiles.
718 **************************************************************************/
719 bool can_freeze_terrain(const struct tile *ptile)
721 int frozen_tiles = count_terrain_flag_near_tile(ptile, FALSE, TRUE,
722 TER_FROZEN);
724 return frozen_tiles >= terrain_control.terrain_freeze_requirement_pct;
727 /**************************************************************************
728 Returns FALSE if a terrain change to 'pterrain' would be prevented by not
729 having enough similar terrain surrounding ptile.
730 **************************************************************************/
731 bool terrain_surroundings_allow_change(const struct tile *ptile,
732 const struct terrain *pterrain)
734 bool ret = TRUE;
736 if (is_ocean(tile_terrain(ptile))
737 && !is_ocean(pterrain) && !can_reclaim_ocean(ptile)) {
738 ret = FALSE;
739 } else if (!is_ocean(tile_terrain(ptile))
740 && is_ocean(pterrain) && !can_channel_land(ptile)) {
741 ret = FALSE;
744 if (ret) {
745 if (terrain_has_flag(tile_terrain(ptile), TER_FROZEN)
746 && !terrain_has_flag(pterrain, TER_FROZEN)
747 && !can_thaw_terrain(ptile)) {
748 ret = FALSE;
749 } else if (!terrain_has_flag(tile_terrain(ptile), TER_FROZEN)
750 && terrain_has_flag(pterrain, TER_FROZEN)
751 && !can_freeze_terrain(ptile)) {
752 ret = FALSE;
756 return ret;
759 /***************************************************************
760 The basic cost to move punit from tile t1 to tile t2.
761 That is, tile_move_cost(), with pre-calculated tile pointers;
762 the tiles are assumed to be adjacent, and the (x,y)
763 values are used only to get the river bonus correct.
765 May also be used with punit == NULL, in which case punit
766 tests are not done (for unit-independent results).
767 ***************************************************************/
768 int tile_move_cost_ptrs(const struct unit *punit,
769 const struct unit_type *punittype,
770 const struct player *pplayer,
771 const struct tile *t1, const struct tile *t2)
773 const struct unit_class *pclass = utype_class(punittype);
774 int cost;
775 bool cardinality_checked = FALSE;
776 bool cardinal_move BAD_HEURISTIC_INIT(FALSE);
777 bool ri;
779 /* Try to exit early for detectable conditions */
780 if (!uclass_has_flag(pclass, UCF_TERRAIN_SPEED)) {
781 /* units without UCF_TERRAIN_SPEED have a constant cost. */
782 return SINGLE_MOVE;
784 } else if (!is_native_tile_to_class(pclass, t2)) {
785 /* Loading to transport or entering port.
786 * UTYF_IGTER units get move benefit. */
787 return (utype_has_flag(punittype, UTYF_IGTER)
788 ? MOVE_COST_IGTER : SINGLE_MOVE);
790 } else if (!is_native_tile_to_class(pclass, t1)) {
791 if (game.info.slow_invasions
792 && !(punit && unit_has_type_flag(punit, UTYF_BEACH_LANDER))
793 && tile_city(t1) == NULL) {
794 /* If "slowinvasions" option is turned on, units moving from
795 * non-native terrain (from transport) to native terrain lose all
796 * their movement unless they have the BeachLander unit type flag.
797 * e.g. ground units moving from sea to land */
798 if (punit != NULL) {
799 return punit->moves_left;
800 } else {
801 /* Needs to be bigger than SINGLE_MOVE * move_rate * MAX(1, fuel)
802 * for the most mobile unit possible. */
803 return FC_INFINITY;
805 } else {
806 /* Disembarking from transport or leaving port.
807 * UTYF_IGTER units get move benefit. */
808 return (utype_has_flag(punittype, UTYF_IGTER)
809 ? MOVE_COST_IGTER : SINGLE_MOVE);
813 cost = tile_terrain(t2)->movement_cost * SINGLE_MOVE;
814 ri = restrict_infra(pplayer, t1, t2);
816 extra_type_list_iterate(pclass->cache.bonus_roads, pextra) {
817 struct road_type *proad = extra_road_get(pextra);
819 /* We check the destination tile first, as that's
820 * the end of move that determines the cost.
821 * If can avoid inner loop about integrating roads
822 * completely if the destination road has too high cost. */
824 if (cost > proad->move_cost
825 && (!ri || road_has_flag(proad, RF_UNRESTRICTED_INFRA))
826 && tile_has_extra(t2, pextra)) {
827 extra_type_list_iterate(proad->integrators, iextra) {
828 /* We have no unrestricted infra related check here,
829 * destination road is the one that counts. */
830 if (tile_has_extra(t1, iextra)
831 && is_native_extra_to_uclass(iextra, pclass)) {
832 if (proad->move_mode == RMM_FAST_ALWAYS) {
833 cost = proad->move_cost;
834 } else {
835 if (!cardinality_checked) {
836 cardinal_move = (ALL_DIRECTIONS_CARDINAL() || is_move_cardinal(t1, t2));
837 cardinality_checked = TRUE;
839 if (cardinal_move) {
840 cost = proad->move_cost;
841 } else {
842 switch (proad->move_mode) {
843 case RMM_CARDINAL:
844 break;
845 case RMM_RELAXED:
846 if (cost > proad->move_cost * 2) {
847 cardinal_between_iterate(t1, t2, between) {
848 if (tile_has_extra(between, pextra)
849 || (pextra != iextra && tile_has_extra(between, iextra))) {
850 /* 'pextra != iextra' is there just to avoid tile_has_extra()
851 * in by far more common case that 'pextra == iextra' */
852 /* TODO: Should we restrict this more?
853 * Should we check against enemy cities on between tile?
854 * Should we check against non-native terrain on between tile?
856 cost = proad->move_cost * 2;
858 } cardinal_between_iterate_end;
860 break;
861 case RMM_FAST_ALWAYS:
862 fc_assert(proad->move_mode != RMM_FAST_ALWAYS); /* Already handled above */
863 cost = proad->move_cost;
864 break;
869 } extra_type_list_iterate_end;
871 } extra_type_list_iterate_end;
873 /* UTYF_IGTER units have a maximum move cost per step. */
874 if (utype_has_flag(punittype, UTYF_IGTER) && MOVE_COST_IGTER < cost) {
875 cost = MOVE_COST_IGTER;
878 if (terrain_control.pythagorean_diagonal) {
879 if (!cardinality_checked) {
880 cardinal_move = (ALL_DIRECTIONS_CARDINAL() || is_move_cardinal(t1, t2));
882 if (!cardinal_move) {
883 return (int) (cost * 1.41421356f);
887 return cost;
890 /****************************************************************************
891 Returns TRUE if there is a restriction with regard to the infrastructure,
892 i.e. at least one of the tiles t1 and t2 is claimed by a unfriendly
893 nation. This means that one can not use of the infrastructure (road,
894 railroad) on this tile.
895 ****************************************************************************/
896 static bool restrict_infra(const struct player *pplayer, const struct tile *t1,
897 const struct tile *t2)
899 struct player *plr1 = tile_owner(t1), *plr2 = tile_owner(t2);
901 if (!pplayer || !game.info.restrictinfra) {
902 return FALSE;
905 if ((plr1 && pplayers_at_war(plr1, pplayer))
906 || (plr2 && pplayers_at_war(plr2, pplayer))) {
907 return TRUE;
910 return FALSE;
913 /***************************************************************
914 Are two tiles adjacent to each other.
915 ***************************************************************/
916 bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
918 return real_map_distance(tile0, tile1) == 1;
921 /***************************************************************
922 Are (x1,y1) and (x2,y2) really the same when adjusted?
923 This function might be necessary ALOT of places...
924 ***************************************************************/
925 bool same_pos(const struct tile *tile1, const struct tile *tile2)
927 fc_assert_ret_val(tile1 != NULL && tile2 != NULL, FALSE);
929 /* In case of virtual tile, tile1 can be different from tile2,
930 * but they have same index */
931 return (tile1->index == tile2->index);
934 /***************************************************************
935 Is given position real position
936 ***************************************************************/
937 bool is_real_map_pos(int x, int y)
939 return normalize_map_pos(&x, &y);
942 /**************************************************************************
943 Returns TRUE iff the map position is normal. "Normal" here means that
944 it is both a real/valid coordinate set and that the coordinates are in
945 their canonical/proper form. In plain English: the coordinates must be
946 on the map.
947 **************************************************************************/
948 bool is_normal_map_pos(int x, int y)
950 int nat_x, nat_y;
952 MAP_TO_NATIVE_POS(&nat_x, &nat_y, x, y);
953 return nat_x >= 0 && nat_x < wld.map.xsize && nat_y >= 0 && nat_y < wld.map.ysize;
956 /**************************************************************************
957 If the position is real, it will be normalized and TRUE will be returned.
958 If the position is unreal, it will be left unchanged and FALSE will be
959 returned.
961 Note, we need to leave x and y with sane values even in the unreal case.
962 Some callers may for instance call nearest_real_pos on these values.
963 **************************************************************************/
964 bool normalize_map_pos(int *x, int *y)
966 struct tile *ptile = map_pos_to_tile(*x, *y);
968 if (ptile) {
969 index_to_map_pos(x, y, tile_index(ptile));
970 return TRUE;
971 } else {
972 return FALSE;
976 /**************************************************************************
977 Twiddle *x and *y to point the the nearest real tile, and ensure that the
978 position is normalized.
979 **************************************************************************/
980 struct tile *nearest_real_tile(int x, int y)
982 int nat_x, nat_y;
984 MAP_TO_NATIVE_POS(&nat_x, &nat_y, x, y);
985 if (!current_topo_has_flag(TF_WRAPX)) {
986 nat_x = CLIP(0, nat_x, wld.map.xsize - 1);
988 if (!current_topo_has_flag(TF_WRAPY)) {
989 nat_y = CLIP(0, nat_y, wld.map.ysize - 1);
991 NATIVE_TO_MAP_POS(&x, &y, nat_x, nat_y);
993 return map_pos_to_tile(x, y);
996 /**************************************************************************
997 Returns the total number of (real) positions (or tiles) on the map.
998 **************************************************************************/
999 int map_num_tiles(void)
1001 return wld.map.xsize * wld.map.ysize;
1004 /****************************************************************************
1005 Finds the difference between the two (unnormalized) positions, in
1006 cartesian (map) coordinates. Most callers should use map_distance_vector
1007 instead.
1008 ****************************************************************************/
1009 void base_map_distance_vector(int *dx, int *dy,
1010 int x0dv, int y0dv, int x1dv, int y1dv)
1012 if (current_topo_has_flag(TF_WRAPX) || current_topo_has_flag(TF_WRAPY)) {
1013 /* Wrapping is done in native coordinates. */
1014 MAP_TO_NATIVE_POS(&x0dv, &y0dv, x0dv, y0dv);
1015 MAP_TO_NATIVE_POS(&x1dv, &y1dv, x1dv, y1dv);
1017 /* Find the "native" distance vector. This corresponds closely to the
1018 * map distance vector but is easier to wrap. */
1019 *dx = x1dv - x0dv;
1020 *dy = y1dv - y0dv;
1021 if (current_topo_has_flag(TF_WRAPX)) {
1022 /* Wrap dx to be in [-map.xsize/2, map.xsize/2). */
1023 *dx = FC_WRAP(*dx + wld.map.xsize / 2, wld.map.xsize) - wld.map.xsize / 2;
1025 if (current_topo_has_flag(TF_WRAPY)) {
1026 /* Wrap dy to be in [-map.ysize/2, map.ysize/2). */
1027 *dy = FC_WRAP(*dy + wld.map.ysize / 2, wld.map.ysize) - wld.map.ysize / 2;
1030 /* Convert the native delta vector back to a pair of map positions. */
1031 x1dv = x0dv + *dx;
1032 y1dv = y0dv + *dy;
1033 NATIVE_TO_MAP_POS(&x0dv, &y0dv, x0dv, y0dv);
1034 NATIVE_TO_MAP_POS(&x1dv, &y1dv, x1dv, y1dv);
1037 /* Find the final (map) vector. */
1038 *dx = x1dv - x0dv;
1039 *dy = y1dv - y0dv;
1042 /****************************************************************************
1043 Topology function to find the vector which has the minimum "real"
1044 distance between the map positions (x0, y0) and (x1, y1). If there is
1045 more than one vector with equal distance, no guarantee is made about
1046 which is found.
1048 Real distance is defined as the larger of the distances in the x and y
1049 direction; since units can travel diagonally this is the "real" distance
1050 a unit has to travel to get from point to point.
1052 (See also: real_map_distance, map_distance, and sq_map_distance.)
1054 With the standard topology the ranges of the return value are:
1055 -map.xsize/2 <= dx <= map.xsize/2
1056 -map.ysize < dy < map.ysize
1057 ****************************************************************************/
1058 void map_distance_vector(int *dx, int *dy,
1059 const struct tile *tile0,
1060 const struct tile *tile1)
1062 int tx0, ty0, tx1, ty1;
1064 index_to_map_pos(&tx0, &ty0, tile_index(tile0));
1065 index_to_map_pos(&tx1, &ty1, tile_index(tile1));
1066 base_map_distance_vector(dx, dy, tx0, ty0, tx1, ty1);
1069 /**************************************************************************
1070 Random neighbouring square.
1071 **************************************************************************/
1072 struct tile *rand_neighbour(const struct tile *ptile)
1074 int n;
1075 struct tile *tile1;
1078 * list of all 8 directions
1080 enum direction8 dirs[8] = {
1081 DIR8_NORTHWEST, DIR8_NORTH, DIR8_NORTHEAST, DIR8_WEST, DIR8_EAST,
1082 DIR8_SOUTHWEST, DIR8_SOUTH, DIR8_SOUTHEAST
1085 /* This clever loop by Trent Piepho will take no more than
1086 * 8 tries to find a valid direction. */
1087 for (n = 8; n > 0; n--) {
1088 enum direction8 choice = (enum direction8) fc_rand(n);
1090 /* this neighbour's OK */
1091 tile1 = mapstep(ptile, dirs[choice]);
1092 if (tile1) {
1093 return tile1;
1096 /* Choice was bad, so replace it with the last direction in the list.
1097 * On the next iteration, one fewer choices will remain. */
1098 dirs[choice] = dirs[n - 1];
1101 fc_assert(FALSE); /* Are we on a 1x1 map with no wrapping??? */
1102 return NULL;
1105 /**************************************************************************
1106 Random square anywhere on the map. Only normal positions (for which
1107 is_normal_map_pos returns true) will be found.
1108 **************************************************************************/
1109 struct tile *rand_map_pos(void)
1111 int nat_x = fc_rand(wld.map.xsize), nat_y = fc_rand(wld.map.ysize);
1113 return native_pos_to_tile(nat_x, nat_y);
1116 /**************************************************************************
1117 Give a random tile anywhere on the map for which the 'filter' function
1118 returns TRUE. Return FALSE if none can be found. The filter may be
1119 NULL if any position is okay; if non-NULL it shouldn't have any side
1120 effects.
1121 **************************************************************************/
1122 struct tile *rand_map_pos_filtered(void *data,
1123 bool (*filter)(const struct tile *ptile,
1124 const void *data))
1126 struct tile *ptile;
1127 int tries = 0;
1128 const int max_tries = MAP_INDEX_SIZE / ACTIVITY_FACTOR;
1130 /* First do a few quick checks to find a spot. The limit on number of
1131 * tries could use some tweaking. */
1132 do {
1133 ptile = wld.map.tiles + fc_rand(MAP_INDEX_SIZE);
1134 } while (filter && !filter(ptile, data) && ++tries < max_tries);
1136 /* If that fails, count all available spots and pick one.
1137 * Slow but reliable. */
1138 if (tries == max_tries) {
1139 int count = 0, *positions;
1141 positions = fc_calloc(MAP_INDEX_SIZE, sizeof(*positions));
1143 whole_map_iterate(&(wld.map), check_tile) {
1144 if (filter(check_tile, data)) {
1145 positions[count] = tile_index(check_tile);
1146 count++;
1148 } whole_map_iterate_end;
1150 if (count == 0) {
1151 ptile = NULL;
1152 } else {
1153 ptile = wld.map.tiles + positions[fc_rand(count)];
1156 FC_FREE(positions);
1158 return ptile;
1161 /**************************************************************************
1162 Return the debugging name of the direction.
1163 **************************************************************************/
1164 const char *dir_get_name(enum direction8 dir)
1166 /* a switch statement is used so the ordering can be changed easily */
1167 switch (dir) {
1168 case DIR8_NORTH:
1169 return "N";
1170 case DIR8_NORTHEAST:
1171 return "NE";
1172 case DIR8_EAST:
1173 return "E";
1174 case DIR8_SOUTHEAST:
1175 return "SE";
1176 case DIR8_SOUTH:
1177 return "S";
1178 case DIR8_SOUTHWEST:
1179 return "SW";
1180 case DIR8_WEST:
1181 return "W";
1182 case DIR8_NORTHWEST:
1183 return "NW";
1184 default:
1185 return "[Undef]";
1189 /**************************************************************************
1190 Returns the next direction clock-wise.
1191 **************************************************************************/
1192 enum direction8 dir_cw(enum direction8 dir)
1194 /* a switch statement is used so the ordering can be changed easily */
1195 switch (dir) {
1196 case DIR8_NORTH:
1197 return DIR8_NORTHEAST;
1198 case DIR8_NORTHEAST:
1199 return DIR8_EAST;
1200 case DIR8_EAST:
1201 return DIR8_SOUTHEAST;
1202 case DIR8_SOUTHEAST:
1203 return DIR8_SOUTH;
1204 case DIR8_SOUTH:
1205 return DIR8_SOUTHWEST;
1206 case DIR8_SOUTHWEST:
1207 return DIR8_WEST;
1208 case DIR8_WEST:
1209 return DIR8_NORTHWEST;
1210 case DIR8_NORTHWEST:
1211 return DIR8_NORTH;
1212 default:
1213 fc_assert(FALSE);
1214 return -1;
1218 /**************************************************************************
1219 Returns the next direction counter-clock-wise.
1220 **************************************************************************/
1221 enum direction8 dir_ccw(enum direction8 dir)
1223 /* a switch statement is used so the ordering can be changed easily */
1224 switch (dir) {
1225 case DIR8_NORTH:
1226 return DIR8_NORTHWEST;
1227 case DIR8_NORTHEAST:
1228 return DIR8_NORTH;
1229 case DIR8_EAST:
1230 return DIR8_NORTHEAST;
1231 case DIR8_SOUTHEAST:
1232 return DIR8_EAST;
1233 case DIR8_SOUTH:
1234 return DIR8_SOUTHEAST;
1235 case DIR8_SOUTHWEST:
1236 return DIR8_SOUTH;
1237 case DIR8_WEST:
1238 return DIR8_SOUTHWEST;
1239 case DIR8_NORTHWEST:
1240 return DIR8_WEST;
1241 default:
1242 fc_assert(FALSE);
1243 return -1;
1247 /**************************************************************************
1248 Returns TRUE iff the given direction is a valid one. Does not use
1249 value from the cache, but can be used to calculate the cache.
1250 **************************************************************************/
1251 static bool is_valid_dir_calculate(enum direction8 dir)
1253 switch (dir) {
1254 case DIR8_SOUTHEAST:
1255 case DIR8_NORTHWEST:
1256 /* These directions are invalid in hex topologies. */
1257 return !(current_topo_has_flag(TF_HEX) && !current_topo_has_flag(TF_ISO));
1258 case DIR8_NORTHEAST:
1259 case DIR8_SOUTHWEST:
1260 /* These directions are invalid in iso-hex topologies. */
1261 return !(current_topo_has_flag(TF_HEX) && current_topo_has_flag(TF_ISO));
1262 case DIR8_NORTH:
1263 case DIR8_EAST:
1264 case DIR8_SOUTH:
1265 case DIR8_WEST:
1266 return TRUE;
1267 default:
1268 return FALSE;
1272 /**************************************************************************
1273 Returns TRUE iff the given direction is a valid one.
1275 If the direction could be out of range you should use
1276 map_untrusted_dir_is_valid() in stead.
1277 **************************************************************************/
1278 bool is_valid_dir(enum direction8 dir)
1280 fc_assert_ret_val(dir <= direction8_invalid(), FALSE);
1282 return dir_validity[dir];
1285 /**************************************************************************
1286 Returns TRUE iff the given direction is a valid one.
1288 Doesn't trust the input. Can be used to validate a direction from an
1289 untrusted source.
1290 **************************************************************************/
1291 bool map_untrusted_dir_is_valid(enum direction8 dir)
1293 if (!direction8_is_valid(dir)) {
1294 /* Isn't even in range of direction8. */
1295 return FALSE;
1298 return is_valid_dir(dir);
1301 /**************************************************************************
1302 Returns TRUE iff the given direction is a cardinal one. Does not use
1303 value from the cache, but can be used to calculate the cache.
1305 Cardinal directions are those in which adjacent tiles share an edge not
1306 just a vertex.
1307 **************************************************************************/
1308 static bool is_cardinal_dir_calculate(enum direction8 dir)
1310 switch (dir) {
1311 case DIR8_NORTH:
1312 case DIR8_SOUTH:
1313 case DIR8_EAST:
1314 case DIR8_WEST:
1315 return TRUE;
1316 case DIR8_SOUTHEAST:
1317 case DIR8_NORTHWEST:
1318 /* These directions are cardinal in iso-hex topologies. */
1319 return current_topo_has_flag(TF_HEX) && current_topo_has_flag(TF_ISO);
1320 case DIR8_NORTHEAST:
1321 case DIR8_SOUTHWEST:
1322 /* These directions are cardinal in hexagonal topologies. */
1323 return current_topo_has_flag(TF_HEX) && !current_topo_has_flag(TF_ISO);
1325 return FALSE;
1328 /**************************************************************************
1329 Returns TRUE iff the given direction is a cardinal one.
1331 Cardinal directions are those in which adjacent tiles share an edge not
1332 just a vertex.
1333 **************************************************************************/
1334 bool is_cardinal_dir(enum direction8 dir)
1336 fc_assert_ret_val(dir <= direction8_invalid(), FALSE);
1338 return dir_cardinality[dir];
1341 /**************************************************************************
1342 Return true and sets dir to the direction of the step if (end_x,
1343 end_y) can be reached from (start_x, start_y) in one step. Return
1344 false otherwise (value of dir is unchanged in this case).
1345 **************************************************************************/
1346 bool base_get_direction_for_step(const struct tile *start_tile,
1347 const struct tile *end_tile,
1348 enum direction8 *dir)
1350 adjc_dir_iterate(start_tile, test_tile, test_dir) {
1351 if (same_pos(end_tile, test_tile)) {
1352 *dir = test_dir;
1353 return TRUE;
1355 } adjc_dir_iterate_end;
1357 return FALSE;
1360 /**************************************************************************
1361 Return the direction which is needed for a step on the map from
1362 (start_x, start_y) to (end_x, end_y).
1363 **************************************************************************/
1364 int get_direction_for_step(const struct tile *start_tile,
1365 const struct tile *end_tile)
1367 enum direction8 dir;
1369 if (base_get_direction_for_step(start_tile, end_tile, &dir)) {
1370 return dir;
1373 fc_assert(FALSE);
1374 return -1;
1377 /**************************************************************************
1378 Returns TRUE iff the move from the position (start_x,start_y) to
1379 (end_x,end_y) is a cardinal one.
1380 **************************************************************************/
1381 bool is_move_cardinal(const struct tile *start_tile,
1382 const struct tile *end_tile)
1384 cardinal_adjc_dir_iterate(start_tile, test_tile, test_dir) {
1385 if (same_pos(end_tile, test_tile)) {
1386 return TRUE;
1388 } cardinal_adjc_dir_iterate_end;
1390 return FALSE;
1393 /****************************************************************************
1394 A "SINGULAR" position is any map position that has an abnormal number of
1395 tiles in the radius of dist.
1397 (map_x, map_y) must be normalized.
1399 dist is the "real" map distance.
1400 ****************************************************************************/
1401 bool is_singular_tile(const struct tile *ptile, int dist)
1403 int tile_x, tile_y;
1405 index_to_map_pos(&tile_x, &tile_y, tile_index(ptile));
1406 do_in_natural_pos(ntl_x, ntl_y, tile_x, tile_y) {
1407 /* Iso-natural coordinates are doubled in scale. */
1408 dist *= MAP_IS_ISOMETRIC ? 2 : 1;
1410 return ((!current_topo_has_flag(TF_WRAPX)
1411 && (ntl_x < dist || ntl_x >= NATURAL_WIDTH - dist))
1412 || (!current_topo_has_flag(TF_WRAPY)
1413 && (ntl_y < dist || ntl_y >= NATURAL_HEIGHT - dist)));
1414 } do_in_natural_pos_end;
1418 /****************************************************************************
1419 Create a new, empty start position.
1420 ****************************************************************************/
1421 static struct startpos *startpos_new(struct tile *ptile)
1423 struct startpos *psp = fc_malloc(sizeof(*psp));
1425 psp->location = ptile;
1426 psp->exclude = FALSE;
1427 psp->nations = nation_hash_new();
1429 return psp;
1432 /****************************************************************************
1433 Free all memory allocated by the start position.
1434 ****************************************************************************/
1435 static void startpos_destroy(struct startpos *psp)
1437 fc_assert_ret(NULL != psp);
1438 nation_hash_destroy(psp->nations);
1439 free(psp);
1442 /****************************************************************************
1443 Returns the start position associated to the given ID.
1444 ****************************************************************************/
1445 struct startpos *map_startpos_by_number(int id)
1447 return map_startpos_get(index_to_tile(&(wld.map), id));
1450 /****************************************************************************
1451 Returns the unique ID number for this start position. This is just the
1452 tile index of the tile where this start position is located.
1453 ****************************************************************************/
1454 int startpos_number(const struct startpos *psp)
1456 fc_assert_ret_val(NULL != psp, -1);
1457 return tile_index(psp->location);
1460 /****************************************************************************
1461 Allow the nation to start at the start position.
1462 NB: in "excluding" mode, this remove the nation from the excluded list.
1463 ****************************************************************************/
1464 bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
1466 fc_assert_ret_val(NULL != psp, FALSE);
1467 fc_assert_ret_val(NULL != pnation, FALSE);
1469 if (0 == nation_hash_size(psp->nations) || !psp->exclude) {
1470 psp->exclude = FALSE; /* Disable "excluding" mode. */
1471 return nation_hash_insert(psp->nations, pnation, NULL);
1472 } else {
1473 return nation_hash_remove(psp->nations, pnation);
1477 /****************************************************************************
1478 Disallow the nation to start at the start position.
1479 NB: in "excluding" mode, this add the nation to the excluded list.
1480 ****************************************************************************/
1481 bool startpos_disallow(struct startpos *psp, struct nation_type *pnation)
1483 fc_assert_ret_val(NULL != psp, FALSE);
1484 fc_assert_ret_val(NULL != pnation, FALSE);
1486 if (0 == nation_hash_size(psp->nations) || psp->exclude) {
1487 psp->exclude = TRUE; /* Enable "excluding" mode. */
1488 return nation_hash_remove(psp->nations, pnation);
1489 } else {
1490 return nation_hash_insert(psp->nations, pnation, NULL);
1494 /****************************************************************************
1495 Returns the tile where this start position is located.
1496 ****************************************************************************/
1497 struct tile *startpos_tile(const struct startpos *psp)
1499 fc_assert_ret_val(NULL != psp, NULL);
1500 return psp->location;
1503 /****************************************************************************
1504 Returns TRUE if the given nation can start here.
1505 ****************************************************************************/
1506 bool startpos_nation_allowed(const struct startpos *psp,
1507 const struct nation_type *pnation)
1509 fc_assert_ret_val(NULL != psp, FALSE);
1510 fc_assert_ret_val(NULL != pnation, FALSE);
1511 return XOR(psp->exclude, nation_hash_lookup(psp->nations, pnation, NULL));
1514 /****************************************************************************
1515 Returns TRUE if any nation can start here.
1516 ****************************************************************************/
1517 bool startpos_allows_all(const struct startpos *psp)
1519 fc_assert_ret_val(NULL != psp, FALSE);
1520 return (0 == nation_hash_size(psp->nations));
1523 /****************************************************************************
1524 Fills the packet with all of the information at this start position.
1525 Returns TRUE if the packet can be sent.
1526 ****************************************************************************/
1527 bool startpos_pack(const struct startpos *psp,
1528 struct packet_edit_startpos_full *packet)
1530 fc_assert_ret_val(NULL != psp, FALSE);
1531 fc_assert_ret_val(NULL != packet, FALSE);
1533 packet->id = startpos_number(psp);
1534 packet->exclude = psp->exclude;
1535 BV_CLR_ALL(packet->nations);
1537 nation_hash_iterate(psp->nations, pnation) {
1538 BV_SET(packet->nations, nation_number(pnation));
1539 } nation_hash_iterate_end;
1540 return TRUE;
1543 /****************************************************************************
1544 Fills the start position with the nation information in the packet.
1545 Returns TRUE if the start position was changed.
1546 ****************************************************************************/
1547 bool startpos_unpack(struct startpos *psp,
1548 const struct packet_edit_startpos_full *packet)
1550 fc_assert_ret_val(NULL != psp, FALSE);
1551 fc_assert_ret_val(NULL != packet, FALSE);
1553 psp->exclude = packet->exclude;
1555 nation_hash_clear(psp->nations);
1556 if (!BV_ISSET_ANY(packet->nations)) {
1557 return TRUE;
1559 nations_iterate(pnation) {
1560 if (BV_ISSET(packet->nations, nation_number(pnation))) {
1561 nation_hash_insert(psp->nations, pnation, NULL);
1563 } nations_iterate_end;
1564 return TRUE;
1567 /****************************************************************************
1568 Returns TRUE if the nations returned by startpos_raw_nations()
1569 are actually excluded from the nations allowed to start at this position.
1571 FIXME: This function exposes the internal implementation and should be
1572 removed when no longer needed by the property editor system.
1573 ****************************************************************************/
1574 bool startpos_is_excluding(const struct startpos *psp)
1576 fc_assert_ret_val(NULL != psp, FALSE);
1577 return psp->exclude;
1580 /****************************************************************************
1581 Return a the nations hash, used for the property editor.
1583 FIXME: This function exposes the internal implementation and should be
1584 removed when no longer needed by the property editor system.
1585 ****************************************************************************/
1586 const struct nation_hash *startpos_raw_nations(const struct startpos *psp)
1588 fc_assert_ret_val(NULL != psp, FALSE);
1589 return psp->nations;
1592 /****************************************************************************
1593 Implementation of iterator 'sizeof' function.
1595 struct startpos_iter can be either a 'struct nation_hash_iter', a 'struct
1596 nation_iter' or 'struct startpos_iter'.
1597 ****************************************************************************/
1598 size_t startpos_iter_sizeof(void)
1600 return MAX(sizeof(struct startpos_iter) + nation_iter_sizeof()
1601 - sizeof(struct iterator), nation_hash_iter_sizeof());
1604 /****************************************************************************
1605 Implementation of iterator 'next' function.
1607 NB: This is only used for the case where 'exclude' is set in the start
1608 position.
1609 ****************************************************************************/
1610 static void startpos_exclude_iter_next(struct iterator *startpos_iter)
1612 struct startpos_iter *iter = STARTPOS_ITER(startpos_iter);
1614 do {
1615 iterator_next(&iter->nation_iter);
1616 } while (iterator_valid(&iter->nation_iter)
1617 || !nation_hash_lookup(iter->psp->nations,
1618 iterator_get(&iter->nation_iter), NULL));
1621 /****************************************************************************
1622 Implementation of iterator 'get' function. Returns a struct nation_type
1623 pointer.
1625 NB: This is only used for the case where 'exclude' is set in the start
1626 position.
1627 ****************************************************************************/
1628 static void *startpos_exclude_iter_get(const struct iterator *startpos_iter)
1630 struct startpos_iter *iter = STARTPOS_ITER(startpos_iter);
1631 return iterator_get(&iter->nation_iter);
1634 /****************************************************************************
1635 Implementation of iterator 'valid' function.
1636 ****************************************************************************/
1637 static bool startpos_exclude_iter_valid(const struct iterator *startpos_iter)
1639 struct startpos_iter *iter = STARTPOS_ITER(startpos_iter);
1640 return iterator_valid(&iter->nation_iter);
1643 /****************************************************************************
1644 Initialize and return an iterator for the nations at this start position.
1645 ****************************************************************************/
1646 struct iterator *startpos_iter_init(struct startpos_iter *iter,
1647 const struct startpos *psp)
1649 if (!psp) {
1650 return invalid_iter_init(ITERATOR(iter));
1653 if (startpos_allows_all(psp)) {
1654 return nation_iter_init((struct nation_iter *) iter);
1657 if (!psp->exclude) {
1658 return nation_hash_key_iter_init((struct nation_hash_iter *) iter,
1659 psp->nations);
1662 iter->vtable.next = startpos_exclude_iter_next;
1663 iter->vtable.get = startpos_exclude_iter_get;
1664 iter->vtable.valid = startpos_exclude_iter_valid;
1665 iter->psp = psp;
1666 (void) nation_iter_init((struct nation_iter *) &iter->nation_iter);
1668 return ITERATOR(iter);
1672 /****************************************************************************
1673 Is there start positions set for map
1674 ****************************************************************************/
1675 int map_startpos_count(void)
1677 if (NULL != wld.map.startpos_table) {
1678 return startpos_hash_size(wld.map.startpos_table);
1679 } else {
1680 return 0;
1684 /****************************************************************************
1685 Create a new start position at the given tile and return it. If a start
1686 position already exists there, it is first removed.
1687 ****************************************************************************/
1688 struct startpos *map_startpos_new(struct tile *ptile)
1690 struct startpos *psp;
1692 fc_assert_ret_val(NULL != ptile, NULL);
1693 fc_assert_ret_val(NULL != wld.map.startpos_table, NULL);
1695 psp = startpos_new(ptile);
1696 startpos_hash_replace(wld.map.startpos_table, tile_hash_key(ptile), psp);
1698 return psp;
1701 /****************************************************************************
1702 Returns the start position at the given tile, or NULL if none exists
1703 there.
1704 ****************************************************************************/
1705 struct startpos *map_startpos_get(const struct tile *ptile)
1707 struct startpos *psp;
1709 fc_assert_ret_val(NULL != ptile, NULL);
1710 fc_assert_ret_val(NULL != wld.map.startpos_table, NULL);
1712 startpos_hash_lookup(wld.map.startpos_table, tile_hash_key(ptile), &psp);
1714 return psp;
1717 /****************************************************************************
1718 Remove the start position at the given tile. Returns TRUE if the start
1719 position was removed.
1720 ****************************************************************************/
1721 bool map_startpos_remove(struct tile *ptile)
1723 fc_assert_ret_val(NULL != ptile, FALSE);
1724 fc_assert_ret_val(NULL != wld.map.startpos_table, FALSE);
1726 return startpos_hash_remove(wld.map.startpos_table, tile_hash_key(ptile));
1729 /****************************************************************************
1730 Implementation of iterator sizeof function.
1731 NB: map_sp_iter just wraps startpos_hash_iter.
1732 ****************************************************************************/
1733 size_t map_startpos_iter_sizeof(void)
1735 return startpos_hash_iter_sizeof();
1738 /****************************************************************************
1739 Implementation of iterator init function.
1740 NB: map_sp_iter just wraps startpos_hash_iter.
1741 ****************************************************************************/
1742 struct iterator *map_startpos_iter_init(struct map_startpos_iter *iter)
1744 return startpos_hash_value_iter_init((struct startpos_hash_iter *) iter,
1745 wld.map.startpos_table);
1748 /****************************************************************************
1749 Return random direction that is valid in current map.
1750 ****************************************************************************/
1751 enum direction8 rand_direction(void)
1753 return wld.map.valid_dirs[fc_rand(wld.map.num_valid_dirs)];
1757 /****************************************************************************
1758 Return direction that is opposite to given one.
1759 ****************************************************************************/
1760 enum direction8 opposite_direction(enum direction8 dir)
1762 return direction8_max() - dir;