Freeciv-3.1
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
44/**************************************************************************
45 The code creates a ruleset cache on ruleset load. This constant cache
46 is used to speed up effects queries. After the cache is created it is
47 not modified again (though it may later be freed).
48
49 Since the cache is constant, the server only needs to send effects data to
50 the client upon connect. It also means that an AI can do fast searches in
51 the effects space by trying the possible combinations of addition or
52 removal of buildings with the effects it cares about.
53
54
55 To know how much a target is being affected, simply use the convenience
56 functions:
57
58 * get_world_bonus()
59 * get_player_bonus()
60 * get_player_output_bonus()
61 * get_city_bonus()
62 * get_city_output_bonus()
63 * get_city_tile_output_bonus()
64 * get_city_specialist_output_bonus()
65 * get_tile_output_bonus()
66 * get_building_bonus()
67 * get_unittype_bonus()
68 * get_unit_bonus()
69 * get_unit_vs_tile_bonus()
70
71 These functions require as arguments the target and the effect type to be
72 queried.
73
74 Effect sources are unique and at a well known place in the
75 data structures. This allows the above queries to be fast:
76 - Look up the possible sources for the effect (O(1) lookup)
77 - For each source, find out if it is present (O(1) lookup per source).
78 The first is commonly called the "ruleset cache" and is stored statically
79 in this file. The second is the "sources cache" and is stored all over.
80
81 Any type of effect range and "survives" is possible if we have a sources
82 cache for that combination. For instance
83 - There is a sources cache of all existing buildings in a city; thus any
84 building effect in a city can have city range.
85 - There is a sources cache of all wonders in the world; thus any wonder
86 effect can have world range.
87 - There is a sources cache of all wonders for each player; thus any
88 wonder effect can have player range.
89 - There is a sources cache of all wonders ever built; thus any wonder
90 effect that survives can have world range.
91 However there is no sources cache for many of the possible sources. For
92 instance non-unique buildings do not have a world-range sources cache, so
93 you can't have a non-wonder building have a world-ranged effect.
94
95 The sources caches could easily be extended by generalizing it to a set
96 of arrays
97 game.buildings[], pplayer->buildings[],
98 pisland->buildings[], pcity->buildings[]
99 which would store the number of buildings of that type present by game,
100 player, island (continent) or city. This would allow non-surviving effects
101 to come from any building at any range. However to allow surviving effects
102 a second set of arrays would be needed. This should enable basic support
103 for small wonders and satellites.
104
105 No matter which sources caches are present, we should always know where
106 to look for a source and so the lookups will always be fast even as the
107 number of possible sources increases.
108**************************************************************************/
109
110/**************************************************************************
111 Ruleset cache. The cache is created during ruleset loading and the data
112 is organized to enable fast queries.
113**************************************************************************/
114static struct {
115 /* A single list containing every effect. */
116 struct effect_list *tracker;
117
118 /* This array provides a full list of the effects of this type
119 * (It's not really a cache, it's the real data.) */
120 struct effect_list *effects[EFT_COUNT];
121
122 struct {
123 /* This cache shows for each building, which effects it provides. */
124 struct effect_list *buildings[B_LAST];
125 /* Same for governments */
126 struct effect_list *govs[G_LAST];
127 /* ...advances... */
128 struct effect_list *advances[A_LAST];
131
132
133/**********************************************************************/
136struct effect_list *get_effects(enum effect_type effect_type)
137{
138 return ruleset_cache.effects[effect_type];
139}
140
141/**********************************************************************/
146struct effect_list *get_req_source_effects(struct universal *psource)
147{
148 int type, value;
149
150 universal_extraction(psource, &type, &value);
151
152 switch (type) {
153 case VUT_GOVERNMENT:
154 if (value >= 0 && value < government_count()) {
155 return ruleset_cache.reqs.govs[value];
156 } else {
157 return NULL;
158 }
159 case VUT_IMPROVEMENT:
160 if (value >= 0 && value < improvement_count()) {
161 return ruleset_cache.reqs.buildings[value];
162 } else {
163 return NULL;
164 }
165 case VUT_ADVANCE:
166 if (value >= 0 && value < advance_count()) {
167 return ruleset_cache.reqs.advances[value];
168 } else {
169 return NULL;
170 }
171 default:
172 return NULL;
173 }
174}
175
176/**********************************************************************/
179struct effect *effect_new(enum effect_type type, int value,
180 struct multiplier *pmul)
181{
182 struct effect *peffect;
183
184 /* Create the effect. */
185 peffect = fc_malloc(sizeof(*peffect));
186 peffect->type = type;
187 peffect->value = value;
188 peffect->multiplier = pmul;
189
190 requirement_vector_init(&peffect->reqs);
191
192 /* Now add the effect to the ruleset cache. */
193 effect_list_append(ruleset_cache.tracker, peffect);
194 effect_list_append(get_effects(type), peffect);
195
196 /* Only relevant for ruledit and other rulesave users. */
197 peffect->ruledit_do_not_save = FALSE;
198
199 return peffect;
200}
201
202/**********************************************************************/
205void effect_remove(struct effect *peffect)
206{
207 effect_list_remove(ruleset_cache.tracker, peffect);
208 effect_list_remove(get_effects(peffect->type), peffect);
209}
210
211/**********************************************************************/
214struct effect *effect_copy(struct effect *old)
215{
216 struct effect *new_eff = effect_new(old->type, old->value,
217 old->multiplier);
218
219 requirement_vector_iterate(&old->reqs, preq) {
220 effect_req_append(new_eff, *preq);
222
223 return new_eff;
224}
225
226/**********************************************************************/
229void effect_req_append(struct effect *peffect, struct requirement req)
230{
231 struct effect_list *eff_list = get_req_source_effects(&req.source);
232
233 requirement_vector_append(&peffect->reqs, req);
234
235 if (eff_list) {
236 effect_list_append(eff_list, peffect);
237 }
238}
239
240/**********************************************************************/
246{
247 int i;
248
250
251 ruleset_cache.tracker = effect_list_new();
252
253 for (i = 0; i < ARRAY_SIZE(ruleset_cache.effects); i++) {
254 ruleset_cache.effects[i] = effect_list_new();
255 }
256 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.buildings); i++) {
257 ruleset_cache.reqs.buildings[i] = effect_list_new();
258 }
259 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.govs); i++) {
260 ruleset_cache.reqs.govs[i] = effect_list_new();
261 }
262 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.advances); i++) {
263 ruleset_cache.reqs.advances[i] = effect_list_new();
264 }
265}
266
267/**********************************************************************/
272{
273 int i;
274 struct effect_list *tracker_list = ruleset_cache.tracker;
275
276 if (tracker_list) {
277 effect_list_iterate(tracker_list, peffect) {
278 requirement_vector_free(&peffect->reqs);
279 free(peffect);
281 effect_list_destroy(tracker_list);
282 ruleset_cache.tracker = NULL;
283 }
284
285 for (i = 0; i < ARRAY_SIZE(ruleset_cache.effects); i++) {
286 struct effect_list *plist = ruleset_cache.effects[i];
287
288 if (plist) {
289 effect_list_destroy(plist);
290 ruleset_cache.effects[i] = NULL;
291 }
292 }
293
294 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.buildings); i++) {
295 struct effect_list *plist = ruleset_cache.reqs.buildings[i];
296
297 if (plist) {
298 effect_list_destroy(plist);
299 ruleset_cache.reqs.buildings[i] = NULL;
300 }
301 }
302
303 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.govs); i++) {
304 struct effect_list *plist = ruleset_cache.reqs.govs[i];
305
306 if (plist) {
307 effect_list_destroy(plist);
308 ruleset_cache.reqs.govs[i] = NULL;
309 }
310 }
311
312 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.advances); i++) {
313 struct effect_list *plist = ruleset_cache.reqs.advances[i];
314
315 if (plist) {
316 effect_list_destroy(plist);
317 ruleset_cache.reqs.advances[i] = NULL;
318 }
319 }
320
322}
323
324/**********************************************************************/
331int effect_cumulative_max(enum effect_type type, struct universal *unis,
332 size_t n_unis)
333{
334 struct effect_list *plist = ruleset_cache.tracker;
335 int value = 0;
336
337 fc_assert_ret_val(((unis == NULL && n_unis == 0)
338 || (unis != NULL && n_unis > 0)),
339 0);
340
341 if (plist) {
342 effect_list_iterate(plist, peffect) {
343 if (peffect->type == type) {
344 if (peffect->value > 0) {
345 if (unis == NULL
346 || !universals_mean_unfulfilled(&(peffect->reqs), unis, n_unis)) {
347 value += peffect->value;
348 }
349 } else if (requirement_vector_size(&peffect->reqs) == 0) {
350 /* Always active negative effect */
351 value += peffect->value;
352 }
353 }
355 }
356
357 return value;
358}
359
360/**********************************************************************/
367int effect_cumulative_min(enum effect_type type, struct universal *for_uni)
368{
369 struct effect_list *plist = ruleset_cache.tracker;
370 int value = 0;
371
372 if (plist) {
373 effect_list_iterate(plist, peffect) {
374 if (peffect->type == type) {
375 if (peffect->value < 0) {
376 if (for_uni == NULL
377 || universal_fulfills_requirements(FALSE, &(peffect->reqs),
378 for_uni)) {
379 value += peffect->value;
380 }
381 } else if (requirement_vector_size(&peffect->reqs) == 0) {
382 /* Always active positive effect */
383 value += peffect->value;
384 }
385 }
387 }
388
389 return value;
390}
391
392/**********************************************************************/
403 struct universal *unis, size_t n_unis)
404{
405 int value = 0;
406 struct effect_list *el = get_effects(type);
407
408 effect_list_iterate(el, peffect) {
409 bool effect_applies = TRUE;
410 bool first_source_mentioned = FALSE;
411
412 if (peffect->multiplier) {
413 /* Discount any effects with multipliers; we are looking for constant
414 * effects */
415 continue;
416 }
417
418 requirement_vector_iterate(&(peffect->reqs), preq) {
419 int i;
420 bool req_mentioned_a_source = FALSE;
421
422 for (i = 0; effect_applies && i < n_unis; i++) {
423 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
425 /* This req not applicable to this source (but might be relevant
426 * to another source in our template). Keep looking. */
427 break;
428 case ITF_NO:
429 req_mentioned_a_source = TRUE; /* this req matched this source */
430 if (preq->present) {
431 /* Requirement contradicts template. Effect doesn't apply. */
432 effect_applies = FALSE;
433 } /* but negative req doesn't count for first_source_mentioned */
434 break;
435 case ITF_YES:
436 req_mentioned_a_source = TRUE; /* this req matched this source */
437 if (preq->present) {
438 if (i == 0) {
439 first_source_mentioned = TRUE;
440 }
441 /* keep looking */
442 } else /* !present */ {
443 /* Requirement contradicts template. Effect doesn't apply. */
444 effect_applies = FALSE;
445 }
446 break;
447 }
448 }
449 if (!req_mentioned_a_source) {
450 /* This requirement isn't relevant to any source in our template,
451 * so it's an extra condition and the effect should be ignored. */
452 effect_applies = FALSE;
453 }
454 if (!effect_applies) {
455 /* Already known to be irrelevant, bail out early */
456 break;
457 }
459
460 if (!first_source_mentioned) {
461 /* First source not positively mentioned anywhere in requirements,
462 * so ignore this effect */
463 continue;
464 }
465 if (effect_applies) {
466 value += peffect->value;
467 }
469
470 return value;
471}
472
473/**********************************************************************/
489 struct universal *unis,
490 size_t n_unis,
491 int min_value)
492{
493 int guaranteed_min_effect_value = 0;
494
496 if (universals_mean_unfulfilled(&peffect->reqs, unis, n_unis)) {
497 /* Not relevant. */
498 continue;
499 }
500
501 if (peffect->multiplier) {
502 /* Multipliers may change during the game. */
503 return FALSE;
504 }
505
506 if (universals_say_everything(&peffect->reqs, unis, n_unis)) {
507 /* This value is guaranteed to be there since the universals alone
508 * fulfill all the requirements in the vector. */
509 guaranteed_min_effect_value += peffect->value;
510 } else if (peffect->value < 0) {
511 /* Can't be ignored. It may apply. It subtracts. */
512 guaranteed_min_effect_value += peffect->value;
513 }
515
516 /* The value of this effect type is never below the guaranteed
517 * minimum. */
518 return guaranteed_min_effect_value >= min_value;
519}
520
521/**********************************************************************/
526{
527 return 1 + (effect_cumulative_min(type, NULL) * -1);
528}
529
530/**********************************************************************/
535{
536 struct effect *peffect;
537 struct multiplier *pmul;
538 int i;
539
540 pmul = packet->has_multiplier ? multiplier_by_number(packet->multiplier)
541 : NULL;
542 peffect = effect_new(packet->effect_type, packet->effect_value, pmul);
543
544 for (i = 0; i < packet->reqs_count; i++) {
545 effect_req_append(peffect, packet->reqs[i]);
546 }
547 fc_assert(peffect->reqs.size == packet->reqs_count);
548}
549
550/**********************************************************************/
553void send_ruleset_cache(struct conn_list *dest)
554{
555 effect_list_iterate(ruleset_cache.tracker, peffect) {
556 struct packet_ruleset_effect effect_packet;
557 int counter;
558
559 effect_packet.effect_type = peffect->type;
560 effect_packet.effect_value = peffect->value;
561 if (peffect->multiplier) {
562 effect_packet.has_multiplier = TRUE;
563 effect_packet.multiplier = multiplier_number(peffect->multiplier);
564 } else {
565 effect_packet.has_multiplier = FALSE;
566 effect_packet.multiplier = 0; /* arbitrary */
567 }
568
569 counter = 0;
570 requirement_vector_iterate(&(peffect->reqs), req) {
571 effect_packet.reqs[counter++] = *req;
573 effect_packet.reqs_count = counter;
574
575 lsend_packet_ruleset_effect(dest, &effect_packet);
577}
578
579/**********************************************************************/
587bool building_has_effect(const struct impr_type *pimprove,
589{
590 struct universal source = {
591 .kind = VUT_IMPROVEMENT,
592 /* just to bamboozle the annoying compiler warning */
593 .value = {.building = improvement_by_number(improvement_number(pimprove))}
594 };
595 struct effect_list *plist = get_req_source_effects(&source);
596
597 if (!plist) {
598 return FALSE;
599 }
600
601 effect_list_iterate(plist, peffect) {
602 if (peffect->type == effect_type) {
603 return TRUE;
604 }
606
607 return FALSE;
608}
609
610/**********************************************************************/
618static bool is_effect_prevented(const struct req_context *context,
619 const struct player *other_player,
620 const struct effect *peffect,
621 const enum req_problem_type prob_type)
622{
623 requirement_vector_iterate(&peffect->reqs, preq) {
624 /* Only check present=FALSE requirements; these will return _FALSE_
625 * from is_req_active() if met, and need reversed prob_type */
626 if (!preq->present
627 && !is_req_active(context, other_player,
628 preq, REVERSED_RPT(prob_type))) {
629 return TRUE;
630 }
632
633 return FALSE;
634}
635
636/**********************************************************************/
641bool is_building_replaced(const struct city *pcity,
642 const struct impr_type *pimprove,
643 const enum req_problem_type prob_type)
644{
645 struct effect_list *plist;
646 struct universal source = {
647 .kind = VUT_IMPROVEMENT,
648 .value = {.building = pimprove}
649 };
650
652
653 /* A building with no effects and no flags is always redundant! */
654 if (!plist) {
655 return TRUE;
656 }
657
658 effect_list_iterate(plist, peffect) {
659 /* We use TARGET_BUILDING as the lowest common denominator. Note that
660 * the building is its own target - but whether this is actually
661 * checked depends on the range of the effect. */
662 /* Prob_type is not reversed here. disabled is equal to replaced, not
663 * reverse */
664 if (!is_effect_prevented(&(const struct req_context) {
665 .player = city_owner(pcity),
666 .city = pcity,
667 .building = pimprove,
668 },
669 NULL,
670 peffect, prob_type)) {
671 return FALSE;
672 }
674
675 return TRUE;
676}
677
678/**********************************************************************/
691int get_target_bonus_effects(struct effect_list *plist,
692 const struct req_context *context,
693 const struct player *other_player,
694 enum effect_type effect_type)
695{
696 int bonus = 0;
697
698 if (context == NULL) {
699 context = req_context_empty();
700 }
701
702 /* Loop over all effects of this type. */
703 effect_list_iterate(get_effects(effect_type), peffect) {
704 /* For each effect, see if it is active. */
705 if (are_reqs_active(context, other_player,
706 &peffect->reqs, RPT_CERTAIN)) {
707 /* This code will add value of effect. If there's multiplier for
708 * effect and target_player aren't null, then value is multiplied
709 * by player's multiplier factor. */
710 if (peffect->multiplier) {
711 if (context->player) {
712 bonus += (peffect->value
714 peffect->multiplier)) / 100;
715 }
716 } else {
717 bonus += peffect->value;
718 }
719
720 if (plist) {
721 effect_list_append(plist, peffect);
722 }
723 }
725
726 return bonus;
727}
728
729/**********************************************************************/
736double get_effect_expected_value(const struct req_context *context,
737 const struct player *other_player,
738 enum effect_type effect_type,
739 eft_value_filter_cb weighter,
740 void *data, int n_data)
741{
742 double sum = 0.;
743
744 if (context == NULL) {
745 context = req_context_empty();
746 }
747
748 /* Loop over all effects of this type. */
749 effect_list_iterate(get_effects(effect_type), peffect) {
750 sum += weighter(peffect, context, other_player, data, n_data);
752
753 return sum;
754}
755
756/**********************************************************************/
759int get_world_bonus(enum effect_type effect_type)
760{
761 if (!initialized) {
762 return 0;
763 }
764
765 return get_target_bonus_effects(NULL, NULL, NULL, effect_type);
766}
767
768/**********************************************************************/
771int get_player_bonus(const struct player *pplayer,
772 enum effect_type effect_type)
773{
774 if (!initialized) {
775 return 0;
776 }
777
778 return get_target_bonus_effects(NULL,
779 &(const struct req_context) {
780 .player = pplayer,
781 },
782 NULL,
783 effect_type);
784}
785
786/**********************************************************************/
789int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
790{
791 if (!initialized) {
792 return 0;
793 }
794
795 return get_target_bonus_effects(NULL,
796 &(const struct req_context) {
797 .player = city_owner(pcity),
798 .city = pcity,
799 .tile = city_tile(pcity),
800 },
801 NULL, effect_type);
802}
803
804/**********************************************************************/
808 const struct specialist *pspecialist,
809 const struct output_type *poutput,
810 enum effect_type effect_type)
811{
812 fc_assert_ret_val(pcity != NULL, 0);
813 fc_assert_ret_val(pspecialist != NULL, 0);
814 fc_assert_ret_val(poutput != NULL, 0);
815 return get_target_bonus_effects(NULL,
816 &(const struct req_context) {
817 .player = city_owner(pcity),
818 .city = pcity,
819 .output = poutput,
820 .specialist = pspecialist,
821 },
822 NULL,
823 effect_type);
824}
825
826/**********************************************************************/
838int get_city_tile_output_bonus(const struct city *pcity,
839 const struct tile *ptile,
840 const struct output_type *poutput,
841 enum effect_type effect_type)
842{
843 fc_assert_ret_val(pcity != NULL, 0);
844 return get_target_bonus_effects(NULL,
845 &(const struct req_context) {
846 .player = city_owner(pcity),
847 .city = pcity,
848 .tile = ptile,
849 .output = poutput,
850 },
851 NULL,
852 effect_type);
853}
854
855/**********************************************************************/
862int get_tile_output_bonus(const struct city *pcity,
863 const struct tile *ptile,
864 const struct output_type *poutput,
865 enum effect_type effect_type)
866{
867 const struct player *pplayer = pcity ? city_owner(pcity) : NULL;
868
869 return get_target_bonus_effects(NULL,
870 &(const struct req_context) {
871 .player = pplayer,
872 .city = pcity,
873 .tile = ptile,
874 .output = poutput,
875 },
876 NULL,
877 effect_type);
878}
879
880/**********************************************************************/
883int get_player_output_bonus(const struct player *pplayer,
884 const struct output_type *poutput,
885 enum effect_type effect_type)
886{
887 if (!initialized) {
888 return 0;
889 }
890
891 fc_assert_ret_val(pplayer != NULL, 0);
892 fc_assert_ret_val(poutput != NULL, 0);
893 fc_assert_ret_val(effect_type != EFT_COUNT, 0);
894 return get_target_bonus_effects(NULL,
895 &(const struct req_context) {
896 .player = pplayer,
897 .output= poutput,
898 },
899 NULL,
900 effect_type);
901}
902
903/**********************************************************************/
906int get_city_output_bonus(const struct city *pcity,
907 const struct output_type *poutput,
908 enum effect_type effect_type)
909{
910 if (!initialized) {
911 return 0;
912 }
913
914 fc_assert_ret_val(pcity != NULL, 0);
915 fc_assert_ret_val(poutput != NULL, 0);
916 fc_assert_ret_val(effect_type != EFT_COUNT, 0);
917 return get_target_bonus_effects(NULL,
918 &(const struct req_context) {
919 .player = city_owner(pcity),
920 .city = pcity,
921 .output = poutput,
922 },
923 NULL,
924 effect_type);
925}
926
927/**********************************************************************/
930int get_building_bonus(const struct city *pcity,
931 const struct impr_type *building,
932 enum effect_type effect_type)
933{
934 if (!initialized) {
935 return 0;
936 }
937
938 fc_assert_ret_val(NULL != pcity && NULL != building, 0);
939 return get_target_bonus_effects(NULL,
940 &(const struct req_context) {
941 .player = city_owner(pcity),
942 .city = pcity,
943 .building = building,
944 },
945 NULL,
946 effect_type);
947}
948
949/**********************************************************************/
957int get_unittype_bonus(const struct player *pplayer,
958 const struct tile *ptile,
959 const struct unit_type *punittype,
960 const struct action *paction,
961 enum effect_type effect_type)
962{
963 struct city *pcity;
964
965 if (!initialized) {
966 return 0;
967 }
968
969 fc_assert_ret_val(pplayer != NULL && punittype != NULL, 0);
970
971 if (ptile != NULL) {
972 pcity = tile_city(ptile);
973 } else {
974 pcity = NULL;
975 }
976
977 return get_target_bonus_effects(NULL,
978 &(const struct req_context) {
979 .player = pplayer,
980 .city = pcity,
981 .tile = ptile,
982 .unittype = punittype,
983 .action = paction,
984 },
985 NULL,
986 effect_type);
987}
988
989/**********************************************************************/
992int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
993{
994 if (!initialized) {
995 return 0;
996 }
997
998 fc_assert_ret_val(punit != NULL, 0);
999 return get_target_bonus_effects(NULL,
1000 &(const struct req_context) {
1001 .player = unit_owner(punit),
1002 .city = unit_tile(punit)
1004 : NULL,
1005 .tile = unit_tile(punit),
1006 .unit = punit,
1007 .unittype = unit_type_get(punit),
1008 },
1009 NULL,
1010 effect_type);
1011}
1012
1013/**********************************************************************/
1016int get_unit_vs_tile_bonus(const struct tile *ptile,
1017 const struct unit *punit,
1018 enum effect_type etype)
1019{
1020 struct player *pplayer = NULL;
1021 const struct unit_type *utype = NULL;
1022
1023 if (!initialized) {
1024 return 0;
1025 }
1026
1027 fc_assert_ret_val(ptile != NULL, 0);
1028
1029 if (punit != NULL) {
1030 pplayer = unit_owner(punit);
1031 utype = unit_type_get(punit);
1032 }
1033
1034 return get_target_bonus_effects(NULL,
1035 &(const struct req_context) {
1036 .player = pplayer,
1037 .city = tile_city(ptile),
1038 .tile = ptile,
1039 .unit = punit,
1040 .unittype = utype,
1041 },
1042 tile_owner(ptile),
1043 etype);
1044}
1045
1046/**********************************************************************/
1052int get_player_bonus_effects(struct effect_list *plist,
1053 const struct player *pplayer,
1054 enum effect_type effect_type)
1055{
1056 if (!initialized) {
1057 return 0;
1058 }
1059
1060 fc_assert_ret_val(pplayer != NULL, 0);
1061 return get_target_bonus_effects(plist,
1062 &(const struct req_context) {
1063 .player = pplayer,
1064 },
1065 NULL,
1066 effect_type);
1067}
1068
1069/**********************************************************************/
1075int get_city_bonus_effects(struct effect_list *plist,
1076 const struct city *pcity,
1077 const struct output_type *poutput,
1078 enum effect_type effect_type)
1079{
1080 if (!initialized) {
1081 return 0;
1082 }
1083
1084 fc_assert_ret_val(pcity != NULL, 0);
1085 return get_target_bonus_effects(plist,
1086 &(const struct req_context) {
1087 .player = city_owner(pcity),
1088 .city = pcity,
1089 .output = poutput,
1090 },
1091 NULL,
1092 effect_type);
1093}
1094
1095/**********************************************************************/
1104int get_current_construction_bonus(const struct city *pcity,
1105 enum effect_type effect_type,
1106 const enum req_problem_type prob_type)
1107{
1108 if (!initialized) {
1109 return 0;
1110 }
1111
1112 if (VUT_IMPROVEMENT == pcity->production.kind) {
1114 pcity, effect_type, prob_type, TRUE);
1115 }
1116
1117 return 0;
1118}
1119
1120/**********************************************************************/
1127 const struct city *pcity,
1128 enum effect_type effect_type,
1129 const enum req_problem_type prob_type,
1130 bool consider_multipliers)
1131{
1132 struct universal source = { .kind = VUT_IMPROVEMENT,
1133 .value = {.building = pimprove}};
1134 struct effect_list *plist = get_req_source_effects(&source);
1135 struct player *owner = NULL;
1136
1137 if (pcity != NULL) {
1138 owner = city_owner(pcity);
1139 }
1140
1141 if (plist) {
1142 int power = 0;
1143 const struct req_context context = {
1144 .player = owner,
1145 .city = pcity,
1146 .building = pimprove,
1147 };
1148
1149 effect_list_iterate(plist, peffect) {
1150 bool present = TRUE;
1151 bool useful = TRUE;
1152
1153 if (peffect->type != effect_type) {
1154 continue;
1155 }
1156
1157 requirement_vector_iterate(&peffect->reqs, preq) {
1158 if (VUT_IMPROVEMENT == preq->source.kind
1159 && preq->source.value.building == pimprove) {
1160 present = preq->present;
1161 continue;
1162 }
1163
1164 if (!is_req_active(&context, NULL, preq, prob_type)) {
1165 useful = FALSE;
1166 break;
1167 }
1169
1170 if (useful) {
1171 int val;
1172
1173 if (present) {
1174 val = peffect->value;
1175 } else {
1176 val = -peffect->value;
1177 }
1178
1179 if (consider_multipliers && peffect->multiplier) {
1180 val = val * player_multiplier_effect_value(owner, peffect->multiplier) / 100;
1181 }
1182
1183 power += val;
1184 }
1186
1187 return power;
1188 }
1189
1190 return 0;
1191}
1192
1193/**********************************************************************/
1197void get_effect_req_text(const struct effect *peffect,
1198 char *buf, size_t buf_len)
1199{
1200 buf[0] = '\0';
1201
1202 if (peffect->multiplier) {
1203 fc_strlcat(buf, multiplier_name_translation(peffect->multiplier), buf_len);
1204 }
1205
1206 /* FIXME: should we do something for present FALSE reqs?
1207 * Currently we just ignore them. */
1208 requirement_vector_iterate(&peffect->reqs, preq) {
1209 if (!preq->present) {
1210 continue;
1211 }
1212 if (buf[0] != '\0') {
1213 fc_strlcat(buf, Q_("?req-list-separator:+"), buf_len);
1214 }
1215
1216 universal_name_translation(&preq->source,
1217 buf + strlen(buf), buf_len - strlen(buf));
1219}
1220
1221/**********************************************************************/
1225void get_effect_list_req_text(const struct effect_list *plist,
1226 struct astring *astr)
1227{
1228 struct strvec *psv = strvec_new();
1229 char req_text[512];
1230
1231 effect_list_iterate(plist, peffect) {
1232 get_effect_req_text(peffect, req_text, sizeof(req_text));
1233 strvec_append(psv, req_text);
1235
1236 strvec_to_and_list(psv, astr);
1237 strvec_destroy(psv);
1238}
1239
1240/**********************************************************************/
1245bool iterate_effect_cache(iec_cb cb, void *data)
1246{
1247 fc_assert_ret_val(cb != NULL, FALSE);
1248
1249 effect_list_iterate(ruleset_cache.tracker, peffect) {
1250 if (!cb(peffect, data)) {
1251 return FALSE;
1252 }
1254
1255 return TRUE;
1256}
#define city_tile(_pcity_)
Definition city.h:544
#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
void effect_remove(struct effect *peffect)
Definition effects.c:205
void recv_ruleset_effect(const struct packet_ruleset_effect *packet)
Definition effects.c:534
struct effect_list * effects[EFT_COUNT]
Definition effects.c:120
struct effect_list * govs[G_LAST]
Definition effects.c:126
struct effect_list * tracker
Definition effects.c:116
bool effect_universals_value_never_below(enum effect_type type, struct universal *unis, size_t n_unis, int min_value)
Definition effects.c:488
struct effect_list * get_req_source_effects(struct universal *psource)
Definition effects.c:146
struct @21::@22 reqs
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:862
int get_player_output_bonus(const struct player *pplayer, const struct output_type *poutput, enum effect_type effect_type)
Definition effects.c:883
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:807
bool is_building_replaced(const struct city *pcity, const struct impr_type *pimprove, const enum req_problem_type prob_type)
Definition effects.c:641
int get_target_bonus_effects(struct effect_list *plist, const struct req_context *context, const struct player *other_player, enum effect_type effect_type)
Definition effects.c:691
int get_player_bonus_effects(struct effect_list *plist, const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:1052
bool iterate_effect_cache(iec_cb cb, void *data)
Definition effects.c:1245
int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
Definition effects.c:789
int get_current_construction_bonus(const struct city *pcity, enum effect_type effect_type, const enum req_problem_type prob_type)
Definition effects.c:1104
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:1075
struct effect * effect_copy(struct effect *old)
Definition effects.c:214
static bool is_effect_prevented(const struct req_context *context, const struct player *other_player, const struct effect *peffect, const enum req_problem_type prob_type)
Definition effects.c:618
int get_unit_vs_tile_bonus(const struct tile *ptile, const struct unit *punit, enum effect_type etype)
Definition effects.c:1016
int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
Definition effects.c:992
int get_city_output_bonus(const struct city *pcity, const struct output_type *poutput, enum effect_type effect_type)
Definition effects.c:906
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:1126
void send_ruleset_cache(struct conn_list *dest)
Definition effects.c:553
void get_effect_req_text(const struct effect *peffect, char *buf, size_t buf_len)
Definition effects.c:1197
static struct @21 ruleset_cache
struct effect_list * buildings[B_LAST]
Definition effects.c:124
void ruleset_cache_free(void)
Definition effects.c:271
struct effect * effect_new(enum effect_type type, int value, struct multiplier *pmul)
Definition effects.c:179
int get_building_bonus(const struct city *pcity, const struct impr_type *building, enum effect_type effect_type)
Definition effects.c:930
int effect_value_from_universals(enum effect_type type, struct universal *unis, size_t n_unis)
Definition effects.c:402
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:838
int effect_cumulative_max(enum effect_type type, struct universal *unis, size_t n_unis)
Definition effects.c:331
void ruleset_cache_init(void)
Definition effects.c:245
struct effect_list * advances[A_LAST]
Definition effects.c:128
int get_world_bonus(enum effect_type effect_type)
Definition effects.c:759
int effect_cumulative_min(enum effect_type type, struct universal *for_uni)
Definition effects.c:367
struct effect_list * get_effects(enum effect_type effect_type)
Definition effects.c:136
bool building_has_effect(const struct impr_type *pimprove, enum effect_type effect_type)
Definition effects.c:587
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:736
static bool initialized
Definition effects.c:42
void effect_req_append(struct effect *peffect, struct requirement req)
Definition effects.c:229
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:957
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:771
void get_effect_list_req_text(const struct effect_list *plist, struct astring *astr)
Definition effects.c:1225
int effect_value_will_make_positive(enum effect_type type)
Definition effects.c:525
#define effect_list_iterate_end
Definition effects.h:375
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:364
bool(* iec_cb)(struct effect *, void *data)
Definition effects.h:485
#define effect_list_iterate(effect_list, peffect)
Definition effects.h:373
req_problem_type
Definition fc_types.h:584
@ RPT_CERTAIN
Definition fc_types.h:586
#define REVERSED_RPT(x)
Definition fc_types.h:589
#define Q_(String)
Definition fcintl.h:70
Government_type_id government_count(void)
Definition government.c:70
#define G_LAST
Definition government.h:48
struct city * owner
Definition citydlg.c:219
static GtkWidget * source
Definition gotodlg.c:58
GType type
Definition repodlgs.c:1312
struct impr_type * improvement_by_number(const Impr_type_id id)
Impr_type_id improvement_number(const struct impr_type *pimprove)
Impr_type_id improvement_count(void)
#define B_LAST
Definition improvement.h:42
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#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
void lsend_packet_ruleset_effect(struct conn_list *dest, const struct packet_ruleset_effect *packet)
int player_multiplier_effect_value(const struct player *pplayer, const struct multiplier *pmul)
Definition player.c:1933
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 player *other_player, const struct requirement *req, const enum req_problem_type prob_type)
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)
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:309
struct universal production
Definition city.h:382
struct tile * tile
Definition city.h:311
int value
Definition effects.h:349
struct multiplier * multiplier
Definition effects.h:344
bool ruledit_do_not_save
Definition effects.h:357
struct requirement_vector reqs
Definition effects.h:353
enum effect_type type
Definition effects.h:341
struct requirement reqs[MAX_NUM_REQS]
Multiplier_type_id multiplier
enum effect_type effect_type
const struct player * player
struct universal source
Definition tile.h:49
Definition unit.h:138
enum universals_n kind
Definition fc_types.h:758
universals_u value
Definition fc_types.h:757
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:832
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
static Tech_type_id advance_count(void)
Definition tech.h:170
#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:95
const struct impr_type * building
Definition fc_types.h:598
#define unit_tile(_pu)
Definition unit.h:395
#define unit_owner(_pu)
Definition unit.h:394
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123