Stop sharing requirement_unit_state_ereq().
[freeciv.git] / common / tile.c
blobb6fef3d0b23c7b2053bae5754c97a4d1b8b68a47
1 /***********************************************************************
2 Freeciv - Copyright (C) 2005 - The Freeciv Project
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
18 /* utility */
19 #include "bitvector.h"
20 #include "log.h"
21 #include "support.h"
23 /* common */
24 #include "fc_interface.h"
25 #include "game.h"
26 #include "map.h"
27 #include "movement.h"
28 #include "road.h"
29 #include "unit.h"
30 #include "unitlist.h"
32 #include "tile.h"
34 static bv_extras empty_extras;
36 #ifndef tile_index
37 /****************************************************************************
38 Return the tile index.
39 ****************************************************************************/
40 int tile_index(const struct tile *ptile)
42 return ptile->index;
44 #endif
46 #ifndef tile_owner
47 /****************************************************************************
48 Return the player who owns this tile (or NULL if none).
49 ****************************************************************************/
50 struct player *tile_owner(const struct tile *ptile)
52 return ptile->owner;
54 #endif
56 #ifndef tile_claimer
57 /****************************************************************************
58 Return the player who owns this tile (or NULL if none).
59 ****************************************************************************/
60 struct tile *tile_claimer(const struct tile *ptile)
62 return ptile->claimer;
64 #endif
66 /****************************************************************************
67 Set the owner of a tile (may be NULL).
68 ****************************************************************************/
69 void tile_set_owner(struct tile *ptile, struct player *pplayer,
70 struct tile *claimer)
72 if (BORDERS_DISABLED != game.info.borders) {
73 ptile->owner = pplayer;
74 ptile->claimer = claimer;
78 /****************************************************************************
79 Return the city on this tile (or NULL), checking for city center.
80 ****************************************************************************/
81 struct city *tile_city(const struct tile *ptile)
83 struct city *pcity = ptile->worked;
85 if (NULL != pcity && is_city_center(pcity, ptile)) {
86 return pcity;
88 return NULL;
91 #ifndef tile_worked
92 /****************************************************************************
93 Return any city working the specified tile (or NULL).
94 ****************************************************************************/
95 struct city *tile_worked(const struct tile *ptile)
97 return ptile->worked;
99 #endif
101 /****************************************************************************
102 Set the city/worker on the tile (may be NULL).
103 ****************************************************************************/
104 void tile_set_worked(struct tile *ptile, struct city *pcity)
106 ptile->worked = pcity;
109 #ifndef tile_terrain
110 /****************************************************************************
111 Return the terrain at the specified tile.
112 ****************************************************************************/
113 struct terrain *tile_terrain(const struct tile *ptile)
115 return ptile->terrain;
117 #endif
119 /****************************************************************************
120 Set the given terrain at the specified tile.
121 ****************************************************************************/
122 void tile_set_terrain(struct tile *ptile, struct terrain *pterrain)
124 /* The terrain change is valid if one of the following is TRUE:
125 * - pterrain is NULL (= unknown terrain)
126 * - ptile is a virtual tile
127 * - pterrain does not has the flag TER_NO_CITIES
128 * - there is no city on ptile
129 * - client may have had tile fogged and is receiving terrain change before
130 * city removal
131 * This should be read as: The terrain change is INVALID if a terrain with
132 * the flag TER_NO_CITIES is given for a real tile with a city (i.e. all
133 * check evaluate to TRUE). */
134 fc_assert_msg(NULL == pterrain
135 || !is_server()
136 || tile_virtual_check(ptile)
137 || !terrain_has_flag(pterrain, TER_NO_CITIES)
138 || NULL == tile_city(ptile),
139 "At (%d, %d), the terrain \"%s\" (nb %d) doesn't "
140 "support cities, whereas \"%s\" (nb %d) is built there.",
141 TILE_XY(ptile), terrain_rule_name(pterrain),
142 terrain_number(pterrain), city_name_get(tile_city(ptile)),
143 tile_city(ptile)->id);
145 ptile->terrain = pterrain;
146 if (ptile->resource != NULL) {
147 if (NULL != pterrain
148 && terrain_has_resource(pterrain, ptile->resource)) {
149 BV_SET(ptile->extras, extra_index(ptile->resource));
150 } else {
151 BV_CLR(ptile->extras, extra_index(ptile->resource));
156 /****************************************************************************
157 Returns a bit vector of the extras present at NULL tile.
158 ****************************************************************************/
159 const bv_extras *tile_extras_null(void)
161 static bool empty_cleared = FALSE;
163 if (!empty_cleared) {
164 BV_CLR_ALL(empty_extras);
165 empty_cleared = TRUE;
168 return &(empty_extras);
171 /****************************************************************************
172 Returns a bit vector of the extras present at the tile.
173 ****************************************************************************/
174 const bv_extras *tile_extras_safe(const struct tile *ptile)
176 if (!ptile) {
177 return tile_extras_null();
180 return &(ptile->extras);
183 /****************************************************************************
184 Adds base to tile.
185 FIXME: Should remove conflicting old base and return bool indicating that.
186 ****************************************************************************/
187 void tile_add_base(struct tile *ptile, const struct base_type *pbase)
189 tile_add_extra(ptile, base_extra_get(pbase));
192 /****************************************************************************
193 Removes base from tile if such exist
194 ****************************************************************************/
195 void tile_remove_base(struct tile *ptile, const struct base_type *pbase)
197 tile_remove_extra(ptile, base_extra_get(pbase));
200 /****************************************************************************
201 Check if tile contains base providing effect
202 ****************************************************************************/
203 bool tile_has_base_flag(const struct tile *ptile, enum base_flag_id flag)
205 extra_type_by_cause_iterate(EC_BASE, pextra) {
206 struct base_type *pbase = extra_base_get(pextra);
208 if (tile_has_extra(ptile, pextra) && base_has_flag(pbase, flag)) {
209 return TRUE;
211 } extra_type_by_cause_iterate_end;
213 return FALSE;
216 /****************************************************************************
217 Check if tile contains base providing effect for unit
218 ****************************************************************************/
219 bool tile_has_base_flag_for_unit(const struct tile *ptile,
220 const struct unit_type *punittype,
221 enum base_flag_id flag)
223 extra_type_by_cause_iterate(EC_BASE, pextra) {
224 struct base_type *pbase = extra_base_get(pextra);
226 if (tile_has_extra(ptile, pextra)
227 && base_has_flag_for_utype(pbase, flag, punittype)) {
228 return TRUE;
230 } extra_type_by_cause_iterate_end;
232 return FALSE;
235 /****************************************************************************
236 Check if tile contains base providing effect for unit
237 ****************************************************************************/
238 bool tile_has_claimable_base(const struct tile *ptile,
239 const struct unit_type *punittype)
241 extra_type_by_cause_iterate(EC_BASE, pextra) {
242 struct base_type *pbase = extra_base_get(pextra);
244 if (tile_has_extra(ptile, pextra)
245 && territory_claiming_base(pbase)
246 && is_native_extra_to_uclass(pextra, utype_class(punittype))) {
247 return TRUE;
249 } extra_type_by_cause_iterate_end;
251 return FALSE;
254 /****************************************************************************
255 Calculate defense bonus given for unit type by bases and roads
256 ****************************************************************************/
257 int tile_extras_defense_bonus(const struct tile *ptile,
258 const struct unit_type *punittype)
260 return tile_extras_class_defense_bonus(ptile, utype_class(punittype));
263 /****************************************************************************
264 Calculate defense bonus given for unit class by extras.
265 ****************************************************************************/
266 int tile_extras_class_defense_bonus(const struct tile *ptile,
267 const struct unit_class *pclass)
269 int natural_bonus = 0;
270 int fortification_bonus = 0;
271 int total_bonus;
273 extra_type_by_cause_iterate(EC_NATURAL_DEFENSIVE, pextra) {
274 if (tile_has_extra(ptile, pextra)
275 && is_native_extra_to_uclass(pextra, pclass)) {
276 natural_bonus += pextra->defense_bonus;
278 } extra_type_by_cause_iterate_end;
280 extra_type_by_cause_iterate(EC_DEFENSIVE, pextra) {
281 if (tile_has_extra(ptile, pextra)
282 && is_native_extra_to_uclass(pextra, pclass)) {
283 fortification_bonus += pextra->defense_bonus;
285 } extra_type_by_cause_iterate_end;
287 total_bonus = (100 + natural_bonus) * (100 + fortification_bonus) / 100 - 100;
289 return total_bonus;
292 /****************************************************************************
293 Calculate output increment given by roads
294 ****************************************************************************/
295 int tile_roads_output_incr(const struct tile *ptile, enum output_type_id o)
297 int const_incr = 0;
298 int incr = 0;
300 extra_type_by_cause_iterate(EC_ROAD, pextra) {
301 if (tile_has_extra(ptile, pextra)) {
302 struct road_type *proad = extra_road_get(pextra);
304 const_incr += proad->tile_incr_const[o];
305 incr += proad->tile_incr[o];
307 } extra_type_by_cause_iterate_end;
309 return const_incr + incr * tile_terrain(ptile)->road_output_incr_pct[o] / 100;
312 /****************************************************************************
313 Calculate output bonus given by roads
314 ****************************************************************************/
315 int tile_roads_output_bonus(const struct tile *ptile, enum output_type_id o)
317 int bonus = 0;
319 extra_type_by_cause_iterate(EC_ROAD, pextra) {
320 if (tile_has_extra(ptile, pextra)) {
321 struct road_type *proad = extra_road_get(pextra);
323 bonus += proad->tile_bonus[o];
325 } extra_type_by_cause_iterate_end;
327 return bonus;
330 /****************************************************************************
331 Check if tile contains refuel extra native for unit
332 ****************************************************************************/
333 bool tile_has_refuel_extra(const struct tile *ptile,
334 const struct unit_type *punittype)
336 extra_type_iterate(pextra) {
337 if (tile_has_extra(ptile, pextra)
338 && extra_has_flag(pextra, EF_REFUEL)
339 && is_native_extra_to_utype(pextra, punittype)) {
340 return TRUE;
342 } extra_type_iterate_end;
344 return FALSE;
347 /****************************************************************************
348 Check if tile contains base native for unit
349 ****************************************************************************/
350 bool tile_has_native_base(const struct tile *ptile,
351 const struct unit_type *punittype)
353 extra_type_by_cause_iterate(EC_BASE, pextra) {
354 if (tile_has_extra(ptile, pextra)
355 && is_native_extra_to_utype(pextra, punittype)) {
356 return TRUE;
358 } extra_type_by_cause_iterate_end;
360 return FALSE;
363 #ifndef tile_resource
364 /****************************************************************************
365 Return the resource at the specified tile.
366 ****************************************************************************/
367 const struct resource_type *tile_resource(const struct tile *ptile)
369 return ptile->resource;
371 #endif
373 /****************************************************************************
374 Set the given resource at the specified tile.
375 ****************************************************************************/
376 void tile_set_resource(struct tile *ptile, struct extra_type *presource)
378 if (presource == ptile->resource) {
379 return; /* No change */
382 if (ptile->resource != NULL) {
383 tile_remove_extra(ptile, ptile->resource);
385 if (presource != NULL) {
386 if (ptile->terrain && terrain_has_resource(ptile->terrain, presource)) {
387 tile_add_extra(ptile, presource);
391 ptile->resource = presource;
394 #ifndef tile_continent
395 /****************************************************************************
396 Return the continent ID of the tile. Typically land has a positive
397 continent number and ocean has a negative number; no tile should have
398 a 0 continent number.
399 ****************************************************************************/
400 Continent_id tile_continent(const struct tile *ptile)
402 return ptile->continent;
404 #endif
406 /****************************************************************************
407 Set the continent ID of the tile. See tile_continent.
408 ****************************************************************************/
409 void tile_set_continent(struct tile *ptile, Continent_id val)
411 ptile->continent = val;
414 /****************************************************************************
415 Return a known_type enumeration value for the tile.
417 Note that the client only has known data about its own player.
418 ****************************************************************************/
419 enum known_type tile_get_known(const struct tile *ptile,
420 const struct player *pplayer)
422 if (!dbv_isset(&pplayer->tile_known, tile_index(ptile))) {
423 return TILE_UNKNOWN;
424 } else if (!fc_funcs->player_tile_vision_get(ptile, pplayer, V_MAIN)) {
425 return TILE_KNOWN_UNSEEN;
426 } else {
427 return TILE_KNOWN_SEEN;
431 /**************************************************************************
432 Returns TRUE iff the target_tile is seen by pow_player.
433 **************************************************************************/
434 bool tile_is_seen(const struct tile *target_tile,
435 const struct player *pow_player)
437 return tile_get_known(target_tile, pow_player) == TILE_KNOWN_SEEN;
440 /****************************************************************************
441 Time to complete the given activity on the given tile.
442 ****************************************************************************/
443 int tile_activity_time(enum unit_activity activity, const struct tile *ptile,
444 struct extra_type *tgt)
446 struct terrain *pterrain = tile_terrain(ptile);
448 /* Make sure nobody uses old activities */
449 fc_assert_ret_val(activity != ACTIVITY_FORTRESS
450 && activity != ACTIVITY_AIRBASE, FC_INFINITY);
452 switch (activity) {
453 case ACTIVITY_POLLUTION:
454 case ACTIVITY_FALLOUT:
455 case ACTIVITY_PILLAGE:
456 return terrain_extra_removal_time(pterrain, activity, tgt) * ACTIVITY_FACTOR;
457 case ACTIVITY_TRANSFORM:
458 return pterrain->transform_time * ACTIVITY_FACTOR;
459 case ACTIVITY_IRRIGATE:
460 case ACTIVITY_MINE:
461 case ACTIVITY_BASE:
462 case ACTIVITY_GEN_ROAD:
463 return terrain_extra_build_time(pterrain, activity, tgt) * ACTIVITY_FACTOR;
464 default:
465 return 0;
469 /****************************************************************************
470 Create extra to tile.
471 ****************************************************************************/
472 static void tile_create_extra(struct tile *ptile, struct extra_type *pextra)
474 if (fc_funcs->create_extra != NULL) {
475 /* Assume callback calls tile_add_extra() itself. */
476 fc_funcs->create_extra(ptile, pextra, NULL);
477 } else {
478 tile_add_extra(ptile, pextra);
482 /****************************************************************************
483 Destroy extra from tile.
484 ****************************************************************************/
485 static void tile_destroy_extra(struct tile *ptile, struct extra_type *pextra)
487 if (fc_funcs->destroy_extra != NULL) {
488 /* Assume callback calls tile_remove_extra() itself. */
489 fc_funcs->destroy_extra(ptile, pextra);
490 } else {
491 tile_remove_extra(ptile, pextra);
495 /****************************************************************************
496 Change the terrain to the given type. This does secondary tile updates to
497 the tile (as will happen when mining/irrigation/transforming changes the
498 tile's terrain).
499 ****************************************************************************/
500 void tile_change_terrain(struct tile *ptile, struct terrain *pterrain)
502 tile_set_terrain(ptile, pterrain);
504 /* Remove unsupported extras */
505 extra_type_iterate(pextra) {
506 if (tile_has_extra(ptile, pextra)
507 && (!is_native_tile_to_extra(pextra, ptile)
508 || extra_has_flag(pextra, EF_TERR_CHANGE_REMOVES))) {
509 tile_destroy_extra(ptile, pextra);
511 } extra_type_iterate_end;
514 /****************************************************************************
515 Recursively add all extra dependencies to add given extra.
516 ****************************************************************************/
517 static bool add_recursive_extras(struct tile *ptile, struct extra_type *pextra,
518 int rec)
520 if (rec > MAX_EXTRA_TYPES) {
521 /* Infinite recursion */
522 return FALSE;
525 /* First place dependency extras */
526 extra_deps_iterate(&(pextra->reqs), pdep) {
527 if (!tile_has_extra(ptile, pdep)) {
528 add_recursive_extras(ptile, pdep, rec + 1);
530 } extra_deps_iterate_end;
532 /* Is tile native for extra after that? */
533 if (!is_native_tile_to_extra(pextra, ptile)) {
534 return FALSE;
537 tile_create_extra(ptile, pextra);
539 return TRUE;
542 /****************************************************************************
543 Recursively remove all extras depending on given extra.
544 ****************************************************************************/
545 static bool rm_recursive_extras(struct tile *ptile, struct extra_type *pextra,
546 int rec)
548 if (rec > MAX_EXTRA_TYPES) {
549 /* Infinite recursion */
550 return FALSE;
553 extra_type_iterate(pdepending) {
554 if (tile_has_extra(ptile, pdepending)) {
555 extra_deps_iterate(&(pdepending->reqs), pdep) {
556 if (pdep == pextra) {
557 /* Depends on what we are going to remove */
558 if (!rm_recursive_extras(ptile, pdepending, rec + 1)) {
559 return FALSE;
562 } extra_deps_iterate_end;
564 } extra_type_iterate_end;
566 tile_destroy_extra(ptile, pextra);
568 return TRUE;
571 /****************************************************************************
572 Add extra and adjust other extras accordingly.
574 If not all necessary adjustments can be done, returns FALSE.
575 When problem occurs, changes to tile extras are not reverted.
576 Pass virtual tile to the function if you are not sure it will success
577 and don't want extras adjusted at all in case of failure.
578 ****************************************************************************/
579 bool tile_extra_apply(struct tile *ptile, struct extra_type *tgt)
581 /* Add extra with its dependencies */
582 if (!add_recursive_extras(ptile, tgt, 0)) {
583 return FALSE;
586 /* Remove conflicting extras */
587 extra_type_iterate(pextra) {
588 if (tile_has_extra(ptile, pextra)
589 && !can_extras_coexist(pextra, tgt)) {
590 tile_destroy_extra(ptile, pextra);
592 } extra_type_iterate_end;
594 return TRUE;
597 /****************************************************************************
598 Remove extra and adjust other extras accordingly.
600 If not all necessary adjustments can be done, returns FALSE.
601 When problem occurs, changes to tile extras are not reverted.
602 Pass virtual tile to the function if you are not sure it will success
603 and don't want extras adjusted at all in case of failure.
604 ****************************************************************************/
605 bool tile_extra_rm_apply(struct tile *ptile, struct extra_type *tgt)
607 /* Remove extra with everything depending on it. */
608 if (!rm_recursive_extras(ptile, tgt, 0)) {
609 return FALSE;
612 return TRUE;
615 /****************************************************************************
616 Build irrigation on the tile. This may change the extras of the tile
617 or change the terrain type itself.
618 ****************************************************************************/
619 static void tile_irrigate(struct tile *ptile, struct extra_type *tgt)
621 struct terrain *pterrain = tile_terrain(ptile);
623 if (pterrain == pterrain->irrigation_result) {
624 /* Ideally activity should already been cancelled before NULL tgt
625 * gets this far, but it's possible that terrain got changed from
626 * one that gets transformed by irrigation (-> NULL tgt) to one
627 * that does not (-> NULL tgt illegal) since legality of the action
628 * was last checked */
629 if (tgt != NULL) {
630 tile_extra_apply(ptile, tgt);
632 } else if (pterrain->irrigation_result) {
633 tile_change_terrain(ptile, pterrain->irrigation_result);
637 /****************************************************************************
638 Build a mine on the tile. This may change the extras of the tile
639 or change the terrain type itself.
640 ****************************************************************************/
641 static void tile_mine(struct tile *ptile, struct extra_type *tgt)
643 struct terrain *pterrain = tile_terrain(ptile);
645 if (pterrain == pterrain->mining_result) {
646 /* Ideally activity should already been cancelled before NULL tgt
647 * gets this far, but it's possible that terrain got changed from
648 * one that gets transformed by mining (-> NULL tgt) to one
649 * that does not (-> NULL tgt illegal) since legality of the action
650 * was last checked */
651 if (tgt != NULL) {
652 tile_extra_apply(ptile, tgt);
654 } else if (pterrain->mining_result) {
655 tile_change_terrain(ptile, pterrain->mining_result);
659 /****************************************************************************
660 Transform (ACTIVITY_TRANSFORM) the tile. This usually changes the tile's
661 terrain type.
662 ****************************************************************************/
663 static void tile_transform(struct tile *ptile)
665 struct terrain *pterrain = tile_terrain(ptile);
667 if (pterrain->transform_result != T_NONE) {
668 tile_change_terrain(ptile, pterrain->transform_result);
672 /****************************************************************************
673 Apply an activity (Activity_type_id, e.g., ACTIVITY_TRANSFORM) to a tile.
674 Return false if there was a error or if the activity is not implemented
675 by this function.
676 ****************************************************************************/
677 bool tile_apply_activity(struct tile *ptile, Activity_type_id act,
678 struct extra_type *tgt)
680 /* FIXME: for irrigate, mine, and transform we always return TRUE
681 * even if the activity fails. */
682 switch(act) {
683 case ACTIVITY_MINE:
684 tile_mine(ptile, tgt);
685 return TRUE;
687 case ACTIVITY_IRRIGATE:
688 tile_irrigate(ptile, tgt);
689 return TRUE;
691 case ACTIVITY_TRANSFORM:
692 tile_transform(ptile);
693 return TRUE;
695 case ACTIVITY_OLD_ROAD:
696 case ACTIVITY_OLD_RAILROAD:
697 case ACTIVITY_FORTRESS:
698 case ACTIVITY_AIRBASE:
699 fc_assert(FALSE);
700 return FALSE;
702 case ACTIVITY_PILLAGE:
703 case ACTIVITY_BASE:
704 case ACTIVITY_GEN_ROAD:
705 case ACTIVITY_POLLUTION:
706 case ACTIVITY_FALLOUT:
707 /* do nothing - not implemented */
708 return FALSE;
710 case ACTIVITY_IDLE:
711 case ACTIVITY_FORTIFIED:
712 case ACTIVITY_SENTRY:
713 case ACTIVITY_GOTO:
714 case ACTIVITY_EXPLORE:
715 case ACTIVITY_CONVERT:
716 case ACTIVITY_UNKNOWN:
717 case ACTIVITY_FORTIFYING:
718 case ACTIVITY_PATROL_UNUSED:
719 case ACTIVITY_LAST:
720 /* do nothing - these activities have no effect
721 on terrain type or tile extras */
722 return FALSE;
724 fc_assert(FALSE);
725 return FALSE;
728 /****************************************************************************
729 Add one entry about pollution situation to buffer.
730 Return if there has been any pollution (even prior calling this)
731 ****************************************************************************/
732 static bool tile_info_pollution(char *buf, int bufsz,
733 const struct tile *ptile,
734 struct extra_type *pextra,
735 bool prevp, bool linebreak)
737 if (tile_has_visible_extra(ptile, pextra)) {
738 if (!prevp) {
739 if (linebreak) {
740 fc_strlcat(buf, "\n[", bufsz);
741 } else {
742 fc_strlcat(buf, " [", bufsz);
744 } else {
745 fc_strlcat(buf, "/", bufsz);
748 fc_strlcat(buf, extra_name_translation(pextra), bufsz);
750 return TRUE;
753 return prevp;
756 /****************************************************************************
757 Return a (static) string with tile name describing terrain and
758 extras of some categories.
759 If include_nuisances is set, pollution and nuclear fallout will be
760 ignored.
762 Examples:
763 "Hills"
764 "Hills (Coals)"
765 "Hills (Coals) [Pollution]"
766 ****************************************************************************/
767 const char *tile_get_info_text(const struct tile *ptile,
768 bool include_nuisances, int linebreaks)
770 static char s[256];
771 bool pollution;
772 bool lb = FALSE;
773 int bufsz = sizeof(s);
775 sz_strlcpy(s, terrain_name_translation(tile_terrain(ptile)));
776 if (linebreaks & TILE_LB_TERRAIN_RIVER) {
777 /* Linebreak needed before next text */
778 lb = TRUE;
781 extra_type_iterate(pextra) {
782 if (pextra->category == ECAT_NATURAL
783 && tile_has_visible_extra(ptile, pextra)) {
784 if (lb) {
785 sz_strlcat(s, "\n");
786 lb = FALSE;
787 } else {
788 sz_strlcat(s, "/");
790 sz_strlcat(s, extra_name_translation(pextra));
792 } extra_type_iterate_end;
793 if (linebreaks & TILE_LB_RIVER_RESOURCE) {
794 /* New linebreak requested */
795 lb = TRUE;
798 if (tile_resource_is_valid(ptile)) {
799 if (lb) {
800 sz_strlcat(s, "\n");
801 lb = FALSE;
802 } else {
803 sz_strlcat(s, " ");
805 cat_snprintf(s, sizeof(s), "(%s)",
806 extra_name_translation(ptile->resource));
808 if (linebreaks & TILE_LB_RESOURCE_POLL) {
809 /* New linebreak requested */
810 lb = TRUE;
813 if (include_nuisances) {
814 pollution = FALSE;
815 extra_type_iterate(pextra) {
816 if (pextra->category == ECAT_NUISANCE) {
817 pollution = tile_info_pollution(s, bufsz, ptile, pextra, pollution,
818 lb);
820 } extra_type_iterate_end;
821 if (pollution) {
822 sz_strlcat(s, "]");
826 return s;
829 /****************************************************************************
830 Returns TRUE if the given tile has a base of given type on it.
831 ****************************************************************************/
832 bool tile_has_base(const struct tile *ptile, const struct base_type *pbase)
834 return tile_has_extra(ptile, base_extra_get(pbase));
837 /****************************************************************************
838 Returns TRUE if the given tile has a road of given type on it.
839 ****************************************************************************/
840 bool tile_has_road(const struct tile *ptile, const struct road_type *proad)
842 return tile_has_extra(ptile, road_extra_get(proad));
845 /****************************************************************************
846 Tile has any river type
847 ****************************************************************************/
848 bool tile_has_river(const struct tile *ptile)
850 /* TODO: Have a list of rivers and iterate only that */
851 extra_type_by_cause_iterate(EC_ROAD, priver) {
852 if (tile_has_extra(ptile, priver)
853 && road_has_flag(extra_road_get(priver), RF_RIVER)) {
854 return TRUE;
856 } extra_type_by_cause_iterate_end;
858 return FALSE;
861 /****************************************************************************
862 Adds road to tile
863 ****************************************************************************/
864 void tile_add_road(struct tile *ptile, const struct road_type *proad)
866 if (proad != NULL) {
867 tile_add_extra(ptile, road_extra_get(proad));
871 /****************************************************************************
872 Removes road from tile if such exist
873 ****************************************************************************/
874 void tile_remove_road(struct tile *ptile, const struct road_type *proad)
876 if (proad != NULL) {
877 tile_remove_extra(ptile, road_extra_get(proad));
881 /****************************************************************************
882 Check if tile contains road providing effect
883 ****************************************************************************/
884 bool tile_has_road_flag(const struct tile *ptile, enum road_flag_id flag)
886 extra_type_by_cause_iterate(EC_ROAD, pextra) {
887 if (tile_has_extra(ptile, pextra)) {
888 struct road_type *proad = extra_road_get(pextra);
890 if (road_has_flag(proad, flag)) {
891 return TRUE;
894 } extra_type_by_cause_iterate_end;
896 return FALSE;
899 /****************************************************************************
900 Check if tile contains extra providing effect
901 ****************************************************************************/
902 bool tile_has_extra_flag(const struct tile *ptile, enum extra_flag_id flag)
904 extra_type_iterate(pextra) {
905 if (tile_has_extra(ptile, pextra)
906 && extra_has_flag(pextra, flag)) {
907 return TRUE;
909 } extra_type_iterate_end;
911 return FALSE;
914 /****************************************************************************
915 Returns TRUE if the given tile has a extra conflicting with the given one.
916 ****************************************************************************/
917 bool tile_has_conflicting_extra(const struct tile *ptile,
918 const struct extra_type *pextra)
920 extra_type_iterate(pconfl) {
921 if (BV_ISSET(pextra->conflicts, extra_index(pconfl))
922 && tile_has_extra(ptile, pconfl)) {
923 return TRUE;
925 } extra_type_iterate_end;
927 return FALSE;
930 /****************************************************************************
931 Returns TRUE if the given tile has a road of given type on it.
932 ****************************************************************************/
933 bool tile_has_visible_extra(const struct tile *ptile, const struct extra_type *pextra)
935 bool hidden = FALSE;
937 if (!BV_ISSET(ptile->extras, extra_index(pextra))) {
938 return FALSE;
941 extra_type_iterate(top) {
942 int topi = extra_index(top);
944 if (BV_ISSET(pextra->hidden_by, topi)
945 && BV_ISSET(ptile->extras, topi)) {
946 hidden = TRUE;
947 break;
949 } extra_type_iterate_end;
951 return !hidden;
954 /****************************************************************************
955 Has tile any extras of the specified cause.
956 ****************************************************************************/
957 bool tile_has_cause_extra(const struct tile *ptile, enum extra_cause cause)
959 extra_type_by_cause_iterate(cause, pextra) {
960 if (tile_has_extra(ptile, pextra)) {
961 return TRUE;
963 } extra_type_by_cause_iterate_end;
965 return FALSE;
968 /****************************************************************************
969 Adds extra to tile
970 ****************************************************************************/
971 void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
973 if (pextra != NULL) {
974 BV_SET(ptile->extras, extra_index(pextra));
978 /****************************************************************************
979 Removes extra from tile if such exist
980 ****************************************************************************/
981 void tile_remove_extra(struct tile *ptile, const struct extra_type *pextra)
983 if (pextra != NULL) {
984 BV_CLR(ptile->extras, extra_index(pextra));
988 /****************************************************************************
989 Returns a virtual tile. If ptile is given, the properties of this tile are
990 copied, else it is completely blank (except for the unit list
991 vtile->units, which is created for you). Be sure to call tile_virtual_free
992 on it when it is no longer needed.
993 ****************************************************************************/
994 struct tile *tile_virtual_new(const struct tile *ptile)
996 struct tile *vtile;
998 vtile = fc_calloc(1, sizeof(*vtile));
1000 /* initialise some values */
1001 vtile->index = -1;
1002 vtile->continent = -1;
1004 BV_CLR_ALL(vtile->extras);
1005 vtile->resource = NULL;
1006 vtile->terrain = NULL;
1007 vtile->units = unit_list_new();
1008 vtile->worked = NULL;
1009 vtile->owner = NULL;
1010 vtile->extras_owner = NULL;
1011 vtile->claimer = NULL;
1012 vtile->spec_sprite = NULL;
1014 if (ptile) {
1015 /* Used by is_city_center to give virtual tiles the output bonuses
1016 * they deserve. */
1017 vtile->index = tile_index(ptile);
1019 /* Copy all but the unit list. */
1020 extra_type_iterate(pextra) {
1021 if (BV_ISSET(ptile->extras, extra_number(pextra))) {
1022 BV_SET(vtile->extras, extra_number(pextra));
1024 } extra_type_iterate_end;
1026 vtile->resource = ptile->resource;
1027 vtile->terrain = ptile->terrain;
1028 vtile->worked = ptile->worked;
1029 vtile->owner = ptile->owner;
1030 vtile->extras_owner = ptile->extras_owner;
1031 vtile->claimer = ptile->claimer;
1032 vtile->spec_sprite = NULL;
1035 return vtile;
1038 /****************************************************************************
1039 Frees all memory used by the virtual tile, including freeing virtual
1040 units in the tile's unit list and the virtual city on this tile if one
1041 exists.
1043 NB: Do not call this on real tiles!
1044 ****************************************************************************/
1045 void tile_virtual_destroy(struct tile *vtile)
1047 struct city *vcity;
1049 if (!vtile) {
1050 return;
1053 if (vtile->units) {
1054 unit_list_iterate(vtile->units, vunit) {
1055 if (unit_is_virtual(vunit)) {
1056 unit_virtual_destroy(vunit);
1058 } unit_list_iterate_end;
1059 unit_list_destroy(vtile->units);
1060 vtile->units = NULL;
1063 vcity = tile_city(vtile);
1064 if (vcity) {
1065 if (city_is_virtual(vcity)) {
1066 destroy_city_virtual(vcity);
1068 tile_set_worked(vtile, NULL);
1071 free(vtile);
1074 /****************************************************************************
1075 Check if the given tile is a virtual one or not.
1076 ****************************************************************************/
1077 bool tile_virtual_check(struct tile *vtile)
1079 int tindex;
1081 if (!vtile || map_is_empty()) {
1082 return FALSE;
1085 tindex = tile_index(vtile);
1086 fc_assert_ret_val(0 <= tindex && tindex < map_num_tiles(), FALSE);
1088 return (vtile != wld.map.tiles + tindex);
1091 /****************************************************************************
1092 Returns key that should be used when storing tile to hash or when
1093 retrieving it from there.
1094 ****************************************************************************/
1095 void *tile_hash_key(const struct tile *ptile)
1097 void *key = 0; /* Initialize whole sizeof(void *) */
1099 key = FC_INT_TO_PTR(ptile->index);
1101 return key;
1104 /****************************************************************************
1105 Sets label for tile. Returns whether label changed.
1106 ****************************************************************************/
1107 bool tile_set_label(struct tile *ptile, const char *label)
1109 bool changed = FALSE;
1111 /* Handle empty label as NULL label */
1112 if (label != NULL && label[0] == '\0') {
1113 label = NULL;
1116 if (ptile->label != NULL) {
1117 if (label == NULL) {
1118 changed = TRUE;
1119 } else if (strcmp(ptile->label, label)) {
1120 changed = TRUE;
1122 FC_FREE(ptile->label);
1123 ptile->label = NULL;
1124 } else if (label != NULL) {
1125 changed = TRUE;
1128 if (label != NULL) {
1129 ptile->label = fc_strdup(label);
1132 return changed;