Stop sharing requirement_unit_state_ereq().
[freeciv.git] / common / terrain.c
blob9726d1b9e1b23e32240d8cd82212b94e327b91cd
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)
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 "fcintl.h"
20 #include "log.h" /* fc_assert */
21 #include "mem.h" /* free */
22 #include "rand.h"
23 #include "shared.h"
24 #include "string_vector.h"
25 #include "support.h"
27 /* common */
28 #include "extras.h"
29 #include "game.h"
30 #include "map.h"
31 #include "rgbcolor.h"
32 #include "road.h"
34 #include "terrain.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)
44 int i;
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);
75 pterrain->rgb = NULL;
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) {
86 return civ_terrains;
88 return NULL;
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];
99 return NULL;
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. */
147 return NULL;
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) {
158 return T_UNKNOWN;
160 terrain_type_iterate(pterrain) {
161 if (pterrain->identifier == identifier) {
162 return pterrain;
164 } terrain_type_iterate_end;
166 return T_UNKNOWN;
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)) {
178 return pterrain;
180 } terrain_type_iterate_end;
182 return T_UNKNOWN;
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)) {
192 return pterrain;
194 } terrain_type_iterate_end;
196 return T_UNKNOWN;
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)
205 int num = 0;
206 struct terrain *terr = NULL;
208 terrain_type_iterate(pterr) {
209 if (terrain_has_flag(pterr, flag)) {
210 num++;
211 if (fc_rand(num) == 1) {
212 terr = pterr;
215 } terrain_type_iterate_end;
217 return terr;
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;
246 while (NULL != *r) {
247 if (*r == presource) {
248 return TRUE;
250 r++;
252 return FALSE;
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;
268 return presource;
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; \
294 int _tile##_count; \
296 if (card_only) { \
297 _tile##_list = wld.map.cardinal_dirs; \
298 _tile##_count = wld.map.num_cardinal_dirs; \
299 } else { \
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,
315 bool check_self)
317 if (!pterrain) {
318 return FALSE;
321 cardinal_adjc_iterate(ptile, adjc_tile) {
322 if (tile_terrain(adjc_tile) == pterrain) {
323 return TRUE;
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,
335 bool check_self)
337 if (!pterrain) {
338 return FALSE;
341 adjc_iterate(ptile, adjc_tile) {
342 if (tile_terrain(adjc_tile) == pterrain) {
343 return TRUE;
345 } adjc_iterate_end;
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) {
361 count++;
363 total++;
364 } variable_adjc_iterate_end;
366 if (percentage) {
367 count = count * 100 / total;
369 return count;
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) {
384 count++;
386 total++;
387 } variable_adjc_iterate_end;
389 if (percentage) {
390 count = count * 100 / total;
392 return count;
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,
400 bool check_self)
402 if (!pres) {
403 return FALSE;
406 cardinal_adjc_iterate(ptile, adjc_tile) {
407 if (tile_resource(adjc_tile) == pres) {
408 return TRUE;
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,
420 bool check_self)
422 if (!pres) {
423 return FALSE;
426 adjc_iterate(ptile, adjc_tile) {
427 if (tile_resource(adjc_tile) == pres) {
428 return TRUE;
430 } adjc_iterate_end;
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)) {
446 return TRUE;
448 } cardinal_adjc_iterate_end;
450 return FALSE;
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)) {
464 return TRUE;
466 } adjc_iterate_end;
468 return FALSE;
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)) {
485 count++;
487 total++;
488 } variable_adjc_iterate_end;
490 if (percentage) {
491 count = count * 100 / total;
493 return count;
496 /****************************************************************************
497 Return a (static) string with extra(s) name(s):
498 eg: "Mine"
499 eg: "Road/Farmland"
500 This only includes "infrastructure", i.e., man-made extras.
501 ****************************************************************************/
502 const char *get_infrastructure_text(bv_extras extras)
504 static char s[256];
505 char *p;
506 int len;
508 s[0] = '\0';
510 extra_type_iterate(pextra) {
511 if (pextra->category == ECAT_INFRA
512 && BV_ISSET(extras, extra_index(pextra))) {
513 bool hidden = FALSE;
515 extra_type_iterate(top) {
516 int topi = extra_index(top);
518 if (BV_ISSET(pextra->hidden_by, topi)
519 && BV_ISSET(extras, topi)) {
520 hidden = TRUE;
521 break;
523 } extra_type_iterate_end;
525 if (!hidden) {
526 cat_snprintf(s, sizeof(s), "%s/", extra_name_translation(pextra));
529 } extra_type_iterate_end;
531 len = strlen(s);
532 p = s + len - 1;
533 if (len > 0 && *p == '/') {
534 *p = '\0';
537 return s;
540 /****************************************************************************
541 Returns the highest-priority (best) infrastructure (man-made extra) to
542 be pillaged from the terrain set. May return NULL if nothing
543 better is available.
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))) {
549 return 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))) {
555 return 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))) {
561 return 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))) {
567 return 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))) {
573 return pextra;
575 } extra_type_by_cause_iterate_rev_end;
577 return NULL;
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) {
600 return TRUE;
603 } cardinal_adjc_iterate_end;
605 return FALSE;
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) {
620 return TRUE;
623 } adjc_iterate_end;
625 return FALSE;
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) {
642 count++;
644 total++;
645 } variable_adjc_iterate_end;
647 if (percentage) {
648 count = count * 100 / total;
651 return count;
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)) {
661 return NULL;
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)
673 switch (alter) {
674 case TA_CAN_IRRIGATE:
675 return (pterrain == pterrain->irrigation_result);
676 case TA_CAN_MINE:
677 return (pterrain == pterrain->mining_result);
678 case TA_CAN_ROAD:
679 return (pterrain->road_time > 0);
680 default:
681 break;
684 fc_assert(FALSE);
685 return FALSE;
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)
695 int factor;
697 if (tgt != NULL && tgt->build_time != 0) {
698 /* Extra specific build time */
699 return tgt->build_time;
702 if (tgt == NULL) {
703 factor = 1;
704 } else {
705 factor = tgt->build_time_factor;
708 /* Terrain and activity specific build time */
709 switch (activity) {
710 case ACTIVITY_BASE:
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;
716 case ACTIVITY_MINE:
717 return pterrain->mining_time * factor;
718 default:
719 fc_assert(FALSE);
720 return 0;
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)
731 int factor;
733 if (tgt != NULL && tgt->removal_time != 0) {
734 /* Extra specific removal time */
735 return tgt->removal_time;
738 if (tgt == NULL) {
739 factor = 1;
740 } else {
741 factor = tgt->removal_time_factor;
744 /* Terrain and activity specific removal time */
745 switch (activity) {
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;
752 default:
753 fc_assert(FALSE);
754 return 0;
758 /**************************************************************************
759 Initialize user terrain type flags.
760 **************************************************************************/
761 void user_terrain_flags_init(void)
763 int i;
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)
775 int i;
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,
786 const char *helptxt)
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) {
817 return NULL;
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;