1 /**********************************************************************
2 Freeciv - Copyright (C) 1996-2004 - The Freeciv Project
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)
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 ***********************************************************************/
14 #include <fc_config.h>
25 #include "government.h"
26 #include "improvement.h"
29 #include "specialist.h"
31 #include "requirements.h"
33 /**************************************************************************
34 Parse requirement type (kind) and value strings into a universal
35 structure. Passing in a NULL type is considered VUT_NONE (not an error).
37 Pass this some values like "Building", "Factory".
38 FIXME: ensure that every caller checks error return!
39 **************************************************************************/
40 struct universal
universal_by_rule_name(const char *kind
,
43 struct universal source
;
45 source
.kind
= universals_n_by_name(kind
, fc_strcasecmp
);
46 if (!universals_n_is_valid(source
.kind
)) {
50 /* Finally scan the value string based on the type of the source. */
51 switch (source
.kind
) {
55 source
.value
.advance
= advance_by_rule_name(value
);
56 if (source
.value
.advance
!= NULL
) {
62 = tech_flag_id_by_name(value
, fc_strcasecmp
);
63 if (tech_flag_id_is_valid(source
.value
.techflag
)) {
68 source
.value
.govern
= government_by_rule_name(value
);
69 if (source
.value
.govern
!= NULL
) {
74 source
.value
.building
= improvement_by_rule_name(value
);
75 if (source
.value
.building
!= NULL
) {
80 source
.value
.special
= special_by_rule_name(value
);
81 if (source
.value
.special
!= S_LAST
) {
86 source
.value
.terrain
= terrain_by_rule_name(value
);
87 if (source
.value
.terrain
!= T_UNKNOWN
) {
92 source
.value
.terrainflag
93 = terrain_flag_id_by_name(value
, fc_strcasecmp
);
94 if (terrain_flag_id_is_valid(source
.value
.terrainflag
)) {
99 source
.value
.resource
= resource_by_rule_name(value
);
100 if (source
.value
.resource
!= NULL
) {
105 source
.value
.nation
= nation_by_rule_name(value
);
106 if (source
.value
.nation
!= NO_NATION_SELECTED
) {
110 case VUT_NATIONALITY
:
111 source
.value
.nationality
= nation_by_rule_name(value
);
112 if (source
.value
.nationality
!= NO_NATION_SELECTED
) {
117 source
.value
.utype
= unit_type_by_rule_name(value
);
118 if (source
.value
.utype
) {
123 source
.value
.unitflag
= unit_type_flag_id_by_name(value
, fc_strcasecmp
);
124 if (unit_type_flag_id_is_valid(source
.value
.unitflag
)) {
129 source
.value
.uclass
= unit_class_by_rule_name(value
);
130 if (source
.value
.uclass
) {
135 source
.value
.unitclassflag
136 = unit_class_flag_id_by_name(value
, fc_strcasecmp
);
137 if (unit_class_flag_id_is_valid(source
.value
.unitclassflag
)) {
142 source
.value
.outputtype
= output_type_by_identifier(value
);
143 if (source
.value
.outputtype
!= O_LAST
) {
148 source
.value
.specialist
= specialist_by_rule_name(value
);
149 if (source
.value
.specialist
) {
153 source
.value
.minsize
= atoi(value
);
154 if (source
.value
.minsize
> 0) {
159 source
.value
.ai_level
= ai_level_by_name(value
);
160 if (source
.value
.ai_level
!= AI_LEVEL_LAST
) {
164 case VUT_TERRAINCLASS
:
165 source
.value
.terrainclass
166 = terrain_class_by_name(value
, fc_strcasecmp
);
167 if (terrain_class_is_valid(source
.value
.terrainclass
)) {
172 source
.value
.base
= base_type_by_rule_name(value
);
173 if (source
.value
.base
!= NULL
) {
178 source
.value
.road
= road_type_by_rule_name(value
);
179 if (source
.value
.road
!= NULL
) {
184 source
.value
.minyear
= atoi(value
);
186 case VUT_TERRAINALTER
:
187 source
.value
.terrainalter
188 = terrain_alteration_by_name(value
, fc_strcasecmp
);
189 if (terrain_alteration_is_valid(source
.value
.terrainalter
)) {
194 source
.value
.citytile
= citytile_by_rule_name(value
);
195 if (source
.value
.citytile
!= CITYT_LAST
) {
203 /* If we reach here there's been an error. */
204 source
.kind
= universals_n_invalid();
208 /**************************************************************************
209 Combine values into a universal structure. This is for serialization
210 and is the opposite of universal_extraction().
211 FIXME: ensure that every caller checks error return!
212 **************************************************************************/
213 struct universal
universal_by_number(const enum universals_n kind
,
216 struct universal source
;
220 switch (source
.kind
) {
222 /* Avoid compiler warning about unitialized source.value */
223 source
.value
.advance
= NULL
;
227 source
.value
.advance
= advance_by_number(value
);
228 if (source
.value
.advance
!= NULL
) {
233 source
.value
.techflag
= value
;
236 source
.value
.govern
= government_by_number(value
);
237 if (source
.value
.govern
!= NULL
) {
241 case VUT_IMPROVEMENT
:
242 source
.value
.building
= improvement_by_number(value
);
243 if (source
.value
.building
!= NULL
) {
248 source
.value
.special
= value
;
251 source
.value
.terrain
= terrain_by_number(value
);
252 if (source
.value
.terrain
!= NULL
) {
257 source
.value
.terrainflag
= value
;
260 source
.value
.resource
= resource_by_number(value
);
261 if (source
.value
.resource
!= NULL
) {
266 source
.value
.nation
= nation_by_number(value
);
267 if (source
.value
.nation
!= NULL
) {
271 case VUT_NATIONALITY
:
272 source
.value
.nationality
= nation_by_number(value
);
273 if (source
.value
.nationality
!= NULL
) {
278 source
.value
.utype
= utype_by_number(value
);
279 if (source
.value
.utype
!= NULL
) {
284 source
.value
.unitflag
= value
;
287 source
.value
.uclass
= uclass_by_number(value
);
288 if (source
.value
.uclass
!= NULL
) {
293 source
.value
.unitclassflag
= value
;
296 source
.value
.outputtype
= value
;
299 source
.value
.specialist
= specialist_by_number(value
);
302 source
.value
.minsize
= value
;
305 source
.value
.ai_level
= value
;
307 case VUT_TERRAINCLASS
:
308 source
.value
.terrainclass
= value
;
311 source
.value
.base
= base_by_number(value
);
314 source
.value
.road
= road_by_number(value
);
317 source
.value
.minyear
= value
;
319 case VUT_TERRAINALTER
:
320 source
.value
.terrainalter
= value
;
323 source
.value
.citytile
= value
;
329 /* If we reach here there's been an error. */
330 source
.kind
= universals_n_invalid();
331 /* Avoid compiler warning about unitialized source.value */
332 source
.value
.advance
= NULL
;
337 /**************************************************************************
338 Extract universal structure into its components for serialization;
339 the opposite of universal_by_number().
340 **************************************************************************/
341 void universal_extraction(const struct universal
*source
,
342 int *kind
, int *value
)
344 *kind
= source
->kind
;
345 *value
= universal_number(source
);
348 /**************************************************************************
349 Return the universal number of the constituent.
350 **************************************************************************/
351 int universal_number(const struct universal
*source
)
353 switch (source
->kind
) {
357 return advance_number(source
->value
.advance
);
359 return source
->value
.techflag
;
361 return government_number(source
->value
.govern
);
362 case VUT_IMPROVEMENT
:
363 return improvement_number(source
->value
.building
);
365 return source
->value
.special
;
367 return terrain_number(source
->value
.terrain
);
369 return source
->value
.terrainflag
;
371 return resource_number(source
->value
.resource
);
373 return nation_number(source
->value
.nation
);
374 case VUT_NATIONALITY
:
375 return nation_number(source
->value
.nationality
);
377 return utype_number(source
->value
.utype
);
379 return source
->value
.unitflag
;
381 return uclass_number(source
->value
.uclass
);
383 return source
->value
.unitclassflag
;
385 return source
->value
.outputtype
;
387 return specialist_number(source
->value
.specialist
);
389 return source
->value
.minsize
;
391 return source
->value
.ai_level
;
392 case VUT_TERRAINCLASS
:
393 return source
->value
.terrainclass
;
395 return base_number(source
->value
.base
);
397 return road_number(source
->value
.road
);
399 return source
->value
.minyear
;
400 case VUT_TERRAINALTER
:
401 return source
->value
.terrainalter
;
403 return source
->value
.citytile
;
408 /* If we reach here there's been an error. */
409 fc_assert_msg(FALSE
, "universal_number(): invalid source kind %d.",
414 /****************************************************************************
415 Parse a requirement type and value string into a requrement structure.
416 Returns the invalid element for enum universal_n on error. Passing in a
417 NULL type is considered VUT_NONE (not an error).
419 Pass this some values like "Building", "Factory".
420 ****************************************************************************/
421 struct requirement
req_from_str(const char *type
, const char *range
,
422 bool survives
, bool negated
,
425 struct requirement req
;
427 const char *error
= NULL
;
429 req
.source
= universal_by_rule_name(type
, value
);
431 /* Scan the range string to find the range. If no range is given a
432 * default fallback is used rather than giving an error. */
433 req
.range
= req_range_by_name(range
, fc_strcasecmp
);
434 if (!req_range_is_valid(req
.range
)) {
435 switch (req
.source
.kind
) {
439 case VUT_IMPROVEMENT
:
450 case VUT_TERRAINCLASS
:
453 case VUT_TERRAINALTER
:
455 req
.range
= REQ_RANGE_LOCAL
;
458 case VUT_NATIONALITY
:
459 req
.range
= REQ_RANGE_CITY
;
466 req
.range
= REQ_RANGE_PLAYER
;
469 req
.range
= REQ_RANGE_WORLD
;
474 req
.survives
= survives
;
475 req
.negated
= negated
;
477 /* These checks match what combinations are supported inside
478 * is_req_active(). However, it's only possible to do basic checks,
479 * not anything that might depend on the rest of the ruleset which
480 * might not have been lodaed yet. */
481 switch (req
.source
.kind
) {
485 case VUT_TERRAINCLASS
:
489 invalid
= (req
.range
!= REQ_RANGE_LOCAL
490 && req
.range
!= REQ_RANGE_CADJACENT
491 && req
.range
!= REQ_RANGE_ADJACENT
492 && req
.range
!= REQ_RANGE_CITY
);
496 invalid
= (req
.range
< REQ_RANGE_PLAYER
);
500 invalid
= (req
.range
!= REQ_RANGE_PLAYER
);
503 case VUT_NATIONALITY
:
504 invalid
= (req
.range
!= REQ_RANGE_CITY
);
507 invalid
= (req
.range
!= REQ_RANGE_PLAYER
508 && req
.range
!= REQ_RANGE_WORLD
);
516 case VUT_TERRAINALTER
: /* XXX could in principle support C/ADJACENT */
517 invalid
= (req
.range
!= REQ_RANGE_LOCAL
);
520 invalid
= (req
.range
!= REQ_RANGE_LOCAL
521 && req
.range
!= REQ_RANGE_CADJACENT
522 && req
.range
!= REQ_RANGE_ADJACENT
);
525 invalid
= (req
.range
!= REQ_RANGE_WORLD
);
527 case VUT_IMPROVEMENT
:
528 /* Valid ranges depend on the building genus (wonder/improvement),
529 * which might not have been loaded from the ruleset yet.
530 * So we allow anything here, and do a proper check once ruleset
531 * loading is complete, in sanity_check_req_individual(). */
542 /* Check 'survives'. */
543 switch (req
.source
.kind
) {
544 case VUT_IMPROVEMENT
:
545 /* See count_buildings_in_range(). */
546 invalid
= survives
&& req
.range
<= REQ_RANGE_CONTINENT
;
549 invalid
= survives
&& req
.range
!= REQ_RANGE_WORLD
;
563 case VUT_TERRAINCLASS
:
566 case VUT_TERRAINALTER
:
571 case VUT_NATIONALITY
:
573 /* Most requirements don't support 'survives'. */
581 error
= "bad 'survives'";
586 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
587 type
, range
, survives
? "survives" : "",
588 negated
? "negated" : "", value
, error
);
589 req
.source
.kind
= universals_n_invalid();
595 /****************************************************************************
596 Set the values of a req from serializable integers. This is the opposite
598 ****************************************************************************/
599 struct requirement
req_from_values(int type
, int range
,
600 bool survives
, bool negated
,
603 struct requirement req
;
605 req
.source
= universal_by_number(type
, value
);
607 req
.survives
= survives
;
608 req
.negated
= negated
;
612 /****************************************************************************
613 Return the value of a req as a serializable integer. This is the opposite
615 ****************************************************************************/
616 void req_get_values(const struct requirement
*req
,
617 int *type
, int *range
,
618 bool *survives
, bool *negated
,
621 universal_extraction(&req
->source
, type
, value
);
623 *survives
= req
->survives
;
624 *negated
= req
->negated
;
627 /****************************************************************************
628 Returns TRUE if req1 and req2 are equal.
629 ****************************************************************************/
630 bool are_requirements_equal(const struct requirement
*req1
,
631 const struct requirement
*req2
)
633 return (are_universals_equal(&req1
->source
, &req2
->source
)
634 && req1
->range
== req2
->range
635 && req1
->survives
== req2
->survives
636 && req1
->negated
== req2
->negated
);
639 /****************************************************************************
640 Returns TRUE if req1 and req2 directly negate each other.
641 ****************************************************************************/
642 bool are_requirements_opposites(const struct requirement
*req1
,
643 const struct requirement
*req2
)
645 return (are_universals_equal(&req1
->source
, &req2
->source
)
646 && req1
->range
== req2
->range
647 && req1
->survives
== req2
->survives
648 && req1
->negated
!= req2
->negated
);
651 /****************************************************************************
652 Returns the number of total world buildings (this includes buildings
653 that have been destroyed).
654 ****************************************************************************/
655 static int num_world_buildings_total(const struct impr_type
*building
)
657 if (is_great_wonder(building
)) {
658 return (great_wonder_is_built(building
)
659 || great_wonder_is_destroyed(building
) ? 1 : 0);
661 log_error("World-ranged requirements are only supported for wonders.");
666 /****************************************************************************
667 Returns the number of buildings of a certain type in the world.
668 ****************************************************************************/
669 static int num_world_buildings(const struct impr_type
*building
)
671 if (is_great_wonder(building
)) {
672 return (great_wonder_is_built(building
) ? 1 : 0);
674 log_error("World-ranged requirements are only supported for wonders.");
679 /****************************************************************************
680 Returns whether a building of a certain type has ever been built by
681 pplayer, even if it has subsequently been destroyed.
683 Note: the implementation of this is no different in principle from
684 num_world_buildings_total(), but the semantics are different because
685 unlike a great wonder, a small wonder could be destroyed and rebuilt
686 many times, requiring return of values >1, but there's no record kept
687 to support that. Fortunately, the only current caller doesn't need the
689 ****************************************************************************/
690 static bool player_has_ever_built(const struct player
*pplayer
,
691 const struct impr_type
*building
)
693 if (is_wonder(building
)) {
694 return (wonder_is_built(pplayer
, building
)
695 || wonder_is_lost(pplayer
, building
) ? TRUE
: FALSE
);
697 log_error("Player-ranged requirements are only supported for wonders.");
702 /****************************************************************************
703 Returns the number of buildings of a certain type owned by plr.
704 ****************************************************************************/
705 static int num_player_buildings(const struct player
*pplayer
,
706 const struct impr_type
*building
)
708 if (is_wonder(building
)) {
709 return (wonder_is_built(pplayer
, building
) ? 1 : 0);
711 log_error("Player-ranged requirements are only supported for wonders.");
716 /****************************************************************************
717 Returns the number of buildings of a certain type on a continent.
718 ****************************************************************************/
719 static int num_continent_buildings(const struct player
*pplayer
,
721 const struct impr_type
*building
)
723 if (is_wonder(building
)) {
724 const struct city
*pcity
;
726 pcity
= city_from_wonder(pplayer
, building
);
727 if (pcity
&& pcity
->tile
&& tile_continent(pcity
->tile
) == continent
) {
731 log_error("Island-ranged requirements are only supported for wonders.");
736 /****************************************************************************
737 Returns the number of buildings of a certain type in a city.
738 ****************************************************************************/
739 static int num_city_buildings(const struct city
*pcity
,
740 const struct impr_type
*building
)
742 return (city_has_building(pcity
, building
) ? 1 : 0);
745 /****************************************************************************
746 Are there any source buildings within range of the target that are not
749 The target gives the type of the target. The exact target is a player,
750 city, or building specified by the target_xxx arguments.
752 The range gives the range of the requirement.
754 "Survives" specifies whether the requirement allows destroyed sources.
755 If set then all source buildings ever built are counted; if not then only
756 living buildings are counted.
758 source gives the building type of the source in question.
759 ****************************************************************************/
760 static enum fc_tristate
761 is_building_in_range(const struct player
*target_player
,
762 const struct city
*target_city
,
763 const struct impr_type
*target_building
,
764 enum req_range range
,
766 const struct impr_type
*source
)
768 /* Check if it's certain that the building is obsolete given the
769 * specification we have */
770 if (improvement_obsolete(target_player
, source
)) {
776 /* Check whether condition has ever held, using cached information. */
778 case REQ_RANGE_WORLD
:
779 return BOOL_TO_TRISTATE(num_world_buildings_total(source
) > 0);
780 case REQ_RANGE_PLAYER
:
781 if (target_player
== NULL
) {
784 return BOOL_TO_TRISTATE(player_has_ever_built(target_player
, source
));
785 case REQ_RANGE_CONTINENT
:
787 case REQ_RANGE_LOCAL
:
788 case REQ_RANGE_CADJACENT
:
789 case REQ_RANGE_ADJACENT
:
790 /* There is no sources cache for this. */
791 log_error("Surviving requirements are only supported at "
792 "world and player ranges.");
794 case REQ_RANGE_COUNT
:
800 /* Non-surviving requirement. */
802 case REQ_RANGE_WORLD
:
803 return BOOL_TO_TRISTATE(num_world_buildings(source
) > 0);
804 case REQ_RANGE_PLAYER
:
805 if (target_player
== NULL
) {
808 return BOOL_TO_TRISTATE(num_player_buildings(target_player
, source
) > 0);
809 case REQ_RANGE_CONTINENT
:
810 /* At present, "Continent" effects can affect only
811 * cities and units in cities. */
812 if (target_player
&& target_city
) {
813 int continent
= tile_continent(target_city
->tile
);
814 return BOOL_TO_TRISTATE(num_continent_buildings(target_player
,
815 continent
, source
) > 0);
821 return BOOL_TO_TRISTATE(num_city_buildings(target_city
, source
) > 0);
825 case REQ_RANGE_LOCAL
:
826 if (target_building
) {
827 if (target_building
== source
) {
828 return BOOL_TO_TRISTATE(num_city_buildings(target_city
, source
) > 0);
833 /* TODO: other local targets */
836 case REQ_RANGE_CADJACENT
:
837 case REQ_RANGE_ADJACENT
:
839 case REQ_RANGE_COUNT
:
845 fc_assert_msg(FALSE
, "Invalid range %d.", range
);
849 /****************************************************************************
850 Is there a source tech within range of the target?
851 ****************************************************************************/
852 static enum fc_tristate
is_tech_in_range(const struct player
*target_player
,
853 enum req_range range
,
857 case REQ_RANGE_PLAYER
:
858 if (NULL
!= target_player
) {
859 return BOOL_TO_TRISTATE(TECH_KNOWN
== player_invention_state(target_player
, tech
));
863 case REQ_RANGE_WORLD
:
864 return BOOL_TO_TRISTATE(game
.info
.global_advances
[tech
]);
865 case REQ_RANGE_LOCAL
:
866 case REQ_RANGE_CADJACENT
:
867 case REQ_RANGE_ADJACENT
:
869 case REQ_RANGE_CONTINENT
:
870 case REQ_RANGE_COUNT
:
874 fc_assert_msg(FALSE
, "Invalid range %d.", range
);
879 /****************************************************************************
880 Is there a source special within range of the target?
881 ****************************************************************************/
882 static enum fc_tristate
is_special_in_range(const struct tile
*target_tile
,
883 const struct city
*target_city
,
884 enum req_range range
, bool survives
,
885 enum tile_special_type special
)
889 case REQ_RANGE_LOCAL
:
893 return BOOL_TO_TRISTATE(tile_has_special(target_tile
, special
));
894 case REQ_RANGE_CADJACENT
:
898 return BOOL_TO_TRISTATE(is_special_card_near(target_tile
, special
, TRUE
));
899 case REQ_RANGE_ADJACENT
:
903 return BOOL_TO_TRISTATE(is_special_near_tile(target_tile
, special
, TRUE
));
908 city_tile_iterate(city_map_radius_sq_get(target_city
),
909 city_tile(target_city
), ptile
) {
910 if (tile_has_special(ptile
, special
)) {
913 } city_tile_iterate_end
;
916 case REQ_RANGE_CONTINENT
:
917 case REQ_RANGE_PLAYER
:
918 case REQ_RANGE_WORLD
:
919 case REQ_RANGE_COUNT
:
923 fc_assert_msg(FALSE
, "Invalid range %d.", range
);
928 /****************************************************************************
929 Is there a source tile within range of the target?
930 ****************************************************************************/
931 static enum fc_tristate
is_terrain_in_range(const struct tile
*target_tile
,
932 const struct city
*target_city
,
933 enum req_range range
, bool survives
,
934 const struct terrain
*pterrain
)
937 case REQ_RANGE_LOCAL
:
938 /* The requirement is filled if the tile has the terrain. */
942 return BOOL_TO_TRISTATE(pterrain
&& tile_terrain(target_tile
) == pterrain
);
943 case REQ_RANGE_CADJACENT
:
947 return BOOL_TO_TRISTATE(pterrain
&& is_terrain_card_near(target_tile
, pterrain
, TRUE
));
948 case REQ_RANGE_ADJACENT
:
952 return BOOL_TO_TRISTATE(pterrain
&& is_terrain_near_tile(target_tile
, pterrain
, TRUE
));
957 if (pterrain
!= NULL
) {
958 city_tile_iterate(city_map_radius_sq_get(target_city
),
959 city_tile(target_city
), ptile
) {
960 if (tile_terrain(ptile
) == pterrain
) {
963 } city_tile_iterate_end
;
967 case REQ_RANGE_CONTINENT
:
968 case REQ_RANGE_PLAYER
:
969 case REQ_RANGE_WORLD
:
970 case REQ_RANGE_COUNT
:
974 fc_assert_msg(FALSE
, "Invalid range %d.", range
);
979 /****************************************************************************
980 Is there a source tile within range of the target?
981 ****************************************************************************/
982 static enum fc_tristate
is_resource_in_range(const struct tile
*target_tile
,
983 const struct city
*target_city
,
984 enum req_range range
, bool survives
,
985 const struct resource
*pres
)
988 case REQ_RANGE_LOCAL
:
992 /* The requirement is filled if the tile has the terrain. */
993 return BOOL_TO_TRISTATE(pres
&& tile_resource(target_tile
) == pres
);
994 case REQ_RANGE_CADJACENT
:
998 return BOOL_TO_TRISTATE(pres
&& is_resource_card_near(target_tile
, pres
, TRUE
));
999 case REQ_RANGE_ADJACENT
:
1003 return BOOL_TO_TRISTATE(pres
&& is_resource_near_tile(target_tile
, pres
, TRUE
));
1004 case REQ_RANGE_CITY
:
1009 city_tile_iterate(city_map_radius_sq_get(target_city
),
1010 city_tile(target_city
), ptile
) {
1011 if (tile_resource(ptile
) == pres
) {
1014 } city_tile_iterate_end
;
1018 case REQ_RANGE_CONTINENT
:
1019 case REQ_RANGE_PLAYER
:
1020 case REQ_RANGE_WORLD
:
1021 case REQ_RANGE_COUNT
:
1025 fc_assert_msg(FALSE
, "Invalid range %d.", range
);
1030 /****************************************************************************
1031 Is there a source terrain class within range of the target?
1032 ****************************************************************************/
1033 static enum fc_tristate
is_terrain_class_in_range(const struct tile
*target_tile
,
1034 const struct city
*target_city
,
1035 enum req_range range
, bool survives
,
1036 enum terrain_class pclass
)
1039 case REQ_RANGE_LOCAL
:
1040 /* The requirement is filled if the tile has the terrain of correct class. */
1044 return BOOL_TO_TRISTATE(terrain_type_terrain_class(tile_terrain(target_tile
)) == pclass
);
1045 case REQ_RANGE_CADJACENT
:
1049 return BOOL_TO_TRISTATE(is_terrain_class_card_near(target_tile
, pclass
));
1050 case REQ_RANGE_ADJACENT
:
1054 return BOOL_TO_TRISTATE(is_terrain_class_near_tile(target_tile
, pclass
));
1055 case REQ_RANGE_CITY
:
1059 city_tile_iterate(city_map_radius_sq_get(target_city
),
1060 city_tile(target_city
), ptile
) {
1061 if (terrain_type_terrain_class(tile_terrain(ptile
)) == pclass
) {
1064 } city_tile_iterate_end
;
1067 case REQ_RANGE_CONTINENT
:
1068 case REQ_RANGE_PLAYER
:
1069 case REQ_RANGE_WORLD
:
1070 case REQ_RANGE_COUNT
:
1074 fc_assert_msg(FALSE
, "Invalid range %d.", range
);
1079 /****************************************************************************
1080 Is there a terrain with the given flag within range of the target?
1081 ****************************************************************************/
1082 static enum fc_tristate
is_terrainflag_in_range(const struct tile
*target_tile
,
1083 const struct city
*target_city
,
1084 enum req_range range
, bool survives
,
1085 enum terrain_flag_id terrflag
)
1088 case REQ_RANGE_LOCAL
:
1089 /* The requirement is filled if the tile has the terrain with correct flag. */
1093 return BOOL_TO_TRISTATE(terrain_has_flag(tile_terrain(target_tile
), terrflag
));
1094 case REQ_RANGE_CADJACENT
:
1098 return BOOL_TO_TRISTATE(is_terrain_flag_card_near(target_tile
, terrflag
));
1099 case REQ_RANGE_ADJACENT
:
1103 return BOOL_TO_TRISTATE(is_terrain_flag_near_tile(target_tile
, terrflag
));
1104 case REQ_RANGE_CITY
:
1108 city_tile_iterate(city_map_radius_sq_get(target_city
),
1109 city_tile(target_city
), ptile
) {
1110 if (terrain_has_flag(tile_terrain(ptile
), terrflag
)) {
1113 } city_tile_iterate_end
;
1116 case REQ_RANGE_CONTINENT
:
1117 case REQ_RANGE_PLAYER
:
1118 case REQ_RANGE_WORLD
:
1119 case REQ_RANGE_COUNT
:
1123 fc_assert_msg(FALSE
, "Invalid range %d.", range
);
1128 /****************************************************************************
1129 Is there a source base type within range of the target?
1130 ****************************************************************************/
1131 static enum fc_tristate
is_base_type_in_range(const struct tile
*target_tile
,
1132 const struct city
*target_city
,
1133 enum req_range range
, bool survives
,
1134 struct base_type
*pbase
)
1137 case REQ_RANGE_LOCAL
:
1138 /* The requirement is filled if the tile has base of requested type. */
1142 return BOOL_TO_TRISTATE(tile_has_base(target_tile
, pbase
));
1143 case REQ_RANGE_CADJACENT
:
1147 return BOOL_TO_TRISTATE(is_base_card_near(target_tile
, pbase
));
1148 case REQ_RANGE_ADJACENT
:
1152 return BOOL_TO_TRISTATE(is_base_near_tile(target_tile
, pbase
));
1153 case REQ_RANGE_CITY
:
1157 city_tile_iterate(city_map_radius_sq_get(target_city
),
1158 city_tile(target_city
), ptile
) {
1159 if (tile_has_base(ptile
, pbase
)) {
1162 } city_tile_iterate_end
;
1165 case REQ_RANGE_CONTINENT
:
1166 case REQ_RANGE_PLAYER
:
1167 case REQ_RANGE_WORLD
:
1168 case REQ_RANGE_COUNT
:
1172 fc_assert_msg(FALSE
, "Invalid range %d.", range
);
1177 /****************************************************************************
1178 Is there a tech with the given flag within range of the target?
1179 ****************************************************************************/
1180 static enum fc_tristate
is_techflag_in_range(const struct player
*target_player
,
1181 enum req_range range
,
1182 enum tech_flag_id techflag
)
1185 case REQ_RANGE_PLAYER
:
1186 if (NULL
!= target_player
) {
1187 return BOOL_TO_TRISTATE(player_knows_techs_with_flag(target_player
, techflag
));
1192 case REQ_RANGE_WORLD
:
1193 players_iterate(pplayer
) {
1194 if (player_knows_techs_with_flag(pplayer
, techflag
)) {
1197 } players_iterate_end
;
1200 case REQ_RANGE_LOCAL
:
1201 case REQ_RANGE_CADJACENT
:
1202 case REQ_RANGE_ADJACENT
:
1203 case REQ_RANGE_CITY
:
1204 case REQ_RANGE_CONTINENT
:
1205 case REQ_RANGE_COUNT
:
1209 fc_assert_msg(FALSE
, "Invalid range %d.", range
);
1214 /****************************************************************************
1215 Is there a source road type within range of the target?
1216 ****************************************************************************/
1217 static enum fc_tristate
is_road_type_in_range(const struct tile
*target_tile
,
1218 const struct city
*target_city
,
1219 enum req_range range
, bool survives
,
1220 struct road_type
*proad
)
1223 case REQ_RANGE_LOCAL
:
1224 /* The requirement is filled if the tile has road of requested type. */
1228 return BOOL_TO_TRISTATE(tile_has_road(target_tile
, proad
));
1229 case REQ_RANGE_CADJACENT
:
1233 return BOOL_TO_TRISTATE(is_road_card_near(target_tile
, proad
));
1234 case REQ_RANGE_ADJACENT
:
1238 return BOOL_TO_TRISTATE(is_road_near_tile(target_tile
, proad
));
1239 case REQ_RANGE_CITY
:
1243 city_tile_iterate(city_map_radius_sq_get(target_city
),
1244 city_tile(target_city
), ptile
) {
1245 if (tile_has_road(ptile
, proad
)) {
1248 } city_tile_iterate_end
;
1251 case REQ_RANGE_CONTINENT
:
1252 case REQ_RANGE_PLAYER
:
1253 case REQ_RANGE_WORLD
:
1254 case REQ_RANGE_COUNT
:
1258 fc_assert_msg(FALSE
, "Invalid range %d.", range
);
1263 /****************************************************************************
1264 Is there a terrain which can support the specified infrastructure
1265 within range of the target?
1266 ****************************************************************************/
1267 static enum fc_tristate
is_terrain_alter_possible_in_range(const struct tile
*target_tile
,
1268 enum req_range range
,
1270 enum terrain_alteration alteration
)
1277 case REQ_RANGE_LOCAL
:
1278 return BOOL_TO_TRISTATE(terrain_can_support_alteration(tile_terrain(target_tile
),
1280 case REQ_RANGE_CADJACENT
:
1281 case REQ_RANGE_ADJACENT
: /* XXX Could in principle support ADJACENT. */
1282 case REQ_RANGE_CITY
:
1283 case REQ_RANGE_CONTINENT
:
1284 case REQ_RANGE_PLAYER
:
1285 case REQ_RANGE_WORLD
:
1286 case REQ_RANGE_COUNT
:
1290 fc_assert_msg(FALSE
, "Invalid range %d.", range
);
1295 /****************************************************************************
1296 Is there a nation within range of the target?
1297 ****************************************************************************/
1298 static enum fc_tristate
is_nation_in_range(const struct player
*target_player
,
1299 enum req_range range
, bool survives
,
1300 const struct nation_type
*nation
)
1303 case REQ_RANGE_PLAYER
:
1304 if (target_player
== NULL
) {
1307 return BOOL_TO_TRISTATE(nation_of_player(target_player
) == nation
);
1308 case REQ_RANGE_WORLD
:
1309 /* NB: if a player is ever removed outright from the game
1310 * (e.g. via /remove), rather than just dying, this 'survives'
1311 * requirement will stop being true for their nation.
1312 * create_command_newcomer() can also cause this to happen. */
1313 return BOOL_TO_TRISTATE(NULL
!= nation
->player
1314 && (survives
|| nation
->player
->is_alive
));
1315 case REQ_RANGE_LOCAL
:
1316 case REQ_RANGE_CADJACENT
:
1317 case REQ_RANGE_ADJACENT
:
1318 case REQ_RANGE_CITY
:
1319 case REQ_RANGE_CONTINENT
:
1320 case REQ_RANGE_COUNT
:
1324 fc_assert_msg(FALSE
, "Invalid range %d.", range
);
1329 /****************************************************************************
1330 Is there a nationality within range of the target?
1331 ****************************************************************************/
1332 static enum fc_tristate
is_nationality_in_range(const struct city
*target_city
,
1333 enum req_range range
,
1334 const struct nation_type
*nationality
)
1337 case REQ_RANGE_CITY
:
1338 if (target_city
== NULL
) {
1341 citizens_iterate(target_city
, slot
, count
) {
1342 if (player_slot_get_player(slot
)->nation
== nationality
) {
1345 } citizens_iterate_end
;
1348 case REQ_RANGE_PLAYER
:
1349 case REQ_RANGE_WORLD
:
1350 case REQ_RANGE_LOCAL
:
1351 case REQ_RANGE_CADJACENT
:
1352 case REQ_RANGE_ADJACENT
:
1353 case REQ_RANGE_CONTINENT
:
1354 case REQ_RANGE_COUNT
:
1358 fc_assert_msg(FALSE
, "Invalid range %d.", range
);
1363 /****************************************************************************
1364 Is there a unit of the given type within range of the target?
1365 ****************************************************************************/
1366 static enum fc_tristate
is_unittype_in_range(const struct unit_type
*target_unittype
,
1367 enum req_range range
, bool survives
,
1368 struct unit_type
*punittype
)
1370 /* If no target_unittype is given, we allow the req to be met. This is
1371 * to allow querying of certain effect types (like the presence of city
1372 * walls) without actually knowing the target unit. */
1373 return BOOL_TO_TRISTATE(range
== REQ_RANGE_LOCAL
1374 && (!target_unittype
1375 || target_unittype
== punittype
));
1378 /****************************************************************************
1379 Is there a unit with the given flag within range of the target?
1380 ****************************************************************************/
1381 static enum fc_tristate
is_unitflag_in_range(const struct unit_type
*target_unittype
,
1382 enum req_range range
, bool survives
,
1383 enum unit_type_flag_id unitflag
)
1385 /* If no target_unittype is given, we allow the req to be met. This is
1386 * to allow querying of certain effect types (like the presence of city
1387 * walls) without actually knowing the target unit. */
1388 if (range
!= REQ_RANGE_LOCAL
) {
1391 if (!target_unittype
) {
1395 return BOOL_TO_TRISTATE(utype_has_flag(target_unittype
, unitflag
));
1398 /****************************************************************************
1399 Is there a unit with the given flag within range of the target?
1400 ****************************************************************************/
1401 static enum fc_tristate
is_unitclass_in_range(const struct unit_type
*target_unittype
,
1402 enum req_range range
, bool survives
,
1403 struct unit_class
*pclass
)
1405 /* If no target_unittype is given, we allow the req to be met. This is
1406 * to allow querying of certain effect types (like the presence of city
1407 * walls) without actually knowing the target unit. */
1408 return BOOL_TO_TRISTATE(range
== REQ_RANGE_LOCAL
1409 && (!target_unittype
1410 || utype_class(target_unittype
) == pclass
));
1413 /****************************************************************************
1414 Is there a unit with the given flag within range of the target?
1415 ****************************************************************************/
1416 static enum fc_tristate
is_unitclassflag_in_range(const struct unit_type
*target_unittype
,
1417 enum req_range range
, bool survives
,
1418 enum unit_class_flag_id ucflag
)
1420 /* If no target_unittype is given, we allow the req to be met. This is
1421 * to allow querying of certain effect types (like the presence of city
1422 * walls) without actually knowing the target unit. */
1423 return BOOL_TO_TRISTATE(range
== REQ_RANGE_LOCAL
1424 && (!target_unittype
1425 || uclass_has_flag(utype_class(target_unittype
), ucflag
)));
1428 /****************************************************************************
1429 Is center of given city in tile. If city is NULL, any city will do.
1430 ****************************************************************************/
1431 static bool is_city_in_tile(const struct tile
*ptile
,
1432 const struct city
*pcity
)
1434 if (pcity
== NULL
) {
1435 return tile_city(ptile
) != NULL
;
1437 return is_city_center(pcity
, ptile
);
1441 /****************************************************************************
1442 Is center of given city in range. If city is NULL, any city will do.
1443 ****************************************************************************/
1444 static enum fc_tristate
is_citytile_in_range(const struct tile
*target_tile
,
1445 const struct city
*target_city
,
1446 enum req_range range
,
1447 enum citytile_type citytile
)
1450 if (citytile
== CITYT_CENTER
) {
1452 case REQ_RANGE_LOCAL
:
1453 return BOOL_TO_TRISTATE(is_city_in_tile(target_tile
, target_city
));
1454 case REQ_RANGE_CADJACENT
:
1455 cardinal_adjc_iterate(target_tile
, adjc_tile
) {
1456 if (is_city_in_tile(adjc_tile
, target_city
)) {
1459 } cardinal_adjc_iterate_end
;
1462 case REQ_RANGE_ADJACENT
:
1463 adjc_iterate(target_tile
, adjc_tile
) {
1464 if (is_city_in_tile(adjc_tile
, target_city
)) {
1470 case REQ_RANGE_CITY
:
1471 case REQ_RANGE_CONTINENT
:
1472 case REQ_RANGE_PLAYER
:
1473 case REQ_RANGE_WORLD
:
1474 case REQ_RANGE_COUNT
:
1478 fc_assert_msg(FALSE
, "Invalid range %d for citytile.", range
);
1482 /* Not implemented */
1483 log_error("is_req_active(): citytile %d not supported.",
1492 /****************************************************************************
1493 Checks the requirement to see if it is active on the given target.
1495 target gives the type of the target
1496 (player,city,building,tile) give the exact target
1497 req gives the requirement itself
1499 Make sure you give all aspects of the target when calling this function:
1500 for instance if you have TARGET_CITY pass the city's owner as the target
1501 player as well as the city itself as the target city.
1502 ****************************************************************************/
1503 bool is_req_active(const struct player
*target_player
,
1504 const struct city
*target_city
,
1505 const struct impr_type
*target_building
,
1506 const struct tile
*target_tile
,
1507 const struct unit_type
*target_unittype
,
1508 const struct output_type
*target_output
,
1509 const struct specialist
*target_specialist
,
1510 const struct requirement
*req
,
1511 const enum req_problem_type prob_type
)
1513 enum fc_tristate eval
= TRI_NO
;
1515 /* Note the target may actually not exist. In particular, effects that
1516 * have a VUT_SPECIAL, VUT_RESOURCE, or VUT_TERRAIN may often be passed
1517 * to this function with a city as their target. In this case the
1518 * requirement is simply not met. */
1519 switch (req
->source
.kind
) {
1524 /* The requirement is filled if the player owns the tech. */
1525 eval
= is_tech_in_range(target_player
, req
->range
,
1526 advance_number(req
->source
.value
.advance
));
1529 eval
= is_techflag_in_range(target_player
, req
->range
,
1530 req
->source
.value
.techflag
);
1532 case VUT_GOVERNMENT
:
1533 /* The requirement is filled if the player is using the government. */
1534 if (target_player
== NULL
) {
1537 eval
= BOOL_TO_TRISTATE(government_of_player(target_player
) == req
->source
.value
.govern
);
1540 case VUT_IMPROVEMENT
:
1541 eval
= is_building_in_range(target_player
, target_city
,
1543 req
->range
, req
->survives
,
1544 req
->source
.value
.building
);
1547 eval
= is_special_in_range(target_tile
, target_city
,
1548 req
->range
, req
->survives
,
1549 req
->source
.value
.special
);
1552 eval
= is_terrain_in_range(target_tile
, target_city
,
1553 req
->range
, req
->survives
,
1554 req
->source
.value
.terrain
);
1557 eval
= is_terrainflag_in_range(target_tile
, target_city
,
1558 req
->range
, req
->survives
,
1559 req
->source
.value
.terrainflag
);
1562 eval
= is_resource_in_range(target_tile
, target_city
,
1563 req
->range
, req
->survives
,
1564 req
->source
.value
.resource
);
1567 eval
= is_nation_in_range(target_player
, req
->range
, req
->survives
,
1568 req
->source
.value
.nation
);
1570 case VUT_NATIONALITY
:
1571 eval
= is_nationality_in_range(target_city
, req
->range
,
1572 req
->source
.value
.nationality
);
1575 if (target_unittype
== NULL
) {
1578 eval
= is_unittype_in_range(target_unittype
,
1579 req
->range
, req
->survives
,
1580 req
->source
.value
.utype
);
1584 eval
= is_unitflag_in_range(target_unittype
,
1585 req
->range
, req
->survives
,
1586 req
->source
.value
.unitflag
);
1589 if (target_unittype
== NULL
) {
1592 eval
= is_unitclass_in_range(target_unittype
,
1593 req
->range
, req
->survives
,
1594 req
->source
.value
.uclass
);
1598 if (target_unittype
== NULL
) {
1601 eval
= is_unitclassflag_in_range(target_unittype
,
1602 req
->range
, req
->survives
,
1603 req
->source
.value
.unitclassflag
);
1607 eval
= BOOL_TO_TRISTATE(target_output
1608 && target_output
->index
== req
->source
.value
.outputtype
);
1610 case VUT_SPECIALIST
:
1611 eval
= BOOL_TO_TRISTATE(target_specialist
1612 && target_specialist
== req
->source
.value
.specialist
);
1615 if (target_city
== NULL
) {
1618 eval
= BOOL_TO_TRISTATE(city_size_get(target_city
) >= req
->source
.value
.minsize
);
1622 if (target_player
== NULL
) {
1625 eval
= BOOL_TO_TRISTATE(target_player
->ai_controlled
1626 && target_player
->ai_common
.skill_level
== req
->source
.value
.ai_level
);
1629 case VUT_TERRAINCLASS
:
1630 eval
= is_terrain_class_in_range(target_tile
, target_city
,
1631 req
->range
, req
->survives
,
1632 req
->source
.value
.terrainclass
);
1635 eval
= is_base_type_in_range(target_tile
, target_city
,
1636 req
->range
, req
->survives
,
1637 req
->source
.value
.base
);
1640 eval
= is_road_type_in_range(target_tile
, target_city
,
1641 req
->range
, req
->survives
,
1642 req
->source
.value
.road
);
1645 eval
= BOOL_TO_TRISTATE(game
.info
.year
>= req
->source
.value
.minyear
);
1647 case VUT_TERRAINALTER
:
1648 if (target_tile
== NULL
) {
1651 eval
= is_terrain_alter_possible_in_range(target_tile
,
1652 req
->range
, req
->survives
,
1653 req
->source
.value
.terrainalter
);
1657 if (target_tile
== NULL
) {
1660 eval
= is_citytile_in_range(target_tile
, target_city
,
1662 req
->source
.value
.citytile
);
1666 log_error("is_req_active(): invalid source kind %d.", req
->source
.kind
);
1670 if (eval
== TRI_MAYBE
) {
1671 if (prob_type
== RPT_POSSIBLE
) {
1679 return (eval
== TRI_NO
);
1681 return (eval
== TRI_YES
);
1685 /****************************************************************************
1686 Checks the requirement(s) to see if they are active on the given target.
1688 target gives the type of the target
1689 (player,city,building,tile) give the exact target
1691 reqs gives the requirement vector.
1692 The function returns TRUE only if all requirements are active.
1694 Make sure you give all aspects of the target when calling this function:
1695 for instance if you have TARGET_CITY pass the city's owner as the target
1696 player as well as the city itself as the target city.
1697 ****************************************************************************/
1698 bool are_reqs_active(const struct player
*target_player
,
1699 const struct city
*target_city
,
1700 const struct impr_type
*target_building
,
1701 const struct tile
*target_tile
,
1702 const struct unit_type
*target_unittype
,
1703 const struct output_type
*target_output
,
1704 const struct specialist
*target_specialist
,
1705 const struct requirement_vector
*reqs
,
1706 const enum req_problem_type prob_type
)
1708 requirement_vector_iterate(reqs
, preq
) {
1709 if (!is_req_active(target_player
, target_city
, target_building
,
1710 target_tile
, target_unittype
, target_output
,
1715 } requirement_vector_iterate_end
;
1719 /****************************************************************************
1720 Return TRUE if this is an "unchanging" requirement. This means that
1721 if a target can't meet the requirement now, it probably won't ever be able
1722 to do so later. This can be used to do requirement filtering when checking
1723 if a target may "eventually" become available.
1725 Note this isn't absolute. Returning TRUE here just means that the
1726 requirement probably can't be met. In some cases (particularly terrains)
1728 *****************************************************************************/
1729 bool is_req_unchanging(const struct requirement
*req
)
1731 switch (req
->source
.kind
) {
1735 case VUT_SPECIALIST
: /* Only so long as it's at local range only */
1741 case VUT_GOVERNMENT
:
1742 case VUT_IMPROVEMENT
:
1744 case VUT_NATIONALITY
:
1745 case VUT_UTYPE
: /* Not sure about this one */
1746 case VUT_UTFLAG
: /* Not sure about this one */
1747 case VUT_UCLASS
: /* Not sure about this one */
1748 case VUT_UCFLAG
: /* Not sure about this one */
1754 case VUT_TERRAINCLASS
:
1756 case VUT_TERRAINALTER
:
1758 /* Terrains, specials and bases aren't really unchanging; in fact they're
1759 * practically guaranteed to change. We return TRUE here for historical
1760 * reasons and so that the AI doesn't get confused (since the AI
1761 * doesn't know how to meet special and terrain requirements). */
1764 /* Once year is reached, it does not change again */
1765 return req
->source
.value
.minyear
> game
.info
.year
;
1769 fc_assert_msg(FALSE
, "Invalid source kind %d.", req
->source
.kind
);
1773 /****************************************************************************
1774 Return TRUE iff the two sources are equivalent. Note this isn't the
1775 same as an == or memcmp check.
1776 *****************************************************************************/
1777 bool are_universals_equal(const struct universal
*psource1
,
1778 const struct universal
*psource2
)
1780 if (psource1
->kind
!= psource2
->kind
) {
1783 switch (psource1
->kind
) {
1787 return psource1
->value
.advance
== psource2
->value
.advance
;
1789 return psource1
->value
.techflag
== psource2
->value
.techflag
;
1790 case VUT_GOVERNMENT
:
1791 return psource1
->value
.govern
== psource2
->value
.govern
;
1792 case VUT_IMPROVEMENT
:
1793 return psource1
->value
.building
== psource2
->value
.building
;
1795 return psource1
->value
.special
== psource2
->value
.special
;
1797 return psource1
->value
.terrain
== psource2
->value
.terrain
;
1799 return psource1
->value
.terrainflag
== psource2
->value
.terrainflag
;
1801 return psource1
->value
.resource
== psource2
->value
.resource
;
1803 return psource1
->value
.nation
== psource2
->value
.nation
;
1804 case VUT_NATIONALITY
:
1805 return psource1
->value
.nationality
== psource2
->value
.nationality
;
1807 return psource1
->value
.utype
== psource2
->value
.utype
;
1809 return psource1
->value
.unitflag
== psource2
->value
.unitflag
;
1811 return psource1
->value
.uclass
== psource2
->value
.uclass
;
1813 return psource1
->value
.unitclassflag
== psource2
->value
.unitclassflag
;
1815 return psource1
->value
.outputtype
== psource2
->value
.outputtype
;
1816 case VUT_SPECIALIST
:
1817 return psource1
->value
.specialist
== psource2
->value
.specialist
;
1819 return psource1
->value
.minsize
== psource2
->value
.minsize
;
1821 return psource1
->value
.ai_level
== psource2
->value
.ai_level
;
1822 case VUT_TERRAINCLASS
:
1823 return psource1
->value
.terrainclass
== psource2
->value
.terrainclass
;
1825 return psource1
->value
.base
== psource2
->value
.base
;
1827 return psource1
->value
.road
== psource2
->value
.road
;
1829 return psource1
->value
.minyear
== psource2
->value
.minyear
;
1830 case VUT_TERRAINALTER
:
1831 return psource1
->value
.terrainalter
== psource2
->value
.terrainalter
;
1833 return psource1
->value
.citytile
== psource2
->value
.citytile
;
1838 fc_assert_msg(FALSE
, "Invalid source kind %d.", psource1
->kind
);
1842 /****************************************************************************
1843 Return the (untranslated) rule name of the universal.
1844 You don't have to free the return pointer.
1845 *****************************************************************************/
1846 const char *universal_rule_name(const struct universal
*psource
)
1848 static char buffer
[10];
1850 switch (psource
->kind
) {
1854 if (psource
->value
.citytile
== CITYT_CENTER
) {
1860 fc_snprintf(buffer
, sizeof(buffer
), "%d", psource
->value
.minyear
);
1864 return advance_rule_name(psource
->value
.advance
);
1866 return tech_flag_id_name(psource
->value
.techflag
);
1867 case VUT_GOVERNMENT
:
1868 return government_rule_name(psource
->value
.govern
);
1869 case VUT_IMPROVEMENT
:
1870 return improvement_rule_name(psource
->value
.building
);
1872 return special_rule_name(psource
->value
.special
);
1874 return terrain_rule_name(psource
->value
.terrain
);
1876 return terrain_flag_id_name(psource
->value
.terrainflag
);
1878 return resource_rule_name(psource
->value
.resource
);
1880 return nation_rule_name(psource
->value
.nation
);
1881 case VUT_NATIONALITY
:
1882 return nation_rule_name(psource
->value
.nationality
);
1884 return utype_rule_name(psource
->value
.utype
);
1886 return unit_type_flag_id_name(psource
->value
.unitflag
);
1888 return uclass_rule_name(psource
->value
.uclass
);
1890 return unit_class_flag_id_name(psource
->value
.unitclassflag
);
1892 return get_output_name(psource
->value
.outputtype
);
1893 case VUT_SPECIALIST
:
1894 return specialist_rule_name(psource
->value
.specialist
);
1896 fc_snprintf(buffer
, sizeof(buffer
), "%d", psource
->value
.minsize
);
1900 return ai_level_name(psource
->value
.ai_level
);
1901 case VUT_TERRAINCLASS
:
1902 return terrain_class_name(psource
->value
.terrainclass
);
1904 return base_rule_name(psource
->value
.base
);
1906 return road_rule_name(psource
->value
.road
);
1907 case VUT_TERRAINALTER
:
1908 return terrain_alteration_name(psource
->value
.terrainalter
);
1913 fc_assert_msg(FALSE
, "Invalid source kind %d.", psource
->kind
);
1917 /****************************************************************************
1918 Make user-friendly text for the source. The text is put into a user
1919 buffer which is also returned.
1920 *****************************************************************************/
1921 const char *universal_name_translation(const struct universal
*psource
,
1922 char *buf
, size_t bufsz
)
1924 buf
[0] = '\0'; /* to be safe. */
1925 switch (psource
->kind
) {
1927 /* TRANS: missing value */
1928 fc_strlcat(buf
, _("(none)"), bufsz
);
1931 fc_strlcat(buf
, advance_name_translation(psource
->value
.advance
), bufsz
);
1934 cat_snprintf(buf
, bufsz
, _("\"%s\" tech"),
1935 /* flag names are never translated */
1936 tech_flag_id_name(psource
->value
.techflag
));
1938 case VUT_GOVERNMENT
:
1939 fc_strlcat(buf
, government_name_translation(psource
->value
.govern
),
1942 case VUT_IMPROVEMENT
:
1943 fc_strlcat(buf
, improvement_name_translation(psource
->value
.building
),
1947 fc_strlcat(buf
, special_name_translation(psource
->value
.special
), bufsz
);
1950 fc_strlcat(buf
, terrain_name_translation(psource
->value
.terrain
), bufsz
);
1953 fc_strlcat(buf
, resource_name_translation(psource
->value
.resource
), bufsz
);
1956 fc_strlcat(buf
, nation_adjective_translation(psource
->value
.nation
),
1959 case VUT_NATIONALITY
:
1960 fc_strlcat(buf
, nation_adjective_translation(psource
->value
.nationality
),
1964 fc_strlcat(buf
, utype_name_translation(psource
->value
.utype
), bufsz
);
1967 cat_snprintf(buf
, bufsz
, _("\"%s\" units"),
1968 /* flag names are never translated */
1969 unit_type_flag_id_name(psource
->value
.unitflag
));
1972 cat_snprintf(buf
, bufsz
, _("%s units"),
1973 uclass_name_translation(psource
->value
.uclass
));
1976 cat_snprintf(buf
, bufsz
, _("\"%s\" units"),
1977 /* flag names are never translated */
1978 unit_class_flag_id_name(psource
->value
.unitclassflag
));
1982 fc_strlcat(buf
, get_output_name(psource
->value
.outputtype
), bufsz
);
1984 case VUT_SPECIALIST
:
1985 fc_strlcat(buf
, specialist_plural_translation(psource
->value
.specialist
),
1989 cat_snprintf(buf
, bufsz
, _("Size %d"),
1990 psource
->value
.minsize
);
1993 /* TRANS: "Hard AI" */
1994 cat_snprintf(buf
, bufsz
, _("%s AI"),
1995 ai_level_name(psource
->value
.ai_level
)); /* FIXME */
1997 case VUT_TERRAINCLASS
:
1998 /* TRANS: "Land terrain" */
1999 cat_snprintf(buf
, bufsz
, _("%s terrain"),
2000 terrain_class_name_translation(psource
->value
.terrainclass
));
2003 cat_snprintf(buf
, bufsz
, _("\"%s\" terrain"),
2004 /* flag names are never translated */
2005 terrain_flag_id_name(psource
->value
.terrainflag
));
2008 /* TRANS: "Fortress base" */
2009 cat_snprintf(buf
, bufsz
, _("%s base"),
2010 base_name_translation(psource
->value
.base
));
2013 /* TRANS: Road type requirement: "Road" / "Railroad" / "Maglev" ... */
2014 cat_snprintf(buf
, bufsz
, Q_("?road:%s"),
2015 road_name_translation(psource
->value
.road
));
2018 cat_snprintf(buf
, bufsz
, _("After %s"),
2019 textyear(psource
->value
.minyear
));
2021 case VUT_TERRAINALTER
:
2022 /* TRANS: "Irrigation possible" */
2023 cat_snprintf(buf
, bufsz
, _("%s possible"),
2024 terrain_alteration_name_translation(psource
->value
.terrainalter
));
2027 fc_strlcat(buf
, _("City center tile"), bufsz
);
2033 fc_assert_msg(FALSE
, "Invalid source kind %d.", psource
->kind
);
2037 /****************************************************************************
2038 Return untranslated name of the universal source name.
2039 *****************************************************************************/
2040 const char *universal_type_rule_name(const struct universal
*psource
)
2042 return universals_n_name(psource
->kind
);
2045 /**************************************************************************
2046 Return the number of shields it takes to build this universal.
2047 **************************************************************************/
2048 int universal_build_shield_cost(const struct universal
*target
)
2050 switch (target
->kind
) {
2051 case VUT_IMPROVEMENT
:
2052 return impr_build_shield_cost(target
->value
.building
);
2054 return utype_build_shield_cost(target
->value
.utype
);