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 user_flag user_terrain_flags
[MAX_NUM_USER_TER_FLAGS
];
39 /****************************************************************************
40 Initialize terrain and resource structures.
41 ****************************************************************************/
42 void terrains_init(void)
46 for (i
= 0; i
< ARRAY_SIZE(civ_terrains
); i
++) {
47 /* Can't use terrain_by_number here because it does a bounds check. */
48 civ_terrains
[i
].item_number
= i
;
49 civ_terrains
[i
].disabled
= FALSE
;
50 civ_terrains
[i
].rgb
= NULL
;
51 civ_terrains
[i
].animal
= NULL
;
55 /****************************************************************************
56 Free memory which is associated with terrain types.
57 ****************************************************************************/
58 void terrains_free(void)
60 terrain_type_iterate(pterrain
) {
61 if (NULL
!= pterrain
->helptext
) {
62 strvec_destroy(pterrain
->helptext
);
63 pterrain
->helptext
= NULL
;
65 if (pterrain
->resources
!= NULL
) {
66 /* Server allocates this on ruleset loading, client when
67 * ruleset packet is received. */
68 free(pterrain
->resources
);
69 pterrain
->resources
= NULL
;
71 if (pterrain
->rgb
!= NULL
) {
72 /* Server allocates this on ruleset loading, client when
73 * ruleset packet is received. */
74 rgbcolor_destroy(pterrain
->rgb
);
77 } terrain_type_iterate_end
;
80 /**************************************************************************
81 Return the first item of terrains.
82 **************************************************************************/
83 struct terrain
*terrain_array_first(void)
85 if (game
.control
.terrain_count
> 0) {
91 /**************************************************************************
92 Return the last item of terrains.
93 **************************************************************************/
94 const struct terrain
*terrain_array_last(void)
96 if (game
.control
.terrain_count
> 0) {
97 return &civ_terrains
[game
.control
.terrain_count
- 1];
102 /**************************************************************************
103 Return the number of terrains.
104 **************************************************************************/
105 Terrain_type_id
terrain_count(void)
107 return game
.control
.terrain_count
;
110 /**************************************************************************
111 Return the terrain identifier.
112 **************************************************************************/
113 char terrain_identifier(const struct terrain
*pterrain
)
115 fc_assert_ret_val(pterrain
, '\0');
116 return pterrain
->identifier
;
119 /**************************************************************************
120 Return the terrain index.
122 Currently same as terrain_number(), paired with terrain_count()
123 indicates use as an array index.
124 **************************************************************************/
125 Terrain_type_id
terrain_index(const struct terrain
*pterrain
)
127 fc_assert_ret_val(pterrain
, -1);
128 return pterrain
- civ_terrains
;
131 /**************************************************************************
132 Return the terrain index.
133 **************************************************************************/
134 Terrain_type_id
terrain_number(const struct terrain
*pterrain
)
136 fc_assert_ret_val(pterrain
, -1);
137 return pterrain
->item_number
;
140 /****************************************************************************
141 Return the terrain for the given terrain index.
142 ****************************************************************************/
143 struct terrain
*terrain_by_number(const Terrain_type_id type
)
145 if (type
< 0 || type
>= game
.control
.terrain_count
) {
146 /* This isn't an error; some T_UNKNOWN callers depend on it. */
149 return &civ_terrains
[type
];
152 /****************************************************************************
153 Return the terrain type matching the identifier, or T_UNKNOWN if none matches.
154 ****************************************************************************/
155 struct terrain
*terrain_by_identifier(const char identifier
)
157 if (TERRAIN_UNKNOWN_IDENTIFIER
== identifier
) {
160 terrain_type_iterate(pterrain
) {
161 if (pterrain
->identifier
== identifier
) {
164 } terrain_type_iterate_end
;
169 /****************************************************************************
170 Return the terrain type matching the name, or T_UNKNOWN if none matches.
171 ****************************************************************************/
172 struct terrain
*terrain_by_rule_name(const char *name
)
174 const char *qname
= Qn_(name
);
176 terrain_type_iterate(pterrain
) {
177 if (0 == fc_strcasecmp(terrain_rule_name(pterrain
), qname
)) {
180 } terrain_type_iterate_end
;
185 /****************************************************************************
186 Return the terrain type matching the name, or T_UNKNOWN if none matches.
187 ****************************************************************************/
188 struct terrain
*terrain_by_translated_name(const char *name
)
190 terrain_type_iterate(pterrain
) {
191 if (0 == strcmp(terrain_name_translation(pterrain
), name
)) {
194 } terrain_type_iterate_end
;
199 /****************************************************************************
200 Return terrain having the flag. If several terrains have the flag,
201 random one is returned.
202 ****************************************************************************/
203 struct terrain
*rand_terrain_by_flag(enum terrain_flag_id flag
)
206 struct terrain
*terr
= NULL
;
208 terrain_type_iterate(pterr
) {
209 if (terrain_has_flag(pterr
, flag
)) {
211 if (fc_rand(num
) == 1) {
215 } terrain_type_iterate_end
;
220 /****************************************************************************
221 Return the (translated) name of the terrain.
222 You don't have to free the return pointer.
223 ****************************************************************************/
224 const char *terrain_name_translation(const struct terrain
*pterrain
)
226 return name_translation_get(&pterrain
->name
);
229 /**************************************************************************
230 Return the (untranslated) rule name of the terrain.
231 You don't have to free the return pointer.
232 **************************************************************************/
233 const char *terrain_rule_name(const struct terrain
*pterrain
)
235 return rule_name_get(&pterrain
->name
);
238 /****************************************************************************
239 Check for resource in terrain resources list.
240 ****************************************************************************/
241 bool terrain_has_resource(const struct terrain
*pterrain
,
242 const struct extra_type
*presource
)
244 struct extra_type
**r
= pterrain
->resources
;
247 if (*r
== presource
) {
255 /****************************************************************************
256 Initialize resource_type structure.
257 ****************************************************************************/
258 struct resource_type
*resource_type_init(struct extra_type
*pextra
)
260 struct resource_type
*presource
;
262 presource
= fc_malloc(sizeof(*presource
));
264 pextra
->data
.resource
= presource
;
266 presource
->self
= pextra
;
271 /****************************************************************************
272 Free the memory associated with resource types
273 ****************************************************************************/
274 void resource_types_free(void)
276 /* Resource structure itself is freed as part of extras destruction. */
279 /**************************************************************************
280 Return extra that resource is.
281 **************************************************************************/
282 struct extra_type
*resource_extra_get(const struct resource_type
*presource
)
284 return presource
->self
;
287 /****************************************************************************
288 This iterator behaves like adjc_iterate or cardinal_adjc_iterate depending
289 on the value of card_only.
290 ****************************************************************************/
291 #define variable_adjc_iterate(nmap, center_tile, _tile, card_only) \
293 enum direction8 *_tile##_list; \
297 _tile##_list = wld.map.cardinal_dirs; \
298 _tile##_count = wld.map.num_cardinal_dirs; \
300 _tile##_list = wld.map.valid_dirs; \
301 _tile##_count = wld.map.num_valid_dirs; \
303 adjc_dirlist_iterate(nmap, center_tile, _tile, _tile##_dir, \
304 _tile##_list, _tile##_count) {
306 #define variable_adjc_iterate_end \
307 } adjc_dirlist_iterate_end; \
310 /****************************************************************************
311 Returns TRUE iff any cardinally adjacent tile contains the given terrain.
312 ****************************************************************************/
313 bool is_terrain_card_near(const struct tile
*ptile
,
314 const struct terrain
*pterrain
,
321 cardinal_adjc_iterate(&(wld
.map
), ptile
, adjc_tile
) {
322 if (tile_terrain(adjc_tile
) == pterrain
) {
325 } cardinal_adjc_iterate_end
;
327 return check_self
&& ptile
->terrain
== pterrain
;
330 /****************************************************************************
331 Returns TRUE iff any adjacent tile contains the given terrain.
332 ****************************************************************************/
333 bool is_terrain_near_tile(const struct tile
*ptile
,
334 const struct terrain
*pterrain
,
341 adjc_iterate(&(wld
.map
), ptile
, adjc_tile
) {
342 if (tile_terrain(adjc_tile
) == pterrain
) {
347 return check_self
&& ptile
->terrain
== pterrain
;
350 /****************************************************************************
351 Return the number of adjacent tiles that have the given terrain.
352 ****************************************************************************/
353 int count_terrain_near_tile(const struct tile
*ptile
,
354 bool cardinal_only
, bool percentage
,
355 const struct terrain
*pterrain
)
357 int count
= 0, total
= 0;
359 variable_adjc_iterate(&(wld
.map
), ptile
, adjc_tile
, cardinal_only
) {
360 if (pterrain
&& tile_terrain(adjc_tile
) == pterrain
) {
364 } variable_adjc_iterate_end
;
367 count
= count
* 100 / total
;
372 /****************************************************************************
373 Return the number of adjacent tiles that have the given terrain property.
374 ****************************************************************************/
375 int count_terrain_property_near_tile(const struct tile
*ptile
,
376 bool cardinal_only
, bool percentage
,
377 enum mapgen_terrain_property prop
)
379 int count
= 0, total
= 0;
381 variable_adjc_iterate(&(wld
.map
), ptile
, adjc_tile
, cardinal_only
) {
382 struct terrain
*pterrain
= tile_terrain(adjc_tile
);
384 if (pterrain
->property
[prop
] > 0) {
388 } variable_adjc_iterate_end
;
391 count
= count
* 100 / total
;
396 /****************************************************************************
397 Returns TRUE iff any cardinally adjacent tile contains the given resource.
398 ****************************************************************************/
399 bool is_resource_card_near(const struct tile
*ptile
,
400 const struct extra_type
*pres
,
407 cardinal_adjc_iterate(&(wld
.map
), ptile
, adjc_tile
) {
408 if (tile_resource(adjc_tile
) == pres
) {
411 } cardinal_adjc_iterate_end
;
413 return check_self
&& tile_resource(ptile
) == pres
;
416 /****************************************************************************
417 Returns TRUE iff any adjacent tile contains the given resource.
418 ****************************************************************************/
419 bool is_resource_near_tile(const struct tile
*ptile
,
420 const struct extra_type
*pres
,
427 adjc_iterate(&(wld
.map
), ptile
, adjc_tile
) {
428 if (tile_resource(adjc_tile
) == pres
) {
433 return check_self
&& tile_resource(ptile
) == pres
;
436 /****************************************************************************
437 Returns TRUE iff any cardinally adjacent tile contains terrain with the
438 given flag (does not check ptile itself).
439 ****************************************************************************/
440 bool is_terrain_flag_card_near(const struct tile
*ptile
,
441 enum terrain_flag_id flag
)
443 cardinal_adjc_iterate(&(wld
.map
), ptile
, adjc_tile
) {
444 struct terrain
* pterrain
= tile_terrain(adjc_tile
);
446 if (T_UNKNOWN
!= pterrain
447 && terrain_has_flag(pterrain
, flag
)) {
450 } cardinal_adjc_iterate_end
;
455 /****************************************************************************
456 Returns TRUE iff any adjacent tile contains terrain with the given flag
457 (does not check ptile itself).
458 ****************************************************************************/
459 bool is_terrain_flag_near_tile(const struct tile
*ptile
,
460 enum terrain_flag_id flag
)
462 adjc_iterate(&(wld
.map
), ptile
, adjc_tile
) {
463 struct terrain
* pterrain
= tile_terrain(adjc_tile
);
465 if (T_UNKNOWN
!= pterrain
466 && terrain_has_flag(pterrain
, flag
)) {
474 /****************************************************************************
475 Return the number of adjacent tiles that have terrain with the given flag
476 (not including ptile itself).
477 ****************************************************************************/
478 int count_terrain_flag_near_tile(const struct tile
*ptile
,
479 bool cardinal_only
, bool percentage
,
480 enum terrain_flag_id flag
)
482 int count
= 0, total
= 0;
484 variable_adjc_iterate(&(wld
.map
), ptile
, adjc_tile
, cardinal_only
) {
485 struct terrain
*pterrain
= tile_terrain(adjc_tile
);
487 if (T_UNKNOWN
!= pterrain
488 && terrain_has_flag(pterrain
, flag
)) {
492 } variable_adjc_iterate_end
;
495 count
= count
* 100 / total
;
500 /****************************************************************************
501 Return a (static) string with extra(s) name(s):
504 This only includes "infrastructure", i.e., man-made extras.
505 ****************************************************************************/
506 const char *get_infrastructure_text(bv_extras extras
)
514 extra_type_iterate(pextra
) {
515 if (pextra
->category
== ECAT_INFRA
516 && BV_ISSET(extras
, extra_index(pextra
))) {
519 extra_type_iterate(top
) {
520 int topi
= extra_index(top
);
522 if (BV_ISSET(pextra
->hidden_by
, topi
)
523 && BV_ISSET(extras
, topi
)) {
527 } extra_type_iterate_end
;
530 cat_snprintf(s
, sizeof(s
), "%s/", extra_name_translation(pextra
));
533 } extra_type_iterate_end
;
537 if (len
> 0 && *p
== '/') {
544 /****************************************************************************
545 Returns the highest-priority (best) infrastructure (man-made extra) to
546 be pillaged from the terrain set. May return NULL if nothing
548 ****************************************************************************/
549 struct extra_type
*get_preferred_pillage(bv_extras extras
)
551 extra_type_by_cause_iterate_rev(EC_IRRIGATION
, pextra
) {
552 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
555 } extra_type_by_cause_iterate_rev_end
;
557 extra_type_by_cause_iterate_rev(EC_MINE
, pextra
) {
558 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
561 } extra_type_by_cause_iterate_rev_end
;
563 extra_type_by_cause_iterate_rev(EC_BASE
, pextra
) {
564 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
567 } extra_type_by_cause_iterate_rev_end
;
569 extra_type_by_cause_iterate_rev(EC_ROAD
, pextra
) {
570 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
573 } extra_type_by_cause_iterate_rev_end
;
575 extra_type_by_cause_iterate_rev(EC_NONE
, pextra
) {
576 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
579 } extra_type_by_cause_iterate_rev_end
;
584 /****************************************************************************
585 What terrain class terrain type belongs to.
586 ****************************************************************************/
587 enum terrain_class
terrain_type_terrain_class(const struct terrain
*pterrain
)
589 return pterrain
->tclass
;
592 /****************************************************************************
593 Is there terrain of the given class cardinally near tile?
594 (Does not check ptile itself.)
595 ****************************************************************************/
596 bool is_terrain_class_card_near(const struct tile
*ptile
,
597 enum terrain_class tclass
)
599 cardinal_adjc_iterate(&(wld
.map
), ptile
, adjc_tile
) {
600 struct terrain
* pterrain
= tile_terrain(adjc_tile
);
602 if (pterrain
!= T_UNKNOWN
) {
603 if (terrain_type_terrain_class(pterrain
) == tclass
) {
607 } cardinal_adjc_iterate_end
;
612 /****************************************************************************
613 Is there terrain of the given class near tile?
614 (Does not check ptile itself.)
615 ****************************************************************************/
616 bool is_terrain_class_near_tile(const struct tile
*ptile
,
617 enum terrain_class tclass
)
619 adjc_iterate(&(wld
.map
), ptile
, adjc_tile
) {
620 struct terrain
* pterrain
= tile_terrain(adjc_tile
);
622 if (pterrain
!= T_UNKNOWN
) {
623 if (terrain_type_terrain_class(pterrain
) == tclass
) {
632 /****************************************************************************
633 Return the number of adjacent tiles that have given terrain class
634 (not including ptile itself).
635 ****************************************************************************/
636 int count_terrain_class_near_tile(const struct tile
*ptile
,
637 bool cardinal_only
, bool percentage
,
638 enum terrain_class tclass
)
640 int count
= 0, total
= 0;
642 variable_adjc_iterate(&(wld
.map
), ptile
, adjc_tile
, cardinal_only
) {
643 struct terrain
*pterrain
= tile_terrain(adjc_tile
);
645 if (T_UNKNOWN
!= pterrain
646 && terrain_type_terrain_class(pterrain
) == tclass
) {
650 } variable_adjc_iterate_end
;
653 count
= count
* 100 / total
;
659 /****************************************************************************
660 Return the (translated) name of the given terrain class.
661 You don't have to free the return pointer.
662 ****************************************************************************/
663 const char *terrain_class_name_translation(enum terrain_class tclass
)
665 if (!terrain_class_is_valid(tclass
)) {
669 return _(terrain_class_name(tclass
));
672 /****************************************************************************
673 Can terrain support given infrastructure?
674 ****************************************************************************/
675 bool terrain_can_support_alteration(const struct terrain
*pterrain
,
676 enum terrain_alteration alter
)
679 case TA_CAN_IRRIGATE
:
680 return (pterrain
== pterrain
->irrigation_result
);
682 return (pterrain
== pterrain
->mining_result
);
684 return (pterrain
->road_time
> 0);
693 /****************************************************************************
694 Time to complete the extra building activity on the given terrain.
695 ****************************************************************************/
696 int terrain_extra_build_time(const struct terrain
*pterrain
,
697 enum unit_activity activity
,
698 const struct extra_type
*tgt
)
702 if (tgt
!= NULL
&& tgt
->build_time
!= 0) {
703 /* Extra specific build time */
704 return tgt
->build_time
;
710 factor
= tgt
->build_time_factor
;
713 /* Terrain and activity specific build time */
716 return pterrain
->base_time
* factor
;
717 case ACTIVITY_GEN_ROAD
:
718 return pterrain
->road_time
* factor
;
719 case ACTIVITY_IRRIGATE
:
720 return pterrain
->irrigation_time
* factor
;
722 return pterrain
->mining_time
* factor
;
729 /****************************************************************************
730 Time to complete the extra removal activity on the given terrain.
731 ****************************************************************************/
732 int terrain_extra_removal_time(const struct terrain
*pterrain
,
733 enum unit_activity activity
,
734 const struct extra_type
*tgt
)
738 if (tgt
!= NULL
&& tgt
->removal_time
!= 0) {
739 /* Extra specific removal time */
740 return tgt
->removal_time
;
746 factor
= tgt
->removal_time_factor
;
749 /* Terrain and activity specific removal time */
751 case ACTIVITY_POLLUTION
:
752 return pterrain
->clean_pollution_time
* factor
;
753 case ACTIVITY_FALLOUT
:
754 return pterrain
->clean_fallout_time
* factor
;
755 case ACTIVITY_PILLAGE
:
756 return pterrain
->pillage_time
* factor
;
763 /**************************************************************************
764 Initialize user terrain type flags.
765 **************************************************************************/
766 void user_terrain_flags_init(void)
770 for (i
= 0; i
< MAX_NUM_USER_TER_FLAGS
; i
++) {
771 user_flag_init(&user_terrain_flags
[i
]);
775 /***************************************************************
776 Frees the memory associated with all user terrain flags
777 ***************************************************************/
778 void user_terrain_flags_free(void)
782 for (i
= 0; i
< MAX_NUM_USER_TER_FLAGS
; i
++) {
783 user_flag_free(&user_terrain_flags
[i
]);
787 /**************************************************************************
788 Sets user defined name for terrain flag.
789 **************************************************************************/
790 void set_user_terrain_flag_name(enum terrain_flag_id id
, const char *name
,
793 int tfid
= id
- TER_USER_1
;
795 fc_assert_ret(id
>= TER_USER_1
&& id
<= TER_USER_LAST
);
797 if (user_terrain_flags
[tfid
].name
!= NULL
) {
798 FC_FREE(user_terrain_flags
[tfid
].name
);
799 user_terrain_flags
[tfid
].name
= NULL
;
802 if (name
&& name
[0] != '\0') {
803 user_terrain_flags
[tfid
].name
= fc_strdup(name
);
806 if (user_terrain_flags
[tfid
].helptxt
!= NULL
) {
807 FC_FREE(user_terrain_flags
[tfid
].helptxt
);
808 user_terrain_flags
[tfid
].helptxt
= NULL
;
811 if (helptxt
&& helptxt
[0] != '\0') {
812 user_terrain_flags
[tfid
].helptxt
= fc_strdup(helptxt
);
816 /**************************************************************************
817 Terrain flag name callback, called from specenum code.
818 **************************************************************************/
819 const char *terrain_flag_id_name_cb(enum terrain_flag_id flag
)
821 if (flag
< TER_USER_1
|| flag
> TER_USER_LAST
) {
825 return user_terrain_flags
[flag
-TER_USER_1
].name
;
828 /**************************************************************************
829 Return the (untranslated) helptxt of the user terrain flag.
830 **************************************************************************/
831 const char *terrain_flag_helptxt(enum terrain_flag_id id
)
833 fc_assert(id
>= TER_USER_1
&& id
<= TER_USER_LAST
);
835 return user_terrain_flags
[id
- TER_USER_1
].helptxt
;