Freeciv-3.3: /fast/freeciv/nightly/main/common/effects.c Source File

Freeciv-3.3

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