Freeciv-3.4
Loading...
Searching...
No Matches
effects.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#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17#include <ctype.h>
18#include <string.h>
19
20/* utility */
21#include "astring.h"
22#include "fcintl.h"
23#include "log.h"
24#include "mem.h"
25#include "support.h"
26#include "shared.h" /* ARRAY_SIZE */
27#include "string_vector.h"
28
29/* common */
30#include "city.h"
31#include "game.h"
32#include "government.h"
33#include "improvement.h"
34#include "map.h"
35#include "packets.h"
36#include "player.h"
37#include "tech.h"
38
39#include "effects.h"
40
41
42static bool initialized = FALSE;
43
45 enum effect_type ai_value_as;
46};
47
49
50/**************************************************************************
51 The code creates a ruleset cache on ruleset load. This constant cache
52 is used to speed up effects queries. After the cache is created it is
53 not modified again (though it may later be freed).
54
55 Since the cache is constant, the server only needs to send effects data to
56 the client upon connect. It also means that an AI can do fast searches in
57 the effects space by trying the possible combinations of addition or
58 removal of buildings with the effects it cares about.
59
60
61 To know how much a target is being affected, simply use the convenience
62 functions:
63
64 * get_world_bonus()
65 * get_player_bonus()
66 * get_player_output_bonus()
67 * get_city_bonus()
68 * get_city_output_bonus()
69 * get_city_tile_output_bonus()
70 * get_city_specialist_output_bonus()
71 * get_tile_bonus()
72 * get_tile_output_bonus()
73 * get_building_bonus()
74 * get_unittype_bonus()
75 * get_unit_bonus()
76 * get_unit_vs_tile_bonus()
77
78 These functions require as arguments the target and the effect type to be
79 queried.
80
81 Effect sources are unique and at a well known place in the
82 data structures. This allows the above queries to be fast:
83 - Look up the possible sources for the effect (O(1) lookup)
84 - For each source, find out if it is present (O(1) lookup per source).
85 The first is commonly called the "ruleset cache" and is stored statically
86 in this file. The second is the "sources cache" and is stored all over.
87
88 Any type of effect range and "survives" is possible if we have a sources
89 cache for that combination. For instance
90 - There is a sources cache of all existing buildings in a city; thus any
91 building effect in a city can have city range.
92 - There is a sources cache of all wonders in the world; thus any wonder
93 effect can have world range.
94 - There is a sources cache of all wonders for each player; thus any
95 wonder effect can have player range.
96 - There is a sources cache of all wonders ever built; thus any wonder
97 effect that survives can have world range.
98 However there is no sources cache for many of the possible sources. For
99 instance non-unique buildings do not have a world-range sources cache, so
100 you can't have a non-wonder building have a world-ranged effect.
101
102 The sources caches could easily be extended by generalizing it to a set
103 of arrays
104 game.buildings[], pplayer->buildings[],
105 pisland->buildings[], pcity->buildings[]
106 which would store the number of buildings of that type present by game,
107 player, island (continent) or city. This would allow non-surviving effects
108 to come from any building at any range. However to allow surviving effects
109 a second set of arrays would be needed. This should enable basic support
110 for small wonders and satellites.
111
112 No matter which sources caches are present, we should always know where
113 to look for a source and so the lookups will always be fast even as the
114 number of possible sources increases.
115**************************************************************************/
116
117/**************************************************************************
118 Ruleset cache. The cache is created during ruleset loading and the data
119 is organized to enable fast queries.
120**************************************************************************/
121static struct {
122 /* A single list containing every effect. */
124
125 /* This array provides a full list of the effects of this type
126 * (It's not really a cache, it's the real data.) */
128
129 struct {
130 /* This cache shows for each building, which effects it provides. */
132 /* Same for governments */
134 /* ...advances... */
138
139
140/**********************************************************************/
143struct effect_list *get_effects(enum effect_type effect_type)
144{
145 return ruleset_cache.effects[effect_type];
146}
147
148/**********************************************************************/
154{
155 int type, value;
156
158
159 switch (type) {
160 case VUT_GOVERNMENT:
161 if (value >= 0 && value < government_count()) {
162 return ruleset_cache.reqs.govs[value];
163 } else {
164 return nullptr;
165 }
166 case VUT_IMPROVEMENT:
167 if (value >= 0 && value < improvement_count()) {
168 return ruleset_cache.reqs.buildings[value];
169 } else {
170 return nullptr;
171 }
172 case VUT_ADVANCE:
173 if (value >= 0 && value < advance_count()) {
174 return ruleset_cache.reqs.advances[value];
175 } else {
176 return nullptr;
177 }
178 default:
179 return nullptr;
180 }
181}
182
183/**********************************************************************/
186struct effect *effect_new(enum effect_type type, int value,
187 struct multiplier *pmul)
188{
189 struct effect *peffect;
190
191 /* Create the effect. */
192 peffect = fc_malloc(sizeof(*peffect));
193 peffect->type = type;
194 peffect->value = value;
195 peffect->multiplier = pmul;
196
198
199 /* Now add the effect to the ruleset cache. */
202
203 /* Only relevant for ruledit and other rulesave users. */
204 peffect->rulesave.do_not_save = FALSE;
205 peffect->rulesave.comment = nullptr;
206
207 return peffect;
208}
209
210/**********************************************************************/
217{
219 if (peffect->rulesave.comment != nullptr) {
220 free(peffect->rulesave.comment);
221 }
222 free(peffect);
223}
224
225/**********************************************************************/
235
236/**********************************************************************/
246struct effect *effect_copy(struct effect *old,
247 enum effect_type override_type)
248{
249 struct effect *new_eff;
250 enum effect_type type = (effect_type_is_valid(override_type)
252 : old->type);
253
254 new_eff = effect_new(type, old->value, old->multiplier);
255
259
260 return new_eff;
261}
262
263/**********************************************************************/
267{
269
271
272 if (eff_list != nullptr) {
274 }
275
276 if (req.source.kind == VUT_IMPR_FLAG) {
277 improvement_iterate(impr) {
279 eff_list = get_req_source_effects(&(const struct universal) {
280 .kind = VUT_IMPROVEMENT,
281 .value.building = impr
282 });
283
284 if (eff_list != nullptr) {
286 }
287 }
289 }
290}
291
292/**********************************************************************/
298{
299 int i;
300
302
303 ruleset_cache.tracker = effect_list_new();
304
305 for (i = 0; i < ARRAY_SIZE(ruleset_cache.effects); i++) {
306 ruleset_cache.effects[i] = effect_list_new();
307 }
308 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.buildings); i++) {
309 ruleset_cache.reqs.buildings[i] = effect_list_new();
310 }
311 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.govs); i++) {
312 ruleset_cache.reqs.govs[i] = effect_list_new();
313 }
314 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.advances); i++) {
315 ruleset_cache.reqs.advances[i] = effect_list_new();
316 }
317
318 /* By default, user effects are valued as themselves
319 * (currently meaning that they get no value at all) */
320 for (i = EFT_USER_EFFECT_1 ; i <= EFT_USER_EFFECT_LAST; i++) {
322 }
323}
324
325/**********************************************************************/
330{
331 int i;
332 struct effect_list *tracker_list = ruleset_cache.tracker;
333
334 if (tracker_list) {
339 ruleset_cache.tracker = nullptr;
340 }
341
342 for (i = 0; i < ARRAY_SIZE(ruleset_cache.effects); i++) {
343 struct effect_list *plist = ruleset_cache.effects[i];
344
345 if (plist) {
347 ruleset_cache.effects[i] = nullptr;
348 }
349 }
350
351 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.buildings); i++) {
352 struct effect_list *plist = ruleset_cache.reqs.buildings[i];
353
354 if (plist) {
356 ruleset_cache.reqs.buildings[i] = nullptr;
357 }
358 }
359
360 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.govs); i++) {
361 struct effect_list *plist = ruleset_cache.reqs.govs[i];
362
363 if (plist) {
365 ruleset_cache.reqs.govs[i] = nullptr;
366 }
367 }
368
369 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.advances); i++) {
370 struct effect_list *plist = ruleset_cache.reqs.advances[i];
371
372 if (plist) {
374 ruleset_cache.reqs.advances[i] = nullptr;
375 }
376 }
377
379}
380
381/**********************************************************************/
388int effect_cumulative_max(enum effect_type type, struct universal *unis,
389 size_t n_unis)
390{
391 struct effect_list *plist = ruleset_cache.tracker;
392 int value = 0;
393
394 fc_assert_ret_val(((unis == nullptr && n_unis == 0)
395 || (unis != nullptr && n_unis > 0)),
396 0);
397
398 if (plist) {
400 if (peffect->type == type) {
401 if (peffect->value > 0) {
402 if (unis == nullptr
404 value += peffect->value;
405 }
406 } else if (requirement_vector_size(&peffect->reqs) == 0) {
407 /* Always active negative effect */
408 value += peffect->value;
409 }
410 }
412 }
413
414 return value;
415}
416
417/**********************************************************************/
424int effect_cumulative_min(enum effect_type type, struct universal *for_uni)
425{
426 struct effect_list *plist = ruleset_cache.tracker;
427 int value = 0;
428
429 if (plist) {
431 if (peffect->type == type) {
432 if (peffect->value < 0) {
433 if (for_uni == nullptr
435 for_uni)) {
436 value += peffect->value;
437 }
438 } else if (requirement_vector_size(&peffect->reqs) == 0) {
439 /* Always active positive effect */
440 value += peffect->value;
441 }
442 }
444 }
445
446 return value;
447}
448
449/**********************************************************************/
460 struct universal *unis, size_t n_unis)
461{
462 int value = 0;
463 struct effect_list *el = get_effects(type);
464
466 bool effect_applies = TRUE;
468
469 if (peffect->multiplier) {
470 /* Discount any effects with multipliers; we are looking for constant
471 * effects */
472 continue;
473 }
474
476 int i;
478
479 for (i = 0; effect_applies && i < n_unis; i++) {
482 /* This req not applicable to this source (but might be relevant
483 * to another source in our template). Keep looking. */
484 break;
485 case ITF_NO:
486 req_mentioned_a_source = TRUE; /* this req matched this source */
487 if (preq->present) {
488 /* Requirement contradicts template. Effect doesn't apply. */
490 } /* but negative req doesn't count for first_source_mentioned */
491 break;
492 case ITF_YES:
493 req_mentioned_a_source = TRUE; /* this req matched this source */
494 if (preq->present) {
495 if (i == 0) {
497 }
498 /* keep looking */
499 } else /* !present */ {
500 /* Requirement contradicts template. Effect doesn't apply. */
502 }
503 break;
504 }
505 }
507 /* This requirement isn't relevant to any source in our template,
508 * so it's an extra condition and the effect should be ignored. */
510 }
511 if (!effect_applies) {
512 /* Already known to be irrelevant, bail out early */
513 break;
514 }
516
518 /* First source not positively mentioned anywhere in requirements,
519 * so ignore this effect */
520 continue;
521 }
522 if (effect_applies) {
523 value += peffect->value;
524 }
526
527 return value;
528}
529
530/**********************************************************************/
546 struct universal *unis,
547 size_t n_unis,
548 int min_value)
549{
551
554 /* Not relevant. */
555 continue;
556 }
557
558 if (peffect->multiplier) {
559 /* Multipliers may change during the game. */
560 return FALSE;
561 }
562
564 /* This value is guaranteed to be there since the universals alone
565 * fulfill all the requirements in the vector. */
567 } else if (peffect->value < 0) {
568 /* Can't be ignored. It may apply. It subtracts. */
570 }
572
573 /* The value of this effect type is never below the guaranteed
574 * minimum. */
575 return guaranteed_min_effect_value >= min_value;
576}
577
578/**********************************************************************/
583{
584 return 1 + (effect_cumulative_min(type, nullptr) * -1);
585}
586
587/**********************************************************************/
592{
593 struct effect *peffect;
594 struct multiplier *pmul;
595
596 pmul = packet->has_multiplier ? multiplier_by_number(packet->multiplier)
597 : nullptr;
598 peffect = effect_new(packet->effect_type, packet->effect_value, pmul);
599
603 fc_assert(peffect->reqs.size == packet->reqs.size);
604}
605
606/**********************************************************************/
610{
613
615 effect_packet.effect_value = peffect->value;
616 if (peffect->multiplier) {
617 effect_packet.has_multiplier = TRUE;
618 effect_packet.multiplier = multiplier_number(peffect->multiplier);
619 } else {
620 effect_packet.has_multiplier = FALSE;
621 effect_packet.multiplier = 0; /* arbitrary */
622 }
623
624 /* Shallow-copy (borrow) requirement vector */
625 effect_packet.reqs = peffect->reqs;
626
629}
630
631/**********************************************************************/
639bool building_has_effect(const struct impr_type *pimprove,
641{
642 struct universal source = {
644 /* just to bamboozle the annoying compiler warning */
645 .value = {.building = improvement_by_number(improvement_number(pimprove))}
646 };
648
649 if (!plist) {
650 return FALSE;
651 }
652
654 if (peffect->type == effect_type) {
655 return TRUE;
656 }
658
659 return FALSE;
660}
661
662/**********************************************************************/
670static bool is_effect_prevented(const struct req_context *context,
671 const struct req_context *other_context,
672 const struct effect *peffect,
673 const enum req_problem_type prob_type)
674{
676 /* Only check present=FALSE requirements; these will return _FALSE_
677 * from is_req_active() if met, and need reversed prob_type */
678 if (!preq->present
681 return TRUE;
682 }
684
685 return FALSE;
686}
687
688/**********************************************************************/
693bool is_building_replaced(const struct city *pcity,
694 const struct impr_type *pimprove,
695 const enum req_problem_type prob_type)
696{
697 struct effect_list *plist;
698 struct universal source = {
700 .value = {.building = pimprove}
701 };
702
704
705 /* A building with no effects and no flags is always redundant! */
706 if (!plist) {
707 return TRUE;
708 }
709
711 /* We use TARGET_BUILDING as the lowest common denominator. Note that
712 * the building is its own target - but whether this is actually
713 * checked depends on the range of the effect. */
714 /* Prob_type is not reversed here. disabled is equal to replaced, not
715 * reverse */
716 if (!is_effect_prevented(&(const struct req_context) {
717 .player = city_owner(pcity),
718 .city = pcity,
719 .building = pimprove,
720 },
721 nullptr,
722 peffect, prob_type)) {
723 return FALSE;
724 }
726
727 return TRUE;
728}
729
730/**********************************************************************/
745 const struct req_context *context,
746 const struct req_context *other_context,
747 enum effect_type effect_type)
748{
749 int bonus = 0;
750
751 if (context == nullptr) {
753 }
754
755 /* Loop over all effects of this type. */
757 /* For each effect, see if it is active. */
759 &peffect->reqs, RPT_CERTAIN)) {
760 /* This code will add value of effect. If there's multiplier for
761 * effect and target_player aren't null, then value is multiplied
762 * by player's multiplier factor. */
763 if (peffect->multiplier) {
764 if (context->player) {
765 bonus += (peffect->value
767 peffect->multiplier)) / 100;
768 }
769 } else {
770 bonus += peffect->value;
771 }
772
773 if (plist) {
775 }
776 }
778
779 return bonus;
780}
781
782/**********************************************************************/
790 const struct player *other_player,
791 enum effect_type effect_type,
793 void *data, int n_data)
794{
795 double sum = 0.;
796
797 if (context == nullptr) {
799 }
800
801 /* Loop over all effects of this type. */
803 sum += weighter(peffect, context, other_player, data, n_data);
805
806 return sum;
807}
808
809/**********************************************************************/
812int get_world_bonus(enum effect_type effect_type)
813{
814 if (!initialized) {
815 return 0;
816 }
817
818 return get_target_bonus_effects(nullptr, nullptr, nullptr, effect_type);
819}
820
821/**********************************************************************/
824int get_player_bonus(const struct player *pplayer,
825 enum effect_type effect_type)
826{
827 if (!initialized) {
828 return 0;
829 }
830
831 return get_target_bonus_effects(nullptr,
832 &(const struct req_context) {
833 .player = pplayer,
834 },
835 nullptr,
836 effect_type);
837}
838
839/**********************************************************************/
842int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
843{
844 if (!initialized) {
845 return 0;
846 }
847
848 return get_target_bonus_effects(nullptr,
849 &(const struct req_context) {
850 .player = city_owner(pcity),
851 .city = pcity,
852 .tile = city_tile(pcity),
853 },
854 nullptr, effect_type);
855}
856
857/**********************************************************************/
862int get_tile_bonus(const struct tile *ptile, enum effect_type effect_type)
863{
864 if (!initialized) {
865 return 0;
866 }
867
868 return get_target_bonus_effects(nullptr,
869 &(const struct req_context) {
870 .player = tile_owner(ptile),
871 .city = tile_city(ptile),
872 .tile = ptile,
873 },
874 nullptr,
875 effect_type);
876}
877
878/**********************************************************************/
882 const struct specialist *pspecialist,
883 const struct output_type *poutput,
884 enum effect_type effect_type)
885{
886 fc_assert_ret_val(pcity != nullptr, 0);
887 fc_assert_ret_val(pspecialist != nullptr, 0);
888 fc_assert_ret_val(poutput != nullptr, 0);
889
890 return get_target_bonus_effects(nullptr,
891 &(const struct req_context) {
892 .player = city_owner(pcity),
893 .city = pcity,
894 .output = poutput,
895 .specialist = pspecialist,
896 },
897 nullptr,
898 effect_type);
899}
900
901/**********************************************************************/
914 const struct tile *ptile,
915 const struct output_type *poutput,
916 enum effect_type effect_type)
917{
918 fc_assert_ret_val(pcity != nullptr, 0);
919
920 return get_target_bonus_effects(nullptr,
921 &(const struct req_context) {
922 .player = city_owner(pcity),
923 .city = pcity,
924 .tile = ptile,
925 .output = poutput,
926 },
927 nullptr,
928 effect_type);
929}
930
931/**********************************************************************/
939 const struct tile *ptile,
940 const struct output_type *poutput,
941 enum effect_type effect_type)
942{
943 const struct player *pplayer = pcity ? city_owner(pcity) : nullptr;
944
945 return get_target_bonus_effects(nullptr,
946 &(const struct req_context) {
947 .player = pplayer,
948 .city = pcity,
949 .tile = ptile,
950 .output = poutput,
951 },
952 nullptr,
953 effect_type);
954}
955
956/**********************************************************************/
959int get_player_output_bonus(const struct player *pplayer,
960 const struct output_type *poutput,
961 enum effect_type effect_type)
962{
963 if (!initialized) {
964 return 0;
965 }
966
967 fc_assert_ret_val(pplayer != nullptr, 0);
968 fc_assert_ret_val(poutput != nullptr, 0);
969 fc_assert_ret_val(effect_type != EFT_COUNT, 0);
970
971 return get_target_bonus_effects(nullptr,
972 &(const struct req_context) {
973 .player = pplayer,
974 .output= poutput,
975 },
976 nullptr,
977 effect_type);
978}
979
980/**********************************************************************/
984 const struct output_type *poutput,
985 enum effect_type effect_type)
986{
987 if (!initialized) {
988 return 0;
989 }
990
991 fc_assert_ret_val(pcity != nullptr, 0);
992 fc_assert_ret_val(poutput != nullptr, 0);
993 fc_assert_ret_val(effect_type != EFT_COUNT, 0);
994
995 return get_target_bonus_effects(nullptr,
996 &(const struct req_context) {
997 .player = city_owner(pcity),
998 .city = pcity,
999 .output = poutput,
1000 },
1001 nullptr,
1002 effect_type);
1003}
1004
1005/**********************************************************************/
1009 const struct impr_type *building,
1010 enum effect_type effect_type)
1011{
1012 if (!initialized) {
1013 return 0;
1014 }
1015
1016 fc_assert_ret_val(pcity != nullptr && building != nullptr, 0);
1017
1018 return get_target_bonus_effects(nullptr,
1019 &(const struct req_context) {
1020 .player = city_owner(pcity),
1021 .city = pcity,
1022 .building = building,
1023 },
1024 nullptr,
1025 effect_type);
1026}
1027
1028/**********************************************************************/
1036int get_unittype_bonus(const struct player *pplayer,
1037 const struct tile *ptile,
1038 const struct unit_type *punittype,
1039 const struct action *paction,
1040 enum effect_type effect_type)
1041{
1042 struct city *pcity;
1043
1044 if (!initialized) {
1045 return 0;
1046 }
1047
1048 fc_assert_ret_val(punittype != nullptr, 0);
1049
1050 if (ptile != nullptr) {
1051 pcity = tile_city(ptile);
1052 } else {
1053 pcity = nullptr;
1054 }
1055
1056 return get_target_bonus_effects(nullptr,
1057 &(const struct req_context) {
1058 .player = pplayer,
1059 .city = pcity,
1060 .tile = ptile,
1061 .unittype = punittype,
1062 .action = paction,
1063 },
1064 nullptr,
1065 effect_type);
1066}
1067
1068/**********************************************************************/
1071int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
1072{
1073 if (!initialized) {
1074 return 0;
1075 }
1076
1077 fc_assert_ret_val(punit != nullptr, 0);
1078
1079 return get_target_bonus_effects(nullptr,
1080 &(const struct req_context) {
1081 .player = unit_owner(punit),
1082 .city = unit_tile(punit)
1084 : nullptr,
1085 .tile = unit_tile(punit),
1086 .unit = punit,
1087 .unittype = unit_type_get(punit),
1088 },
1089 nullptr,
1090 effect_type);
1091}
1092
1093/**********************************************************************/
1096int get_unit_vs_tile_bonus(const struct tile *ptile,
1097 const struct unit *punit,
1098 enum effect_type etype)
1099{
1100 struct player *pplayer = nullptr;
1101 const struct unit_type *utype = nullptr;
1102
1103 if (!initialized) {
1104 return 0;
1105 }
1106
1107 fc_assert_ret_val(ptile != nullptr, 0);
1108
1109 if (punit != nullptr) {
1110 pplayer = unit_owner(punit);
1111 utype = unit_type_get(punit);
1112 }
1113
1114 return get_target_bonus_effects(nullptr,
1115 &(const struct req_context) {
1116 .player = pplayer,
1117 .city = tile_city(ptile),
1118 .tile = ptile,
1119 .unit = punit,
1120 .unittype = utype,
1121 },
1122 &(const struct req_context) {
1123 .player = tile_owner(ptile),
1124 },
1125 etype);
1126}
1127
1128/**********************************************************************/
1135 const struct player *pplayer,
1136 enum effect_type effect_type)
1137{
1138 if (!initialized) {
1139 return 0;
1140 }
1141
1142 fc_assert_ret_val(pplayer != nullptr, 0);
1143
1145 &(const struct req_context) {
1146 .player = pplayer,
1147 },
1148 nullptr,
1149 effect_type);
1150}
1151
1152/**********************************************************************/
1159 const struct city *pcity,
1160 const struct output_type *poutput,
1161 enum effect_type effect_type)
1162{
1163 if (!initialized) {
1164 return 0;
1165 }
1166
1167 fc_assert_ret_val(pcity != nullptr, 0);
1168
1170 &(const struct req_context) {
1171 .player = city_owner(pcity),
1172 .city = pcity,
1173 .output = poutput,
1174 },
1175 nullptr,
1176 effect_type);
1177}
1178
1179/**********************************************************************/
1189 enum effect_type effect_type,
1190 const enum req_problem_type prob_type)
1191{
1192 if (!initialized) {
1193 return 0;
1194 }
1195
1196 if (VUT_IMPROVEMENT == pcity->production.kind) {
1197 return get_potential_improvement_bonus(pcity->production.value.building,
1198 pcity, effect_type, prob_type, TRUE);
1199 }
1200
1201 return 0;
1202}
1203
1204/**********************************************************************/
1211 const struct city *pcity,
1212 enum effect_type effect_type,
1213 const enum req_problem_type prob_type,
1215{
1216 struct universal source = { .kind = VUT_IMPROVEMENT,
1217 .value = {.building = pimprove}};
1219 struct player *owner = nullptr;
1220
1221 if (pcity != nullptr) {
1223 }
1224
1225 if (plist) {
1226 int power = 0;
1227 const struct req_context context = {
1228 .player = owner,
1229 .city = pcity,
1230 .building = pimprove,
1231 };
1232
1234 bool present = TRUE;
1235 bool useful = TRUE;
1236
1237 if (peffect->type != effect_type) {
1238 continue;
1239 }
1240
1242 if (VUT_IMPROVEMENT == preq->source.kind
1243 && preq->source.value.building == pimprove) {
1244 present = preq->present;
1245 continue;
1246 }
1247
1248 if (!is_req_active(&context, nullptr, preq, prob_type)) {
1249 useful = FALSE;
1250 break;
1251 }
1253
1254 if (useful) {
1255 int val;
1256
1257 if (present) {
1258 val = peffect->value;
1259 } else {
1260 val = -peffect->value;
1261 }
1262
1263 if (consider_multipliers && peffect->multiplier) {
1264 val = val * player_multiplier_effect_value(owner, peffect->multiplier) / 100;
1265 }
1266
1267 power += val;
1268 }
1270
1271 return power;
1272 }
1273
1274 return 0;
1275}
1276
1277/**********************************************************************/
1282 char *buf, size_t buf_len)
1283{
1284 buf[0] = '\0';
1285
1286 if (peffect->multiplier) {
1288 }
1289
1290 /* FIXME: should we do something for present FALSE reqs?
1291 * Currently we just ignore them. */
1293 if (!preq->present) {
1294 continue;
1295 }
1296 if (buf[0] != '\0') {
1297 fc_strlcat(buf, Q_("?req-list-separator:+"), buf_len);
1298 }
1299
1301 buf + strlen(buf), buf_len - strlen(buf));
1303}
1304
1305/**********************************************************************/
1310 struct astring *astr)
1311{
1312 struct strvec *psv = strvec_new();
1313 char req_text[512];
1314
1319
1322}
1323
1324/**********************************************************************/
1329bool iterate_effect_cache(iec_cb cb, void *data)
1330{
1331 fc_assert_ret_val(cb != nullptr, FALSE);
1332
1334 if (!cb(peffect, data)) {
1335 return FALSE;
1336 }
1338
1339 return TRUE;
1340}
1341
1342/**********************************************************************/
1345bool is_user_effect(enum effect_type eff)
1346{
1348}
1349
1350/**********************************************************************/
1354void user_effect_ai_valued_set(enum effect_type tgt, enum effect_type valued_as)
1355{
1357
1359}
1360
1361/**********************************************************************/
1365enum effect_type user_effect_ai_valued_as(enum effect_type real)
1366{
1367 /* Client doesn't know these. */
1369
1370 if (!is_user_effect(real)) {
1371 return real;
1372 }
1373
1374 if (!is_user_effect(ueffects[USER_EFFECT_NUMBER(real)].ai_value_as)) {
1376 }
1377
1378 return real;
1379}
#define city_tile(_pcity_)
Definition city.h:565
#define city_owner(_pcity_)
Definition city.h:564
char * incite_cost
Definition comments.c:77
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:74
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 int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
void effect_remove(struct effect *peffect)
Definition effects.c:230
void recv_ruleset_effect(const struct packet_ruleset_effect *packet)
Definition effects.c:591
struct effect_list * effects[EFT_COUNT]
Definition effects.c:127
struct effect_list * govs[G_LAST]
Definition effects.c:133
struct effect_list * tracker
Definition effects.c:123
struct @22::@23 reqs
struct user_effect ueffects[EFT_USER_EFFECT_LAST+1 - EFT_USER_EFFECT_1]
Definition effects.c:48
bool effect_universals_value_never_below(enum effect_type type, struct universal *unis, size_t n_unis, int min_value)
Definition effects.c:545
int get_tile_output_bonus(const struct city *pcity, const struct tile *ptile, const struct output_type *poutput, enum effect_type effect_type)
Definition effects.c:938
int get_player_output_bonus(const struct player *pplayer, const struct output_type *poutput, enum effect_type effect_type)
Definition effects.c:959
int get_city_specialist_output_bonus(const struct city *pcity, const struct specialist *pspecialist, const struct output_type *poutput, enum effect_type effect_type)
Definition effects.c:881
bool is_building_replaced(const struct city *pcity, const struct impr_type *pimprove, const enum req_problem_type prob_type)
Definition effects.c:693
int get_player_bonus_effects(struct effect_list *plist, const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:1134
bool iterate_effect_cache(iec_cb cb, void *data)
Definition effects.c:1329
int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
Definition effects.c:842
int get_current_construction_bonus(const struct city *pcity, enum effect_type effect_type, const enum req_problem_type prob_type)
Definition effects.c:1188
int get_city_bonus_effects(struct effect_list *plist, const struct city *pcity, const struct output_type *poutput, enum effect_type effect_type)
Definition effects.c:1158
int get_unit_vs_tile_bonus(const struct tile *ptile, const struct unit *punit, enum effect_type etype)
Definition effects.c:1096
int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
Definition effects.c:1071
int get_city_output_bonus(const struct city *pcity, const struct output_type *poutput, enum effect_type effect_type)
Definition effects.c:983
int get_potential_improvement_bonus(const struct impr_type *pimprove, const struct city *pcity, enum effect_type effect_type, const enum req_problem_type prob_type, bool consider_multipliers)
Definition effects.c:1210
void send_ruleset_cache(struct conn_list *dest)
Definition effects.c:609
void get_effect_req_text(const struct effect *peffect, char *buf, size_t buf_len)
Definition effects.c:1281
struct effect_list * buildings[B_LAST]
Definition effects.c:131
void ruleset_cache_free(void)
Definition effects.c:329
struct effect * effect_new(enum effect_type type, int value, struct multiplier *pmul)
Definition effects.c:186
static struct @22 ruleset_cache
int get_building_bonus(const struct city *pcity, const struct impr_type *building, enum effect_type effect_type)
Definition effects.c:1008
int effect_value_from_universals(enum effect_type type, struct universal *unis, size_t n_unis)
Definition effects.c:459
int get_city_tile_output_bonus(const struct city *pcity, const struct tile *ptile, const struct output_type *poutput, enum effect_type effect_type)
Definition effects.c:913
void user_effect_ai_valued_set(enum effect_type tgt, enum effect_type valued_as)
Definition effects.c:1354
int get_target_bonus_effects(struct effect_list *plist, const struct req_context *context, const struct req_context *other_context, enum effect_type effect_type)
Definition effects.c:744
struct effect * effect_copy(struct effect *old, enum effect_type override_type)
Definition effects.c:246
int effect_cumulative_max(enum effect_type type, struct universal *unis, size_t n_unis)
Definition effects.c:388
void effect_free(struct effect *peffect)
Definition effects.c:216
void ruleset_cache_init(void)
Definition effects.c:297
struct effect_list * advances[A_LAST]
Definition effects.c:135
int get_world_bonus(enum effect_type effect_type)
Definition effects.c:812
int effect_cumulative_min(enum effect_type type, struct universal *for_uni)
Definition effects.c:424
struct effect_list * get_effects(enum effect_type effect_type)
Definition effects.c:143
struct effect_list * get_req_source_effects(const struct universal *psource)
Definition effects.c:153
enum effect_type user_effect_ai_valued_as(enum effect_type real)
Definition effects.c:1365
static bool is_effect_prevented(const struct req_context *context, const struct req_context *other_context, const struct effect *peffect, const enum req_problem_type prob_type)
Definition effects.c:670
bool building_has_effect(const struct impr_type *pimprove, enum effect_type effect_type)
Definition effects.c:639
double get_effect_expected_value(const struct req_context *context, const struct player *other_player, enum effect_type effect_type, eft_value_filter_cb weighter, void *data, int n_data)
Definition effects.c:789
static bool initialized
Definition effects.c:42
void effect_req_append(struct effect *peffect, struct requirement req)
Definition effects.c:266
int get_tile_bonus(const struct tile *ptile, enum effect_type effect_type)
Definition effects.c:862
int get_unittype_bonus(const struct player *pplayer, const struct tile *ptile, const struct unit_type *punittype, const struct action *paction, enum effect_type effect_type)
Definition effects.c:1036
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:824
void get_effect_list_req_text(const struct effect_list *plist, struct astring *astr)
Definition effects.c:1309
bool is_user_effect(enum effect_type eff)
Definition effects.c:1345
int effect_value_will_make_positive(enum effect_type type)
Definition effects.c:582
#define effect_list_iterate_end
Definition effects.h:81
#define USER_EFFECT_NUMBER(eff)
Definition effects.h:35
double(* eft_value_filter_cb)(const struct effect *eft, const struct req_context *context, const struct player *other_player, void *data, int n_data)
Definition effects.h:70
bool(* iec_cb)(struct effect *, void *data)
Definition effects.h:194
#define EFT_USER_EFFECT_LAST
Definition effects.h:33
#define effect_list_iterate(effect_list, peffect)
Definition effects.h:79
static bool is_server(void)
req_problem_type
Definition fc_types.h:514
@ RPT_CERTAIN
Definition fc_types.h:516
#define REVERSED_RPT(x)
Definition fc_types.h:519
#define Q_(String)
Definition fcintl.h:70
Government_type_id government_count(void)
Definition government.c:73
#define G_LAST
Definition government.h:50
struct city * owner
Definition citydlg.c:226
static GtkWidget * source
Definition gotodlg.c:58
GType type
Definition repodlgs.c:1313
struct impr_type * improvement_by_number(const Impr_type_id id)
Impr_type_id improvement_number(const struct impr_type *pimprove)
bool improvement_has_flag(const struct impr_type *pimprove, enum impr_flag_id flag)
Impr_type_id improvement_count(void)
#define improvement_iterate_end
#define improvement_iterate(_p)
#define B_LAST
Definition improvement.h:42
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
void lsend_packet_ruleset_effect(struct conn_list *dest, const struct packet_ruleset_effect *packet)
#define fc_malloc(sz)
Definition mem.h:34
const char * multiplier_name_translation(const struct multiplier *pmul)
Definition multipliers.c:97
Multiplier_type_id multiplier_number(const struct multiplier *pmul)
Definition multipliers.c:67
struct multiplier * multiplier_by_number(Multiplier_type_id id)
Definition multipliers.c:57
int player_multiplier_effect_value(const struct player *pplayer, const struct multiplier *pmul)
Definition player.c:1958
const struct req_context * req_context_empty(void)
void universal_extraction(const struct universal *source, int *kind, int *value)
bool universal_fulfills_requirements(bool check_necessary, const struct requirement_vector *reqs, const struct universal *source)
bool is_req_active(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, const enum req_problem_type prob_type)
bool are_reqs_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
enum req_item_found universal_fulfills_requirement(const struct requirement *preq, const struct universal *source)
bool universals_say_everything(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
bool universals_mean_unfulfilled(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
#define requirement_vector_iterate_end
#define requirement_vector_iterate(req_vec, preq)
@ ITF_NO
@ ITF_YES
@ ITF_NOT_APPLICABLE
#define ARRAY_SIZE(x)
Definition shared.h:85
void strvec_destroy(struct strvec *psv)
void strvec_append(struct strvec *psv, const char *string)
struct strvec * strvec_new(void)
const char * strvec_to_and_list(const struct strvec *psv, struct astring *astr)
Definition city.h:318
struct tile * tile
Definition city.h:320
int value
Definition effects.h:49
struct requirement_vector reqs
Multiplier_type_id multiplier
enum effect_type effect_type
const struct player * player
struct universal source
Definition tile.h:50
Definition unit.h:140
struct tile * tile
Definition unit.h:142
enum universals_n kind
Definition fc_types.h:595
universals_u value
Definition fc_types.h:594
enum effect_type ai_value_as
Definition effects.c:45
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:822
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
static Tech_type_id advance_count(void)
Definition tech.h:167
#define A_LAST
Definition tech.h:45
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_owner(_tile)
Definition tile.h:97
enum impr_flag_id impr_flag
Definition fc_types.h:570
#define unit_tile(_pu)
Definition unit.h:407
#define unit_owner(_pu)
Definition unit.h:406
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126