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"
31 static struct extra_type extras
[MAX_EXTRA_TYPES
];
33 static struct user_flag user_extra_flags
[MAX_NUM_USER_EXTRA_FLAGS
];
35 static struct extra_type_list
*category_extra
[ECAT_COUNT
];
36 static struct extra_type_list
*caused_by
[EC_LAST
];
37 static struct extra_type_list
*removed_by
[ERM_COUNT
];
38 static struct extra_type_list
*unit_hidden
;
40 /****************************************************************************
41 Initialize extras structures.
42 ****************************************************************************/
43 void extras_init(void)
47 for (i
= 0; i
< EC_LAST
; i
++) {
48 caused_by
[i
] = extra_type_list_new();
50 for (i
= 0; i
< ERM_COUNT
; i
++) {
51 removed_by
[i
] = extra_type_list_new();
53 for (i
= 0; i
< ECAT_COUNT
; i
++) {
54 category_extra
[i
] = extra_type_list_new();
56 unit_hidden
= extra_type_list_new();
58 for (i
= 0; i
< MAX_EXTRA_TYPES
; i
++) {
59 requirement_vector_init(&(extras
[i
].reqs
));
60 requirement_vector_init(&(extras
[i
].rmreqs
));
61 requirement_vector_init(&(extras
[i
].appearance_reqs
));
62 requirement_vector_init(&(extras
[i
].disappearance_reqs
));
64 extras
[i
].hiders
= NULL
;
65 extras
[i
].data
.special_idx
= -1;
66 extras
[i
].data
.base
= NULL
;
67 extras
[i
].data
.road
= NULL
;
68 extras
[i
].data
.resource
= NULL
;
70 extras
[i
].rmcauses
= 0;
71 extras
[i
].helptext
= NULL
;
72 extras
[i
].disabled
= FALSE
;
73 extras
[i
].visibility_req
= A_NONE
;
77 /****************************************************************************
78 Free the memory associated with extras
79 ****************************************************************************/
80 void extras_free(void)
86 resource_types_free();
88 for (i
= 0; i
< game
.control
.num_extra_types
; i
++) {
89 if (extras
[i
].data
.base
!= NULL
) {
90 FC_FREE(extras
[i
].data
.base
);
91 extras
[i
].data
.base
= NULL
;
93 if (extras
[i
].data
.road
!= NULL
) {
94 FC_FREE(extras
[i
].data
.road
);
95 extras
[i
].data
.road
= NULL
;
97 if (extras
[i
].data
.resource
!= NULL
) {
98 FC_FREE(extras
[i
].data
.resource
);
99 extras
[i
].data
.resource
= NULL
;
103 for (i
= 0; i
< EC_LAST
; i
++) {
104 extra_type_list_destroy(caused_by
[i
]);
108 for (i
= 0; i
< ERM_COUNT
; i
++) {
109 extra_type_list_destroy(removed_by
[i
]);
110 removed_by
[i
] = NULL
;
113 for (i
= 0; i
< ECAT_COUNT
; i
++) {
114 extra_type_list_destroy(category_extra
[i
]);
115 category_extra
[i
] = NULL
;
118 extra_type_list_destroy(unit_hidden
);
121 for (i
= 0; i
< MAX_EXTRA_TYPES
; i
++) {
122 requirement_vector_free(&(extras
[i
].reqs
));
123 requirement_vector_free(&(extras
[i
].rmreqs
));
124 requirement_vector_free(&(extras
[i
].appearance_reqs
));
125 requirement_vector_free(&(extras
[i
].disappearance_reqs
));
127 if (NULL
!= extras
[i
].helptext
) {
128 strvec_destroy(extras
[i
].helptext
);
129 extras
[i
].helptext
= NULL
;
133 extra_type_iterate(pextra
) {
134 if (pextra
->hiders
!= NULL
) {
135 extra_type_list_destroy(pextra
->hiders
);
136 pextra
->hiders
= NULL
;
138 } extra_type_iterate_end
;
141 /**************************************************************************
142 Return the number of extra_types.
143 **************************************************************************/
144 int extra_count(void)
146 return game
.control
.num_extra_types
;
149 /**************************************************************************
151 **************************************************************************/
152 int extra_number(const struct extra_type
*pextra
)
154 fc_assert_ret_val(NULL
!= pextra
, -1);
160 /**************************************************************************
161 Return the extra index.
162 **************************************************************************/
163 int extra_index(const struct extra_type
*pextra
)
165 fc_assert_ret_val(NULL
!= pextra
, -1);
167 return pextra
- extras
;
169 #endif /* extra_index */
171 /****************************************************************************
172 Return extras type of given id.
173 ****************************************************************************/
174 struct extra_type
*extra_by_number(int id
)
176 fc_assert_ret_val(id
>= 0 && id
< MAX_EXTRA_TYPES
, NULL
);
181 /**************************************************************************
182 Return the (translated) name of the extra type.
183 You don't have to free the return pointer.
184 **************************************************************************/
185 const char *extra_name_translation(const struct extra_type
*pextra
)
187 return name_translation_get(&pextra
->name
);
190 /**************************************************************************
191 Return the (untranslated) rule name of the extra type.
192 You don't have to free the return pointer.
193 **************************************************************************/
194 const char *extra_rule_name(const struct extra_type
*pextra
)
196 return rule_name_get(&pextra
->name
);
199 /**************************************************************************
200 Returns extra type matching rule name or NULL if there is no extra type
202 **************************************************************************/
203 struct extra_type
*extra_type_by_rule_name(const char *name
)
213 extra_type_iterate(pextra
) {
214 if (!fc_strcasecmp(extra_rule_name(pextra
), qs
)) {
217 } extra_type_iterate_end
;
222 /**************************************************************************
223 Returns extra type matching the translated name, or NULL if there is no
224 extra type with that name.
225 **************************************************************************/
226 struct extra_type
*extra_type_by_translated_name(const char *name
)
228 extra_type_iterate(pextra
) {
229 if (0 == strcmp(extra_name_translation(pextra
), name
)) {
232 } extra_type_iterate_end
;
237 /**************************************************************************
238 Returns extra type for given cause.
239 **************************************************************************/
240 struct extra_type_list
*extra_type_list_by_cause(enum extra_cause cause
)
242 fc_assert(cause
< EC_LAST
);
244 return caused_by
[cause
];
247 /**************************************************************************
248 Returns extra types of the category.
249 **************************************************************************/
250 struct extra_type_list
*extra_type_list_for_category(enum extra_category cat
)
252 fc_assert(cat
< ECAT_LAST
);
254 return category_extra
[cat
];
257 /**************************************************************************
258 Returns extra types that hide units.
259 **************************************************************************/
260 struct extra_type_list
*extra_type_list_of_unit_hiders(void)
265 /**************************************************************************
266 Return random extra type for given cause that is native to the tile.
267 **************************************************************************/
268 struct extra_type
*rand_extra_for_tile(struct tile
*ptile
, enum extra_cause cause
)
270 struct extra_type_list
*full_list
= extra_type_list_by_cause(cause
);
271 struct extra_type_list
*potential
= extra_type_list_new();
273 struct extra_type
*selected
= NULL
;
275 extra_type_list_iterate(full_list
, pextra
) {
276 if (is_native_tile_to_extra(pextra
, ptile
)) {
277 extra_type_list_append(potential
, pextra
);
279 } extra_type_list_iterate_end
;
281 options
= extra_type_list_size(potential
);
284 selected
= extra_type_list_get(potential
, fc_rand(options
));
287 extra_type_list_destroy(potential
);
292 /**************************************************************************
293 Add extra type to list of extra caused by given cause.
294 **************************************************************************/
295 void extra_to_caused_by_list(struct extra_type
*pextra
, enum extra_cause cause
)
297 fc_assert(cause
< EC_LAST
);
299 extra_type_list_append(caused_by
[cause
], pextra
);
302 /**************************************************************************
303 Add extra type to list of extras of a category
304 **************************************************************************/
305 void extra_to_category_list(struct extra_type
*pextra
, enum extra_category cat
)
307 fc_assert(cat
< ECAT_LAST
);
309 extra_type_list_append(category_extra
[cat
], pextra
);
312 /**************************************************************************
313 Returns extra type for given rmcause.
314 **************************************************************************/
315 struct extra_type_list
*extra_type_list_by_rmcause(enum extra_rmcause rmcause
)
317 fc_assert(rmcause
< ERM_COUNT
);
319 return removed_by
[rmcause
];
322 /**************************************************************************
323 Add extra type to list of extra removed by given cause.
324 **************************************************************************/
325 void extra_to_removed_by_list(struct extra_type
*pextra
,
326 enum extra_rmcause rmcause
)
328 fc_assert(rmcause
< ERM_COUNT
);
330 extra_type_list_append(removed_by
[rmcause
], pextra
);
333 /**************************************************************************
334 Is given cause one of the removal causes for given extra?
335 **************************************************************************/
336 bool is_extra_removed_by(const struct extra_type
*pextra
,
337 enum extra_rmcause rmcause
)
339 return (pextra
->rmcauses
& (1 << rmcause
));
342 /****************************************************************************
343 Is there extra of the given type cardinally near tile?
344 (Does not check ptile itself.)
345 ****************************************************************************/
346 bool is_extra_card_near(const struct tile
*ptile
, const struct extra_type
*pextra
)
348 cardinal_adjc_iterate(&(wld
.map
), ptile
, adjc_tile
) {
349 if (tile_has_extra(adjc_tile
, pextra
)) {
352 } cardinal_adjc_iterate_end
;
357 /****************************************************************************
358 Is there extra of the given type near tile?
359 (Does not check ptile itself.)
360 ****************************************************************************/
361 bool is_extra_near_tile(const struct tile
*ptile
, const struct extra_type
*pextra
)
363 adjc_iterate(&(wld
.map
), ptile
, adjc_tile
) {
364 if (tile_has_extra(adjc_tile
, pextra
)) {
372 /****************************************************************************
373 Tells if extra can build to tile if all other requirements are met.
374 ****************************************************************************/
375 bool extra_can_be_built(const struct extra_type
*pextra
,
376 const struct tile
*ptile
)
378 if (!pextra
->buildable
) {
379 /* Extra type not buildable */
383 if (tile_has_extra(ptile
, pextra
)) {
384 /* Extra exist already */
391 /****************************************************************************
392 Tells if player can build extra to tile with suitable unit.
393 ****************************************************************************/
394 static bool can_build_extra_base(const struct extra_type
*pextra
,
395 const struct player
*pplayer
,
396 const struct tile
*ptile
)
398 if (is_extra_caused_by(pextra
, EC_BASE
)
399 && !base_can_be_built(extra_base_get(pextra
), ptile
)) {
403 if (is_extra_caused_by(pextra
, EC_ROAD
)
404 && !can_build_road_base(extra_road_get(pextra
), pplayer
, ptile
)) {
408 if (!extra_can_be_built(pextra
, ptile
)) {
415 /****************************************************************************
416 Tells if player can build extra to tile with suitable unit.
417 ****************************************************************************/
418 bool player_can_build_extra(const struct extra_type
*pextra
,
419 const struct player
*pplayer
,
420 const struct tile
*ptile
)
422 if (!can_build_extra_base(pextra
, pplayer
, ptile
)) {
426 return are_reqs_active(pplayer
, tile_owner(ptile
), NULL
, NULL
, ptile
,
427 NULL
, NULL
, NULL
, NULL
, NULL
, &pextra
->reqs
,
431 /****************************************************************************
432 Tells if unit can build extra on tile.
433 ****************************************************************************/
434 bool can_build_extra(struct extra_type
*pextra
,
435 const struct unit
*punit
,
436 const struct tile
*ptile
)
438 struct player
*pplayer
= unit_owner(punit
);
440 if (!can_build_extra_base(pextra
, pplayer
, ptile
)) {
444 return are_reqs_active(pplayer
, tile_owner(ptile
), NULL
, NULL
, ptile
,
445 punit
, unit_type_get(punit
), NULL
, NULL
, NULL
, &pextra
->reqs
,
449 /****************************************************************************
450 Is it possible at all to remove this extra now
451 ****************************************************************************/
452 static bool can_extra_be_removed(const struct extra_type
*pextra
,
453 const struct tile
*ptile
)
455 struct city
*pcity
= tile_city(ptile
);
457 /* Cannot remove EF_ALWAYS_ON_CITY_CENTER extras from city center. */
459 if (extra_has_flag(pextra
, EF_ALWAYS_ON_CITY_CENTER
)) {
462 if (extra_has_flag(pextra
, EF_AUTO_ON_CITY_CENTER
)) {
463 struct tile
*vtile
= tile_virtual_new(ptile
);
465 /* Would extra get rebuilt if removed */
466 tile_remove_extra(vtile
, pextra
);
467 if (player_can_build_extra(pextra
, city_owner(pcity
), vtile
)) {
468 /* No need to worry about conflicting extras - extra would had
469 * not been here if conflicting one is. */
470 tile_virtual_destroy(vtile
);
475 tile_virtual_destroy(vtile
);
482 /****************************************************************************
483 Tells if player can remove extra from tile with suitable unit.
484 ****************************************************************************/
485 bool player_can_remove_extra(const struct extra_type
*pextra
,
486 const struct player
*pplayer
,
487 const struct tile
*ptile
)
489 if (!can_extra_be_removed(pextra
, ptile
)) {
493 return are_reqs_active(pplayer
, tile_owner(ptile
), NULL
, NULL
, ptile
,
494 NULL
, NULL
, NULL
, NULL
, NULL
, &pextra
->rmreqs
,
498 /****************************************************************************
499 Tells if unit can remove extra from tile.
500 ****************************************************************************/
501 bool can_remove_extra(struct extra_type
*pextra
,
502 const struct unit
*punit
,
503 const struct tile
*ptile
)
505 struct player
*pplayer
;
507 if (!can_extra_be_removed(pextra
, ptile
)) {
511 pplayer
= unit_owner(punit
);
513 return are_reqs_active(pplayer
, tile_owner(ptile
), NULL
, NULL
, ptile
,
514 punit
, unit_type_get(punit
), NULL
, NULL
, NULL
,
515 &pextra
->rmreqs
, RPT_CERTAIN
);
518 /****************************************************************************
519 Is tile native to extra?
520 ****************************************************************************/
521 bool is_native_tile_to_extra(const struct extra_type
*pextra
,
522 const struct tile
*ptile
)
524 struct terrain
*pterr
= tile_terrain(ptile
);
526 if (terrain_has_resource(pterr
, pextra
)) {
530 if (is_extra_caused_by(pextra
, EC_IRRIGATION
)
531 && pterr
->irrigation_result
!= pterr
) {
535 if (is_extra_caused_by(pextra
, EC_MINE
)
536 && pterr
->mining_result
!= pterr
) {
540 if (is_extra_caused_by(pextra
, EC_BASE
)) {
541 if (pterr
->base_time
== 0) {
544 if (tile_city(ptile
) != NULL
&& extra_base_get(pextra
)->border_sq
>= 0) {
549 if (is_extra_caused_by(pextra
, EC_ROAD
)) {
550 struct road_type
*proad
= extra_road_get(pextra
);
552 if (road_has_flag(proad
, RF_RIVER
)) {
553 if (!terrain_has_flag(pterr
, TER_CAN_HAVE_RIVER
)) {
556 } else if (pterr
->road_time
== 0) {
561 return are_reqs_active(NULL
, NULL
, NULL
, NULL
, ptile
,
562 NULL
, NULL
, NULL
, NULL
, NULL
,
563 &pextra
->reqs
, RPT_POSSIBLE
);
566 /****************************************************************************
567 Returns TRUE iff an extra that conflicts with pextra exists at ptile.
568 ****************************************************************************/
569 bool extra_conflicting_on_tile(const struct extra_type
*pextra
,
570 const struct tile
*ptile
)
572 extra_type_iterate(old_extra
) {
573 if (tile_has_extra(ptile
, old_extra
)
574 && !can_extras_coexist(old_extra
, pextra
)) {
577 } extra_type_iterate_end
;
582 /****************************************************************************
583 Returns next extra by cause that unit or player can build to tile.
584 ****************************************************************************/
585 struct extra_type
*next_extra_for_tile(const struct tile
*ptile
, enum extra_cause cause
,
586 const struct player
*pplayer
,
587 const struct unit
*punit
)
589 if (cause
== EC_IRRIGATION
) {
590 struct terrain
*pterrain
= tile_terrain(ptile
);
592 if (pterrain
->irrigation_result
!= pterrain
) {
593 /* No extra can be created by irrigation the tile */
597 if (cause
== EC_MINE
) {
598 struct terrain
*pterrain
= tile_terrain(ptile
);
600 if (pterrain
->mining_result
!= pterrain
) {
601 /* No extra can be created by mining the tile */
606 extra_type_by_cause_iterate(cause
, pextra
) {
607 if (!tile_has_extra(ptile
, pextra
)) {
609 if (can_build_extra(pextra
, punit
, ptile
)) {
613 /* punit is certainly NULL, pplayer can be too */
614 if (player_can_build_extra(pextra
, pplayer
, ptile
)) {
619 } extra_type_by_cause_iterate_end
;
624 /****************************************************************************
625 Returns prev extra by cause that unit or player can remove from tile.
626 ****************************************************************************/
627 struct extra_type
*prev_extra_in_tile(const struct tile
*ptile
,
628 enum extra_rmcause rmcause
,
629 const struct player
*pplayer
,
630 const struct unit
*punit
)
632 fc_assert(punit
!= NULL
|| pplayer
!= NULL
);
634 extra_type_by_rmcause_iterate(rmcause
, pextra
) {
635 if (tile_has_extra(ptile
, pextra
)) {
637 if (can_remove_extra(pextra
, punit
, ptile
)) {
641 if (player_can_remove_extra(pextra
, pplayer
, ptile
)) {
646 } extra_type_by_rmcause_iterate_end
;
651 /****************************************************************************
652 Is extra native to unit class?
653 ****************************************************************************/
654 bool is_native_extra_to_uclass(const struct extra_type
*pextra
,
655 const struct unit_class
*pclass
)
657 return BV_ISSET(pextra
->native_to
, uclass_index(pclass
));
660 /****************************************************************************
661 Is extra native to unit type?
662 ****************************************************************************/
663 bool is_native_extra_to_utype(const struct extra_type
*pextra
,
664 const struct unit_type
*punittype
)
666 return is_native_extra_to_uclass(pextra
, utype_class(punittype
));
669 /****************************************************************************
670 Check if extra has given flag
671 ****************************************************************************/
672 bool extra_has_flag(const struct extra_type
*pextra
, enum extra_flag_id flag
)
674 return BV_ISSET(pextra
->flags
, flag
);
677 /****************************************************************************
678 Returns TRUE iff any cardinally adjacent tile contains an extra with
679 the given flag (does not check ptile itself).
680 ****************************************************************************/
681 bool is_extra_flag_card_near(const struct tile
*ptile
, enum extra_flag_id flag
)
683 extra_type_iterate(pextra
) {
684 if (extra_has_flag(pextra
, flag
)) {
685 cardinal_adjc_iterate(&(wld
.map
), ptile
, adjc_tile
) {
686 if (tile_has_extra(adjc_tile
, pextra
)) {
689 } cardinal_adjc_iterate_end
;
691 } extra_type_iterate_end
;
696 /****************************************************************************
697 Returns TRUE iff any adjacent tile contains an extra with the given flag
698 (does not check ptile itself).
699 ****************************************************************************/
700 bool is_extra_flag_near_tile(const struct tile
*ptile
, enum extra_flag_id flag
)
702 extra_type_iterate(pextra
) {
703 if (extra_has_flag(pextra
, flag
)) {
704 adjc_iterate(&(wld
.map
), ptile
, adjc_tile
) {
705 if (tile_has_extra(adjc_tile
, pextra
)) {
710 } extra_type_iterate_end
;
715 /**************************************************************************
716 Initialize user extra flags.
717 **************************************************************************/
718 void user_extra_flags_init(void)
722 for (i
= 0; i
< MAX_NUM_USER_EXTRA_FLAGS
; i
++) {
723 user_flag_init(&user_extra_flags
[i
]);
727 /***************************************************************
728 Frees the memory associated with all extra flags
729 ***************************************************************/
730 void extra_flags_free(void)
734 for (i
= 0; i
< MAX_NUM_USER_EXTRA_FLAGS
; i
++) {
735 user_flag_free(&user_extra_flags
[i
]);
739 /**************************************************************************
740 Sets user defined name for extra flag.
741 **************************************************************************/
742 void set_user_extra_flag_name(enum extra_flag_id id
, const char *name
,
745 int efid
= id
- EF_USER_FLAG_1
;
747 fc_assert_ret(id
>= EF_USER_FLAG_1
&& id
<= EF_LAST_USER_FLAG
);
749 if (user_extra_flags
[efid
].name
!= NULL
) {
750 FC_FREE(user_extra_flags
[efid
].name
);
751 user_extra_flags
[efid
].name
= NULL
;
754 if (name
&& name
[0] != '\0') {
755 user_extra_flags
[efid
].name
= fc_strdup(name
);
758 if (user_extra_flags
[efid
].helptxt
!= NULL
) {
759 free(user_extra_flags
[efid
].helptxt
);
760 user_extra_flags
[efid
].helptxt
= NULL
;
763 if (helptxt
&& helptxt
[0] != '\0') {
764 user_extra_flags
[efid
].helptxt
= fc_strdup(helptxt
);
768 /**************************************************************************
769 Extra flag name callback, called from specenum code.
770 **************************************************************************/
771 const char *extra_flag_id_name_cb(enum extra_flag_id flag
)
773 if (flag
< EF_USER_FLAG_1
|| flag
> EF_LAST_USER_FLAG
) {
777 return user_extra_flags
[flag
- EF_USER_FLAG_1
].name
;
780 /**************************************************************************
781 Return the (untranslated) help text of the user extra flag.
782 **************************************************************************/
783 const char *extra_flag_helptxt(enum extra_flag_id id
)
785 fc_assert(id
>= EF_USER_FLAG_1
&& id
<= EF_LAST_USER_FLAG
);
787 return user_extra_flags
[id
- EF_USER_FLAG_1
].helptxt
;
790 /**************************************************************************
791 Can two extras coexist in same tile?
792 **************************************************************************/
793 bool can_extras_coexist(const struct extra_type
*pextra1
,
794 const struct extra_type
*pextra2
)
796 if (pextra1
== pextra2
) {
800 return !BV_ISSET(pextra1
->conflicts
, extra_index(pextra2
));
803 /**************************************************************************
804 Does the extra count toward environment upset?
805 **************************************************************************/
806 bool extra_causes_env_upset(struct extra_type
*pextra
,
807 enum environment_upset_type upset
)
810 case EUT_GLOBAL_WARMING
:
811 return extra_has_flag(pextra
, EF_GLOBAL_WARMING
);
812 case EUT_NUCLEAR_WINTER
:
813 return extra_has_flag(pextra
, EF_NUCLEAR_WINTER
);
819 /**************************************************************************
820 Is given cause one of the causes for given extra?
821 **************************************************************************/
822 bool is_extra_caused_by(const struct extra_type
*pextra
, enum extra_cause cause
)
824 /* There's some extra cause lists above EC_COUNT that do not have equivalent
825 * bit in pextra->causes */
826 fc_assert(cause
< EC_COUNT
);
828 return (pextra
->causes
& (1 << cause
));
831 /**************************************************************************
832 Is the extra caused by some kind of worker action?
833 **************************************************************************/
834 bool is_extra_caused_by_worker_action(const struct extra_type
*pextra
)
836 /* Is any of the worker build action bits set? */
837 return (pextra
->causes
838 & (1 << EC_IRRIGATION
844 /**************************************************************************
845 Is the extra removed by some kind of worker action?
846 **************************************************************************/
847 bool is_extra_removed_by_worker_action(const struct extra_type
*pextra
)
849 /* Is any of the worker remove action bits set? */
850 return (pextra
->rmcauses
851 & (1 << ERM_CLEANPOLLUTION
852 | 1 << ERM_CLEANFALLOUT
853 | 1 << ERM_PILLAGE
));
856 /**************************************************************************
857 Is the extra caused by specific worker action?
858 **************************************************************************/
859 bool is_extra_caused_by_action(const struct extra_type
*pextra
,
860 enum unit_activity act
)
862 return is_extra_caused_by(pextra
, activity_to_extra_cause(act
));
865 /**************************************************************************
866 Is the extra removed by specific worker action?
867 **************************************************************************/
868 bool is_extra_removed_by_action(const struct extra_type
*pextra
,
869 enum unit_activity act
)
871 return is_extra_removed_by(pextra
, activity_to_extra_rmcause(act
));
874 /**************************************************************************
875 What extra cause activity is considered to be?
876 **************************************************************************/
877 enum extra_cause
activity_to_extra_cause(enum unit_activity act
)
880 case ACTIVITY_IRRIGATE
:
881 return EC_IRRIGATION
;
886 case ACTIVITY_GEN_ROAD
:
895 /**************************************************************************
896 What extra rmcause activity is considered to be?
897 **************************************************************************/
898 enum extra_rmcause
activity_to_extra_rmcause(enum unit_activity act
)
901 case ACTIVITY_PILLAGE
:
903 case ACTIVITY_POLLUTION
:
904 return ERM_CLEANPOLLUTION
;
905 case ACTIVITY_FALLOUT
:
906 return ERM_CLEANFALLOUT
;
914 /**************************************************************************
915 Who owns extras on tile
916 **************************************************************************/
917 struct player
*extra_owner(const struct tile
*ptile
)
919 return ptile
->extras_owner
;
922 /**************************************************************************
923 Are all the requirements for extra to appear on tile fulfilled.
924 **************************************************************************/
925 bool can_extra_appear(const struct extra_type
*pextra
, const struct tile
*ptile
)
927 return !tile_has_extra(ptile
, pextra
)
928 && is_extra_caused_by(pextra
, EC_APPEARANCE
)
929 && is_native_tile_to_extra(pextra
, ptile
)
930 && !extra_conflicting_on_tile(pextra
, ptile
)
931 && are_reqs_active(NULL
, tile_owner(ptile
), NULL
, NULL
, ptile
,
932 NULL
, NULL
, NULL
, NULL
, NULL
,
933 &pextra
->appearance_reqs
, RPT_CERTAIN
);
936 /**************************************************************************
937 Are all the requirements for extra to disappear from tile fulfilled.
938 **************************************************************************/
939 bool can_extra_disappear(const struct extra_type
*pextra
, const struct tile
*ptile
)
941 return tile_has_extra(ptile
, pextra
)
942 && is_extra_removed_by(pextra
, ERM_DISAPPEARANCE
)
943 && can_extra_be_removed(pextra
, ptile
)
944 && are_reqs_active(NULL
, tile_owner(ptile
), NULL
, NULL
, ptile
,
945 NULL
, NULL
, NULL
, NULL
, NULL
,
946 &pextra
->disappearance_reqs
, RPT_CERTAIN
);
949 /**************************************************************************
950 Extra is not hidden from the user.
951 **************************************************************************/
952 bool player_knows_extra_exist(const struct player
*pplayer
,
953 const struct extra_type
*pextra
,
954 const struct tile
*ptile
)
956 if (!tile_has_extra(ptile
, pextra
)) {
960 return research_invention_state(research_get(pplayer
),
961 pextra
->visibility_req
) == TECH_KNOWN
;