Comment fix: OS is not excluded from permissive.
[freeciv.git] / common / terrain.c
blob4efb5336416f003a94f27b968bb98fca807fc2ce
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(nmap, 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(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,
315 bool check_self)
317 if (!pterrain) {
318 return FALSE;
321 cardinal_adjc_iterate(&(wld.map), 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(&(wld.map), 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(&(wld.map), 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(&(wld.map), ptile, adjc_tile, cardinal_only) {
382 struct terrain *pterrain = tile_terrain(adjc_tile);
384 if (pterrain->property[prop] > 0) {
385 count++;
387 total++;
388 } variable_adjc_iterate_end;
390 if (percentage) {
391 count = count * 100 / total;
393 return count;
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,
401 bool check_self)
403 if (!pres) {
404 return FALSE;
407 cardinal_adjc_iterate(&(wld.map), ptile, adjc_tile) {
408 if (tile_resource(adjc_tile) == pres) {
409 return TRUE;
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,
421 bool check_self)
423 if (!pres) {
424 return FALSE;
427 adjc_iterate(&(wld.map), ptile, adjc_tile) {
428 if (tile_resource(adjc_tile) == pres) {
429 return TRUE;
431 } adjc_iterate_end;
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)) {
448 return TRUE;
450 } cardinal_adjc_iterate_end;
452 return FALSE;
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)) {
467 return TRUE;
469 } adjc_iterate_end;
471 return FALSE;
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)) {
489 count++;
491 total++;
492 } variable_adjc_iterate_end;
494 if (percentage) {
495 count = count * 100 / total;
497 return count;
500 /****************************************************************************
501 Return a (static) string with extra(s) name(s):
502 eg: "Mine"
503 eg: "Road/Farmland"
504 This only includes "infrastructure", i.e., man-made extras.
505 ****************************************************************************/
506 const char *get_infrastructure_text(bv_extras extras)
508 static char s[256];
509 char *p;
510 int len;
512 s[0] = '\0';
514 extra_type_iterate(pextra) {
515 if (pextra->category == ECAT_INFRA
516 && BV_ISSET(extras, extra_index(pextra))) {
517 bool hidden = FALSE;
519 extra_type_iterate(top) {
520 int topi = extra_index(top);
522 if (BV_ISSET(pextra->hidden_by, topi)
523 && BV_ISSET(extras, topi)) {
524 hidden = TRUE;
525 break;
527 } extra_type_iterate_end;
529 if (!hidden) {
530 cat_snprintf(s, sizeof(s), "%s/", extra_name_translation(pextra));
533 } extra_type_iterate_end;
535 len = strlen(s);
536 p = s + len - 1;
537 if (len > 0 && *p == '/') {
538 *p = '\0';
541 return s;
544 /****************************************************************************
545 Returns the highest-priority (best) infrastructure (man-made extra) to
546 be pillaged from the terrain set. May return NULL if nothing
547 better is available.
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))) {
553 return 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))) {
559 return 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))) {
565 return 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))) {
571 return 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))) {
577 return pextra;
579 } extra_type_by_cause_iterate_rev_end;
581 return NULL;
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) {
604 return TRUE;
607 } cardinal_adjc_iterate_end;
609 return FALSE;
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) {
624 return TRUE;
627 } adjc_iterate_end;
629 return FALSE;
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) {
647 count++;
649 total++;
650 } variable_adjc_iterate_end;
652 if (percentage) {
653 count = count * 100 / total;
656 return count;
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)) {
666 return NULL;
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)
678 switch (alter) {
679 case TA_CAN_IRRIGATE:
680 return (pterrain == pterrain->irrigation_result);
681 case TA_CAN_MINE:
682 return (pterrain == pterrain->mining_result);
683 case TA_CAN_ROAD:
684 return (pterrain->road_time > 0);
685 default:
686 break;
689 fc_assert(FALSE);
690 return FALSE;
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)
700 int factor;
702 if (tgt != NULL && tgt->build_time != 0) {
703 /* Extra specific build time */
704 return tgt->build_time;
707 if (tgt == NULL) {
708 factor = 1;
709 } else {
710 factor = tgt->build_time_factor;
713 /* Terrain and activity specific build time */
714 switch (activity) {
715 case ACTIVITY_BASE:
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;
721 case ACTIVITY_MINE:
722 return pterrain->mining_time * factor;
723 default:
724 fc_assert(FALSE);
725 return 0;
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)
736 int factor;
738 if (tgt != NULL && tgt->removal_time != 0) {
739 /* Extra specific removal time */
740 return tgt->removal_time;
743 if (tgt == NULL) {
744 factor = 1;
745 } else {
746 factor = tgt->removal_time_factor;
749 /* Terrain and activity specific removal time */
750 switch (activity) {
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;
757 default:
758 fc_assert(FALSE);
759 return 0;
763 /**************************************************************************
764 Initialize user terrain type flags.
765 **************************************************************************/
766 void user_terrain_flags_init(void)
768 int i;
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)
780 int i;
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,
791 const char *helptxt)
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) {
822 return NULL;
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;