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(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(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(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(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(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(ptile
, adjc_tile
, cardinal_only
) {
382 struct terrain
*pterrain
= tile_terrain(adjc_tile
);
383 if (pterrain
->property
[prop
] > 0) {
387 } variable_adjc_iterate_end
;
390 count
= count
* 100 / total
;
395 /****************************************************************************
396 Returns TRUE iff any cardinally adjacent tile contains the given resource.
397 ****************************************************************************/
398 bool is_resource_card_near(const struct tile
*ptile
,
399 const struct extra_type
*pres
,
406 cardinal_adjc_iterate(ptile
, adjc_tile
) {
407 if (tile_resource(adjc_tile
) == pres
) {
410 } cardinal_adjc_iterate_end
;
412 return check_self
&& tile_resource(ptile
) == pres
;
415 /****************************************************************************
416 Returns TRUE iff any adjacent tile contains the given resource.
417 ****************************************************************************/
418 bool is_resource_near_tile(const struct tile
*ptile
,
419 const struct extra_type
*pres
,
426 adjc_iterate(ptile
, adjc_tile
) {
427 if (tile_resource(adjc_tile
) == pres
) {
432 return check_self
&& tile_resource(ptile
) == pres
;
435 /****************************************************************************
436 Returns TRUE iff any cardinally adjacent tile contains terrain with the
437 given flag (does not check ptile itself).
438 ****************************************************************************/
439 bool is_terrain_flag_card_near(const struct tile
*ptile
,
440 enum terrain_flag_id flag
)
442 cardinal_adjc_iterate(ptile
, adjc_tile
) {
443 struct terrain
* pterrain
= tile_terrain(adjc_tile
);
444 if (T_UNKNOWN
!= pterrain
445 && terrain_has_flag(pterrain
, flag
)) {
448 } cardinal_adjc_iterate_end
;
453 /****************************************************************************
454 Returns TRUE iff any adjacent tile contains terrain with the given flag
455 (does not check ptile itself).
456 ****************************************************************************/
457 bool is_terrain_flag_near_tile(const struct tile
*ptile
,
458 enum terrain_flag_id flag
)
460 adjc_iterate(ptile
, adjc_tile
) {
461 struct terrain
* pterrain
= tile_terrain(adjc_tile
);
462 if (T_UNKNOWN
!= pterrain
463 && terrain_has_flag(pterrain
, flag
)) {
471 /****************************************************************************
472 Return the number of adjacent tiles that have terrain with the given flag
473 (not including ptile itself).
474 ****************************************************************************/
475 int count_terrain_flag_near_tile(const struct tile
*ptile
,
476 bool cardinal_only
, bool percentage
,
477 enum terrain_flag_id flag
)
479 int count
= 0, total
= 0;
481 variable_adjc_iterate(ptile
, adjc_tile
, cardinal_only
) {
482 struct terrain
*pterrain
= tile_terrain(adjc_tile
);
483 if (T_UNKNOWN
!= pterrain
484 && terrain_has_flag(pterrain
, flag
)) {
488 } variable_adjc_iterate_end
;
491 count
= count
* 100 / total
;
496 /****************************************************************************
497 Return a (static) string with extra(s) name(s):
500 This only includes "infrastructure", i.e., man-made extras.
501 ****************************************************************************/
502 const char *get_infrastructure_text(bv_extras extras
)
510 extra_type_iterate(pextra
) {
511 if (pextra
->category
== ECAT_INFRA
512 && BV_ISSET(extras
, extra_index(pextra
))) {
515 extra_type_iterate(top
) {
516 int topi
= extra_index(top
);
518 if (BV_ISSET(pextra
->hidden_by
, topi
)
519 && BV_ISSET(extras
, topi
)) {
523 } extra_type_iterate_end
;
526 cat_snprintf(s
, sizeof(s
), "%s/", extra_name_translation(pextra
));
529 } extra_type_iterate_end
;
533 if (len
> 0 && *p
== '/') {
540 /****************************************************************************
541 Returns the highest-priority (best) infrastructure (man-made extra) to
542 be pillaged from the terrain set. May return NULL if nothing
544 ****************************************************************************/
545 struct extra_type
*get_preferred_pillage(bv_extras extras
)
547 extra_type_by_cause_iterate_rev(EC_IRRIGATION
, pextra
) {
548 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
551 } extra_type_by_cause_iterate_rev_end
;
553 extra_type_by_cause_iterate_rev(EC_MINE
, pextra
) {
554 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
557 } extra_type_by_cause_iterate_rev_end
;
559 extra_type_by_cause_iterate_rev(EC_BASE
, pextra
) {
560 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
563 } extra_type_by_cause_iterate_rev_end
;
565 extra_type_by_cause_iterate_rev(EC_ROAD
, pextra
) {
566 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
569 } extra_type_by_cause_iterate_rev_end
;
571 extra_type_by_cause_iterate_rev(EC_NONE
, pextra
) {
572 if (is_extra_removed_by(pextra
, ERM_PILLAGE
) && BV_ISSET(extras
, extra_index(pextra
))) {
575 } extra_type_by_cause_iterate_rev_end
;
580 /****************************************************************************
581 What terrain class terrain type belongs to.
582 ****************************************************************************/
583 enum terrain_class
terrain_type_terrain_class(const struct terrain
*pterrain
)
585 return pterrain
->tclass
;
588 /****************************************************************************
589 Is there terrain of the given class cardinally near tile?
590 (Does not check ptile itself.)
591 ****************************************************************************/
592 bool is_terrain_class_card_near(const struct tile
*ptile
,
593 enum terrain_class tclass
)
595 cardinal_adjc_iterate(ptile
, adjc_tile
) {
596 struct terrain
* pterrain
= tile_terrain(adjc_tile
);
598 if (pterrain
!= T_UNKNOWN
) {
599 if (terrain_type_terrain_class(pterrain
) == tclass
) {
603 } cardinal_adjc_iterate_end
;
608 /****************************************************************************
609 Is there terrain of the given class near tile?
610 (Does not check ptile itself.)
611 ****************************************************************************/
612 bool is_terrain_class_near_tile(const struct tile
*ptile
,
613 enum terrain_class tclass
)
615 adjc_iterate(ptile
, adjc_tile
) {
616 struct terrain
* pterrain
= tile_terrain(adjc_tile
);
618 if (pterrain
!= T_UNKNOWN
) {
619 if (terrain_type_terrain_class(pterrain
) == tclass
) {
628 /****************************************************************************
629 Return the number of adjacent tiles that have given terrain class
630 (not including ptile itself).
631 ****************************************************************************/
632 int count_terrain_class_near_tile(const struct tile
*ptile
,
633 bool cardinal_only
, bool percentage
,
634 enum terrain_class tclass
)
636 int count
= 0, total
= 0;
638 variable_adjc_iterate(ptile
, adjc_tile
, cardinal_only
) {
639 struct terrain
*pterrain
= tile_terrain(adjc_tile
);
640 if (T_UNKNOWN
!= pterrain
641 && terrain_type_terrain_class(pterrain
) == tclass
) {
645 } variable_adjc_iterate_end
;
648 count
= count
* 100 / total
;
654 /****************************************************************************
655 Return the (translated) name of the given terrain class.
656 You don't have to free the return pointer.
657 ****************************************************************************/
658 const char *terrain_class_name_translation(enum terrain_class tclass
)
660 if (!terrain_class_is_valid(tclass
)) {
664 return _(terrain_class_name(tclass
));
667 /****************************************************************************
668 Can terrain support given infrastructure?
669 ****************************************************************************/
670 bool terrain_can_support_alteration(const struct terrain
*pterrain
,
671 enum terrain_alteration alter
)
674 case TA_CAN_IRRIGATE
:
675 return (pterrain
== pterrain
->irrigation_result
);
677 return (pterrain
== pterrain
->mining_result
);
679 return (pterrain
->road_time
> 0);
688 /****************************************************************************
689 Time to complete the extra building activity on the given terrain.
690 ****************************************************************************/
691 int terrain_extra_build_time(const struct terrain
*pterrain
,
692 enum unit_activity activity
,
693 const struct extra_type
*tgt
)
697 if (tgt
!= NULL
&& tgt
->build_time
!= 0) {
698 /* Extra specific build time */
699 return tgt
->build_time
;
705 factor
= tgt
->build_time_factor
;
708 /* Terrain and activity specific build time */
711 return pterrain
->base_time
* factor
;
712 case ACTIVITY_GEN_ROAD
:
713 return pterrain
->road_time
* factor
;
714 case ACTIVITY_IRRIGATE
:
715 return pterrain
->irrigation_time
* factor
;
717 return pterrain
->mining_time
* factor
;
724 /****************************************************************************
725 Time to complete the extra removal activity on the given terrain.
726 ****************************************************************************/
727 int terrain_extra_removal_time(const struct terrain
*pterrain
,
728 enum unit_activity activity
,
729 const struct extra_type
*tgt
)
733 if (tgt
!= NULL
&& tgt
->removal_time
!= 0) {
734 /* Extra specific removal time */
735 return tgt
->removal_time
;
741 factor
= tgt
->removal_time_factor
;
744 /* Terrain and activity specific removal time */
746 case ACTIVITY_POLLUTION
:
747 return pterrain
->clean_pollution_time
* factor
;
748 case ACTIVITY_FALLOUT
:
749 return pterrain
->clean_fallout_time
* factor
;
750 case ACTIVITY_PILLAGE
:
751 return pterrain
->pillage_time
* factor
;
758 /**************************************************************************
759 Initialize user terrain type flags.
760 **************************************************************************/
761 void user_terrain_flags_init(void)
765 for (i
= 0; i
< MAX_NUM_USER_TER_FLAGS
; i
++) {
766 user_flag_init(&user_terrain_flags
[i
]);
770 /***************************************************************
771 Frees the memory associated with all user terrain flags
772 ***************************************************************/
773 void user_terrain_flags_free(void)
777 for (i
= 0; i
< MAX_NUM_USER_TER_FLAGS
; i
++) {
778 user_flag_free(&user_terrain_flags
[i
]);
782 /**************************************************************************
783 Sets user defined name for terrain flag.
784 **************************************************************************/
785 void set_user_terrain_flag_name(enum terrain_flag_id id
, const char *name
,
788 int tfid
= id
- TER_USER_1
;
790 fc_assert_ret(id
>= TER_USER_1
&& id
<= TER_USER_LAST
);
792 if (user_terrain_flags
[tfid
].name
!= NULL
) {
793 FC_FREE(user_terrain_flags
[tfid
].name
);
794 user_terrain_flags
[tfid
].name
= NULL
;
797 if (name
&& name
[0] != '\0') {
798 user_terrain_flags
[tfid
].name
= fc_strdup(name
);
801 if (user_terrain_flags
[tfid
].helptxt
!= NULL
) {
802 FC_FREE(user_terrain_flags
[tfid
].helptxt
);
803 user_terrain_flags
[tfid
].helptxt
= NULL
;
806 if (helptxt
&& helptxt
[0] != '\0') {
807 user_terrain_flags
[tfid
].helptxt
= fc_strdup(helptxt
);
811 /**************************************************************************
812 Terrain flag name callback, called from specenum code.
813 **************************************************************************/
814 const char *terrain_flag_id_name_cb(enum terrain_flag_id flag
)
816 if (flag
< TER_USER_1
|| flag
> TER_USER_LAST
) {
820 return user_terrain_flags
[flag
-TER_USER_1
].name
;
823 /**************************************************************************
824 Return the (untranslated) helptxt of the user terrain flag.
825 **************************************************************************/
826 const char *terrain_flag_helptxt(enum terrain_flag_id id
)
828 fc_assert(id
>= TER_USER_1
&& id
<= TER_USER_LAST
);
830 return user_terrain_flags
[id
- TER_USER_1
].helptxt
;