Freeciv-3.1
Loading...
Searching...
No Matches
extras.c
Go to the documentation of this file.
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.
7
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****************************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* utility */
19#include "rand.h"
20#include "string_vector.h"
21
22/* common */
23#include "base.h"
24#include "game.h"
25#include "map.h"
26#include "research.h"
27#include "road.h"
28
29#include "extras.h"
30
32
34
35static struct extra_type_list *caused_by[EC_LAST];
36static struct extra_type_list *removed_by[ERM_COUNT];
37static struct extra_type_list *unit_hidden;
38static struct extra_type_list *terr_claimer;
39
40/************************************************************************/
43void extras_init(void)
44{
45 int i;
46
47 for (i = 0; i < EC_LAST; i++) {
48 caused_by[i] = extra_type_list_new();
49 }
50 for (i = 0; i < ERM_COUNT; i++) {
51 removed_by[i] = extra_type_list_new();
52 }
53 unit_hidden = extra_type_list_new();
54 terr_claimer = extra_type_list_new();
55
56 for (i = 0; i < MAX_EXTRA_TYPES; i++) {
57 requirement_vector_init(&(extras[i].reqs));
58 requirement_vector_init(&(extras[i].rmreqs));
59 requirement_vector_init(&(extras[i].appearance_reqs));
60 requirement_vector_init(&(extras[i].disappearance_reqs));
61 extras[i].id = i;
62 extras[i].hiders = NULL;
63 extras[i].bridged = 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;
72 extras[i].ruledit_dlg = NULL;
74 }
75}
76
77/************************************************************************/
80void extras_free(void)
81{
82 int i;
83
87
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;
92 }
93 if (extras[i].data.road != NULL) {
94 FC_FREE(extras[i].data.road);
95 extras[i].data.road = NULL;
96 }
97 if (extras[i].data.resource != NULL) {
98 FC_FREE(extras[i].data.resource);
99 extras[i].data.resource = NULL;
100 }
101 }
102
103 for (i = 0; i < EC_LAST; i++) {
104 extra_type_list_destroy(caused_by[i]);
105 caused_by[i] = NULL;
106 }
107
108 for (i = 0; i < ERM_COUNT; i++) {
109 extra_type_list_destroy(removed_by[i]);
110 removed_by[i] = NULL;
111 }
112
113 extra_type_list_destroy(unit_hidden);
114 unit_hidden = NULL;
115 extra_type_list_destroy(terr_claimer);
116 terr_claimer = NULL;
117
118 for (i = 0; i < MAX_EXTRA_TYPES; i++) {
119 requirement_vector_free(&(extras[i].reqs));
120 requirement_vector_free(&(extras[i].rmreqs));
121 requirement_vector_free(&(extras[i].appearance_reqs));
122 requirement_vector_free(&(extras[i].disappearance_reqs));
123
124 if (NULL != extras[i].helptext) {
125 strvec_destroy(extras[i].helptext);
126 extras[i].helptext = NULL;
127 }
128 }
129
130 extra_type_iterate(pextra) {
131 if (pextra->hiders != NULL) {
132 extra_type_list_destroy(pextra->hiders);
133 pextra->hiders = NULL;
134 }
135 if (pextra->bridged != NULL) {
136 extra_type_list_destroy(pextra->bridged);
137 pextra->bridged = NULL;
138 }
140}
141
142/************************************************************************/
145int extra_count(void)
146{
148}
149
150/************************************************************************/
153int extra_number(const struct extra_type *pextra)
154{
155 fc_assert_ret_val(NULL != pextra, -1);
156
157 return pextra->id;
158}
159
160#ifndef extra_index
161/************************************************************************/
164int extra_index(const struct extra_type *pextra)
165{
166 fc_assert_ret_val(NULL != pextra, -1);
167
168 return pextra - extras;
169}
170#endif /* extra_index */
171
172/************************************************************************/
176{
177 fc_assert_ret_val(id >= 0 && id < MAX_EXTRA_TYPES, NULL);
178
179 return &extras[id];
180}
181
182/************************************************************************/
186const char *extra_name_translation(const struct extra_type *pextra)
187{
188 return name_translation_get(&pextra->name);
189}
190
191/************************************************************************/
195const char *extra_rule_name(const struct extra_type *pextra)
196{
197 return rule_name_get(&pextra->name);
198}
199
200/************************************************************************/
205{
206 const char *qs;
207
208 if (name == NULL) {
209 return NULL;
210 }
211
212 qs = Qn_(name);
213
214 extra_type_iterate(pextra) {
215 if (!fc_strcasecmp(extra_rule_name(pextra), qs)) {
216 return pextra;
217 }
219
220 return NULL;
221}
222
223/************************************************************************/
228{
229 extra_type_iterate(pextra) {
230 if (0 == strcmp(extra_name_translation(pextra), name)) {
231 return pextra;
232 }
234
235 return NULL;
236}
237
238/************************************************************************/
241struct extra_type_list *extra_type_list_by_cause(enum extra_cause cause)
242{
243 fc_assert(cause < EC_LAST);
244
245 return caused_by[cause];
246}
247
248/************************************************************************/
251struct extra_type_list *extra_type_list_of_unit_hiders(void)
252{
253 return unit_hidden;
254}
255
256/************************************************************************/
259struct extra_type_list *extra_type_list_of_terr_claimers(void)
260{
261 return terr_claimer;
262}
263
264/************************************************************************/
267struct extra_type *rand_extra_for_tile(struct tile *ptile, enum extra_cause cause,
268 bool generated)
269{
270 struct extra_type_list *full_list = extra_type_list_by_cause(cause);
271 struct extra_type_list *potential = extra_type_list_new();
272 int options;
273 struct extra_type *selected = NULL;
274
275 extra_type_list_iterate(full_list, pextra) {
276 if ((!generated || pextra->generated)
277 && is_native_tile_to_extra(pextra, ptile)) {
278 extra_type_list_append(potential, pextra);
279 }
281
282 options = extra_type_list_size(potential);
283
284 if (options > 0) {
285 selected = extra_type_list_get(potential, fc_rand(options));
286 }
287
288 extra_type_list_destroy(potential);
289
290 return selected;
291}
292
293/************************************************************************/
296void extra_to_caused_by_list(struct extra_type *pextra, enum extra_cause cause)
297{
298 fc_assert(cause < EC_LAST);
299
300 extra_type_list_append(caused_by[cause], pextra);
301}
302
303/************************************************************************/
306struct extra_type_list *extra_type_list_by_rmcause(enum extra_rmcause rmcause)
307{
308 fc_assert(rmcause < ERM_COUNT);
309
310 return removed_by[rmcause];
311}
312
313/************************************************************************/
317 enum extra_rmcause rmcause)
318{
319 fc_assert(rmcause < ERM_COUNT);
320
321 extra_type_list_append(removed_by[rmcause], pextra);
322}
323
324/************************************************************************/
327bool is_extra_removed_by(const struct extra_type *pextra,
328 enum extra_rmcause rmcause)
329{
330 return (pextra->rmcauses & (1 << rmcause));
331}
332
333/************************************************************************/
337bool is_extra_card_near(const struct civ_map *nmap, const struct tile *ptile,
338 const struct extra_type *pextra)
339{
340 cardinal_adjc_iterate(nmap, ptile, adjc_tile) {
341 if (tile_has_extra(adjc_tile, pextra)) {
342 return TRUE;
343 }
345
346 return FALSE;
347}
348
349/************************************************************************/
353bool is_extra_near_tile(const struct civ_map *nmap, const struct tile *ptile,
354 const struct extra_type *pextra)
355{
356 adjc_iterate(nmap, ptile, adjc_tile) {
357 if (tile_has_extra(adjc_tile, pextra)) {
358 return TRUE;
359 }
361
362 return FALSE;
363}
364
365/************************************************************************/
368bool extra_can_be_built(const struct extra_type *pextra,
369 const struct tile *ptile)
370{
371 if (!pextra->buildable) {
372 /* Extra type not buildable */
373 return FALSE;
374 }
375
376 if (tile_has_extra(ptile, pextra)) {
377 /* Extra exist already */
378 return FALSE;
379 }
380
381 return TRUE;
382}
383
384/************************************************************************/
387bool can_build_extra_base(const struct extra_type *pextra,
388 const struct player *pplayer,
389 const struct tile *ptile)
390{
391 struct terrain *pterr;
392
393 if (!extra_can_be_built(pextra, ptile)) {
394 return FALSE;
395 }
396
397 pterr = tile_terrain(ptile);
398
399 if (is_extra_caused_by(pextra, EC_BASE)) {
400 if (pterr->base_time == 0) {
401 return FALSE;
402 }
403 if (tile_city(ptile) != NULL && extra_base_get(pextra)->border_sq >= 0) {
404 return FALSE;
405 }
406 }
407
408 /* Even if it's a multi-cause extra, just having Build Road as one of the
409 * causes makes it to require that road_time != 0.
410 * Correct functioning of EC_PLACE extras depend on this. */
411 if (is_extra_caused_by(pextra, EC_ROAD)
412 && pterr->road_time == 0) {
413 return FALSE;
414 }
415
416 if (is_extra_caused_by(pextra, EC_IRRIGATION)
417 && pterr->irrigation_time == 0) {
418 return FALSE;
419 }
420
421 if (is_extra_caused_by(pextra, EC_MINE)
422 && pterr->mining_time == 0) {
423 return FALSE;
424 }
425
426 if (pplayer != NULL && !player_knows_techs_with_flag(pplayer, TF_BRIDGE)) {
427 /* Player does not know technology to bridge over extras that require it. */
428 extra_type_list_iterate(pextra->bridged, pbridged) {
429 if (tile_has_extra(ptile, pbridged)) {
430 /* Tile has extra that would require bridging over. */
431 return FALSE;
432 }
434 }
435
436 return TRUE;
437}
438
439/************************************************************************/
442bool player_can_build_extra(const struct extra_type *pextra,
443 const struct player *pplayer,
444 const struct tile *ptile)
445{
446 if (!can_build_extra_base(pextra, pplayer, ptile)) {
447 return FALSE;
448 }
449
450 return are_reqs_active(&(const struct req_context) {
451 .player = pplayer,
452 .tile = ptile,
453 },
454 tile_owner(ptile),
455 &pextra->reqs,
457}
458
459/************************************************************************/
462bool player_can_place_extra(const struct extra_type *pextra,
463 const struct player *pplayer,
464 const struct tile *ptile)
465{
466 if (pextra->infracost == 0) {
467 return FALSE;
468 }
469
470 if (ptile->placing != NULL) {
471 /* Already placing something */
472 return FALSE;
473 }
474
475 if (tile_terrain(ptile)->placing_time <= 0) {
476 /* Can't place to this terrain */
477 return FALSE;
478 }
479
481 if (tile_owner(ptile) != pplayer) {
482 return FALSE;
483 }
484 } else {
485 struct city *pcity = tile_worked(ptile);
486
487 if (pcity == NULL || city_owner(pcity) != pplayer) {
488 return FALSE;
489 }
490 }
491
492 /* Placing extras is not allowed to tiles where also workers do changes. */
493 unit_list_iterate(ptile->units, punit) {
495 if (punit->activity == act) {
496 return FALSE;
497 }
500
501 return player_can_build_extra(pextra, pplayer, ptile);
502}
503
504/************************************************************************/
507bool can_build_extra(const struct extra_type *pextra,
508 const struct unit *punit,
509 const struct tile *ptile)
510{
511 struct player *pplayer = unit_owner(punit);
512
513 if (!can_build_extra_base(pextra, pplayer, ptile)) {
514 return FALSE;
515 }
516
517 return are_reqs_active(&(const struct req_context) {
518 .player = pplayer,
519 .tile = ptile,
520 .unit = punit,
521 .unittype = unit_type_get(punit),
522 },
523 tile_owner(ptile),
524 &pextra->reqs,
526}
527
528/************************************************************************/
531static bool can_extra_be_removed(const struct extra_type *pextra,
532 const struct tile *ptile)
533{
534 struct city *pcity = tile_city(ptile);
535
536 /* Cannot remove EF_ALWAYS_ON_CITY_CENTER extras from city center. */
537 if (pcity != NULL) {
538 if (extra_has_flag(pextra, EF_ALWAYS_ON_CITY_CENTER)) {
539 return FALSE;
540 }
541 if (extra_has_flag(pextra, EF_AUTO_ON_CITY_CENTER)) {
542 struct tile *vtile = tile_virtual_new(ptile);
543
544 /* Would extra get rebuilt if removed */
545 tile_remove_extra(vtile, pextra);
546 if (player_can_build_extra(pextra, city_owner(pcity), vtile)) {
547 /* No need to worry about conflicting extras - extra would had
548 * not been here if conflicting one is. */
550
551 return FALSE;
552 }
553
555 }
556 }
557
558 return TRUE;
559}
560
561/************************************************************************/
564bool player_can_remove_extra(const struct extra_type *pextra,
565 const struct player *pplayer,
566 const struct tile *ptile)
567{
568 if (!can_extra_be_removed(pextra, ptile)) {
569 return FALSE;
570 }
571
572 /* For huts, it's not checked if player has any non-HUT_NOTHING units */
573 return are_reqs_active(&(const struct req_context) {
574 .player = pplayer,
575 .tile = ptile,
576 },
577 tile_owner(ptile),
578 &pextra->rmreqs,
580}
581
582/************************************************************************/
586bool can_remove_extra(const struct extra_type *pextra,
587 const struct unit *punit,
588 const struct tile *ptile)
589{
590
591 if (!can_extra_be_removed(pextra, ptile)) {
592 return FALSE;
593 }
594
595 return are_reqs_active(&(const struct req_context) {
596 .player = unit_owner(punit),
597 .tile = ptile,
598 .unit = punit,
599 .unittype = unit_type_get(punit),
600 },
601 tile_owner(ptile),
602 &pextra->rmreqs, RPT_CERTAIN);
603}
604
605/************************************************************************/
608bool is_native_tile_to_extra(const struct extra_type *pextra,
609 const struct tile *ptile)
610{
611 struct terrain *pterr = tile_terrain(ptile);
612
613 if (terrain_has_resource(pterr, pextra)) {
614 return TRUE;
615 }
616
617 if (is_extra_caused_by(pextra, EC_IRRIGATION)
618 && pterr->irrigation_time == 0) {
619 return FALSE;
620 }
621
622 if (is_extra_caused_by(pextra, EC_MINE)
623 && pterr->mining_time == 0) {
624 return FALSE;
625 }
626
627 if (is_extra_caused_by(pextra, EC_BASE)) {
628 if (pterr->base_time == 0) {
629 return FALSE;
630 }
631 if (tile_city(ptile) != NULL && extra_base_get(pextra)->border_sq >= 0) {
632 return FALSE;
633 }
634 }
635
636 if (is_extra_caused_by(pextra, EC_ROAD)) {
637 struct road_type *proad = extra_road_get(pextra);
638
639 if (road_has_flag(proad, RF_RIVER)) {
640 if (!terrain_has_flag(pterr, TER_CAN_HAVE_RIVER)) {
641 return FALSE;
642 }
643 } else if (pterr->road_time == 0) {
644 return FALSE;
645 }
646 }
647
648 return are_reqs_active(&(const struct req_context) { .tile = ptile },
649 NULL, &pextra->reqs, RPT_POSSIBLE);
650}
651
652/************************************************************************/
655bool extra_conflicting_on_tile(const struct extra_type *pextra,
656 const struct tile *ptile)
657{
658 extra_type_iterate(old_extra) {
659 if (tile_has_extra(ptile, old_extra)
660 && !can_extras_coexist(old_extra, pextra)) {
661 return TRUE;
662 }
664
665 return FALSE;
666}
667
668/************************************************************************/
672bool hut_on_tile(const struct tile *ptile)
673{
674 extra_type_by_rmcause_iterate(ERM_ENTER, extra) {
675 if (tile_has_extra(ptile, extra)) {
676 return TRUE;
677 }
679
680 return FALSE;
681}
682
683/************************************************************************/
687bool unit_can_enter_hut(const struct unit *punit,
688 const struct tile *ptile)
689{
690 const struct req_context context = {
692 .tile = ptile,
693 };
694
695 if (!(unit_can_do_action_result(punit, ACTRES_HUT_ENTER)
696 || unit_can_do_action_sub_result(punit, ACT_SUB_RES_HUT_ENTER))) {
697 return FALSE;
698 }
699 extra_type_by_rmcause_iterate(ERM_ENTER, extra) {
700 if (tile_has_extra(ptile, extra)
701 && are_reqs_active(&context, tile_owner(ptile), &extra->rmreqs,
702 RPT_POSSIBLE)) {
703 return TRUE;
704 }
706 return FALSE;
707}
708
709/************************************************************************/
714 const struct tile *ptile)
715{
716 const struct req_context context = {
718 .tile = ptile,
719 };
720
721 if (!(unit_can_do_action_result(punit, ACTRES_HUT_FRIGHTEN)
722 || unit_can_do_action_sub_result(punit, ACT_SUB_RES_HUT_FRIGHTEN)
723 || unit_can_do_action_result(punit, ACTRES_HUT_ENTER)
724 || unit_can_do_action_sub_result(punit, ACT_SUB_RES_HUT_ENTER))) {
725 return FALSE;
726 }
727 extra_type_by_rmcause_iterate(ERM_ENTER, extra) {
728 if (tile_has_extra(ptile, extra)
729 && are_reqs_active(&context, tile_owner(ptile), &extra->rmreqs,
730 RPT_POSSIBLE)) {
731 return TRUE;
732 }
734 return FALSE;
735}
736
737/************************************************************************/
740struct extra_type *next_extra_for_tile(const struct tile *ptile, enum extra_cause cause,
741 const struct player *pplayer,
742 const struct unit *punit)
743{
744 extra_type_by_cause_iterate(cause, pextra) {
745 if (!tile_has_extra(ptile, pextra)) {
746 if (punit != NULL) {
747 if (can_build_extra(pextra, punit, ptile)) {
748 return pextra;
749 }
750 } else {
751 /* punit is certainly NULL, pplayer can be too */
752 if (player_can_build_extra(pextra, pplayer, ptile)) {
753 return pextra;
754 }
755 }
756 }
758
759 return NULL;
760}
761
762/************************************************************************/
765struct extra_type *prev_extra_in_tile(const struct tile *ptile,
766 enum extra_rmcause rmcause,
767 const struct player *pplayer,
768 const struct unit *punit)
769{
770 fc_assert(punit != NULL || pplayer != NULL);
771
772 extra_type_by_rmcause_iterate(rmcause, pextra) {
773 if (tile_has_extra(ptile, pextra)) {
774 if (punit != NULL) {
775 if (can_remove_extra(pextra, punit, ptile)) {
776 return pextra;
777 }
778 } else {
779 if (player_can_remove_extra(pextra, pplayer, ptile)) {
780 return pextra;
781 }
782 }
783 }
785
786 return NULL;
787}
788
789/************************************************************************/
792bool is_native_extra_to_uclass(const struct extra_type *pextra,
793 const struct unit_class *pclass)
794{
795 return BV_ISSET(pextra->native_to, uclass_index(pclass));
796}
797
798/************************************************************************/
801bool is_native_extra_to_utype(const struct extra_type *pextra,
802 const struct unit_type *punittype)
803{
804 return is_native_extra_to_uclass(pextra, utype_class(punittype));
805}
806
807/************************************************************************/
810bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
811{
812 return BV_ISSET(pextra->flags, flag);
813}
814
815/************************************************************************/
819bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile,
820 enum extra_flag_id flag)
821{
822 extra_type_iterate(pextra) {
823 if (extra_has_flag(pextra, flag)) {
824 cardinal_adjc_iterate(nmap, ptile, adjc_tile) {
825 if (tile_has_extra(adjc_tile, pextra)) {
826 return TRUE;
827 }
829 }
831
832 return FALSE;
833}
834
835/************************************************************************/
839bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile,
840 enum extra_flag_id flag)
841{
842 extra_type_iterate(pextra) {
843 if (extra_has_flag(pextra, flag)) {
844 adjc_iterate(nmap, ptile, adjc_tile) {
845 if (tile_has_extra(adjc_tile, pextra)) {
846 return TRUE;
847 }
849 }
851
852 return FALSE;
853}
854
855/************************************************************************/
859{
860 int i;
861
862 for (i = 0; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
864 }
865}
866
867/************************************************************************/
871{
872 int i;
873
874 for (i = 0; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
876 }
877}
878
879/************************************************************************/
882void set_user_extra_flag_name(enum extra_flag_id id, const char *name,
883 const char *helptxt)
884{
885 int efid = id - EF_USER_FLAG_1;
886
887 fc_assert_ret(id >= EF_USER_FLAG_1 && id <= EF_LAST_USER_FLAG);
888
889 if (user_extra_flags[efid].name != NULL) {
891 user_extra_flags[efid].name = NULL;
892 }
893
894 if (name && name[0] != '\0') {
896 }
897
898 if (user_extra_flags[efid].helptxt != NULL) {
899 free(user_extra_flags[efid].helptxt);
900 user_extra_flags[efid].helptxt = NULL;
901 }
902
903 if (helptxt && helptxt[0] != '\0') {
904 user_extra_flags[efid].helptxt = fc_strdup(helptxt);
905 }
906}
907
908/************************************************************************/
911const char *extra_flag_id_name_cb(enum extra_flag_id flag)
912{
913 if (flag < EF_USER_FLAG_1 || flag > EF_LAST_USER_FLAG) {
914 return NULL;
915 }
916
917 return user_extra_flags[flag - EF_USER_FLAG_1].name;
918}
919
920/************************************************************************/
923const char *extra_flag_helptxt(enum extra_flag_id id)
924{
925 fc_assert(id >= EF_USER_FLAG_1 && id <= EF_LAST_USER_FLAG);
926
927 return user_extra_flags[id - EF_USER_FLAG_1].helptxt;
928}
929
930/**********************************************************************/
936bool extra_flag_is_in_use(enum extra_flag_id id)
937{
939 if (extra_has_flag(pextra, id)) {
940 /* Found a user. */
941 return TRUE;
942 }
944
945 /* No users detected. */
946 return FALSE;
947}
948
949/************************************************************************/
952bool can_extras_coexist(const struct extra_type *pextra1,
953 const struct extra_type *pextra2)
954{
955 if (pextra1 == pextra2) {
956 return TRUE;
957 }
958
959 return !BV_ISSET(pextra1->conflicts, extra_index(pextra2));
960}
961
962/************************************************************************/
966 enum environment_upset_type upset)
967{
968 switch (upset) {
970 return extra_has_flag(pextra, EF_GLOBAL_WARMING);
972 return extra_has_flag(pextra, EF_NUCLEAR_WINTER);
973 }
974
975 return FALSE;
976}
977
978/************************************************************************/
982{
983 /* Is any of the worker build action bits set? */
984 return (pextra->causes
985 & (1 << EC_IRRIGATION
986 | 1 << EC_MINE
987 | 1 << EC_BASE
988 | 1 << EC_ROAD));
989}
990
991/************************************************************************/
995{
996 /* Is any of the worker remove action bits set? */
997 return (pextra->rmcauses
998 & (1 << ERM_CLEANPOLLUTION
999 | 1 << ERM_CLEANFALLOUT
1000 | 1 << ERM_PILLAGE));
1001}
1002
1003/************************************************************************/
1006bool is_extra_caused_by_action(const struct extra_type *pextra,
1007 const struct action *paction)
1008{
1009 enum unit_activity act = actres_get_activity(paction->result);
1010
1011 return is_extra_caused_by(pextra, activity_to_extra_cause(act));
1012}
1013
1014/************************************************************************/
1017bool is_extra_removed_by_action(const struct extra_type *pextra,
1018 const struct action *paction)
1019{
1020 enum unit_activity act = actres_get_activity(paction->result);
1021
1023}
1024
1025/************************************************************************/
1028enum extra_cause activity_to_extra_cause(enum unit_activity act)
1029{
1030 switch (act) {
1031 case ACTIVITY_IRRIGATE:
1032 return EC_IRRIGATION;
1033 case ACTIVITY_MINE:
1034 return EC_MINE;
1035 case ACTIVITY_BASE:
1036 return EC_BASE;
1037 case ACTIVITY_GEN_ROAD:
1038 return EC_ROAD;
1039 default:
1040 break;
1041 }
1042
1043 return EC_NONE;
1044}
1045
1046/************************************************************************/
1049enum extra_rmcause activity_to_extra_rmcause(enum unit_activity act)
1050{
1051 switch (act) {
1052 case ACTIVITY_PILLAGE:
1053 return ERM_PILLAGE;
1054 case ACTIVITY_POLLUTION:
1055 return ERM_CLEANPOLLUTION;
1056 case ACTIVITY_FALLOUT:
1057 return ERM_CLEANFALLOUT;
1058 default:
1059 break;
1060 }
1061
1062 return ERM_NONE;
1063}
1064
1065/************************************************************************/
1068struct player *extra_owner(const struct tile *ptile)
1069{
1070 return ptile->extras_owner;
1071}
1072
1073/************************************************************************/
1076bool can_extra_appear(const struct extra_type *pextra, const struct tile *ptile)
1077{
1078 return !tile_has_extra(ptile, pextra)
1079 && is_extra_caused_by(pextra, EC_APPEARANCE)
1080 && is_native_tile_to_extra(pextra, ptile)
1081 && !extra_conflicting_on_tile(pextra, ptile)
1082 && are_reqs_active(&(const struct req_context) { .tile = ptile },
1083 tile_owner(ptile),
1084 &pextra->appearance_reqs, RPT_CERTAIN);
1085}
1086
1087/************************************************************************/
1090bool can_extra_disappear(const struct extra_type *pextra, const struct tile *ptile)
1091{
1092 return tile_has_extra(ptile, pextra)
1093 && is_extra_removed_by(pextra, ERM_DISAPPEARANCE)
1094 && can_extra_be_removed(pextra, ptile)
1095 && are_reqs_active(&(const struct req_context) { .tile = ptile },
1096 tile_owner(ptile),
1098}
1099
1100/************************************************************************/
1103bool player_knows_extra_exist(const struct player *pplayer,
1104 const struct extra_type *pextra,
1105 const struct tile *ptile)
1106{
1107 if (!tile_has_extra(ptile, pextra)) {
1108 return FALSE;
1109 }
1110
1111 return research_invention_state(research_get(pplayer),
1112 pextra->visibility_req) == TECH_KNOWN;
1113}
enum unit_activity actres_get_activity(enum action_result result)
Definition actions.c:2136
void base_types_free(void)
Definition base.c:132
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
#define city_owner(_pcity_)
Definition city.h:543
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
int int id
Definition editgui_g.h:28
struct @21::@22 reqs
bool is_extra_removed_by_worker_action(const struct extra_type *pextra)
Definition extras.c:994
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:740
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:204
bool extra_causes_env_upset(struct extra_type *pextra, enum environment_upset_type upset)
Definition extras.c:965
bool can_build_extra_base(const struct extra_type *pextra, const struct player *pplayer, const struct tile *ptile)
Definition extras.c:387
bool unit_can_displace_hut(const struct unit *punit, const struct tile *ptile)
Definition extras.c:713
struct extra_type * rand_extra_for_tile(struct tile *ptile, enum extra_cause cause, bool generated)
Definition extras.c:267
bool player_can_place_extra(const struct extra_type *pextra, const struct player *pplayer, const struct tile *ptile)
Definition extras.c:462
void user_extra_flags_init(void)
Definition extras.c:858
struct player * extra_owner(const struct tile *ptile)
Definition extras.c:1068
bool extra_flag_is_in_use(enum extra_flag_id id)
Definition extras.c:936
const char * extra_flag_helptxt(enum extra_flag_id id)
Definition extras.c:923
struct extra_type * extra_type_by_translated_name(const char *name)
Definition extras.c:227
void set_user_extra_flag_name(enum extra_flag_id id, const char *name, const char *helptxt)
Definition extras.c:882
bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:839
static struct extra_type_list * removed_by[ERM_COUNT]
Definition extras.c:36
static struct extra_type_list * terr_claimer
Definition extras.c:38
bool unit_can_enter_hut(const struct unit *punit, const struct tile *ptile)
Definition extras.c:687
bool is_extra_caused_by_worker_action(const struct extra_type *pextra)
Definition extras.c:981
bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:819
void extras_free(void)
Definition extras.c:80
bool can_extra_appear(const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:1076
bool is_extra_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:353
int extra_number(const struct extra_type *pextra)
Definition extras.c:153
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:810
static struct extra_type_list * caused_by[EC_LAST]
Definition extras.c:35
bool is_native_tile_to_extra(const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:608
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Definition extras.c:241
struct extra_type_list * extra_type_list_by_rmcause(enum extra_rmcause rmcause)
Definition extras.c:306
struct extra_type * prev_extra_in_tile(const struct tile *ptile, enum extra_rmcause rmcause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:765
bool hut_on_tile(const struct tile *ptile)
Definition extras.c:672
bool is_extra_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:337
void extra_to_caused_by_list(struct extra_type *pextra, enum extra_cause cause)
Definition extras.c:296
bool player_can_build_extra(const struct extra_type *pextra, const struct player *pplayer, const struct tile *ptile)
Definition extras.c:442
struct extra_type * extra_by_number(int id)
Definition extras.c:175
enum extra_cause activity_to_extra_cause(enum unit_activity act)
Definition extras.c:1028
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
bool extra_can_be_built(const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:368
bool is_native_extra_to_utype(const struct extra_type *pextra, const struct unit_type *punittype)
Definition extras.c:801
const char * extra_flag_id_name_cb(enum extra_flag_id flag)
Definition extras.c:911
bool extra_conflicting_on_tile(const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:655
static struct user_flag user_extra_flags[MAX_NUM_USER_EXTRA_FLAGS]
Definition extras.c:33
void extra_to_removed_by_list(struct extra_type *pextra, enum extra_rmcause rmcause)
Definition extras.c:316
bool can_extras_coexist(const struct extra_type *pextra1, const struct extra_type *pextra2)
Definition extras.c:952
void extra_flags_free(void)
Definition extras.c:870
bool can_remove_extra(const struct extra_type *pextra, const struct unit *punit, const struct tile *ptile)
Definition extras.c:586
static struct extra_type_list * unit_hidden
Definition extras.c:37
struct extra_type_list * extra_type_list_of_terr_claimers(void)
Definition extras.c:259
bool is_extra_caused_by_action(const struct extra_type *pextra, const struct action *paction)
Definition extras.c:1006
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:195
bool is_extra_removed_by(const struct extra_type *pextra, enum extra_rmcause rmcause)
Definition extras.c:327
bool is_extra_removed_by_action(const struct extra_type *pextra, const struct action *paction)
Definition extras.c:1017
enum extra_rmcause activity_to_extra_rmcause(enum unit_activity act)
Definition extras.c:1049
bool player_can_remove_extra(const struct extra_type *pextra, const struct player *pplayer, const struct tile *ptile)
Definition extras.c:564
struct extra_type_list * extra_type_list_of_unit_hiders(void)
Definition extras.c:251
void extras_init(void)
Definition extras.c:43
static bool can_extra_be_removed(const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:531
int extra_count(void)
Definition extras.c:145
bool player_knows_extra_exist(const struct player *pplayer, const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:1103
bool can_build_extra(const struct extra_type *pextra, const struct unit *punit, const struct tile *ptile)
Definition extras.c:507
bool is_native_extra_to_uclass(const struct extra_type *pextra, const struct unit_class *pclass)
Definition extras.c:792
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:186
bool can_extra_disappear(const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:1090
#define extra_type_iterate(_p)
Definition extras.h:291
#define extra_type_list_iterate(extralist, pextra)
Definition extras.h:159
#define extra_type_iterate_end
Definition extras.h:297
#define extra_type_by_rmcause_iterate_end
Definition extras.h:334
#define is_extra_caused_by(e, c)
Definition extras.h:196
#define extra_index(_e_)
Definition extras.h:177
#define extra_type_by_rmcause_iterate(_rmcause, _extra)
Definition extras.h:329
#define extra_type_re_active_iterate_end
Definition extras.h:305
#define extra_type_list_iterate_end
Definition extras.h:161
#define extra_base_get(_e_)
Definition extras.h:184
#define extra_road_get(_e_)
Definition extras.h:185
#define extra_type_re_active_iterate(_p)
Definition extras.h:301
#define extra_type_by_cause_iterate_end
Definition extras.h:315
#define EF_LAST_USER_FLAG
Definition extras.h:79
#define MAX_NUM_USER_EXTRA_FLAGS
Definition extras.h:80
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:309
#define EC_LAST
Definition fc_types.h:972
environment_upset_type
Definition fc_types.h:1129
@ EUT_NUCLEAR_WINTER
Definition fc_types.h:1131
@ EUT_GLOBAL_WARMING
Definition fc_types.h:1130
@ RPT_CERTAIN
Definition fc_types.h:586
@ RPT_POSSIBLE
Definition fc_types.h:585
#define EC_NONE
Definition fc_types.h:967
#define MAX_EXTRA_TYPES
Definition fc_types.h:50
#define ERM_NONE
Definition fc_types.h:992
@ BORDERS_DISABLED
Definition fc_types.h:891
#define Qn_(String)
Definition fcintl.h:89
void user_flag_init(struct user_flag *flag)
Definition game.c:804
void user_flag_free(struct user_flag *flag)
Definition game.c:813
struct civ_game game
Definition game.c:57
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define adjc_iterate_end
Definition map.h:427
#define cardinal_adjc_iterate_end
Definition map.h:453
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:422
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:449
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
static const char * rule_name_get(const struct name_translation *ptrans)
static const char * name_translation_get(const struct name_translation *ptrans)
bool player_knows_techs_with_flag(const struct player *pplayer, enum tech_flag_id flag)
Definition player.c:1304
#define fc_rand(_size)
Definition rand.h:34
bool are_reqs_active(const struct req_context *context, const struct player *other_player, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
struct research * research_get(const struct player *pplayer)
Definition research.c:126
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:616
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Definition road.c:410
void road_types_free(void)
Definition road.c:134
void strvec_destroy(struct strvec *psv)
enum action_result result
Definition actions.h:382
Definition city.h:309
struct packet_ruleset_control control
Definition game.h:83
struct packet_game_info info
Definition game.h:89
bv_unit_classes native_to
Definition extras.h:126
bv_extras conflicts
Definition extras.h:129
uint8_t rmcauses
Definition extras.h:92
struct requirement_vector appearance_reqs
Definition extras.h:104
struct strvec * helptext
Definition extras.h:143
bv_extra_flags flags
Definition extras.h:128
struct extra_type_list * hiders
Definition extras.h:138
uint16_t causes
Definition extras.h:91
struct road_type * road
Definition extras.h:149
struct resource_type * resource
Definition extras.h:150
struct extra_type_list * bridged
Definition extras.h:141
bool ruledit_disabled
Definition extras.h:88
struct requirement_vector disappearance_reqs
Definition extras.h:105
bool generated
Definition extras.h:113
int special_idx
Definition extras.h:147
struct requirement_vector rmreqs
Definition extras.h:103
struct extra_type::@24 data
Tech_type_id visibility_req
Definition extras.h:133
int id
Definition extras.h:86
void * ruledit_dlg
Definition extras.h:89
struct requirement_vector reqs
Definition extras.h:102
bool buildable
Definition extras.h:112
int infracost
Definition extras.h:118
struct name_translation name
Definition extras.h:87
struct base_type * base
Definition extras.h:148
enum borders_mode borders
const struct player * player
int placing_time
Definition terrain.h:215
int road_time
Definition terrain.h:201
int mining_time
Definition terrain.h:213
int irrigation_time
Definition terrain.h:210
int base_time
Definition terrain.h:200
Definition tile.h:49
struct unit_list * units
Definition tile.h:57
struct player * extras_owner
Definition tile.h:62
struct extra_type * placing
Definition tile.h:60
Definition unit.h:138
enum unit_activity activity
Definition unit.h:157
char * name
Definition game.h:74
char * helptxt
Definition game.h:75
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define A_NONE
Definition tech.h:43
void resource_types_free(void)
Definition terrain.c:276
bool terrain_has_resource(const struct terrain *pterrain, const struct extra_type *presource)
Definition terrain.c:243
#define terrain_has_flag(terr, flag)
Definition terrain.h:269
void tile_virtual_destroy(struct tile *vtile)
Definition tile.c:1018
void tile_remove_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:950
struct tile * tile_virtual_new(const struct tile *ptile)
Definition tile.c:966
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_worked(_tile)
Definition tile.h:113
#define tile_terrain(_tile)
Definition tile.h:109
#define tile_has_extra(ptile, pextra)
Definition tile.h:146
#define tile_owner(_tile)
Definition tile.h:95
bool unit_can_do_action_sub_result(const struct unit *punit, enum action_sub_result sub_result)
Definition unit.c:348
bool unit_can_do_action_result(const struct unit *punit, enum action_result result)
Definition unit.c:338
#define tile_changing_activities_iterate_end
Definition unit.h:302
#define unit_owner(_pu)
Definition unit.h:394
#define tile_changing_activities_iterate(_act_)
Definition unit.h:298
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
#define utype_class(_t_)
Definition unittype.h:736
#define uclass_index(_c_)
Definition unittype.h:729