Stop sharing requirement_unit_state_ereq().
[freeciv.git] / common / extras.c
blob90685f65a369f54151c7ddce6d0a663b113dd8f2
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)
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 "rand.h"
20 #include "string_vector.h"
22 /* common */
23 #include "base.h"
24 #include "game.h"
25 #include "map.h"
26 #include "road.h"
28 #include "extras.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)
44 int i;
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));
62 extras[i].id = i;
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;
68 extras[i].causes = 0;
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)
80 int i;
82 base_types_free();
83 road_types_free();
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]);
103 caused_by[i] = NULL;
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);
117 unit_hidden = NULL;
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 /**************************************************************************
148 Return the extra id.
149 **************************************************************************/
150 int extra_number(const struct extra_type *pextra)
152 fc_assert_ret_val(NULL != pextra, -1);
154 return pextra->id;
157 #ifndef extra_index
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);
176 return &extras[id];
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
199 with such name.
200 **************************************************************************/
201 struct extra_type *extra_type_by_rule_name(const char *name)
203 const char *qs;
205 if (name == NULL) {
206 return NULL;
209 qs = Qn_(name);
211 extra_type_iterate(pextra) {
212 if (!fc_strcasecmp(extra_rule_name(pextra), qs)) {
213 return pextra;
215 } extra_type_iterate_end;
217 return NULL;
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)) {
228 return pextra;
230 } extra_type_iterate_end;
232 return NULL;
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)
260 return unit_hidden;
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();
270 int options;
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);
281 if (options > 0) {
282 selected = extra_type_list_get(potential, fc_rand(options));
285 extra_type_list_destroy(potential);
287 return selected;
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)) {
348 return TRUE;
350 } cardinal_adjc_iterate_end;
352 return FALSE;
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)) {
363 return TRUE;
365 } adjc_iterate_end;
367 return FALSE;
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 */
378 return FALSE;
381 if (tile_has_extra(ptile, pextra)) {
382 /* Extra exist already */
383 return FALSE;
386 return TRUE;
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)) {
398 return FALSE;
401 if (is_extra_caused_by(pextra, EC_ROAD)
402 && !can_build_road_base(extra_road_get(pextra), pplayer, ptile)) {
403 return FALSE;
406 if (!extra_can_be_built(pextra, ptile)) {
407 return FALSE;
410 return TRUE;
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)) {
421 return FALSE;
424 return are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
425 NULL, NULL, NULL, NULL, NULL, &pextra->reqs,
426 RPT_POSSIBLE);
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)) {
439 return FALSE;
442 return are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
443 punit, unit_type_get(punit), NULL, NULL, NULL, &pextra->reqs,
444 RPT_CERTAIN);
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. */
456 if (pcity != NULL) {
457 if (extra_has_flag(pextra, EF_ALWAYS_ON_CITY_CENTER)) {
458 return FALSE;
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);
470 return FALSE;
473 tile_virtual_destroy(vtile);
477 return TRUE;
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)) {
488 return FALSE;
491 return are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
492 NULL, NULL, NULL, NULL, NULL, &pextra->rmreqs,
493 RPT_POSSIBLE);
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)) {
506 return FALSE;
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)) {
525 return TRUE;
528 if (is_extra_caused_by(pextra, EC_IRRIGATION)
529 && pterr->irrigation_result != pterr) {
530 return FALSE;
533 if (is_extra_caused_by(pextra, EC_MINE)
534 && pterr->mining_result != pterr) {
535 return FALSE;
538 if (is_extra_caused_by(pextra, EC_BASE)) {
539 if (pterr->base_time == 0) {
540 return FALSE;
542 if (tile_city(ptile) != NULL && extra_base_get(pextra)->border_sq >= 0) {
543 return FALSE;
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)) {
552 return FALSE;
554 } else if (pterr->road_time == 0) {
555 return FALSE;
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)) {
573 return TRUE;
575 } extra_type_iterate_end;
577 return FALSE;
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 */
592 return NULL;
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 */
600 return NULL;
604 extra_type_by_cause_iterate(cause, pextra) {
605 if (!tile_has_extra(ptile, pextra)) {
606 if (punit != NULL) {
607 if (can_build_extra(pextra, punit, ptile)) {
608 return pextra;
610 } else {
611 /* punit is certainly NULL, pplayer can be too */
612 if (player_can_build_extra(pextra, pplayer, ptile)) {
613 return pextra;
617 } extra_type_by_cause_iterate_end;
619 return NULL;
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)) {
634 if (punit != NULL) {
635 if (can_remove_extra(pextra, punit, ptile)) {
636 return pextra;
638 } else {
639 if (player_can_remove_extra(pextra, pplayer, ptile)) {
640 return pextra;
644 } extra_type_by_rmcause_iterate_end;
646 return NULL;
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)) {
685 return TRUE;
687 } cardinal_adjc_iterate_end;
689 } extra_type_iterate_end;
691 return FALSE;
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)) {
704 return TRUE;
706 } adjc_iterate_end;
708 } extra_type_iterate_end;
710 return FALSE;
713 /**************************************************************************
714 Initialize user extra flags.
715 **************************************************************************/
716 void user_extra_flags_init(void)
718 int i;
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)
730 int i;
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,
741 const char *helptxt)
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) {
772 return NULL;
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) {
795 return TRUE;
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)
807 switch (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);
814 return FALSE;
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
837 | 1 << EC_MINE
838 | 1 << EC_BASE
839 | 1 << EC_ROAD));
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)
877 switch(act) {
878 case ACTIVITY_IRRIGATE:
879 return EC_IRRIGATION;
880 case ACTIVITY_MINE:
881 return EC_MINE;
882 case ACTIVITY_BASE:
883 return EC_BASE;
884 case ACTIVITY_GEN_ROAD:
885 return EC_ROAD;
886 default:
887 break;
890 return EC_NONE;
893 /**************************************************************************
894 What extra rmcause activity is considered to be?
895 **************************************************************************/
896 enum extra_rmcause activity_to_extra_rmcause(enum unit_activity act)
898 switch(act) {
899 case ACTIVITY_PILLAGE:
900 return ERM_PILLAGE;
901 case ACTIVITY_POLLUTION:
902 return ERM_CLEANPOLLUTION;
903 case ACTIVITY_FALLOUT:
904 return ERM_CLEANFALLOUT;
905 default:
906 break;
909 return ERM_NONE;
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);