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)
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 ***********************************************************************/
15 #include <fc_config.h>
17 #include <string.h> /* strlen */
41 struct tile
*location
;
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
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.
73 * x1 = x + DIR_DX[dir];
74 * y1 = y + DIR_DY[dir];
75 * will give you the tile as shown below.
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
,
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
)) {
123 } extra_type_iterate_end
;
125 tile_virtual_destroy(missingset
);
128 BV_SET(pspresent
, extra_index(pextra
));
132 } extra_type_iterate_end
;
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
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;
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
;
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
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
);
275 fc_assert(i
== tiles
);
277 qsort(wld
.map
.iterate_outwards_indices
, tiles
,
278 sizeof(*wld
.map
.iterate_outwards_indices
), compare_iter_index
);
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
);
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)
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
;
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
;
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
)) {
374 index_to_map_pos(&tile_x
, &tile_y
, tile_index(ptile
));
375 DIRSTEP(dx
, dy
, dir
);
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
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
) {
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
) {
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. */
421 if (!wld
.map
.tiles
) {
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
);
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
) {
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
)
454 if (mindex
>= 0 && mindex
< MAP_INDEX_SIZE
) {
455 return imap
->tiles
+ mindex
;
457 /* Unwrapped index coordinates are impossible, so the best we can do is
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
;
476 FC_FREE(ptile
->label
);
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
));
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
)
524 /* it is possible that map_init was called but not map_allocate */
526 whole_map_iterate(fmap
, ptile
) {
528 } whole_map_iterate_end
;
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
);
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
;
573 /* Diagonal moves in this direction *are* allowed. */
574 return MAX(absdx
, absdy
);
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
;
584 /* Diagonal moves in this direction *are* allowed. */
585 return MAX(absdx
, absdy
);
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
);
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
)
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. */
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. */
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
)) {
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
) {
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
,
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
,
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
,
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
)
736 if (is_ocean(tile_terrain(ptile
))
737 && !is_ocean(pterrain
) && !can_reclaim_ocean(ptile
)) {
739 } else if (!is_ocean(tile_terrain(ptile
))
740 && is_ocean(pterrain
) && !can_channel_land(ptile
)) {
745 if (terrain_has_flag(tile_terrain(ptile
), TER_FROZEN
)
746 && !terrain_has_flag(pterrain
, TER_FROZEN
)
747 && !can_thaw_terrain(ptile
)) {
749 } else if (!terrain_has_flag(tile_terrain(ptile
), TER_FROZEN
)
750 && terrain_has_flag(pterrain
, TER_FROZEN
)
751 && !can_freeze_terrain(ptile
)) {
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
);
775 bool cardinality_checked
= FALSE
;
776 bool cardinal_move
BAD_HEURISTIC_INIT(FALSE
);
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. */
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 */
799 return punit
->moves_left
;
801 /* Needs to be bigger than SINGLE_MOVE * move_rate * MAX(1, fuel)
802 * for the most mobile unit possible. */
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
;
835 if (!cardinality_checked
) {
836 cardinal_move
= (ALL_DIRECTIONS_CARDINAL() || is_move_cardinal(t1
, t2
));
837 cardinality_checked
= TRUE
;
840 cost
= proad
->move_cost
;
842 switch (proad
->move_mode
) {
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
;
861 case RMM_FAST_ALWAYS
:
862 fc_assert(proad
->move_mode
!= RMM_FAST_ALWAYS
); /* Already handled above */
863 cost
= proad
->move_cost
;
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
);
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
) {
905 if ((plr1
&& pplayers_at_war(plr1
, pplayer
))
906 || (plr2
&& pplayers_at_war(plr2
, pplayer
))) {
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
947 **************************************************************************/
948 bool is_normal_map_pos(int x
, int 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
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
);
969 index_to_map_pos(x
, y
, tile_index(ptile
));
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
)
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
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. */
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. */
1033 NATIVE_TO_MAP_POS(&x0dv
, &y0dv
, x0dv
, y0dv
);
1034 NATIVE_TO_MAP_POS(&x1dv
, &y1dv
, x1dv
, y1dv
);
1037 /* Find the final (map) vector. */
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
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
)
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
]);
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??? */
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
1121 **************************************************************************/
1122 struct tile
*rand_map_pos_filtered(void *data
,
1123 bool (*filter
)(const struct tile
*ptile
,
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. */
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
);
1148 } whole_map_iterate_end
;
1153 ptile
= wld
.map
.tiles
+ positions
[fc_rand(count
)];
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 */
1170 case DIR8_NORTHEAST
:
1174 case DIR8_SOUTHEAST
:
1178 case DIR8_SOUTHWEST
:
1182 case DIR8_NORTHWEST
:
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 */
1197 return DIR8_NORTHEAST
;
1198 case DIR8_NORTHEAST
:
1201 return DIR8_SOUTHEAST
;
1202 case DIR8_SOUTHEAST
:
1205 return DIR8_SOUTHWEST
;
1206 case DIR8_SOUTHWEST
:
1209 return DIR8_NORTHWEST
;
1210 case DIR8_NORTHWEST
:
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 */
1226 return DIR8_NORTHWEST
;
1227 case DIR8_NORTHEAST
:
1230 return DIR8_NORTHEAST
;
1231 case DIR8_SOUTHEAST
:
1234 return DIR8_SOUTHEAST
;
1235 case DIR8_SOUTHWEST
:
1238 return DIR8_SOUTHWEST
;
1239 case DIR8_NORTHWEST
:
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
)
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
));
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
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. */
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
1307 **************************************************************************/
1308 static bool is_cardinal_dir_calculate(enum direction8 dir
)
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
);
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
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
)) {
1355 } adjc_dir_iterate_end
;
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
)) {
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
)) {
1388 } cardinal_adjc_dir_iterate_end
;
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
)
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();
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
);
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
);
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
);
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
;
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
)) {
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
;
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
1609 ****************************************************************************/
1610 static void startpos_exclude_iter_next(struct iterator
*startpos_iter
)
1612 struct startpos_iter
*iter
= STARTPOS_ITER(startpos_iter
);
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
1625 NB: This is only used for the case where 'exclude' is set in the start
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
)
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
,
1662 iter
->vtable
.next
= startpos_exclude_iter_next
;
1663 iter
->vtable
.get
= startpos_exclude_iter_get
;
1664 iter
->vtable
.valid
= startpos_exclude_iter_valid
;
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
);
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
);
1701 /****************************************************************************
1702 Returns the start position at the given tile, or NULL if none exists
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
);
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
;