1 /****************************************************************************
2 Freeciv - Copyright (C) 2004 - The Freeciv Team
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 "string_vector.h"
30 static struct extra_type extras
[MAX_EXTRA_TYPES
];
32 static struct user_flag user_extra_flags
[MAX_NUM_USER_EXTRA_FLAGS
];
34 static struct extra_type_list
*category_extra
[ECAT_COUNT
];
35 static struct extra_type_list
*caused_by
[EC_LAST
];
36 static struct extra_type_list
*removed_by
[ERM_COUNT
];
37 static struct extra_type_list
*unit_hidden
;
39 /****************************************************************************
40 Initialize extras structures.
41 ****************************************************************************/
42 void extras_init(void)
46 for (i
= 0; i
< EC_LAST
; i
++) {
47 caused_by
[i
] = extra_type_list_new();
49 for (i
= 0; i
< ERM_COUNT
; i
++) {
50 removed_by
[i
] = extra_type_list_new();
52 for (i
= 0; i
< ECAT_COUNT
; i
++) {
53 category_extra
[i
] = extra_type_list_new();
55 unit_hidden
= extra_type_list_new();
57 for (i
= 0; i
< MAX_EXTRA_TYPES
; i
++) {
58 requirement_vector_init(&(extras
[i
].reqs
));
59 requirement_vector_init(&(extras
[i
].rmreqs
));
60 requirement_vector_init(&(extras
[i
].appearance_reqs
));
61 requirement_vector_init(&(extras
[i
].disappearance_reqs
));
63 extras
[i
].hiders
= NULL
;
64 extras
[i
].data
.special_idx
= -1;
65 extras
[i
].data
.base
= NULL
;
66 extras
[i
].data
.road
= NULL
;
67 extras
[i
].data
.resource
= NULL
;
69 extras
[i
].rmcauses
= 0;
70 extras
[i
].helptext
= NULL
;
71 extras
[i
].disabled
= FALSE
;
75 /****************************************************************************
76 Free the memory associated with extras
77 ****************************************************************************/
78 void extras_free(void)
84 resource_types_free();
86 for (i
= 0; i
< game
.control
.num_extra_types
; i
++) {
87 if (extras
[i
].data
.base
!= NULL
) {
88 FC_FREE(extras
[i
].data
.base
);
89 extras
[i
].data
.base
= NULL
;
91 if (extras
[i
].data
.road
!= NULL
) {
92 FC_FREE(extras
[i
].data
.road
);
93 extras
[i
].data
.road
= NULL
;
95 if (extras
[i
].data
.resource
!= NULL
) {
96 FC_FREE(extras
[i
].data
.resource
);
97 extras
[i
].data
.resource
= NULL
;
101 for (i
= 0; i
< EC_LAST
; i
++) {
102 extra_type_list_destroy(caused_by
[i
]);
106 for (i
= 0; i
< ERM_COUNT
; i
++) {
107 extra_type_list_destroy(removed_by
[i
]);
108 removed_by
[i
] = NULL
;
111 for (i
= 0; i
< ECAT_COUNT
; i
++) {
112 extra_type_list_destroy(category_extra
[i
]);
113 category_extra
[i
] = NULL
;
116 extra_type_list_destroy(unit_hidden
);
119 for (i
= 0; i
< MAX_EXTRA_TYPES
; i
++) {
120 requirement_vector_free(&(extras
[i
].reqs
));
121 requirement_vector_free(&(extras
[i
].rmreqs
));
122 requirement_vector_free(&(extras
[i
].appearance_reqs
));
123 requirement_vector_free(&(extras
[i
].disappearance_reqs
));
125 if (NULL
!= extras
[i
].helptext
) {
126 strvec_destroy(extras
[i
].helptext
);
127 extras
[i
].helptext
= NULL
;
131 extra_type_iterate(pextra
) {
132 if (pextra
->hiders
!= NULL
) {
133 extra_type_list_destroy(pextra
->hiders
);
134 pextra
->hiders
= NULL
;
136 } extra_type_iterate_end
;
139 /**************************************************************************
140 Return the number of extra_types.
141 **************************************************************************/
142 int extra_count(void)
144 return game
.control
.num_extra_types
;
147 /**************************************************************************
149 **************************************************************************/
150 int extra_number(const struct extra_type
*pextra
)
152 fc_assert_ret_val(NULL
!= pextra
, -1);
158 /**************************************************************************
159 Return the extra index.
160 **************************************************************************/
161 int extra_index(const struct extra_type
*pextra
)
163 fc_assert_ret_val(NULL
!= pextra
, -1);
165 return pextra
- extras
;
167 #endif /* extra_index */
169 /****************************************************************************
170 Return extras type of given id.
171 ****************************************************************************/
172 struct extra_type
*extra_by_number(int id
)
174 fc_assert_ret_val(id
>= 0 && id
< MAX_EXTRA_TYPES
, NULL
);
179 /**************************************************************************
180 Return the (translated) name of the extra type.
181 You don't have to free the return pointer.
182 **************************************************************************/
183 const char *extra_name_translation(const struct extra_type
*pextra
)
185 return name_translation_get(&pextra
->name
);
188 /**************************************************************************
189 Return the (untranslated) rule name of the extra type.
190 You don't have to free the return pointer.
191 **************************************************************************/
192 const char *extra_rule_name(const struct extra_type
*pextra
)
194 return rule_name_get(&pextra
->name
);
197 /**************************************************************************
198 Returns extra type matching rule name or NULL if there is no extra type
200 **************************************************************************/
201 struct extra_type
*extra_type_by_rule_name(const char *name
)
211 extra_type_iterate(pextra
) {
212 if (!fc_strcasecmp(extra_rule_name(pextra
), qs
)) {
215 } extra_type_iterate_end
;
220 /**************************************************************************
221 Returns extra type matching the translated name, or NULL if there is no
222 extra type with that name.
223 **************************************************************************/
224 struct extra_type
*extra_type_by_translated_name(const char *name
)
226 extra_type_iterate(pextra
) {
227 if (0 == strcmp(extra_name_translation(pextra
), name
)) {
230 } extra_type_iterate_end
;
235 /**************************************************************************
236 Returns extra type for given cause.
237 **************************************************************************/
238 struct extra_type_list
*extra_type_list_by_cause(enum extra_cause cause
)
240 fc_assert(cause
< EC_LAST
);
242 return caused_by
[cause
];
245 /**************************************************************************
246 Returns extra types of the category.
247 **************************************************************************/
248 struct extra_type_list
*extra_type_list_for_category(enum extra_category cat
)
250 fc_assert(cat
< ECAT_LAST
);
252 return category_extra
[cat
];
255 /**************************************************************************
256 Returns extra types that hide units.
257 **************************************************************************/
258 struct extra_type_list
*extra_type_list_of_unit_hiders(void)
263 /**************************************************************************
264 Return random extra type for given cause that is native to the tile.
265 **************************************************************************/
266 struct extra_type
*rand_extra_for_tile(struct tile
*ptile
, enum extra_cause cause
)
268 struct extra_type_list
*full_list
= extra_type_list_by_cause(cause
);
269 struct extra_type_list
*potential
= extra_type_list_new();
271 struct extra_type
*selected
= NULL
;
273 extra_type_list_iterate(full_list
, pextra
) {
274 if (is_native_tile_to_extra(pextra
, ptile
)) {
275 extra_type_list_append(potential
, pextra
);
277 } extra_type_list_iterate_end
;
279 options
= extra_type_list_size(potential
);
282 selected
= extra_type_list_get(potential
, fc_rand(options
));
285 extra_type_list_destroy(potential
);
290 /**************************************************************************
291 Add extra type to list of extra caused by given cause.
292 **************************************************************************/
293 void extra_to_caused_by_list(struct extra_type
*pextra
, enum extra_cause cause
)
295 fc_assert(cause
< EC_LAST
);
297 extra_type_list_append(caused_by
[cause
], pextra
);
300 /**************************************************************************
301 Add extra type to list of extras of a category
302 **************************************************************************/
303 void extra_to_category_list(struct extra_type
*pextra
, enum extra_category cat
)
305 fc_assert(cat
< ECAT_LAST
);
307 extra_type_list_append(category_extra
[cat
], pextra
);
310 /**************************************************************************
311 Returns extra type for given rmcause.
312 **************************************************************************/
313 struct extra_type_list
*extra_type_list_by_rmcause(enum extra_rmcause rmcause
)
315 fc_assert(rmcause
< ERM_COUNT
);
317 return removed_by
[rmcause
];
320 /**************************************************************************
321 Add extra type to list of extra removed by given cause.
322 **************************************************************************/
323 void extra_to_removed_by_list(struct extra_type
*pextra
,
324 enum extra_rmcause rmcause
)
326 fc_assert(rmcause
< ERM_COUNT
);
328 extra_type_list_append(removed_by
[rmcause
], pextra
);
331 /**************************************************************************
332 Is given cause one of the removal causes for given extra?
333 **************************************************************************/
334 bool is_extra_removed_by(const struct extra_type
*pextra
,
335 enum extra_rmcause rmcause
)
337 return (pextra
->rmcauses
& (1 << rmcause
));
340 /****************************************************************************
341 Is there extra of the given type cardinally near tile?
342 (Does not check ptile itself.)
343 ****************************************************************************/
344 bool is_extra_card_near(const struct tile
*ptile
, const struct extra_type
*pextra
)
346 cardinal_adjc_iterate(ptile
, adjc_tile
) {
347 if (tile_has_extra(adjc_tile
, pextra
)) {
350 } cardinal_adjc_iterate_end
;
355 /****************************************************************************
356 Is there extra of the given type near tile?
357 (Does not check ptile itself.)
358 ****************************************************************************/
359 bool is_extra_near_tile(const struct tile
*ptile
, const struct extra_type
*pextra
)
361 adjc_iterate(ptile
, adjc_tile
) {
362 if (tile_has_extra(adjc_tile
, pextra
)) {
370 /****************************************************************************
371 Tells if extra can build to tile if all other requirements are met.
372 ****************************************************************************/
373 bool extra_can_be_built(const struct extra_type
*pextra
,
374 const struct tile
*ptile
)
376 if (!pextra
->buildable
) {
377 /* Extra type not buildable */
381 if (tile_has_extra(ptile
, pextra
)) {
382 /* Extra exist already */
389 /****************************************************************************
390 Tells if player can build extra to tile with suitable unit.
391 ****************************************************************************/
392 static bool can_build_extra_base(const struct extra_type
*pextra
,
393 const struct player
*pplayer
,
394 const struct tile
*ptile
)
396 if (is_extra_caused_by(pextra
, EC_BASE
)
397 && !base_can_be_built(extra_base_get(pextra
), ptile
)) {
401 if (is_extra_caused_by(pextra
, EC_ROAD
)
402 && !can_build_road_base(extra_road_get(pextra
), pplayer
, ptile
)) {
406 if (!extra_can_be_built(pextra
, ptile
)) {
413 /****************************************************************************
414 Tells if player can build extra to tile with suitable unit.
415 ****************************************************************************/
416 bool player_can_build_extra(const struct extra_type
*pextra
,
417 const struct player
*pplayer
,
418 const struct tile
*ptile
)
420 if (!can_build_extra_base(pextra
, pplayer
, ptile
)) {
424 return are_reqs_active(pplayer
, tile_owner(ptile
), NULL
, NULL
, ptile
,
425 NULL
, NULL
, NULL
, NULL
, NULL
, &pextra
->reqs
,
429 /****************************************************************************
430 Tells if unit can build extra on tile.
431 ****************************************************************************/
432 bool can_build_extra(struct extra_type
*pextra
,
433 const struct unit
*punit
,
434 const struct tile
*ptile
)
436 struct player
*pplayer
= unit_owner(punit
);
438 if (!can_build_extra_base(pextra
, pplayer
, ptile
)) {
442 return are_reqs_active(pplayer
, tile_owner(ptile
), NULL
, NULL
, ptile
,
443 punit
, unit_type_get(punit
), NULL
, NULL
, NULL
, &pextra
->reqs
,
447 /****************************************************************************
448 Is it possible at all to remove this extra now
449 ****************************************************************************/
450 static bool can_extra_be_removed(const struct extra_type
*pextra
,
451 const struct tile
*ptile
)
453 struct city
*pcity
= tile_city(ptile
);
455 /* Cannot remove EF_ALWAYS_ON_CITY_CENTER extras from city center. */
457 if (extra_has_flag(pextra
, EF_ALWAYS_ON_CITY_CENTER
)) {
460 if (extra_has_flag(pextra
, EF_AUTO_ON_CITY_CENTER
)) {
461 struct tile
*vtile
= tile_virtual_new(ptile
);
463 /* Would extra get rebuilt if removed */
464 tile_remove_extra(vtile
, pextra
);
465 if (player_can_build_extra(pextra
, city_owner(pcity
), vtile
)) {
466 /* No need to worry about conflicting extras - extra would had
467 * not been here if conflicting one is. */
468 tile_virtual_destroy(vtile
);
473 tile_virtual_destroy(vtile
);
480 /****************************************************************************
481 Tells if player can remove extra from tile with suitable unit.
482 ****************************************************************************/
483 bool player_can_remove_extra(const struct extra_type
*pextra
,
484 const struct player
*pplayer
,
485 const struct tile
*ptile
)
487 if (!can_extra_be_removed(pextra
, ptile
)) {
491 return are_reqs_active(pplayer
, tile_owner(ptile
), NULL
, NULL
, ptile
,
492 NULL
, NULL
, NULL
, NULL
, NULL
, &pextra
->rmreqs
,
496 /****************************************************************************
497 Tells if unit can remove extra from tile.
498 ****************************************************************************/
499 bool can_remove_extra(struct extra_type
*pextra
,
500 const struct unit
*punit
,
501 const struct tile
*ptile
)
503 struct player
*pplayer
;
505 if (!can_extra_be_removed(pextra
, ptile
)) {
509 pplayer
= unit_owner(punit
);
511 return are_reqs_active(pplayer
, tile_owner(ptile
), NULL
, NULL
, ptile
,
512 punit
, unit_type_get(punit
), NULL
, NULL
, NULL
,
513 &pextra
->rmreqs
, RPT_CERTAIN
);
516 /****************************************************************************
517 Is tile native to extra?
518 ****************************************************************************/
519 bool is_native_tile_to_extra(const struct extra_type
*pextra
,
520 const struct tile
*ptile
)
522 struct terrain
*pterr
= tile_terrain(ptile
);
524 if (terrain_has_resource(pterr
, pextra
)) {
528 if (is_extra_caused_by(pextra
, EC_IRRIGATION
)
529 && pterr
->irrigation_result
!= pterr
) {
533 if (is_extra_caused_by(pextra
, EC_MINE
)
534 && pterr
->mining_result
!= pterr
) {
538 if (is_extra_caused_by(pextra
, EC_BASE
)) {
539 if (pterr
->base_time
== 0) {
542 if (tile_city(ptile
) != NULL
&& extra_base_get(pextra
)->border_sq
>= 0) {
547 if (is_extra_caused_by(pextra
, EC_ROAD
)) {
548 struct road_type
*proad
= extra_road_get(pextra
);
550 if (road_has_flag(proad
, RF_RIVER
)) {
551 if (!terrain_has_flag(pterr
, TER_CAN_HAVE_RIVER
)) {
554 } else if (pterr
->road_time
== 0) {
559 return are_reqs_active(NULL
, NULL
, NULL
, NULL
, ptile
,
560 NULL
, NULL
, NULL
, NULL
, NULL
,
561 &pextra
->reqs
, RPT_POSSIBLE
);
564 /****************************************************************************
565 Returns TRUE iff an extra that conflicts with pextra exists at ptile.
566 ****************************************************************************/
567 bool extra_conflicting_on_tile(const struct extra_type
*pextra
,
568 const struct tile
*ptile
)
570 extra_type_iterate(old_extra
) {
571 if (tile_has_extra(ptile
, old_extra
)
572 && !can_extras_coexist(old_extra
, pextra
)) {
575 } extra_type_iterate_end
;
580 /****************************************************************************
581 Returns next extra by cause that unit or player can build to tile.
582 ****************************************************************************/
583 struct extra_type
*next_extra_for_tile(const struct tile
*ptile
, enum extra_cause cause
,
584 const struct player
*pplayer
,
585 const struct unit
*punit
)
587 if (cause
== EC_IRRIGATION
) {
588 struct terrain
*pterrain
= tile_terrain(ptile
);
590 if (pterrain
->irrigation_result
!= pterrain
) {
591 /* No extra can be created by irrigation the tile */
595 if (cause
== EC_MINE
) {
596 struct terrain
*pterrain
= tile_terrain(ptile
);
598 if (pterrain
->mining_result
!= pterrain
) {
599 /* No extra can be created by mining the tile */
604 extra_type_by_cause_iterate(cause
, pextra
) {
605 if (!tile_has_extra(ptile
, pextra
)) {
607 if (can_build_extra(pextra
, punit
, ptile
)) {
611 /* punit is certainly NULL, pplayer can be too */
612 if (player_can_build_extra(pextra
, pplayer
, ptile
)) {
617 } extra_type_by_cause_iterate_end
;
622 /****************************************************************************
623 Returns prev extra by cause that unit or player can remove from tile.
624 ****************************************************************************/
625 struct extra_type
*prev_extra_in_tile(const struct tile
*ptile
,
626 enum extra_rmcause rmcause
,
627 const struct player
*pplayer
,
628 const struct unit
*punit
)
630 fc_assert(punit
!= NULL
|| pplayer
!= NULL
);
632 extra_type_by_rmcause_iterate(rmcause
, pextra
) {
633 if (tile_has_extra(ptile
, pextra
)) {
635 if (can_remove_extra(pextra
, punit
, ptile
)) {
639 if (player_can_remove_extra(pextra
, pplayer
, ptile
)) {
644 } extra_type_by_rmcause_iterate_end
;
649 /****************************************************************************
650 Is extra native to unit class?
651 ****************************************************************************/
652 bool is_native_extra_to_uclass(const struct extra_type
*pextra
,
653 const struct unit_class
*pclass
)
655 return BV_ISSET(pextra
->native_to
, uclass_index(pclass
));
658 /****************************************************************************
659 Is extra native to unit type?
660 ****************************************************************************/
661 bool is_native_extra_to_utype(const struct extra_type
*pextra
,
662 const struct unit_type
*punittype
)
664 return is_native_extra_to_uclass(pextra
, utype_class(punittype
));
667 /****************************************************************************
668 Check if extra has given flag
669 ****************************************************************************/
670 bool extra_has_flag(const struct extra_type
*pextra
, enum extra_flag_id flag
)
672 return BV_ISSET(pextra
->flags
, flag
);
675 /****************************************************************************
676 Returns TRUE iff any cardinally adjacent tile contains an extra with
677 the given flag (does not check ptile itself).
678 ****************************************************************************/
679 bool is_extra_flag_card_near(const struct tile
*ptile
, enum extra_flag_id flag
)
681 extra_type_iterate(pextra
) {
682 if (extra_has_flag(pextra
, flag
)) {
683 cardinal_adjc_iterate(ptile
, adjc_tile
) {
684 if (tile_has_extra(adjc_tile
, pextra
)) {
687 } cardinal_adjc_iterate_end
;
689 } extra_type_iterate_end
;
694 /****************************************************************************
695 Returns TRUE iff any adjacent tile contains an extra with the given flag
696 (does not check ptile itself).
697 ****************************************************************************/
698 bool is_extra_flag_near_tile(const struct tile
*ptile
, enum extra_flag_id flag
)
700 extra_type_iterate(pextra
) {
701 if (extra_has_flag(pextra
, flag
)) {
702 adjc_iterate(ptile
, adjc_tile
) {
703 if (tile_has_extra(adjc_tile
, pextra
)) {
708 } extra_type_iterate_end
;
713 /**************************************************************************
714 Initialize user extra flags.
715 **************************************************************************/
716 void user_extra_flags_init(void)
720 for (i
= 0; i
< MAX_NUM_USER_EXTRA_FLAGS
; i
++) {
721 user_flag_init(&user_extra_flags
[i
]);
725 /***************************************************************
726 Frees the memory associated with all extra flags
727 ***************************************************************/
728 void extra_flags_free(void)
732 for (i
= 0; i
< MAX_NUM_USER_EXTRA_FLAGS
; i
++) {
733 user_flag_free(&user_extra_flags
[i
]);
737 /**************************************************************************
738 Sets user defined name for extra flag.
739 **************************************************************************/
740 void set_user_extra_flag_name(enum extra_flag_id id
, const char *name
,
743 int efid
= id
- EF_USER_FLAG_1
;
745 fc_assert_ret(id
>= EF_USER_FLAG_1
&& id
<= EF_LAST_USER_FLAG
);
747 if (user_extra_flags
[efid
].name
!= NULL
) {
748 FC_FREE(user_extra_flags
[efid
].name
);
749 user_extra_flags
[efid
].name
= NULL
;
752 if (name
&& name
[0] != '\0') {
753 user_extra_flags
[efid
].name
= fc_strdup(name
);
756 if (user_extra_flags
[efid
].helptxt
!= NULL
) {
757 free(user_extra_flags
[efid
].helptxt
);
758 user_extra_flags
[efid
].helptxt
= NULL
;
761 if (helptxt
&& helptxt
[0] != '\0') {
762 user_extra_flags
[efid
].helptxt
= fc_strdup(helptxt
);
766 /**************************************************************************
767 Extra flag name callback, called from specenum code.
768 **************************************************************************/
769 const char *extra_flag_id_name_cb(enum extra_flag_id flag
)
771 if (flag
< EF_USER_FLAG_1
|| flag
> EF_LAST_USER_FLAG
) {
775 return user_extra_flags
[flag
- EF_USER_FLAG_1
].name
;
778 /**************************************************************************
779 Return the (untranslated) help text of the user extra flag.
780 **************************************************************************/
781 const char *extra_flag_helptxt(enum extra_flag_id id
)
783 fc_assert(id
>= EF_USER_FLAG_1
&& id
<= EF_LAST_USER_FLAG
);
785 return user_extra_flags
[id
- EF_USER_FLAG_1
].helptxt
;
788 /**************************************************************************
789 Can two extras coexist in same tile?
790 **************************************************************************/
791 bool can_extras_coexist(const struct extra_type
*pextra1
,
792 const struct extra_type
*pextra2
)
794 if (pextra1
== pextra2
) {
798 return !BV_ISSET(pextra1
->conflicts
, extra_index(pextra2
));
801 /**************************************************************************
802 Does the extra count toward environment upset?
803 **************************************************************************/
804 bool extra_causes_env_upset(struct extra_type
*pextra
,
805 enum environment_upset_type upset
)
808 case EUT_GLOBAL_WARMING
:
809 return extra_has_flag(pextra
, EF_GLOBAL_WARMING
);
810 case EUT_NUCLEAR_WINTER
:
811 return extra_has_flag(pextra
, EF_NUCLEAR_WINTER
);
817 /**************************************************************************
818 Is given cause one of the causes for given extra?
819 **************************************************************************/
820 bool is_extra_caused_by(const struct extra_type
*pextra
, enum extra_cause cause
)
822 /* There's some extra cause lists above EC_COUNT that do not have equivalent
823 * bit in pextra->causes */
824 fc_assert(cause
< EC_COUNT
);
826 return (pextra
->causes
& (1 << cause
));
829 /**************************************************************************
830 Is the extra caused by some kind of worker action?
831 **************************************************************************/
832 bool is_extra_caused_by_worker_action(const struct extra_type
*pextra
)
834 /* Is any of the worker build action bits set? */
835 return (pextra
->causes
836 & (1 << EC_IRRIGATION
842 /**************************************************************************
843 Is the extra removed by some kind of worker action?
844 **************************************************************************/
845 bool is_extra_removed_by_worker_action(const struct extra_type
*pextra
)
847 /* Is any of the worker remove action bits set? */
848 return (pextra
->rmcauses
849 & (1 << ERM_CLEANPOLLUTION
850 | 1 << ERM_CLEANFALLOUT
851 | 1 << ERM_PILLAGE
));
854 /**************************************************************************
855 Is the extra caused by specific worker action?
856 **************************************************************************/
857 bool is_extra_caused_by_action(const struct extra_type
*pextra
,
858 enum unit_activity act
)
860 return is_extra_caused_by(pextra
, activity_to_extra_cause(act
));
863 /**************************************************************************
864 Is the extra removed by specific worker action?
865 **************************************************************************/
866 bool is_extra_removed_by_action(const struct extra_type
*pextra
,
867 enum unit_activity act
)
869 return is_extra_removed_by(pextra
, activity_to_extra_rmcause(act
));
872 /**************************************************************************
873 What extra cause activity is considered to be?
874 **************************************************************************/
875 enum extra_cause
activity_to_extra_cause(enum unit_activity act
)
878 case ACTIVITY_IRRIGATE
:
879 return EC_IRRIGATION
;
884 case ACTIVITY_GEN_ROAD
:
893 /**************************************************************************
894 What extra rmcause activity is considered to be?
895 **************************************************************************/
896 enum extra_rmcause
activity_to_extra_rmcause(enum unit_activity act
)
899 case ACTIVITY_PILLAGE
:
901 case ACTIVITY_POLLUTION
:
902 return ERM_CLEANPOLLUTION
;
903 case ACTIVITY_FALLOUT
:
904 return ERM_CLEANFALLOUT
;
912 /**************************************************************************
913 Who owns extras on tile
914 **************************************************************************/
915 struct player
*extra_owner(const struct tile
*ptile
)
917 return ptile
->extras_owner
;
920 /**************************************************************************
921 Are all the requirements for extra to appear on tile fulfilled.
922 **************************************************************************/
923 bool can_extra_appear(const struct extra_type
*pextra
, const struct tile
*ptile
)
925 return !tile_has_extra(ptile
, pextra
)
926 && is_extra_caused_by(pextra
, EC_APPEARANCE
)
927 && is_native_tile_to_extra(pextra
, ptile
)
928 && !extra_conflicting_on_tile(pextra
, ptile
)
929 && are_reqs_active(NULL
, tile_owner(ptile
), NULL
, NULL
, ptile
,
930 NULL
, NULL
, NULL
, NULL
, NULL
,
931 &pextra
->appearance_reqs
, RPT_CERTAIN
);
934 /**************************************************************************
935 Are all the requirements for extra to disappear from tile fulfilled.
936 **************************************************************************/
937 bool can_extra_disappear(const struct extra_type
*pextra
, const struct tile
*ptile
)
939 return tile_has_extra(ptile
, pextra
)
940 && is_extra_removed_by(pextra
, ERM_DISAPPEARANCE
)
941 && can_extra_be_removed(pextra
, ptile
)
942 && are_reqs_active(NULL
, tile_owner(ptile
), NULL
, NULL
, ptile
,
943 NULL
, NULL
, NULL
, NULL
, NULL
,
944 &pextra
->disappearance_reqs
, RPT_CERTAIN
);