Stop sharing requirement_unit_state_ereq().
[freeciv.git] / common / effects.c
blob47739afa574485bae995a0542c06d6dbf6031f5e
1 /***********************************************************************
2 Freeciv - Copyright (C) 2004 - The Freeciv Team
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
13 #ifdef HAVE_CONFIG_H
14 #include <fc_config.h>
15 #endif
17 #include <ctype.h>
18 #include <string.h>
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"
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"
39 #include "effects.h"
42 static bool initialized = FALSE;
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).
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.
55 To know how much a target is being affected, simply use the convenience
56 functions:
58 * get_player_bonus
59 * get_city_bonus
60 * get_city_tile_bonus
61 * get_building_bonus
63 These functions require as arguments the target and the effect type to be
64 queried.
66 Effect sources are unique and at a well known place in the
67 data structures. This allows the above queries to be fast:
68 - Look up the possible sources for the effect (O(1) lookup)
69 - For each source, find out if it is present (O(1) lookup per source).
70 The first is commonly called the "ruleset cache" and is stored statically
71 in this file. The second is the "sources cache" and is stored all over.
73 Any type of effect range and "survives" is possible if we have a sources
74 cache for that combination. For instance
75 - There is a sources cache of all existing buildings in a city; thus any
76 building effect in a city can have city range.
77 - There is a sources cache of all wonders in the world; thus any wonder
78 effect can have world range.
79 - There is a sources cache of all wonders for each player; thus any
80 wonder effect can have player range.
81 - There is a sources cache of all wonders ever built; thus any wonder
82 effect that survives can have world range.
83 However there is no sources cache for many of the possible sources. For
84 instance non-unique buildings do not have a world-range sources cahce, so
85 you can't have a non-wonder building have a world-ranged effect.
87 The sources caches could easily be extended by generalizing it to a set
88 of arrays
89 game.buildings[], pplayer->buildings[],
90 pisland->builidngs[], pcity->buildings[]
91 which would store the number of buildings of that type present by game,
92 player, island (continent) or city. This would allow non-surviving effects
93 to come from any building at any range. However to allow surviving effects
94 a second set of arrays would be needed. This should enable basic support
95 for small wonders and satellites.
97 No matter which sources caches are present, we should always know where
98 to look for a source and so the lookups will always be fast even as the
99 number of possible sources increases.
100 **************************************************************************/
102 /**************************************************************************
103 Ruleset cache. The cache is created during ruleset loading and the data
104 is organized to enable fast queries.
105 **************************************************************************/
106 static struct {
107 /* A single list containing every effect. */
108 struct effect_list *tracker;
110 /* This array provides a full list of the effects of this type
111 * (It's not really a cache, it's the real data.) */
112 struct effect_list *effects[EFT_COUNT];
114 struct {
115 /* This cache shows for each building, which effects it provides. */
116 struct effect_list *buildings[B_LAST];
117 /* Same for governments */
118 struct effect_list *govs[G_LAST];
119 /* ...advances... */
120 struct effect_list *advances[A_LAST];
121 } reqs;
122 } ruleset_cache;
125 /**************************************************************************
126 Get a list of effects of this type.
127 **************************************************************************/
128 struct effect_list *get_effects(enum effect_type effect_type)
130 return ruleset_cache.effects[effect_type];
133 /**************************************************************************
134 Get a list of effects with this requirement source.
136 Note: currently only buildings and governments are supported.
137 **************************************************************************/
138 struct effect_list *get_req_source_effects(struct universal *psource)
140 int type, value;
142 universal_extraction(psource, &type, &value);
144 switch (type) {
145 case VUT_GOVERNMENT:
146 if (value >= 0 && value < government_count()) {
147 return ruleset_cache.reqs.govs[value];
148 } else {
149 return NULL;
151 case VUT_IMPROVEMENT:
152 if (value >= 0 && value < improvement_count()) {
153 return ruleset_cache.reqs.buildings[value];
154 } else {
155 return NULL;
157 case VUT_ADVANCE:
158 if (value >= 0 && value < advance_count()) {
159 return ruleset_cache.reqs.advances[value];
160 } else {
161 return NULL;
163 default:
164 return NULL;
168 /**************************************************************************
169 Add effect to ruleset cache.
170 **************************************************************************/
171 struct effect *effect_new(enum effect_type type, int value,
172 struct multiplier *pmul)
174 struct effect *peffect;
176 /* Create the effect. */
177 peffect = fc_malloc(sizeof(*peffect));
178 peffect->type = type;
179 peffect->value = value;
180 peffect->multiplier = pmul;
182 requirement_vector_init(&peffect->reqs);
184 /* Now add the effect to the ruleset cache. */
185 effect_list_append(ruleset_cache.tracker, peffect);
186 effect_list_append(get_effects(type), peffect);
188 return peffect;
191 /**************************************************************************
192 Return new copy of the effect
193 **************************************************************************/
194 struct effect *effect_copy(struct effect *old)
196 struct effect *new_eff = effect_new(old->type, old->value,
197 old->multiplier);
199 requirement_vector_iterate(&old->reqs, preq) {
200 effect_req_append(new_eff, *preq);
201 } requirement_vector_iterate_end;
203 return new_eff;
206 /**************************************************************************
207 Append requirement to effect.
208 **************************************************************************/
209 void effect_req_append(struct effect *peffect, struct requirement req)
211 struct effect_list *eff_list = get_req_source_effects(&req.source);
213 requirement_vector_append(&peffect->reqs, req);
215 if (eff_list) {
216 effect_list_append(eff_list, peffect);
220 /**************************************************************************
221 Initialize the ruleset cache. The ruleset cache should be empty
222 before this is done (so if it's previously been initialized, it needs
223 to be freed (see ruleset_cache_free) before it can be reused).
224 **************************************************************************/
225 void ruleset_cache_init(void)
227 int i;
229 initialized = TRUE;
231 ruleset_cache.tracker = effect_list_new();
233 for (i = 0; i < ARRAY_SIZE(ruleset_cache.effects); i++) {
234 ruleset_cache.effects[i] = effect_list_new();
236 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.buildings); i++) {
237 ruleset_cache.reqs.buildings[i] = effect_list_new();
239 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.govs); i++) {
240 ruleset_cache.reqs.govs[i] = effect_list_new();
242 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.advances); i++) {
243 ruleset_cache.reqs.advances[i] = effect_list_new();
247 /**************************************************************************
248 Free the ruleset cache. This should be called at the end of the game or
249 when the client disconnects from the server. See ruleset_cache_init.
250 **************************************************************************/
251 void ruleset_cache_free(void)
253 int i;
254 struct effect_list *tracker_list = ruleset_cache.tracker;
256 if (tracker_list) {
257 effect_list_iterate(tracker_list, peffect) {
258 requirement_vector_free(&peffect->reqs);
259 free(peffect);
260 } effect_list_iterate_end;
261 effect_list_destroy(tracker_list);
262 ruleset_cache.tracker = NULL;
265 for (i = 0; i < ARRAY_SIZE(ruleset_cache.effects); i++) {
266 struct effect_list *plist = ruleset_cache.effects[i];
268 if (plist) {
269 effect_list_destroy(plist);
270 ruleset_cache.effects[i] = NULL;
274 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.buildings); i++) {
275 struct effect_list *plist = ruleset_cache.reqs.buildings[i];
277 if (plist) {
278 effect_list_destroy(plist);
279 ruleset_cache.reqs.buildings[i] = NULL;
283 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.govs); i++) {
284 struct effect_list *plist = ruleset_cache.reqs.govs[i];
286 if (plist) {
287 effect_list_destroy(plist);
288 ruleset_cache.reqs.govs[i] = NULL;
292 for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.advances); i++) {
293 struct effect_list *plist = ruleset_cache.reqs.advances[i];
295 if (plist) {
296 effect_list_destroy(plist);
297 ruleset_cache.reqs.advances[i] = NULL;
301 initialized = FALSE;
304 /****************************************************************************
305 Get the maximum effect value in this ruleset for the universal
306 (that is, the sum of all positive effects clauses that apply specifically
307 to this universal -- this can be an overestimate in the case of
308 mutually exclusive effects).
309 for_uni can be NULL to get max effect value ignoring requirements.
310 ****************************************************************************/
311 int effect_cumulative_max(enum effect_type type, struct universal *for_uni)
313 struct effect_list *plist = ruleset_cache.tracker;
314 int value = 0;
316 if (plist) {
317 effect_list_iterate(plist, peffect) {
318 if (peffect->type == type && peffect->value > 0) {
319 if (for_uni == NULL
320 || universal_fulfills_requirement(FALSE, &(peffect->reqs), for_uni)) {
321 value += peffect->value;
324 } effect_list_iterate_end;
327 return value;
330 /****************************************************************************
331 Get the minimum effect value in this ruleset for the universal
332 (that is, the sum of all negative effects clauses that apply specifically
333 to this universal -- this can be an overestimate in the case of
334 mutually exclusive effects).
335 for_uni can be NULL to get min effect value ignoring requirements.
336 ****************************************************************************/
337 int effect_cumulative_min(enum effect_type type, struct universal *for_uni)
339 struct effect_list *plist = ruleset_cache.tracker;
340 int value = 0;
342 if (plist) {
343 effect_list_iterate(plist, peffect) {
344 if (peffect->type == type && peffect->value < 0) {
345 if (for_uni == NULL
346 || universal_fulfills_requirement(FALSE, &(peffect->reqs), for_uni)) {
347 value += peffect->value;
350 } effect_list_iterate_end;
353 return value;
356 /****************************************************************************
357 Receives a new effect. This is called by the client when the packet
358 arrives.
359 ****************************************************************************/
360 void recv_ruleset_effect(const struct packet_ruleset_effect *packet)
362 struct effect *peffect;
363 struct multiplier *pmul;
364 int i;
366 pmul = packet->has_multiplier ? multiplier_by_number(packet->multiplier)
367 : NULL;
368 peffect = effect_new(packet->effect_type, packet->effect_value, pmul);
370 for (i = 0; i < packet->reqs_count; i++) {
371 effect_req_append(peffect, packet->reqs[i]);
373 fc_assert(peffect->reqs.size == packet->reqs_count);
376 /**************************************************************************
377 Send the ruleset cache data over the network.
378 **************************************************************************/
379 void send_ruleset_cache(struct conn_list *dest)
381 effect_list_iterate(ruleset_cache.tracker, peffect) {
382 struct packet_ruleset_effect effect_packet;
383 int counter;
385 effect_packet.effect_type = peffect->type;
386 effect_packet.effect_value = peffect->value;
387 if (peffect->multiplier) {
388 effect_packet.has_multiplier = TRUE;
389 effect_packet.multiplier = multiplier_number(peffect->multiplier);
390 } else {
391 effect_packet.has_multiplier = FALSE;
392 effect_packet.multiplier = 0; /* arbitrary */
395 counter = 0;
396 requirement_vector_iterate(&(peffect->reqs), req) {
397 effect_packet.reqs[counter++] = *req;
398 } requirement_vector_iterate_end;
399 effect_packet.reqs_count = counter;
401 lsend_packet_ruleset_effect(dest, &effect_packet);
402 } effect_list_iterate_end;
405 /**************************************************************************
406 Returns TRUE if the building has any effect bonuses of the given type.
408 Note that this function returns a boolean rather than an integer value
409 giving the exact bonus. Finding the exact bonus requires knowing the
410 effect range and may take longer. This function should only be used
411 in situations where the range doesn't matter.
412 **************************************************************************/
413 bool building_has_effect(const struct impr_type *pimprove,
414 enum effect_type effect_type)
416 struct universal source = {
417 .kind = VUT_IMPROVEMENT,
418 /* just to bamboozle the annoying compiler warning */
419 .value = {.building = improvement_by_number(improvement_number(pimprove))}
421 struct effect_list *plist = get_req_source_effects(&source);
423 if (!plist) {
424 return FALSE;
427 effect_list_iterate(plist, peffect) {
428 if (peffect->type == effect_type) {
429 return TRUE;
431 } effect_list_iterate_end;
432 return FALSE;
435 /**************************************************************************
436 Return TRUE iff any of the disabling requirements for this effect are
437 active, which would prevent it from taking effect.
438 (Assumes that any requirement specified in the ruleset with a negative
439 sense is an impediment.)
440 **************************************************************************/
441 static bool is_effect_prevented(const struct player *target_player,
442 const struct player *other_player,
443 const struct city *target_city,
444 const struct impr_type *target_building,
445 const struct tile *target_tile,
446 const struct unit *target_unit,
447 const struct unit_type *target_unittype,
448 const struct output_type *target_output,
449 const struct specialist *target_specialist,
450 const struct effect *peffect,
451 const enum req_problem_type prob_type)
453 requirement_vector_iterate(&peffect->reqs, preq) {
454 /* Only check present=FALSE requirements; these will return _FALSE_
455 * from is_req_active() if met, and need reversed prob_type */
456 if (!preq->present
457 && !is_req_active(target_player, other_player, target_city,
458 target_building, target_tile,
459 target_unit, target_unittype,
460 target_output, target_specialist, NULL,
461 preq, REVERSED_RPT(prob_type))) {
462 return TRUE;
464 } requirement_vector_iterate_end;
465 return FALSE;
468 /**************************************************************************
469 Returns TRUE if a building is replaced. To be replaced, all its effects
470 must be made redundant by groups that it is in.
471 prob_type CERTAIN or POSSIBLE is answer to function name.
472 **************************************************************************/
473 bool is_building_replaced(const struct city *pcity,
474 struct impr_type *pimprove,
475 const enum req_problem_type prob_type)
477 struct effect_list *plist;
478 struct universal source = {
479 .kind = VUT_IMPROVEMENT,
480 .value = {.building = pimprove}
483 plist = get_req_source_effects(&source);
485 /* A building with no effects and no flags is always redundant! */
486 if (!plist) {
487 return TRUE;
490 effect_list_iterate(plist, peffect) {
491 /* We use TARGET_BUILDING as the lowest common denominator. Note that
492 * the building is its own target - but whether this is actually
493 * checked depends on the range of the effect. */
494 /* Prob_type is not reversed here. disabled is equal to replaced, not
495 * reverse */
496 if (!is_effect_prevented(city_owner(pcity), NULL, pcity,
497 pimprove,
498 NULL, NULL, NULL, NULL, NULL,
499 peffect, prob_type)) {
500 return FALSE;
502 } effect_list_iterate_end;
503 return TRUE;
506 /**************************************************************************
507 Returns the effect bonus of a given type for any target.
509 target gives the type of the target
510 (player,city,building,tile) give the exact target
511 effect_type gives the effect type to be considered
513 Returns the effect sources of this type _currently active_.
515 The returned vector must be freed (building_vector_free) when the caller
516 is done with it.
517 **************************************************************************/
518 int get_target_bonus_effects(struct effect_list *plist,
519 const struct player *target_player,
520 const struct player *other_player,
521 const struct city *target_city,
522 const struct impr_type *target_building,
523 const struct tile *target_tile,
524 const struct unit *target_unit,
525 const struct unit_type *target_unittype,
526 const struct output_type *target_output,
527 const struct specialist *target_specialist,
528 const struct action *target_action,
529 enum effect_type effect_type)
531 int bonus = 0;
533 /* Loop over all effects of this type. */
534 effect_list_iterate(get_effects(effect_type), peffect) {
535 /* For each effect, see if it is active. */
536 if (are_reqs_active(target_player, other_player, target_city,
537 target_building, target_tile,
538 target_unit, target_unittype,
539 target_output, target_specialist, target_action,
540 &peffect->reqs, RPT_CERTAIN)) {
541 /* This code will add value of effect. If there's multiplier for
542 * effect and target_player aren't null, then value is multiplied
543 * by player's multiplier factor. */
544 if (peffect->multiplier) {
545 if (target_player) {
546 bonus += (peffect->value
547 * player_multiplier_effect_value(target_player,
548 peffect->multiplier)) / 100;
550 } else {
551 bonus += peffect->value;
554 if (plist) {
555 effect_list_append(plist, peffect);
558 } effect_list_iterate_end;
560 return bonus;
563 /**************************************************************************
564 Returns the effect bonus for the whole world.
565 **************************************************************************/
566 int get_world_bonus(enum effect_type effect_type)
568 if (!initialized) {
569 return 0;
572 return get_target_bonus_effects(NULL,
573 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
574 NULL, NULL, NULL,
575 effect_type);
578 /**************************************************************************
579 Returns the effect bonus for a player.
580 **************************************************************************/
581 int get_player_bonus(const struct player *pplayer,
582 enum effect_type effect_type)
584 if (!initialized) {
585 return 0;
588 return get_target_bonus_effects(NULL,
589 pplayer, NULL, NULL, NULL,
590 NULL, NULL, NULL, NULL, NULL,
591 NULL, effect_type);
594 /**************************************************************************
595 Returns the effect bonus at a city.
596 **************************************************************************/
597 int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
599 if (!initialized) {
600 return 0;
603 return get_target_bonus_effects(NULL,
604 city_owner(pcity), NULL, pcity, NULL,
605 city_tile(pcity), NULL, NULL, NULL, NULL,
606 NULL, effect_type);
609 /**************************************************************************
610 Returns the effect bonus of a specialist in a city.
611 **************************************************************************/
612 int get_city_specialist_output_bonus(const struct city *pcity,
613 const struct specialist *pspecialist,
614 const struct output_type *poutput,
615 enum effect_type effect_type)
617 fc_assert_ret_val(pcity != NULL, 0);
618 fc_assert_ret_val(pspecialist != NULL, 0);
619 fc_assert_ret_val(poutput != NULL, 0);
620 return get_target_bonus_effects(NULL,
621 city_owner(pcity), NULL, pcity, NULL,
622 NULL, NULL, NULL, poutput, pspecialist,
623 NULL,
624 effect_type);
627 /**************************************************************************
628 Returns the effect bonus at a city tile.
630 FIXME: this is now used both for tile bonuses, tile-output bonuses,
631 and city-output bonuses. Thus ptile or poutput may be NULL for
632 certain callers. This could be changed by adding 2 new functions to
633 the interface but they'd be almost identical and their likely names
634 would conflict with functions already in city.c.
635 **************************************************************************/
636 int get_city_tile_output_bonus(const struct city *pcity,
637 const struct tile *ptile,
638 const struct output_type *poutput,
639 enum effect_type effect_type)
641 fc_assert_ret_val(pcity != NULL, 0);
642 return get_target_bonus_effects(NULL,
643 city_owner(pcity), NULL, pcity, NULL,
644 ptile, NULL, NULL, poutput, NULL, NULL,
645 effect_type);
648 /**************************************************************************
649 Returns the player effect bonus of an output.
650 **************************************************************************/
651 int get_player_output_bonus(const struct player *pplayer,
652 const struct output_type *poutput,
653 enum effect_type effect_type)
655 if (!initialized) {
656 return 0;
659 fc_assert_ret_val(pplayer != NULL, 0);
660 fc_assert_ret_val(poutput != NULL, 0);
661 fc_assert_ret_val(effect_type != EFT_COUNT, 0);
662 return get_target_bonus_effects(NULL, pplayer, NULL, NULL, NULL, NULL,
663 NULL, NULL, poutput, NULL, NULL,
664 effect_type);
667 /**************************************************************************
668 Returns the player effect bonus of an output.
669 **************************************************************************/
670 int get_city_output_bonus(const struct city *pcity,
671 const struct output_type *poutput,
672 enum effect_type effect_type)
674 if (!initialized) {
675 return 0;
678 fc_assert_ret_val(pcity != NULL, 0);
679 fc_assert_ret_val(poutput != NULL, 0);
680 fc_assert_ret_val(effect_type != EFT_COUNT, 0);
681 return get_target_bonus_effects(NULL, city_owner(pcity), NULL, pcity,
682 NULL, NULL, NULL, NULL, poutput, NULL,
683 NULL,
684 effect_type);
687 /**************************************************************************
688 Returns the effect bonus at a building.
689 **************************************************************************/
690 int get_building_bonus(const struct city *pcity,
691 const struct impr_type *building,
692 enum effect_type effect_type)
694 if (!initialized) {
695 return 0;
698 fc_assert_ret_val(NULL != pcity && NULL != building, 0);
699 return get_target_bonus_effects(NULL,
700 city_owner(pcity), NULL, pcity,
701 building,
702 NULL, NULL, NULL, NULL,
703 NULL, NULL, effect_type);
706 /**************************************************************************
707 Returns the effect bonus that applies at a tile for a given unittype.
709 For instance with EFT_DEFEND_BONUS the attacker's unittype and the
710 defending tile should be passed in. Slightly counter-intuitive!
711 See doc/README.effects to see how the unittype applies for each effect
712 here.
713 **************************************************************************/
714 int get_unittype_bonus(const struct player *pplayer,
715 const struct tile *ptile,
716 const struct unit_type *punittype,
717 enum effect_type effect_type)
719 struct city *pcity;
721 if (!initialized) {
722 return 0;
725 fc_assert_ret_val(pplayer != NULL && punittype != NULL, 0);
727 if (ptile != NULL) {
728 pcity = tile_city(ptile);
729 } else {
730 pcity = NULL;
733 return get_target_bonus_effects(NULL,
734 pplayer, NULL, pcity, NULL, ptile,
735 NULL, punittype, NULL,
736 NULL, NULL, effect_type);
739 /**************************************************************************
740 Returns the effect bonus at a unit
741 **************************************************************************/
742 int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
744 if (!initialized) {
745 return 0;
748 fc_assert_ret_val(punit != NULL, 0);
749 return get_target_bonus_effects(NULL,
750 unit_owner(punit),
751 NULL,
752 unit_tile(punit)
753 ? tile_city(unit_tile(punit)) : NULL,
754 NULL, unit_tile(punit),
755 punit, unit_type_get(punit), NULL, NULL,
756 NULL,
757 effect_type);
760 /**************************************************************************
761 Returns the effect bonus at a tile
762 **************************************************************************/
763 int get_tile_bonus(const struct tile *ptile, const struct unit *punit,
764 enum effect_type etype)
766 struct player *pplayer = NULL;
767 struct unit_type *utype = NULL;
769 if (!initialized) {
770 return 0;
773 fc_assert_ret_val(ptile != NULL, 0);
775 if (punit != NULL) {
776 pplayer = unit_owner(punit);
777 utype = unit_type_get(punit);
780 return get_target_bonus_effects(NULL,
781 pplayer,
782 NULL,
783 tile_city(ptile),
784 NULL,
785 ptile,
786 punit,
787 utype,
788 NULL, NULL, NULL,
789 etype);
792 /**************************************************************************
793 Returns the effect sources of this type _currently active_ at the player.
795 The returned vector must be freed (building_vector_free) when the caller
796 is done with it.
797 **************************************************************************/
798 int get_player_bonus_effects(struct effect_list *plist,
799 const struct player *pplayer,
800 enum effect_type effect_type)
802 if (!initialized) {
803 return 0;
806 fc_assert_ret_val(pplayer != NULL, 0);
807 return get_target_bonus_effects(plist,
808 pplayer, NULL, NULL, NULL,
809 NULL, NULL, NULL, NULL, NULL, NULL,
810 effect_type);
813 /**************************************************************************
814 Returns the effect sources of this type _currently active_ at the city.
816 The returned vector must be freed (building_vector_free) when the caller
817 is done with it.
818 **************************************************************************/
819 int get_city_bonus_effects(struct effect_list *plist,
820 const struct city *pcity,
821 const struct output_type *poutput,
822 enum effect_type effect_type)
824 if (!initialized) {
825 return 0;
828 fc_assert_ret_val(pcity != NULL, 0);
829 return get_target_bonus_effects(plist,
830 city_owner(pcity), NULL, pcity, NULL,
831 NULL, NULL, NULL, poutput, NULL, NULL,
832 effect_type);
835 /**************************************************************************
836 Returns the effect bonus the currently-in-construction-item will provide.
838 Note this is not called get_current_production_bonus because that would
839 be confused with EFT_PROD_BONUS.
841 Problem type tells if we need to be CERTAIN about bonus before counting
842 it or is POSSIBLE bonus enough.
843 **************************************************************************/
844 int get_current_construction_bonus(const struct city *pcity,
845 enum effect_type effect_type,
846 const enum req_problem_type prob_type)
848 if (!initialized) {
849 return 0;
852 if (VUT_IMPROVEMENT == pcity->production.kind) {
853 return get_potential_improvement_bonus(pcity->production.value.building,
854 pcity, effect_type, prob_type);
856 return 0;
859 /**************************************************************************
860 Returns the effect bonus the improvement would or does provide if present.
862 Problem type tells if we need to be CERTAIN about bonus before counting
863 it or is POSSIBLE bonus enough.
864 **************************************************************************/
865 int get_potential_improvement_bonus(struct impr_type *pimprove,
866 const struct city *pcity,
867 enum effect_type effect_type,
868 const enum req_problem_type prob_type)
870 struct universal source = { .kind = VUT_IMPROVEMENT,
871 .value = {.building = pimprove}};
872 struct effect_list *plist = get_req_source_effects(&source);
875 if (plist) {
876 int power = 0;
878 effect_list_iterate(plist, peffect) {
879 bool present = TRUE;
880 bool useful = TRUE;
882 if (peffect->type != effect_type) {
883 continue;
886 requirement_vector_iterate(&peffect->reqs, preq) {
887 if (VUT_IMPROVEMENT == preq->source.kind
888 && preq->source.value.building == pimprove) {
889 present = preq->present;
890 continue;
893 if (!is_req_active(city_owner(pcity), NULL, pcity, pimprove,
894 NULL, NULL, NULL, NULL, NULL, NULL,
895 preq, prob_type)) {
896 useful = FALSE;
897 break;
899 } requirement_vector_iterate_end;
901 if (useful) {
902 if (present) {
903 power += peffect->value;
904 } else {
905 power -= peffect->value;
908 } effect_list_iterate_end;
910 return power;
912 return 0;
915 /**************************************************************************
916 Make user-friendly text for the source. The text is put into a user
917 buffer.
918 **************************************************************************/
919 void get_effect_req_text(const struct effect *peffect,
920 char *buf, size_t buf_len)
922 buf[0] = '\0';
924 if (peffect->multiplier) {
925 fc_strlcat(buf, multiplier_name_translation(peffect->multiplier), buf_len);
928 /* FIXME: should we do something for present == FALSE reqs?
929 * Currently we just ignore them. */
930 requirement_vector_iterate(&peffect->reqs, preq) {
931 if (!preq->present) {
932 continue;
934 if (buf[0] != '\0') {
935 fc_strlcat(buf, Q_("?req-list-separator:+"), buf_len);
938 universal_name_translation(&preq->source,
939 buf + strlen(buf), buf_len - strlen(buf));
940 } requirement_vector_iterate_end;
943 /****************************************************************************
944 Make user-friendly text for an effect list. The text is put into a user
945 astring.
946 ****************************************************************************/
947 void get_effect_list_req_text(const struct effect_list *plist,
948 struct astring *astr)
950 struct strvec *psv = strvec_new();
951 char req_text[512];
953 effect_list_iterate(plist, peffect) {
954 get_effect_req_text(peffect, req_text, sizeof(req_text));
955 strvec_append(psv, req_text);
956 } effect_list_iterate_end;
958 strvec_to_and_list(psv, astr);
959 strvec_destroy(psv);
962 /**************************************************************************
963 Iterate through all the effects in cache, and call callback for each.
964 This is currently not very generic implementation, as we have only one user;
965 ruleset sanity checking. If any callback returns FALSE, there is no
966 further checking and this will return FALSE.
967 **************************************************************************/
968 bool iterate_effect_cache(iec_cb cb, void *data)
970 fc_assert_ret_val(cb != NULL, FALSE);
972 effect_list_iterate(ruleset_cache.tracker, peffect) {
973 if (!cb(peffect, data)) {
974 return FALSE;
976 } effect_list_iterate_end;
978 return TRUE;