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 
42 static 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_player_bonus
59   * get_city_bonus
60   * get_city_tile_bonus
61   * get_building_bonus
62 
63   These functions require as arguments the target and the effect type to be
64   queried.
65 
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.
72 
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.
86 
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.
96 
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 **************************************************************************/
101 
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;
109 
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];
113 
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;
123 
124 
125 /**************************************************************************
126   Get a list of effects of this type.
127 **************************************************************************/
get_effects(enum effect_type effect_type)128 struct effect_list *get_effects(enum effect_type effect_type)
129 {
130   return ruleset_cache.effects[effect_type];
131 }
132 
133 /**************************************************************************
134   Get a list of effects with this requirement source.
135 
136   Note: currently only buildings and governments are supported.
137 **************************************************************************/
get_req_source_effects(struct universal * psource)138 struct effect_list *get_req_source_effects(struct universal *psource)
139 {
140   int type, value;
141 
142   universal_extraction(psource, &type, &value);
143 
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;
150     }
151   case VUT_IMPROVEMENT:
152     if (value >= 0 && value < improvement_count()) {
153       return ruleset_cache.reqs.buildings[value];
154     } else {
155       return NULL;
156     }
157   case VUT_ADVANCE:
158     if (value >= 0 && value < advance_count()) {
159       return ruleset_cache.reqs.advances[value];
160     } else {
161       return NULL;
162     }
163   default:
164     return NULL;
165   }
166 }
167 
168 /**************************************************************************
169   Add effect to ruleset cache.
170 **************************************************************************/
effect_new(enum effect_type type,int value,struct multiplier * pmul)171 struct effect *effect_new(enum effect_type type, int value,
172                           struct multiplier *pmul)
173 {
174   struct effect *peffect;
175 
176   /* Create the effect. */
177   peffect = fc_malloc(sizeof(*peffect));
178   peffect->type = type;
179   peffect->value = value;
180   peffect->multiplier = pmul;
181 
182   requirement_vector_init(&peffect->reqs);
183 
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);
187   return peffect;
188 }
189 
190 /**************************************************************************
191   Append requirement to effect.
192 **************************************************************************/
effect_req_append(struct effect * peffect,struct requirement req)193 void effect_req_append(struct effect *peffect, struct requirement req)
194 {
195   struct effect_list *eff_list = get_req_source_effects(&req.source);
196 
197   requirement_vector_append(&peffect->reqs, req);
198 
199   if (eff_list) {
200     effect_list_append(eff_list, peffect);
201   }
202 }
203 
204 /**************************************************************************
205   Initialize the ruleset cache.  The ruleset cache should be empty
206   before this is done (so if it's previously been initialized, it needs
207   to be freed (see ruleset_cache_free) before it can be reused).
208 **************************************************************************/
ruleset_cache_init(void)209 void ruleset_cache_init(void)
210 {
211   int i;
212 
213   initialized = TRUE;
214 
215   ruleset_cache.tracker = effect_list_new();
216 
217   for (i = 0; i < ARRAY_SIZE(ruleset_cache.effects); i++) {
218     ruleset_cache.effects[i] = effect_list_new();
219   }
220   for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.buildings); i++) {
221     ruleset_cache.reqs.buildings[i] = effect_list_new();
222   }
223   for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.govs); i++) {
224     ruleset_cache.reqs.govs[i] = effect_list_new();
225   }
226   for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.advances); i++) {
227     ruleset_cache.reqs.advances[i] = effect_list_new();
228   }
229 }
230 
231 /**************************************************************************
232   Free the ruleset cache.  This should be called at the end of the game or
233   when the client disconnects from the server.  See ruleset_cache_init.
234 **************************************************************************/
ruleset_cache_free(void)235 void ruleset_cache_free(void)
236 {
237   int i;
238   struct effect_list *tracker_list = ruleset_cache.tracker;
239 
240   if (tracker_list) {
241     effect_list_iterate(tracker_list, peffect) {
242       requirement_vector_free(&peffect->reqs);
243       free(peffect);
244     } effect_list_iterate_end;
245     effect_list_destroy(tracker_list);
246     ruleset_cache.tracker = NULL;
247   }
248 
249   for (i = 0; i < ARRAY_SIZE(ruleset_cache.effects); i++) {
250     struct effect_list *plist = ruleset_cache.effects[i];
251 
252     if (plist) {
253       effect_list_destroy(plist);
254       ruleset_cache.effects[i] = NULL;
255     }
256   }
257 
258   for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.buildings); i++) {
259     struct effect_list *plist = ruleset_cache.reqs.buildings[i];
260 
261     if (plist) {
262       effect_list_destroy(plist);
263       ruleset_cache.reqs.buildings[i] = NULL;
264     }
265   }
266 
267   for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.govs); i++) {
268     struct effect_list *plist = ruleset_cache.reqs.govs[i];
269 
270     if (plist) {
271       effect_list_destroy(plist);
272       ruleset_cache.reqs.govs[i] = NULL;
273     }
274   }
275 
276   for (i = 0; i < ARRAY_SIZE(ruleset_cache.reqs.advances); i++) {
277     struct effect_list *plist = ruleset_cache.reqs.advances[i];
278 
279     if (plist) {
280       effect_list_destroy(plist);
281       ruleset_cache.reqs.advances[i] = NULL;
282     }
283   }
284 
285   initialized = FALSE;
286 }
287 
288 /****************************************************************************
289   Get the maximum effect value in this ruleset for the universal
290   (that is, the sum of all positive effects clauses that apply specifically
291   to this universal -- this can be an overestimate in the case of
292   mutually exclusive effects).
293   for_uni can be NULL to get max effect value ignoring requirements.
294 ****************************************************************************/
effect_cumulative_max(enum effect_type type,struct universal * for_uni)295 int effect_cumulative_max(enum effect_type type, struct universal *for_uni)
296 {
297   struct effect_list *plist = ruleset_cache.tracker;
298   int value = 0;
299 
300   if (plist) {
301     effect_list_iterate(plist, peffect) {
302       if (peffect->type == type && peffect->value > 0) {
303         if (for_uni == NULL
304             || universal_fulfills_requirements(FALSE, &(peffect->reqs),
305                                                for_uni)) {
306           value += peffect->value;
307         }
308       }
309     } effect_list_iterate_end;
310   }
311 
312   return value;
313 }
314 
315 /****************************************************************************
316   Get the minimum effect value in this ruleset for the universal
317   (that is, the sum of all negative effects clauses that apply specifically
318   to this universal -- this can be an overestimate in the case of
319   mutually exclusive effects).
320   for_uni can be NULL to get min effect value ignoring requirements.
321 ****************************************************************************/
effect_cumulative_min(enum effect_type type,struct universal * for_uni)322 int effect_cumulative_min(enum effect_type type, struct universal *for_uni)
323 {
324   struct effect_list *plist = ruleset_cache.tracker;
325   int value = 0;
326 
327   if (plist) {
328     effect_list_iterate(plist, peffect) {
329       if (peffect->type == type && peffect->value < 0) {
330         if (for_uni == NULL
331             || universal_fulfills_requirements(FALSE, &(peffect->reqs),
332                                                for_uni)) {
333           value += peffect->value;
334         }
335       }
336     } effect_list_iterate_end;
337   }
338 
339   return value;
340 }
341 
342 /**********************************************************************//**
343   Return the base value of a given effect that can always be expected from
344   just the sources in the list, independent of other factors.
345   Adds up all the effects that rely only on these universals; effects that
346   have extra conditions are ignored. In effect, 'unis' is a template
347   against which effects are matched.
348   The first universal in the list is special: effects must have a
349   condition that specifically applies to that source to be included
350   (may be a superset requirement, e.g. ExtraFlag for VUT_EXTRA source).
351 **************************************************************************/
effect_value_from_universals(enum effect_type type,struct universal * unis,size_t n_unis)352 int effect_value_from_universals(enum effect_type type,
353                                  struct universal *unis, size_t n_unis)
354 {
355   int value = 0;
356   struct effect_list *el = get_effects(type);
357 
358   effect_list_iterate(el, peffect) {
359     bool effect_applies = TRUE;
360     bool first_source_mentioned = FALSE;
361 
362     if (peffect->multiplier) {
363       /* Discount any effects with multipliers; we are looking for constant
364        * effects */
365       continue;
366     }
367 
368     requirement_vector_iterate(&(peffect->reqs), preq) {
369       int i;
370       bool req_mentioned_a_source = FALSE;
371 
372       for (i = 0; effect_applies && i < n_unis; i++) {
373         switch (universal_fulfills_requirement(preq, &(unis[i]))) {
374         case ITF_NOT_APPLICABLE:
375           /* This req not applicable to this source (but might be relevant
376            * to another source in our template). Keep looking. */
377           break;
378         case ITF_NO:
379           req_mentioned_a_source = TRUE; /* this req matched this source */
380           if (preq->present) {
381             /* Requirement contradicts template. Effect doesn't apply. */
382             effect_applies = FALSE;
383           } /* but negative req doesn't count for first_source_mentioned */
384           break;
385         case ITF_YES:
386           req_mentioned_a_source = TRUE; /* this req matched this source */
387           if (preq->present) {
388             if (i == 0) {
389               first_source_mentioned = TRUE;
390             }
391             /* keep looking */
392           } else /* !present */ {
393             /* Requirement contradicts template. Effect doesn't apply. */
394             effect_applies = FALSE;
395           }
396           break;
397         }
398       }
399       if (!req_mentioned_a_source) {
400         /* This requirement isn't relevant to any source in our template,
401          * so it's an extra condition and the effect should be ignored. */
402         effect_applies = FALSE;
403       }
404       if (!effect_applies) {
405         /* Already known to be irrelevant, bail out early */
406         break;
407       }
408     } requirement_vector_iterate_end;
409 
410     if (!first_source_mentioned) {
411       /* First source not positively mentioned anywhere in requirements,
412        * so ignore this effect */
413       continue;
414     }
415     if (effect_applies) {
416       value += peffect->value;
417     }
418   } effect_list_iterate_end;
419 
420   return value;
421 }
422 
423 /****************************************************************************
424   Receives a new effect.  This is called by the client when the packet
425   arrives.
426 ****************************************************************************/
recv_ruleset_effect(const struct packet_ruleset_effect * packet)427 void recv_ruleset_effect(const struct packet_ruleset_effect *packet)
428 {
429   struct effect *peffect;
430   struct multiplier *pmul;
431   int i;
432 
433   pmul = packet->has_multiplier ? multiplier_by_number(packet->multiplier)
434                                 : NULL;
435   peffect = effect_new(packet->effect_type, packet->effect_value, pmul);
436 
437   for (i = 0; i < packet->reqs_count; i++) {
438     effect_req_append(peffect, packet->reqs[i]);
439   }
440   fc_assert(peffect->reqs.size == packet->reqs_count);
441 }
442 
443 /**************************************************************************
444   Send the ruleset cache data over the network.
445 **************************************************************************/
send_ruleset_cache(struct conn_list * dest)446 void send_ruleset_cache(struct conn_list *dest)
447 {
448   effect_list_iterate(ruleset_cache.tracker, peffect) {
449     struct packet_ruleset_effect effect_packet;
450     int counter;
451 
452     effect_packet.effect_type = peffect->type;
453     effect_packet.effect_value = peffect->value;
454     if (peffect->multiplier) {
455       effect_packet.has_multiplier = TRUE;
456       effect_packet.multiplier = multiplier_number(peffect->multiplier);
457     } else {
458       effect_packet.has_multiplier = FALSE;
459       effect_packet.multiplier = 0; /* arbitrary */
460     }
461 
462     counter = 0;
463     requirement_vector_iterate(&(peffect->reqs), req) {
464       effect_packet.reqs[counter++] = *req;
465     } requirement_vector_iterate_end;
466     effect_packet.reqs_count = counter;
467 
468     lsend_packet_ruleset_effect(dest, &effect_packet);
469   } effect_list_iterate_end;
470 }
471 
472 /**************************************************************************
473   Returns TRUE if the building has any effect bonuses of the given type.
474 
475   Note that this function returns a boolean rather than an integer value
476   giving the exact bonus.  Finding the exact bonus requires knowing the
477   effect range and may take longer.  This function should only be used
478   in situations where the range doesn't matter.
479 **************************************************************************/
building_has_effect(const struct impr_type * pimprove,enum effect_type effect_type)480 bool building_has_effect(const struct impr_type *pimprove,
481 			 enum effect_type effect_type)
482 {
483   struct universal source = {
484     .kind = VUT_IMPROVEMENT,
485     /* just to bamboozle the annoying compiler warning */
486     .value = {.building = improvement_by_number(improvement_number(pimprove))}
487   };
488   struct effect_list *plist = get_req_source_effects(&source);
489 
490   if (!plist) {
491     return FALSE;
492   }
493 
494   effect_list_iterate(plist, peffect) {
495     if (peffect->type == effect_type) {
496       return TRUE;
497     }
498   } effect_list_iterate_end;
499   return FALSE;
500 }
501 
502 /**************************************************************************
503   Return TRUE iff any of the disabling requirements for this effect are
504   active, which would prevent it from taking effect.
505   (Assumes that any requirement specified in the ruleset with a negative
506   sense is an impediment.)
507 **************************************************************************/
is_effect_prevented(const struct player * target_player,const struct player * other_player,const struct city * target_city,const struct impr_type * target_building,const struct tile * target_tile,const struct unit * target_unit,const struct unit_type * target_unittype,const struct output_type * target_output,const struct specialist * target_specialist,const struct effect * peffect,const enum req_problem_type prob_type)508 static bool is_effect_prevented(const struct player *target_player,
509                                 const struct player *other_player,
510                                 const struct city *target_city,
511                                 const struct impr_type *target_building,
512                                 const struct tile *target_tile,
513                                 const struct unit *target_unit,
514                                 const struct unit_type *target_unittype,
515                                 const struct output_type *target_output,
516                                 const struct specialist *target_specialist,
517                                 const struct effect *peffect,
518                                 const enum   req_problem_type prob_type)
519 {
520   requirement_vector_iterate(&peffect->reqs, preq) {
521     /* Only check present=FALSE requirements; these will return _FALSE_
522      * from is_req_active() if met, and need reversed prob_type */
523     if (!preq->present
524         && !is_req_active(target_player, other_player, target_city,
525                           target_building, target_tile,
526                           target_unit, target_unittype,
527                           target_output, target_specialist,
528                           preq, REVERSED_RPT(prob_type))) {
529       return TRUE;
530     }
531   } requirement_vector_iterate_end;
532   return FALSE;
533 }
534 
535 /**************************************************************************
536   Returns TRUE if a building is replaced.  To be replaced, all its effects
537   must be made redundant by groups that it is in.
538   prob_type CERTAIN or POSSIBLE is answer to function name.
539 **************************************************************************/
is_building_replaced(const struct city * pcity,struct impr_type * pimprove,const enum req_problem_type prob_type)540 bool is_building_replaced(const struct city *pcity,
541                           struct impr_type *pimprove,
542                           const enum req_problem_type prob_type)
543 {
544   struct effect_list *plist;
545   struct universal source = {
546     .kind = VUT_IMPROVEMENT,
547     .value = {.building = pimprove}
548   };
549 
550   plist = get_req_source_effects(&source);
551 
552   /* A building with no effects and no flags is always redundant! */
553   if (!plist) {
554     return TRUE;
555   }
556 
557   effect_list_iterate(plist, peffect) {
558     /* We use TARGET_BUILDING as the lowest common denominator.  Note that
559      * the building is its own target - but whether this is actually
560      * checked depends on the range of the effect. */
561     /* Prob_type is not reversed here. disabled is equal to replaced, not
562      * reverse */
563     if (!is_effect_prevented(city_owner(pcity), NULL, pcity,
564                              pimprove,
565                              NULL, NULL, NULL, NULL, NULL,
566                              peffect, prob_type)) {
567       return FALSE;
568     }
569   } effect_list_iterate_end;
570   return TRUE;
571 }
572 
573 /**************************************************************************
574   Returns the effect bonus of a given type for any target.
575 
576   target gives the type of the target
577   (player,city,building,tile) give the exact target
578   effect_type gives the effect type to be considered
579 
580   Returns the effect sources of this type _currently active_.
581 
582   The returned vector must be freed (building_vector_free) when the caller
583   is done with it.
584 **************************************************************************/
get_target_bonus_effects(struct effect_list * plist,const struct player * target_player,const struct player * other_player,const struct city * target_city,const struct impr_type * target_building,const struct tile * target_tile,const struct unit * target_unit,const struct unit_type * target_unittype,const struct output_type * target_output,const struct specialist * target_specialist,enum effect_type effect_type)585 int get_target_bonus_effects(struct effect_list *plist,
586                              const struct player *target_player,
587                              const struct player *other_player,
588                              const struct city *target_city,
589                              const struct impr_type *target_building,
590                              const struct tile *target_tile,
591                              const struct unit *target_unit,
592                              const struct unit_type *target_unittype,
593                              const struct output_type *target_output,
594                              const struct specialist *target_specialist,
595                              enum effect_type effect_type)
596 {
597   int bonus = 0;
598 
599   /* Loop over all effects of this type. */
600   effect_list_iterate(get_effects(effect_type), peffect) {
601     /* For each effect, see if it is active. */
602     if (are_reqs_active(target_player, other_player, target_city,
603                         target_building, target_tile,
604                         target_unit, target_unittype,
605                         target_output, target_specialist,
606 			&peffect->reqs, RPT_CERTAIN)) {
607       /* This code will add value of effect. If there's multiplier for
608        * effect and target_player aren't null, then value is multiplied
609        * by player's multiplier factor. */
610       if (peffect->multiplier) {
611         if (target_player) {
612           bonus += (peffect->value
613             * player_multiplier_effect_value(target_player,
614                                              peffect->multiplier)) / 100;
615         }
616       } else {
617         bonus += peffect->value;
618       }
619 
620       if (plist) {
621 	effect_list_append(plist, peffect);
622       }
623     }
624   } effect_list_iterate_end;
625 
626   return bonus;
627 }
628 
629 /**************************************************************************
630   Returns the effect bonus for the whole world.
631 **************************************************************************/
get_world_bonus(enum effect_type effect_type)632 int get_world_bonus(enum effect_type effect_type)
633 {
634   if (!initialized) {
635     return 0;
636   }
637 
638   return get_target_bonus_effects(NULL,
639                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
640                                   NULL, NULL,
641 				  effect_type);
642 }
643 
644 /**************************************************************************
645   Returns the effect bonus for a player.
646 **************************************************************************/
get_player_bonus(const struct player * pplayer,enum effect_type effect_type)647 int get_player_bonus(const struct player *pplayer,
648 		     enum effect_type effect_type)
649 {
650   if (!initialized) {
651     return 0;
652   }
653 
654   return get_target_bonus_effects(NULL,
655                                   pplayer, NULL, NULL, NULL,
656                                   NULL, NULL, NULL, NULL,
657                                   NULL, effect_type);
658 }
659 
660 /**************************************************************************
661   Returns the effect bonus at a city.
662 **************************************************************************/
get_city_bonus(const struct city * pcity,enum effect_type effect_type)663 int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
664 {
665   if (!initialized) {
666     return 0;
667   }
668 
669   return get_target_bonus_effects(NULL,
670                                   city_owner(pcity), NULL, pcity, NULL,
671                                   city_tile(pcity), NULL, NULL, NULL,
672                                   NULL, effect_type);
673 }
674 
675 /**************************************************************************
676   Returns the effect bonus of a specialist in a city.
677 **************************************************************************/
get_city_specialist_output_bonus(const struct city * pcity,const struct specialist * pspecialist,const struct output_type * poutput,enum effect_type effect_type)678 int get_city_specialist_output_bonus(const struct city *pcity,
679 				     const struct specialist *pspecialist,
680 				     const struct output_type *poutput,
681 				     enum effect_type effect_type)
682 {
683   fc_assert_ret_val(pcity != NULL, 0);
684   fc_assert_ret_val(pspecialist != NULL, 0);
685   fc_assert_ret_val(poutput != NULL, 0);
686   return get_target_bonus_effects(NULL,
687                                   city_owner(pcity), NULL, pcity, NULL,
688                                   NULL, NULL, NULL, poutput, pspecialist,
689 				  effect_type);
690 }
691 
692 /**************************************************************************
693   Returns the effect bonus at a city tile.
694   pcity must be supplied.
695 
696   FIXME: this is now used both for tile bonuses, tile-output bonuses,
697   and city-output bonuses.  Thus ptile or poutput may be NULL for
698   certain callers.  This could be changed by adding 2 new functions to
699   the interface but they'd be almost identical and their likely names
700   would conflict with functions already in city.c.
701   It's also very similar to get_tile_output_bonus(); it should be
702   called when the city is mandatory.
703 **************************************************************************/
get_city_tile_output_bonus(const struct city * pcity,const struct tile * ptile,const struct output_type * poutput,enum effect_type effect_type)704 int get_city_tile_output_bonus(const struct city *pcity,
705 			       const struct tile *ptile,
706 			       const struct output_type *poutput,
707 			       enum effect_type effect_type)
708 {
709   fc_assert_ret_val(pcity != NULL, 0);
710   return get_target_bonus_effects(NULL,
711                                   city_owner(pcity), NULL, pcity, NULL,
712                                   ptile, NULL, NULL, poutput, NULL,
713 				  effect_type);
714 }
715 
716 /**************************************************************************
717   Returns the effect bonus at a tile for given output type (or NULL for
718   output-type-independent bonus).
719   If pcity is supplied, it's the bonus for that particular city, otherwise
720   it's the player/city-independent bonus (and any city on the tile is
721   ignored).
722 **************************************************************************/
get_tile_output_bonus(const struct city * pcity,const struct tile * ptile,const struct output_type * poutput,enum effect_type effect_type)723 int get_tile_output_bonus(const struct city *pcity,
724                           const struct tile *ptile,
725                           const struct output_type *poutput,
726                           enum effect_type effect_type)
727 {
728   const struct player *pplayer = pcity ? city_owner(pcity) : NULL;
729 
730   return get_target_bonus_effects(NULL,
731                                   pplayer, NULL, pcity, NULL,
732                                   ptile, NULL, NULL, poutput, NULL,
733                                   effect_type);
734 }
735 
736 /**************************************************************************
737   Returns the player effect bonus of an output.
738 **************************************************************************/
get_player_output_bonus(const struct player * pplayer,const struct output_type * poutput,enum effect_type effect_type)739 int get_player_output_bonus(const struct player *pplayer,
740                             const struct output_type *poutput,
741                             enum effect_type effect_type)
742 {
743   if (!initialized) {
744     return 0;
745   }
746 
747   fc_assert_ret_val(pplayer != NULL, 0);
748   fc_assert_ret_val(poutput != NULL, 0);
749   fc_assert_ret_val(effect_type != EFT_COUNT, 0);
750   return get_target_bonus_effects(NULL, pplayer, NULL, NULL, NULL, NULL,
751                                   NULL, NULL, poutput, NULL, effect_type);
752 }
753 
754 /**************************************************************************
755   Returns the player effect bonus of an output.
756 **************************************************************************/
get_city_output_bonus(const struct city * pcity,const struct output_type * poutput,enum effect_type effect_type)757 int get_city_output_bonus(const struct city *pcity,
758                           const struct output_type *poutput,
759                           enum effect_type effect_type)
760 {
761   if (!initialized) {
762     return 0;
763   }
764 
765   fc_assert_ret_val(pcity != NULL, 0);
766   fc_assert_ret_val(poutput != NULL, 0);
767   fc_assert_ret_val(effect_type != EFT_COUNT, 0);
768   return get_target_bonus_effects(NULL, city_owner(pcity), NULL, pcity,
769                                   NULL, NULL, NULL, NULL, poutput, NULL,
770                                   effect_type);
771 }
772 
773 /**************************************************************************
774   Returns the effect bonus at a building.
775 **************************************************************************/
get_building_bonus(const struct city * pcity,const struct impr_type * building,enum effect_type effect_type)776 int get_building_bonus(const struct city *pcity,
777 		       const struct impr_type *building,
778 		       enum effect_type effect_type)
779 {
780   if (!initialized) {
781     return 0;
782   }
783 
784   fc_assert_ret_val(NULL != pcity && NULL != building, 0);
785   return get_target_bonus_effects(NULL,
786                                   city_owner(pcity), NULL, pcity,
787 				  building,
788 				  NULL, NULL, NULL, NULL,
789                                   NULL, effect_type);
790 }
791 
792 /**************************************************************************
793   Returns the effect bonus that applies at a tile for a given unittype.
794 
795   For instance with EFT_DEFEND_BONUS the attacker's unittype and the
796   defending tile should be passed in.  Slightly counter-intuitive!
797   See doc/README.effects to see how the unittype applies for each effect
798   here.
799 **************************************************************************/
get_unittype_bonus(const struct player * pplayer,const struct tile * ptile,const struct unit_type * punittype,enum effect_type effect_type)800 int get_unittype_bonus(const struct player *pplayer,
801 		       const struct tile *ptile,
802 		       const struct unit_type *punittype,
803 		       enum effect_type effect_type)
804 {
805   struct city *pcity;
806 
807   if (!initialized) {
808     return 0;
809   }
810 
811   fc_assert_ret_val(pplayer != NULL && punittype != NULL, 0);
812 
813   if (ptile != NULL) {
814     pcity = tile_city(ptile);
815   } else {
816     pcity = NULL;
817   }
818 
819   return get_target_bonus_effects(NULL,
820                                   pplayer, NULL, pcity, NULL, ptile,
821                                   NULL, punittype, NULL,
822                                   NULL, effect_type);
823 }
824 
825 /**************************************************************************
826   Returns the effect bonus at a unit
827 **************************************************************************/
get_unit_bonus(const struct unit * punit,enum effect_type effect_type)828 int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
829 {
830   if (!initialized) {
831     return 0;
832   }
833 
834   fc_assert_ret_val(punit != NULL, 0);
835   return get_target_bonus_effects(NULL,
836                                   unit_owner(punit),
837                                   NULL,
838                                   unit_tile(punit)
839                                     ? tile_city(unit_tile(punit)) : NULL,
840                                   NULL, unit_tile(punit),
841                                   punit, unit_type_get(punit), NULL, NULL,
842                                   effect_type);
843 }
844 
845 /**************************************************************************
846   Returns the effect bonus at a tile
847 **************************************************************************/
get_tile_bonus(const struct tile * ptile,const struct unit * punit,enum effect_type etype)848 int get_tile_bonus(const struct tile *ptile, const struct unit *punit,
849                    enum effect_type etype)
850 {
851   struct player *pplayer = NULL;
852   struct unit_type *utype = NULL;
853 
854   if (!initialized) {
855     return 0;
856   }
857 
858   fc_assert_ret_val(ptile != NULL, 0);
859 
860   if (punit != NULL) {
861     pplayer = unit_owner(punit);
862     utype = unit_type_get(punit);
863   }
864 
865   return get_target_bonus_effects(NULL,
866                                   pplayer,
867                                   NULL,
868                                   tile_city(ptile),
869                                   NULL,
870                                   ptile,
871                                   punit,
872                                   utype,
873                                   NULL, NULL,
874                                   etype);
875 }
876 
877 /**************************************************************************
878   Returns the effect sources of this type _currently active_ at the player.
879 
880   The returned vector must be freed (building_vector_free) when the caller
881   is done with it.
882 **************************************************************************/
get_player_bonus_effects(struct effect_list * plist,const struct player * pplayer,enum effect_type effect_type)883 int get_player_bonus_effects(struct effect_list *plist,
884 			     const struct player *pplayer,
885 			     enum effect_type effect_type)
886 {
887   if (!initialized) {
888     return 0;
889   }
890 
891   fc_assert_ret_val(pplayer != NULL, 0);
892   return get_target_bonus_effects(plist,
893                                   pplayer, NULL, NULL, NULL,
894                                   NULL, NULL, NULL, NULL, NULL,
895 				  effect_type);
896 }
897 
898 /**************************************************************************
899   Returns the effect sources of this type _currently active_ at the city.
900 
901   The returned vector must be freed (building_vector_free) when the caller
902   is done with it.
903 **************************************************************************/
get_city_bonus_effects(struct effect_list * plist,const struct city * pcity,const struct output_type * poutput,enum effect_type effect_type)904 int get_city_bonus_effects(struct effect_list *plist,
905 			   const struct city *pcity,
906 			   const struct output_type *poutput,
907 			   enum effect_type effect_type)
908 {
909   if (!initialized) {
910     return 0;
911   }
912 
913   fc_assert_ret_val(pcity != NULL, 0);
914   return get_target_bonus_effects(plist,
915                                   city_owner(pcity), NULL, pcity, NULL,
916                                   NULL, NULL, NULL, poutput, NULL,
917 				  effect_type);
918 }
919 
920 /**************************************************************************
921   Returns the effect bonus the currently-in-construction-item will provide.
922 
923   Note this is not called get_current_production_bonus because that would
924   be confused with EFT_PROD_BONUS.
925 
926   Problem type tells if we need to be CERTAIN about bonus before counting
927   it or is POSSIBLE bonus enough.
928 **************************************************************************/
get_current_construction_bonus(const struct city * pcity,enum effect_type effect_type,const enum req_problem_type prob_type)929 int get_current_construction_bonus(const struct city *pcity,
930 				   enum effect_type effect_type,
931                                    const enum req_problem_type prob_type)
932 {
933   if (!initialized) {
934     return 0;
935   }
936 
937   if (VUT_IMPROVEMENT == pcity->production.kind) {
938     return get_potential_improvement_bonus(pcity->production.value.building,
939                                            pcity, effect_type, prob_type);
940   }
941   return 0;
942 }
943 
944 /**************************************************************************
945   Returns the effect bonus the improvement would or does provide if present.
946 
947   Problem type tells if we need to be CERTAIN about bonus before counting
948   it or is POSSIBLE bonus enough.
949 **************************************************************************/
get_potential_improvement_bonus(struct impr_type * pimprove,const struct city * pcity,enum effect_type effect_type,const enum req_problem_type prob_type)950 int get_potential_improvement_bonus(struct impr_type *pimprove,
951                                     const struct city *pcity,
952                                     enum effect_type effect_type,
953                                     const enum req_problem_type prob_type)
954 {
955   struct universal source = { .kind = VUT_IMPROVEMENT,
956                                 .value = {.building = pimprove}};
957   struct effect_list *plist = get_req_source_effects(&source);
958 
959 
960   if (plist) {
961     int power = 0;
962 
963     effect_list_iterate(plist, peffect) {
964       bool present = TRUE;
965       bool useful = TRUE;
966 
967       if (peffect->type != effect_type) {
968         continue;
969       }
970 
971       requirement_vector_iterate(&peffect->reqs, preq) {
972         if (VUT_IMPROVEMENT == preq->source.kind
973             && preq->source.value.building == pimprove) {
974           present = preq->present;
975           continue;
976         }
977 
978         if (!is_req_active(city_owner(pcity), NULL, pcity, pimprove,
979                            NULL, NULL, NULL, NULL, NULL,
980                            preq, prob_type)) {
981           useful = FALSE;
982           break;
983         }
984       } requirement_vector_iterate_end;
985 
986       if (useful) {
987         if (present) {
988           power += peffect->value;
989         } else {
990           power -= peffect->value;
991         }
992       }
993     } effect_list_iterate_end;
994 
995     return power;
996   }
997   return 0;
998 }
999 
1000 /**************************************************************************
1001   Make user-friendly text for the source.  The text is put into a user
1002   buffer.
1003 **************************************************************************/
get_effect_req_text(const struct effect * peffect,char * buf,size_t buf_len)1004 void get_effect_req_text(const struct effect *peffect,
1005                          char *buf, size_t buf_len)
1006 {
1007   buf[0] = '\0';
1008 
1009   if (peffect->multiplier) {
1010     fc_strlcat(buf, multiplier_name_translation(peffect->multiplier), buf_len);
1011   }
1012 
1013   /* FIXME: should we do something for present==FALSE reqs?
1014    * Currently we just ignore them. */
1015   requirement_vector_iterate(&peffect->reqs, preq) {
1016     if (!preq->present) {
1017       continue;
1018     }
1019     if (buf[0] != '\0') {
1020       fc_strlcat(buf, Q_("?req-list-separator:+"), buf_len);
1021     }
1022 
1023     universal_name_translation(&preq->source,
1024 			buf + strlen(buf), buf_len - strlen(buf));
1025   } requirement_vector_iterate_end;
1026 }
1027 
1028 /****************************************************************************
1029   Make user-friendly text for an effect list. The text is put into a user
1030   astring.
1031 ****************************************************************************/
get_effect_list_req_text(const struct effect_list * plist,struct astring * astr)1032 void get_effect_list_req_text(const struct effect_list *plist,
1033                               struct astring *astr)
1034 {
1035   struct strvec *psv = strvec_new();
1036   char req_text[512];
1037 
1038   effect_list_iterate(plist, peffect) {
1039     get_effect_req_text(peffect, req_text, sizeof(req_text));
1040     strvec_append(psv, req_text);
1041   } effect_list_iterate_end;
1042 
1043   strvec_to_and_list(psv, astr);
1044   strvec_destroy(psv);
1045 }
1046 
1047 /**************************************************************************
1048   Iterate through all the effects in cache, and call callback for each.
1049   If any callback returns FALSE, there is no further checking and
1050   this will return FALSE.
1051 **************************************************************************/
iterate_effect_cache(iec_cb cb,void * data)1052 bool iterate_effect_cache(iec_cb cb, void *data)
1053 {
1054   fc_assert_ret_val(cb != NULL, FALSE);
1055 
1056   effect_list_iterate(ruleset_cache.tracker, peffect) {
1057     if (!cb(peffect, data)) {
1058       return FALSE;
1059     }
1060   } effect_list_iterate_end;
1061 
1062   return TRUE;
1063 }
1064