1 /***********************************************************************
2 Freeciv - Copyright (C) 2003 - 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)
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>
20 #include "log.h" /* fc_assert */
21 #include "mem.h" /* free */
24 #include "string_vector.h"
36 static struct terrain civ_terrains
[MAX_NUM_TERRAINS
];
37 static struct resource civ_resources
[MAX_NUM_RESOURCES
];
38 static struct user_flag user_terrain_flags
[MAX_NUM_USER_TER_FLAGS
];
40 /****************************************************************************
41 Initialize terrain and resource structures.
42 ****************************************************************************/
43 void terrains_init(void)
47 for (i
= 0; i
< ARRAY_SIZE(civ_terrains
); i
++) {
48 /* Can't use terrain_by_number here because it does a bounds check. */
49 civ_terrains
[i
].item_number
= i
;
50 civ_terrains
[i
].rgb
= NULL
;
51 civ_terrains
[i
].animal
= NULL
;
53 for (i
= 0; i
< ARRAY_SIZE(civ_resources
); i
++) {
54 civ_resources
[i
].item_number
= i
;
58 /****************************************************************************
59 Free memory which is associated with terrain types.
60 ****************************************************************************/
61 void terrains_free(void)
63 terrain_type_iterate(pterrain
) {
64 if (NULL
!= pterrain
->helptext
) {
65 strvec_destroy(pterrain
->helptext
);
66 pterrain
->helptext
= NULL
;
68 if (pterrain
->resources
!= NULL
) {
69 /* Server allocates this on ruleset loading, client when
70 * ruleset packet is received. */
71 free(pterrain
->resources
);
72 pterrain
->resources
= NULL
;
74 if (pterrain
->rgb
!= NULL
) {
75 /* Server allocates this on ruleset loading, client when
76 * ruleset packet is received. */
77 rgbcolor_destroy(pterrain
->rgb
);
80 } terrain_type_iterate_end
;
83 /**************************************************************************
84 Return the first item of terrains.
85 **************************************************************************/
86 struct terrain
*terrain_array_first(void)
88 if (game
.control
.terrain_count
> 0) {
94 /**************************************************************************
95 Return the last item of terrains.
96 **************************************************************************/
97 const struct terrain
*terrain_array_last(void)
99 if (game
.control
.terrain_count
> 0) {
100 return &civ_terrains
[game
.control
.terrain_count
- 1];
105 /**************************************************************************
106 Return the number of terrains.
107 **************************************************************************/
108 Terrain_type_id
terrain_count(void)
110 return game
.control
.terrain_count
;
113 /**************************************************************************
114 Return the terrain identifier.
115 **************************************************************************/
116 char terrain_identifier(const struct terrain
*pterrain
)
118 fc_assert_ret_val(pterrain
, '\0');
119 return pterrain
->identifier
;
122 /**************************************************************************
123 Return the terrain index.
125 Currently same as terrain_number(), paired with terrain_count()
126 indicates use as an array index.
127 **************************************************************************/
128 Terrain_type_id
terrain_index(const struct terrain
*pterrain
)
130 fc_assert_ret_val(pterrain
, -1);
131 return pterrain
- civ_terrains
;
134 /**************************************************************************
135 Return the terrain index.
136 **************************************************************************/
137 Terrain_type_id
terrain_number(const struct terrain
*pterrain
)
139 fc_assert_ret_val(pterrain
, -1);
140 return pterrain
->item_number
;
143 /****************************************************************************
144 Return the terrain for the given terrain index.
145 ****************************************************************************/
146 struct terrain
*terrain_by_number(const Terrain_type_id type
)
148 if (type
< 0 || type
>= game
.control
.terrain_count
) {
149 /* This isn't an error; some T_UNKNOWN callers depend on it. */
152 return &civ_terrains
[type
];
155 /****************************************************************************
156 Return the terrain type matching the identifier, or T_UNKNOWN if none matches.
157 ****************************************************************************/
158 struct terrain
*terrain_by_identifier(const char identifier
)
160 if (TERRAIN_UNKNOWN_IDENTIFIER
== identifier
) {
163 terrain_type_iterate(pterrain
) {
164 if (pterrain
->identifier
== identifier
) {
167 } terrain_type_iterate_end
;
172 /****************************************************************************
173 Return the terrain type matching the name, or T_UNKNOWN if none matches.
174 ****************************************************************************/
175 struct terrain
*terrain_by_rule_name(const char *name
)
177 const char *qname
= Qn_(name
);
179 terrain_type_iterate(pterrain
) {
180 if (0 == fc_strcasecmp(terrain_rule_name(pterrain
), qname
)) {
183 } terrain_type_iterate_end
;
188 /****************************************************************************
189 Return the terrain type matching the name, or T_UNKNOWN if none matches.
190 ****************************************************************************/
191 struct terrain
*terrain_by_translated_name(const char *name
)
193 terrain_type_iterate(pterrain
) {
194 if (0 == strcmp(terrain_name_translation(pterrain
), name
)) {
197 } terrain_type_iterate_end
;
202 /****************************************************************************
203 Return terrain having the flag. If several terrains have the flag,
204 random one is returned.
205 ****************************************************************************/
206 struct terrain
*rand_terrain_by_flag(enum terrain_flag_id flag
)
209 struct terrain
*terr
= NULL
;
211 terrain_type_iterate(pterr
) {
212 if (terrain_has_flag(pterr
, flag
)) {
214 if (fc_rand(num
) == 1) {
218 } terrain_type_iterate_end
;
223 /****************************************************************************
224 Return the (translated) name of the terrain.
225 You don't have to free the return pointer.
226 ****************************************************************************/
227 const char *terrain_name_translation(const struct terrain
*pterrain
)
229 return name_translation_get(&pterrain
->name
);
232 /**************************************************************************
233 Return the (untranslated) rule name of the terrain.
234 You don't have to free the return pointer.
235 **************************************************************************/
236 const char *terrain_rule_name(const struct terrain
*pterrain
)
238 return rule_name_get(&pterrain
->name
);
241 /****************************************************************************
242 Check for resource in terrain resources list.
243 ****************************************************************************/
244 bool terrain_has_resource(const struct terrain
*pterrain
,
245 const struct resource
*presource
)
247 struct resource
**r
= pterrain
->resources
;
250 if (*r
== presource
) {
258 /**************************************************************************
259 Return the first item of resources.
260 **************************************************************************/
261 struct resource
*resource_array_first(void)
263 if (game
.control
.resource_count
> 0) {
264 return civ_resources
;
269 /**************************************************************************
270 Return the last item of resources.
271 **************************************************************************/
272 const struct resource
*resource_array_last(void)
274 if (game
.control
.resource_count
> 0) {
275 return &civ_resources
[game
.control
.resource_count
- 1];
280 /**************************************************************************
281 Return the resource count.
282 **************************************************************************/
283 Resource_type_id
resource_count(void)
285 return game
.control
.resource_count
;
288 /**************************************************************************
289 Return the resource index.
291 Currently same as resource_number(), paired with resource_count()
292 indicates use as an array index.
293 **************************************************************************/
294 Resource_type_id
resource_index(const struct resource
*presource
)
296 fc_assert_ret_val(NULL
!= presource
, -1);
297 return presource
- civ_resources
;
300 /**************************************************************************
301 Return the resource index.
302 **************************************************************************/
303 Resource_type_id
resource_number(const struct resource
*presource
)
305 fc_assert_ret_val(NULL
!= presource
, -1);
306 return presource
->item_number
;
309 /****************************************************************************
310 Return the resource for the given resource index.
311 ****************************************************************************/
312 struct resource
*resource_by_number(const Resource_type_id type
)
314 if (type
< 0 || type
>= game
.control
.resource_count
) {
315 /* This isn't an error; some callers depend on it. */
318 return &civ_resources
[type
];
321 /****************************************************************************
322 Return the resource type matching the identifier, or NULL when none matches.
323 ****************************************************************************/
324 struct resource
*resource_by_identifier(const char identifier
)
326 resource_type_iterate(presource
) {
327 if (presource
->identifier
== identifier
) {
330 } resource_type_iterate_end
;
335 /****************************************************************************
336 Return the resource type matching the name, or NULL when none matches.
337 ****************************************************************************/
338 struct resource
*resource_by_rule_name(const char *name
)
340 const char *qname
= Qn_(name
);
342 resource_type_iterate(presource
) {
343 if (0 == fc_strcasecmp(resource_rule_name(presource
), qname
)) {
346 } resource_type_iterate_end
;
351 /****************************************************************************
352 Return the (translated) name of the resource.
353 You don't have to free the return pointer.
354 ****************************************************************************/
355 const char *resource_name_translation(const struct resource
*presource
)
357 return name_translation_get(&presource
->name
);
360 /**************************************************************************
361 Return the (untranslated) rule name of the resource.
362 You don't have to free the return pointer.
363 **************************************************************************/
364 const char *resource_rule_name(const struct resource
*presource
)
366 return rule_name_get(&presource
->name
);
369 /****************************************************************************
370 This iterator behaves like adjc_iterate or cardinal_adjc_iterate depending
371 on the value of card_only.
372 ****************************************************************************/
373 #define variable_adjc_iterate(center_tile, _tile, card_only) \
375 enum direction8 *_tile##_list; \
379 _tile##_list = game.map.cardinal_dirs; \
380 _tile##_count = game.map.num_cardinal_dirs; \
382 _tile##_list = game.map.valid_dirs; \
383 _tile##_count = game.map.num_valid_dirs; \
385 adjc_dirlist_iterate(center_tile, _tile, _tile##_dir, \
386 _tile##_list, _tile##_count) {
388 #define variable_adjc_iterate_end \
389 } adjc_dirlist_iterate_end; \
392 /****************************************************************************
393 Returns TRUE iff any cardinally adjacent tile contains the given terrain.
394 ****************************************************************************/
395 bool is_terrain_card_near(const struct tile
*ptile
,
396 const struct terrain
*pterrain
,
403 cardinal_adjc_iterate(ptile
, adjc_tile
) {
404 if (tile_terrain(adjc_tile
) == pterrain
) {
407 } cardinal_adjc_iterate_end
;
409 return check_self
&& ptile
->terrain
== pterrain
;
412 /****************************************************************************
413 Returns TRUE iff any adjacent tile contains the given terrain.
414 ****************************************************************************/
415 bool is_terrain_near_tile(const struct tile
*ptile
,
416 const struct terrain
*pterrain
,
423 adjc_iterate(ptile
, adjc_tile
) {
424 if (tile_terrain(adjc_tile
) == pterrain
) {
429 return check_self
&& ptile
->terrain
== pterrain
;
432 /****************************************************************************
433 Return the number of adjacent tiles that have the given terrain.
434 ****************************************************************************/
435 int count_terrain_near_tile(const struct tile
*ptile
,
436 bool cardinal_only
, bool percentage
,
437 const struct terrain
*pterrain
)
439 int count
= 0, total
= 0;
441 variable_adjc_iterate(ptile
, adjc_tile
, cardinal_only
) {
442 if (pterrain
&& tile_terrain(adjc_tile
) == pterrain
) {
446 } variable_adjc_iterate_end
;
449 count
= count
* 100 / total
;
454 /****************************************************************************
455 Return the number of adjacent tiles that have the given terrain property.
456 ****************************************************************************/
457 int count_terrain_property_near_tile(const struct tile
*ptile
,
458 bool cardinal_only
, bool percentage
,
459 enum mapgen_terrain_property prop
)
461 int count
= 0, total
= 0;
463 variable_adjc_iterate(ptile
, adjc_tile
, cardinal_only
) {
464 struct terrain
*pterrain
= tile_terrain(adjc_tile
);
465 if (pterrain
->property
[prop
] > 0) {
469 } variable_adjc_iterate_end
;
472 count
= count
* 100 / total
;
477 /****************************************************************************
478 Returns TRUE iff any cardinally adjacent tile contains the given resource.
479 ****************************************************************************/
480 bool is_resource_card_near(const struct tile
*ptile
,
481 const struct resource
*pres
,
488 cardinal_adjc_iterate(ptile
, adjc_tile
) {
489 if (tile_resource(adjc_tile
) == pres
) {
492 } cardinal_adjc_iterate_end
;
494 return check_self
&& tile_resource(ptile
) == pres
;
497 /****************************************************************************
498 Returns TRUE iff any adjacent tile contains the given resource.
499 ****************************************************************************/
500 bool is_resource_near_tile(const struct tile
*ptile
,
501 const struct resource
*pres
,
508 adjc_iterate(ptile
, adjc_tile
) {
509 if (tile_resource(adjc_tile
) == pres
) {
514 return check_self
&& tile_resource(ptile
) == pres
;
517 /****************************************************************************
518 Returns TRUE iff any cardinally adjacent tile contains terrain with the
519 given flag (does not check ptile itself).
520 ****************************************************************************/
521 bool is_terrain_flag_card_near(const struct tile
*ptile
,
522 enum terrain_flag_id flag
)
524 cardinal_adjc_iterate(ptile
, adjc_tile
) {
525 struct terrain
* pterrain
= tile_terrain(adjc_tile
);
526 if (T_UNKNOWN
!= pterrain
527 && terrain_has_flag(pterrain
, flag
)) {
530 } cardinal_adjc_iterate_end
;
535 /****************************************************************************
536 Returns TRUE iff any adjacent tile contains terrain with the given flag
537 (does not check ptile itself).
538 ****************************************************************************/
539 bool is_terrain_flag_near_tile(const struct tile
*ptile
,
540 enum terrain_flag_id flag
)
542 adjc_iterate(ptile
, adjc_tile
) {
543 struct terrain
* pterrain
= tile_terrain(adjc_tile
);
544 if (T_UNKNOWN
!= pterrain
545 && terrain_has_flag(pterrain
, flag
)) {
553 /****************************************************************************
554 Return the number of adjacent tiles that have terrain with the given flag
555 (not including ptile itself).
556 ****************************************************************************/
557 int count_terrain_flag_near_tile(const struct tile
*ptile
,
558 bool cardinal_only
, bool percentage
,
559 enum terrain_flag_id flag
)
561 int count
= 0, total
= 0;
563 variable_adjc_iterate(ptile
, adjc_tile
, cardinal_only
) {
564 struct terrain
*pterrain
= tile_terrain(adjc_tile
);
565 if (T_UNKNOWN
!= pterrain
566 && terrain_has_flag(pterrain
, flag
)) {
570 } variable_adjc_iterate_end
;
573 count
= count
* 100 / total
;
578 /****************************************************************************
579 Return a (static) string with extra(s) name(s):
582 This only includes "infrastructure", i.e., man-made extras.
583 ****************************************************************************/
584 const char *get_infrastructure_text(bv_extras extras
)
592 extra_type_iterate(pextra
) {
593 if (pextra
->category
== ECAT_INFRA
594 && BV_ISSET(extras
, extra_index(pextra
))) {
597 extra_type_iterate(top
) {
598 int topi
= extra_index(top
);
600 if (BV_ISSET(pextra
->hidden_by
, topi
)
601 && BV_ISSET(extras
, topi
)) {
605 } extra_type_iterate_end
;
608 cat_snprintf(s
, sizeof(s
), "%s/", extra_name_translation(pextra
));
611 } extra_type_iterate_end
;
615 if (len
> 0 && *p
== '/') {
622 /****************************************************************************
623 Returns the highest-priority (best) infrastructure (man-made extra) to
624 be pillaged from the terrain set. May return NULL if nothing
626 ****************************************************************************/
627 struct extra_type
*get_preferred_pillage(bv_extras extras
)
629 extra_type_by_cause_iterate_rev(EC_IRRIGATION
, pextra
) {
630 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
633 } extra_type_by_cause_iterate_rev_end
;
635 extra_type_by_cause_iterate_rev(EC_MINE
, pextra
) {
636 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
639 } extra_type_by_cause_iterate_rev_end
;
641 extra_type_by_cause_iterate_rev(EC_BASE
, pextra
) {
642 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
645 } extra_type_by_cause_iterate_rev_end
;
647 extra_type_by_cause_iterate_rev(EC_ROAD
, pextra
) {
648 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
651 } extra_type_by_cause_iterate_rev_end
;
653 extra_type_by_cause_iterate_rev(EC_NONE
, pextra
) {
654 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
657 } extra_type_by_cause_iterate_rev_end
;
662 /****************************************************************************
663 What terrain class terrain type belongs to.
664 ****************************************************************************/
665 enum terrain_class
terrain_type_terrain_class(const struct terrain
*pterrain
)
667 return pterrain
->tclass
;
670 /****************************************************************************
671 Is there terrain of the given class cardinally near tile?
672 (Does not check ptile itself.)
673 ****************************************************************************/
674 bool is_terrain_class_card_near(const struct tile
*ptile
,
675 enum terrain_class tclass
)
677 cardinal_adjc_iterate(ptile
, adjc_tile
) {
678 struct terrain
* pterrain
= tile_terrain(adjc_tile
);
680 if (pterrain
!= T_UNKNOWN
) {
681 if (terrain_type_terrain_class(pterrain
) == tclass
) {
685 } cardinal_adjc_iterate_end
;
690 /****************************************************************************
691 Is there terrain of the given class near tile?
692 (Does not check ptile itself.)
693 ****************************************************************************/
694 bool is_terrain_class_near_tile(const struct tile
*ptile
,
695 enum terrain_class tclass
)
697 adjc_iterate(ptile
, adjc_tile
) {
698 struct terrain
* pterrain
= tile_terrain(adjc_tile
);
700 if (pterrain
!= T_UNKNOWN
) {
701 if (terrain_type_terrain_class(pterrain
) == tclass
) {
710 /****************************************************************************
711 Return the number of adjacent tiles that have given terrain class
712 (not including ptile itself).
713 ****************************************************************************/
714 int count_terrain_class_near_tile(const struct tile
*ptile
,
715 bool cardinal_only
, bool percentage
,
716 enum terrain_class tclass
)
718 int count
= 0, total
= 0;
720 variable_adjc_iterate(ptile
, adjc_tile
, cardinal_only
) {
721 struct terrain
*pterrain
= tile_terrain(adjc_tile
);
722 if (T_UNKNOWN
!= pterrain
723 && terrain_type_terrain_class(pterrain
) == tclass
) {
727 } variable_adjc_iterate_end
;
730 count
= count
* 100 / total
;
736 /****************************************************************************
737 Return the (translated) name of the given terrain class.
738 You don't have to free the return pointer.
739 ****************************************************************************/
740 const char *terrain_class_name_translation(enum terrain_class tclass
)
742 if (!terrain_class_is_valid(tclass
)) {
746 return _(terrain_class_name(tclass
));
749 /****************************************************************************
750 Can terrain support given infrastructure?
751 ****************************************************************************/
752 bool terrain_can_support_alteration(const struct terrain
*pterrain
,
753 enum terrain_alteration alter
)
756 case TA_CAN_IRRIGATE
:
757 return (pterrain
== pterrain
->irrigation_result
);
759 return (pterrain
== pterrain
->mining_result
);
761 return (pterrain
->road_time
> 0);
770 /****************************************************************************
771 Time to complete the extra building activity on the given terrain.
772 ****************************************************************************/
773 int terrain_extra_build_time(const struct terrain
*pterrain
,
774 enum unit_activity activity
,
775 const struct extra_type
*tgt
)
779 if (tgt
!= NULL
&& tgt
->build_time
!= 0) {
780 /* Extra specific build time */
781 return tgt
->build_time
;
787 factor
= tgt
->build_time_factor
;
790 /* Terrain and activity specific build time */
793 return pterrain
->base_time
* factor
;
794 case ACTIVITY_GEN_ROAD
:
795 return pterrain
->road_time
* factor
;
796 case ACTIVITY_IRRIGATE
:
797 return pterrain
->irrigation_time
* factor
;
799 return pterrain
->mining_time
* factor
;
806 /****************************************************************************
807 Time to complete the extra removal activity on the given terrain.
808 ****************************************************************************/
809 int terrain_extra_removal_time(const struct terrain
*pterrain
,
810 enum unit_activity activity
,
811 const struct extra_type
*tgt
)
815 if (tgt
!= NULL
&& tgt
->removal_time
!= 0) {
816 /* Extra specific removal time */
817 return tgt
->removal_time
;
823 factor
= tgt
->removal_time_factor
;
826 /* Terrain and activity specific removal time */
828 case ACTIVITY_POLLUTION
:
829 return pterrain
->clean_pollution_time
* factor
;
830 case ACTIVITY_FALLOUT
:
831 return pterrain
->clean_fallout_time
* factor
;
832 case ACTIVITY_PILLAGE
:
833 return pterrain
->pillage_time
* factor
;
840 /**************************************************************************
841 Initialize user terrain type flags.
842 **************************************************************************/
843 void user_terrain_flags_init(void)
847 for (i
= 0; i
< MAX_NUM_USER_TER_FLAGS
; i
++) {
848 user_flag_init(&user_terrain_flags
[i
]);
852 /***************************************************************
853 Frees the memory associated with all user terrain flags
854 ***************************************************************/
855 void user_terrain_flags_free(void)
859 for (i
= 0; i
< MAX_NUM_USER_TER_FLAGS
; i
++) {
860 user_flag_free(&user_terrain_flags
[i
]);
864 /**************************************************************************
865 Sets user defined name for terrain flag.
866 **************************************************************************/
867 void set_user_terrain_flag_name(enum terrain_flag_id id
, const char *name
,
870 int tfid
= id
- TER_USER_1
;
872 fc_assert_ret(id
>= TER_USER_1
&& id
<= TER_USER_LAST
);
874 if (user_terrain_flags
[tfid
].name
!= NULL
) {
875 FC_FREE(user_terrain_flags
[tfid
].name
);
876 user_terrain_flags
[tfid
].name
= NULL
;
879 if (name
&& name
[0] != '\0') {
880 user_terrain_flags
[tfid
].name
= fc_strdup(name
);
883 if (user_terrain_flags
[tfid
].helptxt
!= NULL
) {
884 FC_FREE(user_terrain_flags
[tfid
].helptxt
);
885 user_terrain_flags
[tfid
].helptxt
= NULL
;
888 if (helptxt
&& helptxt
[0] != '\0') {
889 user_terrain_flags
[tfid
].helptxt
= fc_strdup(helptxt
);
893 /**************************************************************************
894 Terrain flag name callback, called from specenum code.
895 **************************************************************************/
896 const char *terrain_flag_id_name_cb(enum terrain_flag_id flag
)
898 if (flag
< TER_USER_1
|| flag
> TER_USER_LAST
) {
902 return user_terrain_flags
[flag
-TER_USER_1
].name
;
905 /**************************************************************************
906 Return the (untranslated) helptxt of the user terrain flag.
907 **************************************************************************/
908 const char *terrain_flag_helptxt(enum terrain_flag_id id
)
910 fc_assert(id
>= TER_USER_1
&& id
<= TER_USER_LAST
);
912 return user_terrain_flags
[id
- TER_USER_1
].helptxt
;