Freeciv-3.4
Loading...
Searching...
No Matches
requirements.c
Go to the documentation of this file.
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)
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 <stdarg.h>
18
19/* utility */
20#include "astring.h"
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "achievements.h"
27#include "calendar.h"
28#include "citizens.h"
29#include "counters.h"
30#include "culture.h"
31#include "game.h"
32#include "government.h"
33#include "improvement.h"
34#include "movement.h"
35#include "nation.h"
36#include "player.h"
37#include "map.h"
38#include "research.h"
39#include "road.h"
40#include "server_settings.h"
41#include "specialist.h"
42#include "style.h"
43#include "victory.h" /* victory_enabled() */
44
45#include "requirements.h"
46
47/************************************************************************
48 Container for req_item_found functions
49************************************************************************/
50typedef enum req_item_found (*universal_found)(const struct requirement *,
51 const struct universal *);
53
54static
56 const struct req_context *context,
57 const struct req_context *other_context,
58 const struct requirement *req);
59
60/* Function pointer for requirement-type-specific is_req_active handlers */
61typedef enum fc_tristate
62(*is_req_active_cb)(const struct civ_map *nmap,
63 const struct req_context *context,
64 const struct req_context *other_context,
65 const struct requirement *req);
66
67static inline bool are_tiles_in_range(const struct tile *tile1,
68 const struct tile *tile2,
69 enum req_range range);
70
71/**********************************************************************/
76static enum req_unchanging_status
78 enum req_unchanging_status def,
79 const struct req_context *context,
80 const struct requirement *req)
81{
82 return req->range == REQ_RANGE_LOCAL ? REQUCH_YES : def;
83}
84#define REQUC_LOCAL unchanging_local
85
86/**********************************************************************/
89static enum req_unchanging_status
91 enum req_unchanging_status def,
92 const struct req_context *context,
93 const struct requirement *req)
94{
95 if (TRI_YES != tri_req_present(nmap, context, nullptr, req)) {
96 return REQUCH_NO;
97 }
98 return def;
99}
100#define REQUC_PRESENT unchanging_present
101
102/**********************************************************************/
105static enum req_unchanging_status
107 enum req_unchanging_status def,
108 const struct req_context *context,
109 const struct requirement *req)
110{
111 return
113 context, req);
114}
115#define REQUC_WORLD unchanging_world
116
117/**********************************************************************/
121static enum req_unchanging_status
123 enum req_unchanging_status def,
124 const struct req_context *context,
125 const struct requirement *req)
126{
127 if (REQ_RANGE_ALLIANCE == req->range
128 || REQ_RANGE_TEAM == req->range) {
129 struct requirement preq;
130
131 req_copy(&preq, req);
132 preq.range = REQ_RANGE_PLAYER;
133 if (TRI_YES != tri_req_present(nmap, context, nullptr, &preq)) {
134 return REQ_RANGE_TEAM == req->range ? REQUCH_ACT : REQUCH_NO;
135 }
136 }
137 return def;
138}
139#define REQUC_NALLY unchanging_noally
140
141/**********************************************************************/
144static enum req_unchanging_status
146 enum req_unchanging_status def,
147 const struct req_context *context,
148 const struct requirement *req)
149{
153 && context->city != nullptr && context->tile != nullptr
154 && city_tile(context->city) != nullptr
156 req->range))){
157 /* Cities don't move, and most reqs are present on city center */
158 return REQUCH_YES;
159 }
160 return def;
161}
162#define REQUC_CITYTILE unchanging_citytile
163
164/**********************************************************************/
167static enum req_unchanging_status
169 enum req_unchanging_status def,
170 const struct req_context *context,
171 const struct requirement *req)
172{
174
175 if (REQ_RANGE_CITY == req->range
178 return REQUCH_CTRL;
179 }
180
181 return def;
182}
183#define REQUC_CITYSTATUS unchanging_citystatus
184
185/**********************************************************************/
190static enum req_unchanging_status
192 enum req_unchanging_status def,
193 const struct req_context *context,
194 const struct requirement *req)
195{
196 const struct impr_type *b = req->source.value.building;
197
199 || VUT_SITE == req->source.kind, REQUCH_NO);
200 if (REQ_RANGE_LOCAL == req->range) {
201 /* Likely, won't be questioned for an obsolete building */
202 return REQUCH_YES;
203 }
204
205 if (req->source.kind == VUT_IMPROVEMENT
206 && improvement_obsolete(context->player, b, context->city)) {
207 /* FIXME: Sometimes can unobsolete, but considering it
208 * may sometimes put the function on endless recursion */
209 return REQUCH_ACT; /* Mostly about techs */
210 }
211 if (is_great_wonder(b)) {
214 && (req->range <= REQ_RANGE_CITY && TRI_YES
215 == tri_req_present(nmap, context, nullptr, req)))) {
216 /* If the wonder stays somewhere, it may either remain there
217 * or be destroyed. If it is destroyed, it is nowhere. */
218 return REQUCH_SCRIPTS;
219 }
220 }
221 return def;
222}
223#define REQUC_IMPR unchanging_building
224
230
231/**********************************************************************/
239 const char *value)
240{
241 struct universal source;
242
244 if (!universals_n_is_valid(source.kind)) {
245 return source;
246 }
247
249
250 return source;
251}
252
253/**********************************************************************/
258{
259 return unit_activity_is_valid(act)
260 && act != ACTIVITY_SENTRY
261 && act != ACTIVITY_GOTO
262 && act != ACTIVITY_EXPLORE;
263}
264
265/**********************************************************************/
270{
271 if (univ->kind == VUT_ACTIVITY) {
273 }
274
275 return TRUE;
276}
277
278/**********************************************************************/
283{
284 /* Finally scan the value string based on the type of the source. */
285 switch (source->kind) {
286 case VUT_NONE:
287 return;
288 case VUT_ADVANCE:
289 source->value.advance = advance_by_rule_name(value);
290 if (source->value.advance != nullptr) {
291 return;
292 }
293 break;
294 case VUT_TECHFLAG:
295 source->value.techflag
297 if (tech_flag_id_is_valid(source->value.techflag)) {
298 return;
299 }
300 break;
301 case VUT_GOVERNMENT:
302 source->value.govern = government_by_rule_name(value);
303 if (source->value.govern != nullptr) {
304 return;
305 }
306 break;
307 case VUT_GOVFLAG:
309 if (gov_flag_id_is_valid(source->value.govflag)) {
310 return;
311 }
312 break;
313 case VUT_ACHIEVEMENT:
314 source->value.achievement = achievement_by_rule_name(value);
315 if (source->value.achievement != nullptr) {
316 return;
317 }
318 break;
319 case VUT_STYLE:
320 source->value.style = style_by_rule_name(value);
321 if (source->value.style != nullptr) {
322 return;
323 }
324 break;
325 case VUT_IMPROVEMENT:
326 case VUT_SITE:
327 source->value.building = improvement_by_rule_name(value);
328 if (source->value.building != nullptr) {
329 return;
330 }
331 break;
332 case VUT_IMPR_GENUS:
333 source->value.impr_genus = impr_genus_id_by_name(value, fc_strcasecmp);
334 if (impr_genus_id_is_valid(source->value.impr_genus)) {
335 return;
336 }
337 break;
338 case VUT_IMPR_FLAG:
339 source->value.impr_flag = impr_flag_id_by_name(value, fc_strcasecmp);
340 if (impr_flag_id_is_valid(source->value.impr_flag)) {
341 return;
342 }
343 break;
344 case VUT_PLAYER_FLAG:
345 source->value.plr_flag = plr_flag_id_by_name(value, fc_strcasecmp);
346 if (plr_flag_id_is_valid(source->value.plr_flag)) {
347 return;
348 }
349 break;
350 case VUT_EXTRA:
351 source->value.extra = extra_type_by_rule_name(value);
352 if (source->value.extra != nullptr) {
353 return;
354 }
355 break;
356 case VUT_GOOD:
357 source->value.good = goods_by_rule_name(value);
358 if (source->value.good != nullptr) {
359 return;
360 }
361 break;
362 case VUT_TERRAIN:
363 source->value.terrain = terrain_by_rule_name(value);
364 if (source->value.terrain != T_UNKNOWN) {
365 return;
366 }
367 break;
368 case VUT_TERRFLAG:
369 source->value.terrainflag
371 if (terrain_flag_id_is_valid(source->value.terrainflag)) {
372 return;
373 }
374 break;
375 case VUT_NATION:
376 source->value.nation = nation_by_rule_name(value);
377 if (source->value.nation != NO_NATION_SELECTED) {
378 return;
379 }
380 break;
381 case VUT_NATIONGROUP:
382 source->value.nationgroup = nation_group_by_rule_name(value);
383 if (source->value.nationgroup != nullptr) {
384 return;
385 }
386 break;
387 case VUT_NATIONALITY:
388 source->value.nationality = nation_by_rule_name(value);
389 if (source->value.nationality != NO_NATION_SELECTED) {
390 return;
391 }
392 break;
394 source->value.origowner = nation_by_rule_name(value);
395 if (source->value.origowner != NO_NATION_SELECTED) {
396 return;
397 }
398 break;
399 case VUT_DIPLREL:
400 case VUT_DIPLREL_TILE:
404 source->value.diplrel = diplrel_by_rule_name(value);
405 if (source->value.diplrel != diplrel_other_invalid()) {
406 return;
407 }
408 break;
409 case VUT_UTYPE:
410 source->value.utype = unit_type_by_rule_name(value);
411 if (source->value.utype) {
412 return;
413 }
414 break;
415 case VUT_UTFLAG:
417 if (unit_type_flag_id_is_valid(source->value.unitflag)) {
418 return;
419 }
420 break;
421 case VUT_UCLASS:
422 source->value.uclass = unit_class_by_rule_name(value);
423 if (source->value.uclass) {
424 return;
425 }
426 break;
427 case VUT_UCFLAG:
428 source->value.unitclassflag
430 if (unit_class_flag_id_is_valid(source->value.unitclassflag)) {
431 return;
432 }
433 break;
434 case VUT_MINVETERAN:
435 source->value.minveteran = atoi(value);
436 if (source->value.minveteran > 0) {
437 return;
438 }
439 break;
440 case VUT_UNITSTATE:
441 source->value.unit_state = ustate_prop_by_name(value, fc_strcasecmp);
442 if (ustate_prop_is_valid(source->value.unit_state)) {
443 return;
444 }
445 break;
446 case VUT_ACTIVITY:
448 if (activity_is_valid_in_requirement(source->value.activity)) {
449 return;
450 }
451 break;
452 case VUT_MINMOVES:
453 source->value.minmoves = atoi(value);
454 if (source->value.minmoves > 0) {
455 return;
456 }
457 break;
458 case VUT_MINHP:
459 source->value.min_hit_points = atoi(value);
460 if (source->value.min_hit_points > 0) {
461 return;
462 }
463 break;
464 case VUT_AGE:
465 source->value.age = atoi(value);
466 if (source->value.age > 0) {
467 return;
468 }
469 break;
470 case VUT_FORM_AGE:
471 source->value.form_age = atoi(value);
472 if (source->value.form_age > 0) {
473 return;
474 }
475 break;
476 case VUT_MINTECHS:
477 source->value.min_techs = atoi(value);
478 if (source->value.min_techs > 0) {
479 return;
480 }
481 break;
482 case VUT_FUTURETECHS:
483 source->value.future_techs = atoi(value);
484 if (source->value.future_techs > 0) {
485 return;
486 }
487 break;
488 case VUT_MINCITIES:
489 source->value.min_cities = atoi(value);
490 if (source->value.min_cities > 0) {
491 return;
492 }
493 break;
494 case VUT_ACTION:
495 source->value.action = action_by_rule_name(value);
496 if (source->value.action != nullptr) {
497 return;
498 }
499 break;
500 case VUT_OTYPE:
501 source->value.outputtype = output_type_by_identifier(value);
502 if (source->value.outputtype != O_LAST) {
503 return;
504 }
505 break;
506 case VUT_SPECIALIST:
507 source->value.specialist = specialist_by_rule_name(value);
508 if (source->value.specialist) {
509 return;
510 }
511 break;
512 case VUT_MINSIZE:
513 source->value.minsize = atoi(value);
514 if (source->value.minsize > 0) {
515 return;
516 }
517 break;
518 case VUT_MINCULTURE:
519 source->value.minculture = atoi(value);
520 if (source->value.minculture > 0) {
521 return;
522 }
523 break;
525 source->value.minforeignpct = atoi(value);
526 if (source->value.minforeignpct > 0) {
527 return;
528 }
529 break;
530 case VUT_AI_LEVEL:
531 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
532 if (ai_level_is_valid(source->value.ai_level)) {
533 return;
534 }
535 break;
537 source->value.max_tile_total_units = atoi(value);
538 if (0 <= source->value.max_tile_total_units) {
539 return;
540 }
541 break;
543 source->value.max_tile_top_units = atoi(value);
544 if (0 <= source->value.max_tile_top_units) {
545 return;
546 }
547 break;
548 case VUT_TERRAINCLASS:
549 source->value.terrainclass
551 if (terrain_class_is_valid(source->value.terrainclass)) {
552 return;
553 }
554 break;
555 case VUT_ROADFLAG:
557 if (road_flag_id_is_valid(source->value.roadflag)) {
558 return;
559 }
560 break;
561 case VUT_EXTRAFLAG:
562 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
563 if (extra_flag_id_is_valid(source->value.extraflag)) {
564 return;
565 }
566 break;
567 case VUT_MINYEAR:
568 source->value.minyear = atoi(value);
569 return;
570 case VUT_MINCALFRAG:
571 /* Rule names are 0-based numbers, not pretty names from ruleset */
572 source->value.mincalfrag = atoi(value);
573 if (source->value.mincalfrag >= 0) {
574 /* More range checking done later, in sanity_check_req_individual() */
575 return;
576 }
577 break;
578 case VUT_TOPO:
579 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
580 if (topo_flag_is_valid(source->value.topo_property)) {
581 return;
582 }
583 break;
584 case VUT_WRAP:
585 source->value.wrap_property = wrap_flag_by_name(value, fc_strcasecmp);
586 if (wrap_flag_is_valid(source->value.wrap_property)) {
587 return;
588 }
589 break;
591 source->value.ssetval = ssetv_by_rule_name(value);
592 if (source->value.ssetval != SSETV_NONE) {
593 return;
594 }
595 break;
596 case VUT_TERRAINALTER:
597 source->value.terrainalter
599 if (terrain_alteration_is_valid(source->value.terrainalter)) {
600 return;
601 }
602 break;
603 case VUT_CITYTILE:
605 if (source->value.citytile != CITYT_LAST) {
606 return;
607 }
608 break;
609 case VUT_CITYSTATUS:
611 if (source->value.citystatus != CITYS_LAST) {
612 return;
613 }
614 break;
615 case VUT_PLAYER_STATE:
617 if (source->value.plrstate != PLRS_LAST) {
618 return;
619 }
620 break;
621 case VUT_MINLATITUDE:
622 case VUT_MAXLATITUDE:
623 source->value.latitude = atoi(value);
624 if (source->value.latitude >= -MAP_MAX_LATITUDE
625 && source->value.latitude <= MAP_MAX_LATITUDE) {
626 return;
627 }
628 break;
629 case VUT_COUNTER:
630 source->value.counter = counter_by_rule_name(value);
631 if (source->value.counter != nullptr) {
632 return;
633 }
634 break;
636 source->value.distance_sq = atoi(value);
637 if (0 <= source->value.distance_sq) {
638 return;
639 }
640 break;
642 source->value.region_tiles = atoi(value);
643 if (0 < source->value.region_tiles) {
644 return;
645 }
646 break;
647 case VUT_TILE_REL:
649 if (source->value.tilerel != TREL_COUNT) {
650 return;
651 }
652 break;
653 case VUT_COUNT:
654 break;
655 }
656
657 /* If we reach here there's been an error. */
659}
660
661/**********************************************************************/
668{
669 struct universal source;
670
671 source.kind = kind;
672
673 switch (source.kind) {
674 case VUT_NONE:
675 /* Avoid compiler warning about uninitialized source.value */
676 source.value.advance = nullptr;
677
678 return source;
679 case VUT_ADVANCE:
680 source.value.advance = advance_by_number(value);
681 if (source.value.advance != nullptr) {
682 return source;
683 }
684 break;
685 case VUT_TECHFLAG:
686 source.value.techflag = value;
687 return source;
688 case VUT_GOVERNMENT:
690 if (source.value.govern != nullptr) {
691 return source;
692 }
693 break;
694 case VUT_GOVFLAG:
695 source.value.govflag = value;
696 return source;
697 case VUT_ACHIEVEMENT:
699 if (source.value.achievement != nullptr) {
700 return source;
701 }
702 break;
703 case VUT_STYLE:
704 source.value.style = style_by_number(value);
705 if (source.value.style != nullptr) {
706 return source;
707 }
708 break;
709 case VUT_IMPROVEMENT:
710 case VUT_SITE:
711 source.value.building = improvement_by_number(value);
712 if (source.value.building != nullptr) {
713 return source;
714 }
715 break;
716 case VUT_IMPR_GENUS:
717 source.value.impr_genus = value;
718 return source;
719 case VUT_IMPR_FLAG:
720 source.value.impr_flag = value;
721 return source;
722 case VUT_PLAYER_FLAG:
723 source.value.plr_flag = value;
724 return source;
725 case VUT_EXTRA:
727 return source;
728 case VUT_GOOD:
729 source.value.good = goods_by_number(value);
730 return source;
731 case VUT_TERRAIN:
732 source.value.terrain = terrain_by_number(value);
733 if (source.value.terrain != nullptr) {
734 return source;
735 }
736 break;
737 case VUT_TERRFLAG:
738 source.value.terrainflag = value;
739 return source;
740 case VUT_NATION:
742 if (source.value.nation != nullptr) {
743 return source;
744 }
745 break;
746 case VUT_NATIONGROUP:
747 source.value.nationgroup = nation_group_by_number(value);
748 if (source.value.nationgroup != nullptr) {
749 return source;
750 }
751 break;
752 case VUT_DIPLREL:
753 case VUT_DIPLREL_TILE:
757 source.value.diplrel = value;
758 if (source.value.diplrel != diplrel_other_invalid()) {
759 return source;
760 }
761 break;
762 case VUT_NATIONALITY:
764 if (source.value.nationality != nullptr) {
765 return source;
766 }
767 break;
769 source.value.origowner = nation_by_number(value);
770 if (source.value.origowner != nullptr) {
771 return source;
772 }
773 break;
774 case VUT_UTYPE:
775 source.value.utype = utype_by_number(value);
776 if (source.value.utype != nullptr) {
777 return source;
778 }
779 break;
780 case VUT_UTFLAG:
781 source.value.unitflag = value;
782 return source;
783 case VUT_UCLASS:
785 if (source.value.uclass != nullptr) {
786 return source;
787 }
788 break;
789 case VUT_UCFLAG:
790 source.value.unitclassflag = value;
791 return source;
792 case VUT_MINVETERAN:
793 source.value.minveteran = value;
794 return source;
795 case VUT_UNITSTATE:
796 source.value.unit_state = value;
797 return source;
798 case VUT_ACTIVITY:
799 source.value.activity = value;
800 return source;
801 case VUT_MINMOVES:
802 source.value.minmoves = value;
803 return source;
804 case VUT_MINHP:
806 return source;
807 case VUT_AGE:
808 source.value.age = value;
809 return source;
810 case VUT_FORM_AGE:
811 source.value.form_age = value;
812 return source;
813 case VUT_MINTECHS:
814 source.value.min_techs = value;
815 return source;
816 case VUT_FUTURETECHS:
817 source.value.future_techs = value;
818 return source;
819 case VUT_MINCITIES:
820 source.value.min_cities = value;
821 return source;
822 case VUT_ACTION:
824 if (source.value.action != nullptr) {
825 return source;
826 }
827 break;
828 case VUT_OTYPE:
829 source.value.outputtype = value;
830 return source;
831 case VUT_SPECIALIST:
833 return source;
834 case VUT_MINSIZE:
835 source.value.minsize = value;
836 return source;
837 case VUT_MINCULTURE:
838 source.value.minculture = value;
839 return source;
841 source.value.minforeignpct = value;
842 return source;
843 case VUT_AI_LEVEL:
844 source.value.ai_level = value;
845 return source;
848 return source;
851 return source;
852 case VUT_TERRAINCLASS:
853 source.value.terrainclass = value;
854 return source;
855 case VUT_ROADFLAG:
856 source.value.roadflag = value;
857 return source;
858 case VUT_EXTRAFLAG:
859 source.value.extraflag = value;
860 return source;
861 case VUT_MINYEAR:
862 source.value.minyear = value;
863 return source;
864 case VUT_MINCALFRAG:
865 source.value.mincalfrag = value;
866 return source;
867 case VUT_TOPO:
868 source.value.topo_property = value;
869 return source;
870 case VUT_WRAP:
871 source.value.wrap_property = value;
872 return source;
874 source.value.ssetval = value;
875 return source;
876 case VUT_TERRAINALTER:
877 source.value.terrainalter = value;
878 return source;
879 case VUT_CITYTILE:
880 source.value.citytile = value;
881 return source;
882 case VUT_CITYSTATUS:
883 source.value.citystatus = value;
884 return source;
885 case VUT_PLAYER_STATE:
886 source.value.plrstate = value;
887 return source;
888 case VUT_COUNTER:
890 return source;
891 case VUT_MINLATITUDE:
892 case VUT_MAXLATITUDE:
893 source.value.latitude = value;
894 return source;
896 source.value.distance_sq = value;
897 return source;
899 source.value.region_tiles = value;
900 return source;
901 case VUT_TILE_REL:
902 source.value.tilerel = value;
903 return source;
904 case VUT_COUNT:
905 break;
906 }
907
908 /* If we reach here there's been an error. */
910 /* Avoid compiler warning about uninitialized source.value */
911 source.value.advance = nullptr;
912
913 return source;
914}
915
916/**********************************************************************/
919void universal_copy(struct universal *dst, const struct universal *src)
920{
921 dst->value = src->value;
922 dst->kind = src->kind;
923}
924
925/**********************************************************************/
930 int *kind, int *value)
931{
932 *kind = source->kind;
934}
935
936/**********************************************************************/
940{
941 switch (source->kind) {
942 case VUT_NONE:
943 return 0;
944 case VUT_ADVANCE:
945 return advance_number(source->value.advance);
946 case VUT_TECHFLAG:
947 return source->value.techflag;
948 case VUT_GOVERNMENT:
949 return government_number(source->value.govern);
950 case VUT_GOVFLAG:
951 return source->value.govflag;
952 case VUT_ACHIEVEMENT:
953 return achievement_number(source->value.achievement);
954 case VUT_STYLE:
955 return style_number(source->value.style);
956 case VUT_IMPROVEMENT:
957 case VUT_SITE:
958 return improvement_number(source->value.building);
959 case VUT_IMPR_GENUS:
960 return source->value.impr_genus;
961 case VUT_IMPR_FLAG:
962 return source->value.impr_flag;
963 case VUT_PLAYER_FLAG:
964 return source->value.plr_flag;
965 case VUT_EXTRA:
966 return extra_number(source->value.extra);
967 case VUT_GOOD:
968 return goods_number(source->value.good);
969 case VUT_TERRAIN:
970 return terrain_number(source->value.terrain);
971 case VUT_TERRFLAG:
972 return source->value.terrainflag;
973 case VUT_NATION:
974 return nation_number(source->value.nation);
975 case VUT_NATIONGROUP:
976 return nation_group_number(source->value.nationgroup);
977 case VUT_NATIONALITY:
978 return nation_number(source->value.nationality);
980 return nation_number(source->value.origowner);
981 case VUT_DIPLREL:
982 case VUT_DIPLREL_TILE:
986 return source->value.diplrel;
987 case VUT_UTYPE:
988 return utype_number(source->value.utype);
989 case VUT_UTFLAG:
990 return source->value.unitflag;
991 case VUT_UCLASS:
992 return uclass_number(source->value.uclass);
993 case VUT_UCFLAG:
994 return source->value.unitclassflag;
995 case VUT_MINVETERAN:
996 return source->value.minveteran;
997 case VUT_UNITSTATE:
998 return source->value.unit_state;
999 case VUT_ACTIVITY:
1000 return source->value.activity;
1001 case VUT_MINMOVES:
1002 return source->value.minmoves;
1003 case VUT_MINHP:
1004 return source->value.min_hit_points;
1005 case VUT_AGE:
1006 return source->value.age;
1007 case VUT_FORM_AGE:
1008 return source->value.form_age;
1009 case VUT_MINTECHS:
1010 return source->value.min_techs;
1011 case VUT_FUTURETECHS:
1012 return source->value.future_techs;
1013 case VUT_MINCITIES:
1014 return source->value.min_cities;
1015 case VUT_ACTION:
1016 return action_number(source->value.action);
1017 case VUT_OTYPE:
1018 return source->value.outputtype;
1019 case VUT_SPECIALIST:
1020 return specialist_number(source->value.specialist);
1021 case VUT_MINSIZE:
1022 return source->value.minsize;
1023 case VUT_MINCULTURE:
1024 return source->value.minculture;
1025 case VUT_MINFOREIGNPCT:
1026 return source->value.minforeignpct;
1027 case VUT_AI_LEVEL:
1028 return source->value.ai_level;
1030 return source->value.max_tile_total_units;
1032 return source->value.max_tile_top_units;
1033 case VUT_TERRAINCLASS:
1034 return source->value.terrainclass;
1035 case VUT_ROADFLAG:
1036 return source->value.roadflag;
1037 case VUT_EXTRAFLAG:
1038 return source->value.extraflag;
1039 case VUT_MINYEAR:
1040 return source->value.minyear;
1041 case VUT_MINCALFRAG:
1042 return source->value.mincalfrag;
1043 case VUT_TOPO:
1044 return source->value.topo_property;
1045 case VUT_WRAP:
1046 return source->value.wrap_property;
1047 case VUT_SERVERSETTING:
1048 return source->value.ssetval;
1049 case VUT_TERRAINALTER:
1050 return source->value.terrainalter;
1051 case VUT_CITYTILE:
1052 return source->value.citytile;
1053 case VUT_CITYSTATUS:
1054 return source->value.citystatus;
1055 case VUT_PLAYER_STATE:
1056 return source->value.plrstate;
1057 case VUT_COUNTER:
1058 return counter_id(source->value.counter);
1059 case VUT_MINLATITUDE:
1060 case VUT_MAXLATITUDE:
1061 return source->value.latitude;
1063 return source->value.distance_sq;
1065 return source->value.region_tiles;
1066 case VUT_TILE_REL:
1067 return source->value.tilerel;
1068 case VUT_COUNT:
1069 break;
1070 }
1071
1072 /* If we reach here there's been an error. */
1073 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
1074 source->kind);
1075 return 0;
1076}
1077
1078
1079/**********************************************************************/
1083{
1084 static const struct req_context empty = {};
1085 return &empty;
1086}
1087
1088
1089/**********************************************************************/
1097const char *req_to_fstring(const struct requirement *req,
1098 struct astring *astr)
1099{
1100 astr_init(astr);
1101
1102 astr_set(astr, "%s%s %s %s%s",
1103 req->survives ? "surviving " : "",
1104 req_range_name(req->range),
1106 req->present ? "" : "!",
1108
1109 return astr_str(astr);
1110}
1111
1112/**********************************************************************/
1120 bool survives, bool present, bool quiet,
1121 const char *value)
1122{
1123 struct requirement req;
1124 bool invalid;
1125 const char *error = nullptr;
1126
1127 req.source = universal_by_rule_name(type, value);
1128
1130 if (invalid) {
1131 error = "bad type or name";
1132 } else {
1133 /* Scan the range string to find the range. If no range is given a
1134 * default fallback is used rather than giving an error. */
1135 if (range != nullptr) {
1137 if (!req_range_is_valid(req.range)) {
1138 invalid = TRUE;
1139 }
1140 } else {
1141 switch (req.source.kind) {
1142 case VUT_NONE:
1143 case VUT_COUNT:
1144 break;
1145 case VUT_IMPROVEMENT:
1146 case VUT_SITE:
1147 case VUT_IMPR_GENUS:
1148 case VUT_IMPR_FLAG:
1149 case VUT_UTYPE:
1150 case VUT_UTFLAG:
1151 case VUT_UCLASS:
1152 case VUT_UCFLAG:
1153 case VUT_MINVETERAN:
1154 case VUT_UNITSTATE:
1155 case VUT_ACTIVITY:
1156 case VUT_MINMOVES:
1157 case VUT_MINHP:
1158 case VUT_AGE:
1159 case VUT_FORM_AGE:
1160 case VUT_ACTION:
1161 case VUT_OTYPE:
1162 case VUT_SPECIALIST:
1163 case VUT_DIPLREL_TILE_O:
1165 req.range = REQ_RANGE_LOCAL;
1166 break;
1167 case VUT_EXTRA:
1168 case VUT_ROADFLAG:
1169 case VUT_EXTRAFLAG:
1170 /* Keep old behavior */
1171 req.range = REQ_RANGE_TILE;
1172 break;
1173 case VUT_TERRAIN:
1174 case VUT_TERRFLAG:
1175 case VUT_TERRAINCLASS:
1176 case VUT_TERRAINALTER:
1177 case VUT_CITYTILE:
1180 case VUT_MINLATITUDE:
1181 case VUT_MAXLATITUDE:
1183 req.range = REQ_RANGE_TILE;
1184 break;
1185 case VUT_COUNTER:
1186 case VUT_MINSIZE:
1187 case VUT_MINCULTURE:
1188 case VUT_MINFOREIGNPCT:
1189 case VUT_NATIONALITY:
1190 case VUT_ORIGINAL_OWNER:
1191 case VUT_CITYSTATUS:
1192 case VUT_GOOD:
1193 req.range = REQ_RANGE_CITY;
1194 break;
1195 case VUT_GOVERNMENT:
1196 case VUT_GOVFLAG:
1197 case VUT_ACHIEVEMENT:
1198 case VUT_STYLE:
1199 case VUT_ADVANCE:
1200 case VUT_TECHFLAG:
1201 case VUT_NATION:
1202 case VUT_NATIONGROUP:
1203 case VUT_DIPLREL:
1204 case VUT_DIPLREL_TILE:
1206 case VUT_AI_LEVEL:
1207 case VUT_PLAYER_FLAG:
1208 case VUT_PLAYER_STATE:
1209 case VUT_MINCITIES:
1210 case VUT_FUTURETECHS:
1211 req.range = REQ_RANGE_PLAYER;
1212 break;
1213 case VUT_MINYEAR:
1214 case VUT_MINCALFRAG:
1215 case VUT_TOPO:
1216 case VUT_WRAP:
1217 case VUT_MINTECHS:
1218 case VUT_SERVERSETTING:
1219 req.range = REQ_RANGE_WORLD;
1220 break;
1223 break;
1224 case VUT_TILE_REL:
1225 req.range = REQ_RANGE_TILE;
1227 /* Not available at Tile range */
1229 }
1230 break;
1231 }
1232 }
1233
1234 req.survives = survives;
1235 req.present = present;
1236 req.quiet = quiet;
1237
1238 /* These checks match what combinations are supported inside
1239 * is_req_active(). However, it's only possible to do basic checks,
1240 * not anything that might depend on the rest of the ruleset which
1241 * might not have been loaded yet. */
1242 switch (req.source.kind) {
1243 case VUT_TERRAIN:
1244 case VUT_TERRAINCLASS:
1245 case VUT_TERRFLAG:
1246 invalid = (req.range != REQ_RANGE_TILE
1247 && req.range != REQ_RANGE_CADJACENT
1248 && req.range != REQ_RANGE_ADJACENT
1249 && req.range != REQ_RANGE_CITY
1250 && req.range != REQ_RANGE_TRADE_ROUTE);
1251 break;
1252 case VUT_EXTRA:
1253 case VUT_ROADFLAG:
1254 case VUT_EXTRAFLAG:
1256 break;
1257 case VUT_ACHIEVEMENT:
1258 case VUT_MINTECHS:
1259 case VUT_FUTURETECHS:
1260 invalid = (req.range < REQ_RANGE_PLAYER);
1261 break;
1262 case VUT_ADVANCE:
1263 case VUT_TECHFLAG:
1265 && req.range != REQ_RANGE_LOCAL);
1266 break;
1267 case VUT_GOVERNMENT:
1268 case VUT_GOVFLAG:
1269 case VUT_AI_LEVEL:
1270 case VUT_STYLE:
1271 case VUT_MINCITIES:
1272 invalid = (req.range != REQ_RANGE_PLAYER);
1273 break;
1274 case VUT_MINSIZE:
1275 case VUT_MINFOREIGNPCT:
1276 case VUT_NATIONALITY:
1277 case VUT_CITYSTATUS:
1278 invalid = (req.range != REQ_RANGE_CITY
1279 && req.range != REQ_RANGE_TRADE_ROUTE);
1280 break;
1281 case VUT_GOOD:
1282 case VUT_ORIGINAL_OWNER:
1283 invalid = (req.range != REQ_RANGE_CITY);
1284 break;
1285 case VUT_MINCULTURE:
1286 invalid = (req.range != REQ_RANGE_CITY
1288 && req.range != REQ_RANGE_PLAYER
1289 && req.range != REQ_RANGE_TEAM
1290 && req.range != REQ_RANGE_ALLIANCE
1291 && req.range != REQ_RANGE_WORLD);
1292 break;
1293 case VUT_DIPLREL:
1294 invalid = (req.range != REQ_RANGE_LOCAL
1295 && req.range != REQ_RANGE_PLAYER
1296 && req.range != REQ_RANGE_TEAM
1297 && req.range != REQ_RANGE_ALLIANCE
1298 && req.range != REQ_RANGE_WORLD)
1299 /* Non local foreign makes no sense. */
1300 || (req.source.value.diplrel == DRO_FOREIGN
1301 && req.range != REQ_RANGE_LOCAL);
1302 break;
1303 case VUT_DIPLREL_TILE:
1304 invalid = (req.range != REQ_RANGE_LOCAL
1305 && req.range != REQ_RANGE_PLAYER
1306 && req.range != REQ_RANGE_TEAM
1307 && req.range != REQ_RANGE_ALLIANCE)
1308 /* Non local foreign makes no sense. */
1309 || (req.source.value.diplrel == DRO_FOREIGN
1310 && req.range != REQ_RANGE_LOCAL);
1311 break;
1312 case VUT_DIPLREL_TILE_O:
1313 invalid = (req.range != REQ_RANGE_LOCAL);
1314 break;
1316 invalid = (req.range != REQ_RANGE_LOCAL
1317 && req.range != REQ_RANGE_PLAYER
1318 && req.range != REQ_RANGE_TEAM
1319 && req.range != REQ_RANGE_ALLIANCE)
1320 /* Non local foreign makes no sense. */
1321 || (req.source.value.diplrel == DRO_FOREIGN
1322 && req.range != REQ_RANGE_LOCAL);
1323 break;
1325 invalid = (req.range != REQ_RANGE_LOCAL);
1326 break;
1327 case VUT_NATION:
1328 case VUT_NATIONGROUP:
1330 && req.range != REQ_RANGE_TEAM
1331 && req.range != REQ_RANGE_ALLIANCE
1332 && req.range != REQ_RANGE_WORLD);
1333 break;
1334 case VUT_MINVETERAN:
1335 case VUT_UNITSTATE:
1336 case VUT_ACTIVITY:
1337 case VUT_MINMOVES:
1338 case VUT_MINHP:
1339 case VUT_ACTION:
1340 case VUT_OTYPE:
1341 case VUT_SPECIALIST:
1342 invalid = (req.range != REQ_RANGE_LOCAL);
1343 break;
1344 case VUT_UTYPE:
1345 case VUT_UTFLAG:
1346 case VUT_UCLASS:
1347 case VUT_UCFLAG:
1348 invalid = (req.range != REQ_RANGE_LOCAL
1349 && req.range != REQ_RANGE_TILE
1350 && req.range != REQ_RANGE_CADJACENT
1351 && req.range != REQ_RANGE_ADJACENT);
1352 break;
1353 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1355 invalid = (req.range != REQ_RANGE_TILE);
1356 break;
1357 case VUT_CITYTILE:
1360 invalid = (req.range != REQ_RANGE_TILE
1361 && req.range != REQ_RANGE_CADJACENT
1362 && req.range != REQ_RANGE_ADJACENT);
1363 break;
1364 case VUT_MINLATITUDE:
1365 case VUT_MAXLATITUDE:
1366 invalid = (req.range != REQ_RANGE_TILE
1367 && req.range != REQ_RANGE_CADJACENT
1368 && req.range != REQ_RANGE_ADJACENT
1369 && req.range != REQ_RANGE_WORLD)
1370 /* Avoid redundancy at tile range: no negated requirements
1371 * that could be emulated by a present requirement of the
1372 * other type */
1373 || (req.range == REQ_RANGE_TILE && !req.present);
1374 break;
1375 case VUT_MINYEAR:
1376 case VUT_MINCALFRAG:
1377 case VUT_TOPO:
1378 case VUT_WRAP:
1379 case VUT_SERVERSETTING:
1380 invalid = (req.range != REQ_RANGE_WORLD);
1381 break;
1382 case VUT_AGE:
1383 /* FIXME: Could support TRADE_ROUTE, TEAM, etc */
1384 invalid = (req.range != REQ_RANGE_LOCAL
1385 && req.range != REQ_RANGE_CITY
1386 && req.range != REQ_RANGE_PLAYER);
1387 break;
1388 case VUT_FORM_AGE:
1389 invalid = (req.range != REQ_RANGE_LOCAL);
1390 break;
1391 case VUT_IMPR_GENUS:
1392 /* TODO: Support other ranges too. */
1393 invalid = (req.range != REQ_RANGE_LOCAL);
1394 break;
1395 case VUT_IMPR_FLAG:
1396 invalid = (req.range != REQ_RANGE_LOCAL
1397 && req.range != REQ_RANGE_TILE
1398 && req.range != REQ_RANGE_CITY);
1399 break;
1400 case VUT_COUNTER:
1401 invalid = req.range != REQ_RANGE_CITY;
1402 break;
1403 case VUT_PLAYER_FLAG:
1404 case VUT_PLAYER_STATE:
1405 invalid = (req.range != REQ_RANGE_PLAYER);
1406 break;
1409 && req.range != REQ_RANGE_CADJACENT
1410 && req.range != REQ_RANGE_ADJACENT);
1411 break;
1412 case VUT_TILE_REL:
1414 && req.range != REQ_RANGE_CADJACENT
1415 && req.range != REQ_RANGE_TILE)
1416 /* TREL_ONLY_OTHER_REGION not supported at Tile range */
1418 && req.range == REQ_RANGE_TILE);
1419 break;
1420 case VUT_IMPROVEMENT:
1421 case VUT_SITE:
1422 /* Valid ranges depend on the building genus (wonder/improvement),
1423 * which might not have been loaded from the ruleset yet.
1424 * So we allow anything here, and do a proper check once ruleset
1425 * loading is complete, in sanity_check_req_individual(). */
1426 case VUT_NONE:
1427 invalid = FALSE;
1428 break;
1429 case VUT_COUNT:
1430 break;
1431 }
1432 if (invalid) {
1433 error = "bad range";
1434 }
1435 }
1436
1437 if (!invalid) {
1438 /* Check 'survives'. */
1439 switch (req.source.kind) {
1440 case VUT_IMPROVEMENT:
1441 case VUT_SITE:
1442 /* See buildings_in_range(). */
1444 break;
1445 case VUT_NATION:
1446 case VUT_ADVANCE:
1448 break;
1449 case VUT_COUNTER:
1450 case VUT_IMPR_GENUS:
1451 case VUT_IMPR_FLAG:
1452 case VUT_PLAYER_FLAG:
1453 case VUT_PLAYER_STATE:
1454 case VUT_GOVERNMENT:
1455 case VUT_GOVFLAG:
1456 case VUT_TERRAIN:
1457 case VUT_UTYPE:
1458 case VUT_UTFLAG:
1459 case VUT_UCLASS:
1460 case VUT_UCFLAG:
1461 case VUT_MINVETERAN:
1462 case VUT_UNITSTATE:
1463 case VUT_ACTIVITY:
1464 case VUT_MINMOVES:
1465 case VUT_MINHP:
1466 case VUT_AGE:
1467 case VUT_FORM_AGE:
1468 case VUT_ACTION:
1469 case VUT_OTYPE:
1470 case VUT_SPECIALIST:
1471 case VUT_MINSIZE:
1472 case VUT_MINCULTURE:
1473 case VUT_MINFOREIGNPCT:
1474 case VUT_AI_LEVEL:
1475 case VUT_TERRAINCLASS:
1476 case VUT_MINYEAR:
1477 case VUT_MINCALFRAG:
1478 case VUT_TOPO:
1479 case VUT_WRAP:
1480 case VUT_SERVERSETTING:
1481 case VUT_TERRAINALTER:
1482 case VUT_CITYTILE:
1483 case VUT_CITYSTATUS:
1484 case VUT_TERRFLAG:
1485 case VUT_NATIONALITY:
1486 case VUT_ORIGINAL_OWNER:
1487 case VUT_ROADFLAG:
1488 case VUT_EXTRAFLAG:
1489 case VUT_EXTRA:
1490 case VUT_GOOD:
1491 case VUT_TECHFLAG:
1492 case VUT_ACHIEVEMENT:
1493 case VUT_NATIONGROUP:
1494 case VUT_STYLE:
1495 case VUT_DIPLREL:
1496 case VUT_DIPLREL_TILE:
1497 case VUT_DIPLREL_TILE_O:
1502 case VUT_MINTECHS:
1503 case VUT_FUTURETECHS:
1504 case VUT_MINCITIES:
1505 case VUT_MINLATITUDE:
1506 case VUT_MAXLATITUDE:
1509 case VUT_TILE_REL:
1510 /* Most requirements don't support 'survives'. */
1511 invalid = survives;
1512 break;
1513 case VUT_NONE:
1514 case VUT_COUNT:
1515 break;
1516 }
1517 if (invalid) {
1518 error = "bad 'survives'";
1519 }
1520 }
1521
1522 if (invalid) {
1523 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1524 type, range, survives ? "survives" : "",
1525 present ? "present" : "", value, error);
1527 }
1528
1529 return req;
1530}
1531
1532/**********************************************************************/
1538 int value)
1539{
1540 struct requirement req;
1541
1542 req.source = universal_by_number(type, value);
1543 req.range = range;
1544 req.survives = survives;
1545 req.present = present;
1546 req.quiet = quiet;
1547
1548 return req;
1549}
1550
1551/**********************************************************************/
1555void req_get_values(const struct requirement *req,
1556 int *type, int *range,
1557 bool *survives, bool *present, bool *quiet,
1558 int *value)
1559{
1560 universal_extraction(&req->source, type, value);
1561 *range = req->range;
1562 *survives = req->survives;
1563 *present = req->present;
1564 *quiet = req->quiet;
1565}
1566
1567/**********************************************************************/
1570void req_copy(struct requirement *dst, const struct requirement *src)
1571{
1572 universal_copy(&(dst->source), &(src->source));
1573 dst->range = src->range;
1574 dst->survives = src->survives;
1575 dst->present = src->present;
1576 dst->quiet = src->quiet;
1577}
1578
1579/**********************************************************************/
1583bool are_requirements_equal(const struct requirement *req1,
1584 const struct requirement *req2)
1585{
1586 return (are_universals_equal(&req1->source, &req2->source)
1587 && req1->range == req2->range
1588 && req1->survives == req2->survives
1589 && req1->present == req2->present);
1590}
1591
1592/**********************************************************************/
1595static bool are_requirements_opposites(const struct requirement *req1,
1596 const struct requirement *req2)
1597{
1598 return (are_universals_equal(&req1->source, &req2->source)
1599 && req1->range == req2->range
1600 && req1->survives == req2->survives
1601 && req1->present != req2->present);
1602}
1603
1604/**********************************************************************/
1608static bool impr_contra_genus(const struct requirement *impr_req,
1609 const struct requirement *genus_req)
1610{
1611 /* The input is sane. */
1613 || impr_req->source.kind == VUT_SITE, FALSE);
1615
1616 if (impr_req->range == REQ_RANGE_LOCAL
1617 && genus_req->range == REQ_RANGE_LOCAL) {
1618 /* Applies to the same target building. */
1619
1620 if (impr_req->present && !genus_req->present) {
1621 /* The target building can't not have the genus it has. */
1622 return (impr_req->source.value.building->genus
1623 == genus_req->source.value.impr_genus);
1624 }
1625
1626 if (impr_req->present && genus_req->present) {
1627 /* The target building can't have another genus than it has. */
1628 return (impr_req->source.value.building->genus
1629 != genus_req->source.value.impr_genus);
1630 }
1631 }
1632
1633 /* No special knowledge. */
1634 return FALSE;
1635}
1636
1637/**********************************************************************/
1641static bool impr_contra_flag(const struct requirement *impr_req,
1642 const struct requirement *flag_req)
1643{
1644 /* The input is sane. */
1646 || impr_req->source.kind == VUT_SITE, FALSE);
1648
1649 if (impr_req->range == REQ_RANGE_LOCAL
1650 && flag_req->range == REQ_RANGE_LOCAL) {
1651 /* Applies to the same target building. */
1652
1653 if (impr_req->present && !flag_req->present) {
1654 /* The target building can't not have the flag it has. */
1655 return improvement_has_flag(impr_req->source.value.building,
1656 flag_req->source.value.impr_flag);
1657 }
1658
1659 if (impr_req->present && flag_req->present) {
1660 /* The target building can't have another flag than it has. */
1661 return !improvement_has_flag(impr_req->source.value.building,
1662 flag_req->source.value.impr_flag);
1663 }
1664 }
1665
1666 /* No special knowledge. */
1667 return FALSE;
1668}
1669
1670/**********************************************************************/
1675 const struct requirement *group_req)
1676{
1677 /* The input is sane. */
1678 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1680
1681 if (nation_req->range == REQ_RANGE_PLAYER
1682 && group_req->range == REQ_RANGE_PLAYER) {
1683 /* Applies to the same target building. */
1684
1685 if (nation_req->present && !group_req->present) {
1686 /* The target nation can't be in the group. */
1687 return nation_is_in_group(nation_req->source.value.nation,
1688 group_req->source.value.nationgroup);
1689 }
1690 }
1691
1692 /* No special knowledge. */
1693 return FALSE;
1694}
1695
1696/**********************************************************************/
1700static bool city_center_contra(const struct requirement *cc_req,
1701 const struct requirement *ct_req)
1702{
1703 /* The input is sane. */
1704 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1705 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1706
1707 if (cc_req->source.value.citytile == CITYT_CENTER
1708 && cc_req->present && cc_req->range <= ct_req->range) {
1709 switch (ct_req->source.value.citytile) {
1710 case CITYT_CENTER:
1711 case CITYT_CLAIMED:
1712 case CITYT_EXTRAS_OWNED:
1713 case CITYT_WORKED:
1715 /* Should be always on city center */
1716 return !ct_req->present;
1718 /* Handled later */
1719 break;
1720 case CITYT_LAST:
1721 /* Error */
1722 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1723 }
1724 }
1725 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1726 || cc_req->source.value.citytile == CITYT_CENTER)
1727 && ct_req->source.value.citytile
1729 && REQ_RANGE_TILE == cc_req->range
1730 && REQ_RANGE_TILE == ct_req->range) {
1731 /* Can't coexist */
1732 return cc_req->present ? ct_req->present : !ct_req->present;
1733 }
1734
1735 return FALSE;
1736}
1737
1738/**********************************************************************/
1743static bool present_implies_not_present(const struct requirement *req1,
1744 const struct requirement *req2)
1745{
1746 const struct requirement *absent, *present;
1747
1748 if (req1->present == req2->present) {
1749 /* Can't use the knowledge in universal_found_function when both are
1750 * required to be absent or when both are required to be present.
1751 * It is no contradiction to require !Spy unit and !Missile unit class.
1752 * It is no contradiction to require River and Irrigation at the same
1753 * tile. */
1754 return FALSE;
1755 }
1756
1757 if (req1->present) {
1758 absent = req2;
1759 present = req1;
1760 } else {
1761 absent = req1;
1762 present = req2;
1763 }
1764
1765 if (!universal_found_function[present->source.kind]) {
1766 /* No knowledge to exploit. */
1767 return FALSE;
1768 }
1769
1770 if (present->range != absent->range) {
1771 /* Larger ranges are not always strict supersets of smaller ranges.
1772 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1773 * but not in Trade Route. */
1774 return FALSE;
1775 }
1776
1778 &present->source);
1779}
1780
1781/**********************************************************************/
1784bool req_implies_req(const struct requirement *req1,
1785 const struct requirement *req2)
1786{
1787 struct requirement nreq2;
1788
1789 req_copy(&nreq2, req2);
1790 nreq2.present = !nreq2.present;
1792}
1793
1794/**********************************************************************/
1799static inline bool are_bounds_contradictions(int bound1, bool is_upper1,
1800 int bound2, bool is_upper2)
1801{
1802 /* If the bounds are on opposite sides, and one is inclusive, the other
1803 * exclusive, the number of values that satisfy both bounds is exactly
1804 * their difference, (upper bound) - (lower bound).
1805 * The bounds contradict each other iff this difference is 0 or less,
1806 * i.e. iff (upper bound) <= (lower bound) */
1807 if (is_upper1 && !is_upper2) {
1808 return bound1 <= bound2;
1809 } else if (!is_upper1 && is_upper2) {
1810 return bound1 >= bound2;
1811 }
1812 /* Both are upper or both are lower ~> no contradiction possible */
1813 return FALSE;
1814}
1815
1816/**********************************************************************/
1824 const struct requirement *req2)
1825{
1826 if (are_requirements_opposites(req1, req2)) {
1827 /* The exact opposite. */
1828 return TRUE;
1829 }
1830
1831 if (present_implies_not_present(req1, req2)) {
1832 return TRUE;
1833 }
1834
1835 switch (req1->source.kind) {
1836 case VUT_IMPROVEMENT:
1837 case VUT_SITE:
1838 if (req2->source.kind == VUT_IMPR_GENUS) {
1839 return impr_contra_genus(req1, req2);
1840 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1841 return impr_contra_flag(req1, req2);
1842 } else if (req2->source.kind == VUT_CITYTILE
1843 && req2->source.value.citytile == CITYT_CENTER
1844 && REQ_RANGE_TILE == req2->range
1845 && REQ_RANGE_TILE == req1->range
1846 && req1->present) {
1847 /* A building must be in a city */
1848 return !req2->present;
1849 }
1850
1851 /* No special knowledge. */
1852 return FALSE;
1853 case VUT_IMPR_GENUS:
1854 if (req2->source.kind == VUT_IMPROVEMENT
1855 || req2->source.kind == VUT_SITE) {
1856 return impr_contra_genus(req2, req1);
1857 }
1858
1859 /* No special knowledge. */
1860 return FALSE;
1861 case VUT_IMPR_FLAG:
1862 if (req2->source.kind == VUT_IMPROVEMENT
1863 || req2->source.kind == VUT_SITE) {
1864 return impr_contra_flag(req2, req1);
1865 }
1866
1867 /* No special knowledge. */
1868 return FALSE;
1869 case VUT_DIPLREL:
1870 case VUT_DIPLREL_TILE:
1871 case VUT_DIPLREL_TILE_O:
1874 if (req2->source.kind != req1->source.kind) {
1875 /* Finding contradictions across requirement kinds aren't supported
1876 * for DiplRel requirements. */
1877 return FALSE;
1878 } else {
1879 /* Use the special knowledge about DiplRel requirements to find
1880 * contradictions. */
1881
1883 int req2_pos;
1884
1887 req2->range,
1888 req2->present);
1889
1890 return BV_ISSET(req1_contra, req2_pos);
1891 }
1892 break;
1893 case VUT_MINMOVES:
1894 if (req2->source.kind != VUT_MINMOVES) {
1895 /* Finding contradictions across requirement kinds aren't supported
1896 * for MinMoveFrags requirements. */
1897 return FALSE;
1898 }
1900 req1->source.value.minmoves, !req1->present,
1901 req2->source.value.minmoves, !req2->present);
1902 case VUT_MINLATITUDE:
1903 case VUT_MAXLATITUDE:
1904 if (req2->source.kind != VUT_MINLATITUDE
1905 && req2->source.kind != VUT_MAXLATITUDE) {
1906 /* Finding contradictions across requirement kinds other than each
1907 * other is not supported for MinLatitude and MaxLatitude. */
1908 return FALSE;
1909 } else {
1910 /* For a contradiction, we need
1911 * - a minimum (present MinLatitude or negated MaxLatitude)
1912 * - a maximum (negated MinLatitude or present MaxLatitude)
1913 * - the maximum to be less than the minimum
1914 * - a requirement at the larger range that applies to the entire
1915 * range (i.e. a negated requirement, unless the range is Tile)
1916 * Otherwise, the two requirements could still be fulfilled
1917 * simultaneously by different tiles in the range */
1918
1919 /* Initial values beyond the boundaries to avoid edge cases */
1920 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
1922
1923#define EXTRACT_INFO(req) \
1924 if (req->present) { \
1925 if (req->source.kind == VUT_MINLATITUDE) { \
1926 /* present MinLatitude */ \
1927 minimum = MAX(minimum, req->source.value.latitude); \
1928 } else { \
1929 /* present MaxLatitude */ \
1930 maximum = MIN(maximum, req->source.value.latitude); \
1931 } \
1932 } else { \
1933 covered_range = MAX(covered_range, req->range); \
1934 if (req->source.kind == VUT_MINLATITUDE) { \
1935 /* negated MinLatitude */ \
1936 maximum = MIN(maximum, req->source.value.latitude - 1); \
1937 } else { \
1938 /* negated MaxLatitude */ \
1939 minimum = MAX(minimum, req->source.value.latitude + 1); \
1940 } \
1941 }
1942
1943 EXTRACT_INFO(req1);
1944 EXTRACT_INFO(req2);
1945
1946#undef EXTRACT_INFO
1947
1948 return (maximum < minimum
1949 && covered_range >= req1->range
1950 && covered_range >= req2->range);
1951 }
1952 break;
1953 case VUT_NATION:
1954 if (req2->source.kind == VUT_NATIONGROUP) {
1955 return nation_contra_group(req1, req2);
1956 }
1957
1958 /* No special knowledge. */
1959 return FALSE;
1960 break;
1961 case VUT_NATIONGROUP:
1962 if (req2->source.kind == VUT_NATION) {
1963 return nation_contra_group(req2, req1);
1964 }
1965
1966 /* No special knowledge. */
1967 return FALSE;
1968 break;
1969 case VUT_CITYTILE:
1970 if (req2->source.kind == VUT_CITYTILE) {
1971 return city_center_contra(req1, req2)
1972 || city_center_contra(req2, req1);
1973 } else if (req1->source.value.citytile == CITYT_CENTER
1974 && (req2->source.kind == VUT_IMPROVEMENT
1975 || req2->source.kind == VUT_SITE)
1976 && REQ_RANGE_TILE == req2->range
1977 && REQ_RANGE_TILE == req1->range
1978 && req2->present) {
1979 /* A building must be in a city */
1980 return !req1->present;
1981 }
1982
1983 return FALSE;
1985 if (req2->source.kind != VUT_MAX_DISTANCE_SQ) {
1986 /* Finding contradictions across requirement kinds isn't supported
1987 * for MaxDistanceSq requirements. */
1988 return FALSE;
1989 }
1991 req1->source.value.distance_sq, req1->present,
1992 req2->source.value.distance_sq, req2->present);
1994 if (req2->source.kind != VUT_MAX_REGION_TILES) {
1995 /* Finding contradictions across requirement kinds isn't supported
1996 * for MaxRegionTiles requirements. */
1997 return FALSE;
1998 } else if (req1->range != req2->range) {
1999 /* FIXME: Finding contradictions across ranges not yet supported.
2000 * In particular, a max at a small range and a min at a larger range
2001 * needs extra work to figure out. */
2002 return FALSE;
2003 }
2005 req1->source.value.region_tiles, req1->present,
2006 req2->source.value.region_tiles, req2->present);
2007 case VUT_TILE_REL:
2008 if (req2->source.kind != VUT_TILE_REL) {
2009 /* Finding contradictions across requirement kinds isn't supported
2010 * for TileRel requirements. */
2011 return FALSE;
2012 }
2013 if (req1->source.value.tilerel == req2->source.value.tilerel) {
2014 /* Same requirement at different ranges. Note that same range is
2015 * already covered by are_requirements_opposites() above. */
2016 switch (req1->source.value.tilerel) {
2017 case TREL_SAME_TCLASS:
2018 case TREL_SAME_REGION:
2020 /* Negated req at larger range contradicts present req at
2021 * smaller range. */
2022 if (req1->range > req2->range) {
2023 return !req1->present && req2->present;
2024 } else {
2025 return req1->present && !req2->present;
2026 }
2027 break;
2029 /* Present req at larger range contradicts negated req at
2030 * smaller range */
2031 if (req1->range > req2->range) {
2032 return req1->present && !req2->present;
2033 } else {
2034 return !req1->present && req2->present;
2035 }
2036 break;
2037 default:
2038 return FALSE;
2039 }
2040 }
2042 && req2->source.value.tilerel == TREL_SAME_REGION) {
2043 /* Same region at any range implies same terrain class at that range
2044 * and any larger range ~> contradicts negated */
2045 return (!req1->present && req2->present
2046 && (req1->range >= req2->range));
2047 } else if (req2->source.value.tilerel == TREL_SAME_TCLASS
2048 && req1->source.value.tilerel == TREL_SAME_REGION) {
2049 /* Same as above */
2050 return (req1->present && !req2->present
2051 && (req1->range <= req2->range));
2052 } else if (req1->source.value.tilerel == TREL_REGION_SURROUNDED
2054 const struct requirement *surr, *other;
2056 surr = req1;
2057 other = req2;
2058 } else {
2059 surr = req2;
2060 other = req1;
2061 }
2062 if (surr->present && surr->range == REQ_RANGE_TILE) {
2063 /* Target tile must be part of a surrounded region
2064 * ~> not the same terrain class
2065 * ~> not the same region
2066 * ~> not touched by a third region */
2067 switch (other->source.value.tilerel) {
2068 case TREL_SAME_TCLASS:
2069 case TREL_SAME_REGION:
2070 return (other->present && other->range == REQ_RANGE_TILE);
2072 return (!other->present);
2073 default:
2074 break;
2075 }
2076 }
2077 }
2078 /* No further contradictions we can detect */
2079 return FALSE;
2080 default:
2081 /* No special knowledge exists. The requirements aren't the exact
2082 * opposite of each other per the initial check. */
2083 return FALSE;
2084 }
2085}
2086
2087/**********************************************************************/
2095struct requirement *
2097 const struct requirement_vector *vec)
2098{
2099 /* If the requirement is contradicted by any requirement in the vector it
2100 * contradicts the entire requirement vector. */
2103 return preq;
2104 }
2106
2107 /* Not a single requirement in the requirement vector is contradicted to be
2108 * the specified requirement. */
2109 return nullptr;
2110}
2111
2112/**********************************************************************/
2117 const struct requirement_vector *vec)
2118{
2119 return req_vec_first_contradiction_in_vec(req, vec) != nullptr;
2120}
2121
2122/**********************************************************************/
2125static inline bool are_tiles_in_range(const struct tile *tile1,
2126 const struct tile *tile2,
2127 enum req_range range)
2128{
2129 switch (range) {
2130 case REQ_RANGE_ADJACENT:
2132 return TRUE;
2133 }
2135 case REQ_RANGE_TILE:
2136 return same_pos(tile1, tile2);
2138 return map_distance(tile1, tile2) <= 1;
2139 case REQ_RANGE_CITY:
2141 case REQ_RANGE_LOCAL:
2143 case REQ_RANGE_PLAYER:
2144 case REQ_RANGE_TEAM:
2145 case REQ_RANGE_ALLIANCE:
2146 case REQ_RANGE_WORLD:
2147 case REQ_RANGE_COUNT:
2148 /* Invalid */
2150 }
2151 return FALSE;
2152}
2153
2154/**********************************************************************/
2157static inline bool players_in_same_range(const struct player *pplayer1,
2158 const struct player *pplayer2,
2159 enum req_range range)
2160{
2161 switch (range) {
2162 case REQ_RANGE_WORLD:
2163 return TRUE;
2164 case REQ_RANGE_ALLIANCE:
2166 case REQ_RANGE_TEAM:
2168 case REQ_RANGE_PLAYER:
2169 return pplayer1 == pplayer2;
2172 case REQ_RANGE_CITY:
2173 case REQ_RANGE_ADJACENT:
2175 case REQ_RANGE_TILE:
2176 case REQ_RANGE_LOCAL:
2177 case REQ_RANGE_COUNT:
2178 break;
2179 }
2180
2181 fc_assert_msg(FALSE, "Invalid range %d.", range);
2182 return FALSE;
2183}
2184
2185#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
2186{ \
2187 fc_assert_ret_val(req != nullptr, TRI_MAYBE); \
2188 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
2189 fc_assert(context != nullptr); \
2190 fc_assert(other_context != nullptr); \
2191}
2192
2193/**********************************************************************/
2201static enum fc_tristate
2203 const struct req_context *context,
2204 const struct req_context *other_context,
2205 const struct requirement *req)
2206{
2208
2209 return TRI_YES;
2210}
2211
2212/**********************************************************************/
2216static int num_world_buildings_total(const struct impr_type *building)
2217{
2218 if (is_great_wonder(building)) {
2219 return (great_wonder_is_built(building)
2220 || great_wonder_is_destroyed(building) ? 1 : 0);
2221 } else {
2222 log_error("World-ranged requirements are only supported for wonders.");
2223 return 0;
2224 }
2225}
2226
2227/**********************************************************************/
2230static int num_world_buildings(const struct impr_type *building)
2231{
2232 if (is_great_wonder(building)) {
2233 return (great_wonder_is_built(building) ? 1 : 0);
2234 } else {
2235 log_error("World-ranged requirements are only supported for wonders.");
2236 return 0;
2237 }
2238}
2239
2240/**********************************************************************/
2251static bool player_has_ever_built(const struct player *pplayer,
2252 const struct impr_type *building)
2253{
2254 if (is_wonder(building)) {
2255 return (wonder_is_built(pplayer, building)
2256 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2257 } else {
2258 log_error("Player-ranged requirements are only supported for wonders.");
2259 return FALSE;
2260 }
2261}
2262
2263/**********************************************************************/
2266static int num_player_buildings(const struct player *pplayer,
2267 const struct impr_type *building)
2268{
2269 if (is_wonder(building)) {
2270 return (wonder_is_built(pplayer, building) ? 1 : 0);
2271 } else {
2272 log_error("Player-ranged requirements are only supported for wonders.");
2273 return 0;
2274 }
2275}
2276
2277/**********************************************************************/
2280static int num_continent_buildings(const struct player *pplayer,
2281 int continent,
2282 const struct impr_type *building)
2283{
2284 if (is_wonder(building)) {
2285 const struct city *pcity;
2286
2287 pcity = city_from_wonder(pplayer, building);
2288 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2289 return 1;
2290 }
2291 } else {
2292 log_error("Island-ranged requirements are only supported for wonders.");
2293 }
2294 return 0;
2295}
2296
2297/**********************************************************************/
2305static enum fc_tristate
2307 const struct req_context *context,
2308 const struct req_context *other_context,
2309 const struct requirement *req)
2310{
2311 const struct impr_type *building;
2312
2313 /* Can't use this assertion, as both VUT_IMPROVEMENT and VUT_SITE
2314 * are handled here. */
2315 /* IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT); */
2316
2317 building = req->source.value.building;
2318
2319 /* Check if it's certain that the building is obsolete given the
2320 * specification we have */
2321 if (req->source.kind == VUT_IMPROVEMENT
2322 && improvement_obsolete(context->player, building, context->city)) {
2323 return TRI_NO;
2324 }
2325
2326 if (req->survives) {
2327
2328 /* Check whether condition has ever held, using cached information. */
2329 switch (req->range) {
2330 case REQ_RANGE_WORLD:
2331 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2332 case REQ_RANGE_ALLIANCE:
2333 case REQ_RANGE_TEAM:
2334 if (context->player == nullptr) {
2335 return TRI_MAYBE;
2336 }
2337 players_iterate_alive(plr2) {
2338 if (players_in_same_range(context->player, plr2, req->range)
2339 && player_has_ever_built(plr2, building)) {
2340 return TRI_YES;
2341 }
2343 return TRI_NO;
2344 case REQ_RANGE_PLAYER:
2345 if (context->player == nullptr) {
2346 return TRI_MAYBE;
2347 }
2349 building));
2352 case REQ_RANGE_CITY:
2353 case REQ_RANGE_LOCAL:
2354 case REQ_RANGE_TILE:
2356 case REQ_RANGE_ADJACENT:
2357 /* There is no sources cache for this. */
2358 log_error("Surviving requirements are only supported at "
2359 "World/Alliance/Team/Player ranges.");
2360 return TRI_NO;
2361 case REQ_RANGE_COUNT:
2362 break;
2363 }
2364
2365 } else {
2366
2367 /* Non-surviving requirement. */
2368 switch (req->range) {
2369 case REQ_RANGE_WORLD:
2370 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2371 case REQ_RANGE_ALLIANCE:
2372 case REQ_RANGE_TEAM:
2373 if (context->player == nullptr) {
2374 return TRI_MAYBE;
2375 }
2376 players_iterate_alive(plr2) {
2377 if (players_in_same_range(context->player, plr2, req->range)
2378 && num_player_buildings(plr2, building) > 0) {
2379 return TRI_YES;
2380 }
2382 return TRI_NO;
2383 case REQ_RANGE_PLAYER:
2384 if (context->player == nullptr) {
2385 return TRI_MAYBE;
2386 }
2388 building)
2389 > 0);
2391 /* At present, "Continent" effects can affect only
2392 * cities and units in cities. */
2393 if (context->player && context->city) {
2394 int continent = tile_continent(context->city->tile);
2396 continent, building)
2397 > 0);
2398 } else {
2399 return TRI_MAYBE;
2400 }
2402 if (context->city) {
2403 if (city_has_building(context->city, building)) {
2404 return TRI_YES;
2405 } else {
2406 enum fc_tristate ret = TRI_NO;
2407
2409 if (trade_partner == nullptr) {
2410 ret = TRI_MAYBE;
2411 } else if (city_has_building(trade_partner, building)) {
2412 return TRI_YES;
2413 }
2415
2416 return ret;
2417 }
2418 } else {
2419 return TRI_MAYBE;
2420 }
2421 case REQ_RANGE_CITY:
2422 if (context->city) {
2423 return BOOL_TO_TRISTATE(city_has_building(context->city, building));
2424 } else {
2425 return TRI_MAYBE;
2426 }
2427 case REQ_RANGE_LOCAL:
2428 if (context->building) {
2429 if (context->building == building) {
2430 return TRI_YES;
2431 } else {
2432 return TRI_NO;
2433 }
2434 } else {
2435 /* TODO: Other local targets */
2436 return TRI_MAYBE;
2437 }
2438 case REQ_RANGE_TILE:
2439 if (context->tile) {
2440 const struct city *pcity = tile_city(context->tile);
2441
2442 if (pcity) {
2443 return BOOL_TO_TRISTATE(city_has_building(pcity, building));
2444 } else {
2445 return TRI_NO;
2446 }
2447 } else {
2448 return TRI_MAYBE;
2449 }
2451 case REQ_RANGE_ADJACENT:
2452 case REQ_RANGE_COUNT:
2453 break;
2454 }
2455
2456 }
2457
2458 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2459 return TRI_NO;
2460}
2461
2462/**********************************************************************/
2470static enum fc_tristate
2472 const struct req_context *context,
2473 const struct req_context *other_context,
2474 const struct requirement *req)
2475{
2477
2478 return (context->building ? BOOL_TO_TRISTATE(
2479 context->building->genus
2480 == req->source.value.impr_genus)
2481 : TRI_MAYBE);
2482}
2483
2484/**********************************************************************/
2488 enum impr_flag_id flag)
2489{
2490 struct player *owner;
2491
2492 if (pcity == nullptr) {
2493 return TRI_MAYBE;
2494 }
2495
2497 city_built_iterate(pcity, impr) {
2498 if (improvement_has_flag(impr, flag)
2499 && !improvement_obsolete(owner, impr, pcity)) {
2500 return TRI_YES;
2501 }
2503
2504 return TRI_NO;
2505}
2506
2507/**********************************************************************/
2515static enum fc_tristate
2517 const struct req_context *context,
2518 const struct req_context *other_context,
2519 const struct requirement *req)
2520{
2522
2523 switch (req->range) {
2524 case REQ_RANGE_LOCAL:
2525 return (context->building
2527 req->source.value.impr_flag))
2528 : TRI_MAYBE);
2529 case REQ_RANGE_CITY:
2531 case REQ_RANGE_TILE:
2532 if (context->tile == nullptr) {
2533 return TRI_MAYBE;
2534 }
2536 req->source.value.impr_flag);
2538 case REQ_RANGE_ADJACENT:
2541 case REQ_RANGE_PLAYER:
2542 case REQ_RANGE_ALLIANCE:
2543 case REQ_RANGE_TEAM:
2544 case REQ_RANGE_WORLD:
2545 case REQ_RANGE_COUNT:
2546 break;
2547 }
2548
2549 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2550
2551 return TRI_MAYBE;
2552}
2553
2554/**********************************************************************/
2562static enum fc_tristate
2564 const struct req_context *context,
2565 const struct req_context *other_context,
2566 const struct requirement *req)
2567{
2569
2570 switch (req->range) {
2571 case REQ_RANGE_PLAYER:
2572 return (context->player != nullptr
2574 req->source.value.plr_flag))
2575 : TRI_MAYBE);
2576 case REQ_RANGE_LOCAL:
2577 case REQ_RANGE_CITY:
2578 case REQ_RANGE_TILE:
2580 case REQ_RANGE_ADJACENT:
2583 case REQ_RANGE_ALLIANCE:
2584 case REQ_RANGE_TEAM:
2585 case REQ_RANGE_WORLD:
2586 case REQ_RANGE_COUNT:
2587 break;
2588 }
2589
2590 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2591
2592 return TRI_MAYBE;
2593}
2594
2595/**********************************************************************/
2603static enum fc_tristate
2605 const struct req_context *context,
2606 const struct req_context *other_context,
2607 const struct requirement *req)
2608{
2610
2611 switch (req->range) {
2612 case REQ_RANGE_PLAYER:
2613 return (context->player != nullptr
2615 req->source.value.plrstate))
2616 : TRI_MAYBE);
2617 case REQ_RANGE_LOCAL:
2618 case REQ_RANGE_CITY:
2619 case REQ_RANGE_TILE:
2621 case REQ_RANGE_ADJACENT:
2624 case REQ_RANGE_ALLIANCE:
2625 case REQ_RANGE_TEAM:
2626 case REQ_RANGE_WORLD:
2627 case REQ_RANGE_COUNT:
2628 break;
2629 }
2630
2631 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2632
2633 return TRI_MAYBE;
2634}
2635
2636/**********************************************************************/
2644static enum fc_tristate
2646 const struct req_context *context,
2647 const struct req_context *other_context,
2648 const struct requirement *req)
2649{
2650 Tech_type_id tech;
2651
2653
2654 tech = advance_number(req->source.value.advance);
2655
2656 if (req->survives) {
2659 }
2660
2661 /* Not a 'surviving' requirement. */
2662 switch (req->range) {
2663 case REQ_RANGE_PLAYER:
2664 if (context->player != nullptr) {
2666 (research_get(context->player), tech));
2667 } else {
2668 return TRI_MAYBE;
2669 }
2670 case REQ_RANGE_TEAM:
2671 case REQ_RANGE_ALLIANCE:
2672 case REQ_RANGE_WORLD:
2673 if (context->player == nullptr) {
2674 return TRI_MAYBE;
2675 }
2676 players_iterate_alive(plr2) {
2677 if (players_in_same_range(context->player, plr2, req->range)) {
2678 if (research_invention_state(research_get(plr2), tech)
2679 == TECH_KNOWN) {
2680 return TRI_YES;
2681 }
2682 }
2684
2685 return TRI_NO;
2686 case REQ_RANGE_LOCAL:
2687 if (context->player == nullptr) {
2688 return TRI_MAYBE;
2689 }
2690 if (research_get(context->player)->researching == tech) {
2691 return TRI_YES;
2692 }
2693 return TRI_NO;
2694 case REQ_RANGE_TILE:
2696 case REQ_RANGE_ADJACENT:
2697 case REQ_RANGE_CITY:
2700 case REQ_RANGE_COUNT:
2701 break;
2702 }
2703
2704 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2705
2706 return TRI_MAYBE;
2707}
2708
2709/**********************************************************************/
2717static enum fc_tristate
2719 const struct req_context *context,
2720 const struct req_context *other_context,
2721 const struct requirement *req)
2722{
2723 enum tech_flag_id techflag;
2724
2726
2727 techflag = req->source.value.techflag;
2728
2729 switch (req->range) {
2730 case REQ_RANGE_PLAYER:
2731 if (context->player != nullptr) {
2733 techflag));
2734 } else {
2735 return TRI_MAYBE;
2736 }
2737 break;
2738 case REQ_RANGE_TEAM:
2739 case REQ_RANGE_ALLIANCE:
2740 if (context->player == nullptr) {
2741 return TRI_MAYBE;
2742 }
2743 players_iterate_alive(plr2) {
2744 if (players_in_same_range(context->player, plr2, req->range)
2745 && player_knows_techs_with_flag(plr2, techflag)) {
2746 return TRI_YES;
2747 }
2749 return TRI_NO;
2750 case REQ_RANGE_WORLD:
2751 players_iterate(pplayer) {
2752 if (player_knows_techs_with_flag(pplayer, techflag)) {
2753 return TRI_YES;
2754 }
2756
2757 return TRI_NO;
2758 case REQ_RANGE_LOCAL:
2759 if (context->player == nullptr) {
2760 return TRI_MAYBE;
2761 }
2762 if (advance_has_flag(research_get(context->player)->researching, techflag)) {
2763 return TRI_YES;
2764 }
2765 return TRI_NO;
2766 case REQ_RANGE_TILE:
2768 case REQ_RANGE_ADJACENT:
2769 case REQ_RANGE_CITY:
2772 case REQ_RANGE_COUNT:
2773 break;
2774 }
2775
2776 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2777
2778 return TRI_MAYBE;
2779}
2780
2781/**********************************************************************/
2789static enum fc_tristate
2791 const struct req_context *context,
2792 const struct req_context *other_context,
2793 const struct requirement *req)
2794{
2795 int minculture;
2796
2798
2799 minculture = req->source.value.minculture;
2800
2801 switch (req->range) {
2802 case REQ_RANGE_CITY:
2803 if (!context->city) {
2804 return TRI_MAYBE;
2805 }
2806 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2808 if (!context->city) {
2809 return TRI_MAYBE;
2810 }
2811 if (city_culture(context->city) >= minculture) {
2812 return TRI_YES;
2813 } else {
2814 enum fc_tristate ret = TRI_NO;
2815
2817 if (trade_partner == nullptr) {
2818 ret = TRI_MAYBE;
2819 } else if (city_culture(trade_partner) >= minculture) {
2820 return TRI_YES;
2821 }
2823
2824 return ret;
2825 }
2826 case REQ_RANGE_PLAYER:
2827 case REQ_RANGE_TEAM:
2828 case REQ_RANGE_ALLIANCE:
2829 case REQ_RANGE_WORLD:
2830 if (context->player == nullptr) {
2831 return TRI_MAYBE;
2832 }
2833 players_iterate_alive(plr2) {
2834 if (players_in_same_range(context->player, plr2, req->range)) {
2835 if (player_culture(plr2) >= minculture) {
2836 return TRI_YES;
2837 }
2838 }
2840 return TRI_NO;
2841 case REQ_RANGE_LOCAL:
2842 case REQ_RANGE_TILE:
2844 case REQ_RANGE_ADJACENT:
2846 case REQ_RANGE_COUNT:
2847 break;
2848 }
2849
2850 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2851
2852 return TRI_MAYBE;
2853}
2854
2855/**********************************************************************/
2863static enum fc_tristate
2865 const struct req_context *context,
2866 const struct req_context *other_context,
2867 const struct requirement *req)
2868{
2870
2872
2874
2875 switch (req->range) {
2876 case REQ_RANGE_CITY:
2877 if (!context->city) {
2878 return TRI_MAYBE;
2879 }
2881 / city_size_get(context->city);
2884 if (!context->city) {
2885 return TRI_MAYBE;
2886 }
2888 / city_size_get(context->city);
2890 return TRI_YES;
2891 } else {
2892 enum fc_tristate ret = TRI_NO;
2893
2895 if (trade_partner == nullptr) {
2896 ret = TRI_MAYBE;
2897 } else {
2901 return TRI_YES;
2902 }
2903 }
2905
2906 return ret;
2907 }
2908 case REQ_RANGE_PLAYER:
2909 case REQ_RANGE_TEAM:
2910 case REQ_RANGE_ALLIANCE:
2911 case REQ_RANGE_WORLD:
2912 case REQ_RANGE_LOCAL:
2913 case REQ_RANGE_TILE:
2915 case REQ_RANGE_ADJACENT:
2917 case REQ_RANGE_COUNT:
2918 break;
2919 }
2920
2921 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2922
2923 return TRI_MAYBE;
2924}
2925
2926/**********************************************************************/
2934static enum fc_tristate
2936 const struct req_context *context,
2937 const struct req_context *other_context,
2938 const struct requirement *req)
2939{
2940 int max_units;
2941
2943
2945
2946 /* TODO: If can't see V_INVIS -> TRI_MAYBE */
2947 switch (req->range) {
2948 case REQ_RANGE_TILE:
2949 if (!context->tile) {
2950 return TRI_MAYBE;
2951 }
2952 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
2954 if (!context->tile) {
2955 return TRI_MAYBE;
2956 }
2957 if (unit_list_size(context->tile->units) <= max_units) {
2958 return TRI_YES;
2959 }
2961 if (unit_list_size(adjc_tile->units) <= max_units) {
2962 return TRI_YES;
2963 }
2965 return TRI_NO;
2966 case REQ_RANGE_ADJACENT:
2967 if (!context->tile) {
2968 return TRI_MAYBE;
2969 }
2970 if (unit_list_size(context->tile->units) <= max_units) {
2971 return TRI_YES;
2972 }
2974 if (unit_list_size(adjc_tile->units) <= max_units) {
2975 return TRI_YES;
2976 }
2978 return TRI_NO;
2979 case REQ_RANGE_CITY:
2982 case REQ_RANGE_PLAYER:
2983 case REQ_RANGE_TEAM:
2984 case REQ_RANGE_ALLIANCE:
2985 case REQ_RANGE_WORLD:
2986 case REQ_RANGE_LOCAL:
2987 case REQ_RANGE_COUNT:
2988 break;
2989 }
2990
2991 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2992
2993 return TRI_MAYBE;
2994}
2995
2996
2997/**********************************************************************/
3005static enum fc_tristate
3007 const struct req_context *context,
3008 const struct req_context *other_context,
3009 const struct requirement *req)
3010{
3011 int max_units;
3012 int count;
3013
3015
3017
3018 /* TODO: If can't see V_INVIS -> TRI_MAYBE */
3019 switch (req->range) {
3020 case REQ_RANGE_TILE:
3021 if (!context->tile) {
3022 return TRI_MAYBE;
3023 }
3024 count = 0;
3025 unit_list_iterate(context->tile->units, punit) {
3026 if (!unit_transported(punit)) {
3027 count++;
3028 }
3030 return BOOL_TO_TRISTATE(count <= max_units);
3032 if (!context->tile) {
3033 return TRI_MAYBE;
3034 }
3035 count = 0;
3036 unit_list_iterate(context->tile->units, punit) {
3037 if (!unit_transported(punit)) {
3038 count++;
3039 }
3041 if (count <= max_units) {
3042 return TRI_YES;
3043 }
3045 count = 0;
3047 if (!unit_transported(punit)) {
3048 count++;
3049 }
3051 if (count <= max_units) {
3052 return TRI_YES;
3053 }
3055
3056 return TRI_NO;
3057 case REQ_RANGE_ADJACENT:
3058 if (!context->tile) {
3059 return TRI_MAYBE;
3060 }
3061 count = 0;
3062 unit_list_iterate(context->tile->units, punit) {
3063 if (!unit_transported(punit)) {
3064 count++;
3065 }
3067 if (count <= max_units) {
3068 return TRI_YES;
3069 }
3071 count = 0;
3073 if (!unit_transported(punit)) {
3074 count++;
3075 }
3077 if (count <= max_units) {
3078 return TRI_YES;
3079 }
3081 return TRI_NO;
3082 case REQ_RANGE_CITY:
3085 case REQ_RANGE_PLAYER:
3086 case REQ_RANGE_TEAM:
3087 case REQ_RANGE_ALLIANCE:
3088 case REQ_RANGE_WORLD:
3089 case REQ_RANGE_LOCAL:
3090 case REQ_RANGE_COUNT:
3091 break;
3092 }
3093
3094 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3095
3096 return TRI_MAYBE;
3097}
3098
3099/**********************************************************************/
3107static enum fc_tristate
3109 const struct req_context *context,
3110 const struct req_context *other_context,
3111 const struct requirement *req)
3112{
3113 const struct extra_type *pextra;
3114 enum fc_tristate ret;
3115
3117
3118 pextra = req->source.value.extra;
3119
3120 switch (req->range) {
3121 case REQ_RANGE_LOCAL:
3122 if (!context->extra) {
3123 return TRI_MAYBE;
3124 }
3125 return BOOL_TO_TRISTATE(context->extra == pextra);
3126 case REQ_RANGE_TILE:
3127 /* The requirement is filled if the tile has extra of requested type. */
3128 if (!context->tile) {
3129 return TRI_MAYBE;
3130 }
3131 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
3133 if (!context->tile) {
3134 return TRI_MAYBE;
3135 }
3136 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
3137 || is_extra_card_near(nmap, context->tile, pextra));
3138 case REQ_RANGE_ADJACENT:
3139 if (!context->tile) {
3140 return TRI_MAYBE;
3141 }
3142 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
3143 || is_extra_near_tile(nmap, context->tile, pextra));
3144 case REQ_RANGE_CITY:
3145 if (!context->city) {
3146 return TRI_MAYBE;
3147 }
3149 city_tile(context->city), ptile) {
3150 if (tile_has_extra(ptile, pextra)) {
3151 return TRI_YES;
3152 }
3154
3155 return TRI_NO;
3156
3158 if (!context->city) {
3159 return TRI_MAYBE;
3160 }
3162 city_tile(context->city), ptile) {
3163 if (tile_has_extra(ptile, pextra)) {
3164 return TRI_YES;
3165 }
3167
3168 ret = TRI_NO;
3170 if (trade_partner == nullptr) {
3171 ret = TRI_MAYBE;
3172 } else {
3174 city_tile(trade_partner), ptile) {
3175 if (tile_has_extra(ptile, pextra)) {
3176 return TRI_YES;
3177 }
3179 }
3181
3182 return ret;
3183
3185 case REQ_RANGE_PLAYER:
3186 case REQ_RANGE_TEAM:
3187 case REQ_RANGE_ALLIANCE:
3188 case REQ_RANGE_WORLD:
3189 case REQ_RANGE_COUNT:
3190 break;
3191 }
3192
3193 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3194
3195 return TRI_MAYBE;
3196}
3197
3198/**********************************************************************/
3206static enum fc_tristate
3208 const struct req_context *context,
3209 const struct req_context *other_context,
3210 const struct requirement *req)
3211{
3212 const struct goods_type *pgood;
3213
3215
3216 pgood = req->source.value.good;
3217
3218 switch (req->range) {
3219 case REQ_RANGE_LOCAL:
3220 case REQ_RANGE_CITY:
3221 /* The requirement is filled if the city imports good of requested type. */
3222 if (!context->city) {
3223 return TRI_MAYBE;
3224 }
3228 nullptr)));
3229 case REQ_RANGE_TILE:
3231 case REQ_RANGE_ADJACENT:
3234 case REQ_RANGE_PLAYER:
3235 case REQ_RANGE_TEAM:
3236 case REQ_RANGE_ALLIANCE:
3237 case REQ_RANGE_WORLD:
3238 case REQ_RANGE_COUNT:
3239 break;
3240 }
3241
3242 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3243
3244 return TRI_MAYBE;
3245}
3246
3247/**********************************************************************/
3255static enum fc_tristate
3257 const struct req_context *context,
3258 const struct req_context *other_context,
3259 const struct requirement *req)
3260{
3262
3263 if (context->action) {
3264 return BOOL_TO_TRISTATE(action_number(context->action)
3265 == action_number(req->source.value.action));
3266 }
3267
3268 if (context->unit != nullptr && context->unit->action != ACTION_NONE) {
3269 log_normal("Unit action %s", action_id_rule_name(context->unit->action));
3270 return BOOL_TO_TRISTATE(context->unit->action
3271 == action_number(req->source.value.action));
3272 }
3273
3274 return TRI_NO;
3275}
3276
3277/**********************************************************************/
3285static enum fc_tristate
3287 const struct req_context *context,
3288 const struct req_context *other_context,
3289 const struct requirement *req)
3290{
3292
3293 return BOOL_TO_TRISTATE(context->output
3294 && context->output->index
3295 == req->source.value.outputtype);
3296}
3297
3298/**********************************************************************/
3306static enum fc_tristate
3308 const struct req_context *context,
3309 const struct req_context *other_context,
3310 const struct requirement *req)
3311{
3313
3314 return BOOL_TO_TRISTATE(context->specialist
3315 && context->specialist
3316 == req->source.value.specialist);
3317}
3318
3319/**********************************************************************/
3327static enum fc_tristate
3329 const struct req_context *context,
3330 const struct req_context *other_context,
3331 const struct requirement *req)
3332{
3333 const struct terrain *pterrain;
3334
3336
3337 pterrain = req->source.value.terrain;
3338
3339 switch (req->range) {
3340 case REQ_RANGE_TILE:
3341 /* The requirement is filled if the tile has the terrain. */
3342 if (!context->tile) {
3343 return TRI_MAYBE;
3344 }
3345 return pterrain && tile_terrain(context->tile) == pterrain;
3347 if (!context->tile) {
3348 return TRI_MAYBE;
3349 }
3350 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
3351 case REQ_RANGE_ADJACENT:
3352 if (!context->tile) {
3353 return TRI_MAYBE;
3354 }
3355 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
3356 case REQ_RANGE_CITY:
3357 if (!context->city) {
3358 return TRI_MAYBE;
3359 }
3360 if (pterrain != nullptr) {
3362 city_tile(context->city), ptile) {
3363 if (tile_terrain(ptile) == pterrain) {
3364 return TRI_YES;
3365 }
3367 }
3368 return TRI_NO;
3370 if (!context->city) {
3371 return TRI_MAYBE;
3372 }
3373 if (pterrain != nullptr) {
3374 enum fc_tristate ret;
3375
3377 city_tile(context->city), ptile) {
3378 if (tile_terrain(ptile) == pterrain) {
3379 return TRI_YES;
3380 }
3382
3383 ret = TRI_NO;
3385 if (trade_partner == nullptr) {
3386 ret = TRI_MAYBE;
3387 } else {
3389 city_tile(trade_partner), ptile) {
3390 if (tile_terrain(ptile) == pterrain) {
3391 return TRI_YES;
3392 }
3394 }
3396
3397 return ret;
3398 }
3399
3400 return TRI_MAYBE;
3402 case REQ_RANGE_PLAYER:
3403 case REQ_RANGE_TEAM:
3404 case REQ_RANGE_ALLIANCE:
3405 case REQ_RANGE_WORLD:
3406 case REQ_RANGE_LOCAL:
3407 case REQ_RANGE_COUNT:
3408 break;
3409 }
3410
3411 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3412
3413 return TRI_MAYBE;
3414}
3415
3416/**********************************************************************/
3424static enum fc_tristate
3426 const struct req_context *context,
3427 const struct req_context *other_context,
3428 const struct requirement *req)
3429{
3430 enum terrain_class pclass;
3431 enum fc_tristate ret;
3432
3434
3436
3437 switch (req->range) {
3438 case REQ_RANGE_TILE:
3439 /* The requirement is filled if the tile has the terrain of correct class. */
3440 if (!context->tile) {
3441 return TRI_MAYBE;
3442 }
3445 if (!context->tile) {
3446 return TRI_MAYBE;
3447 }
3450 case REQ_RANGE_ADJACENT:
3451 if (!context->tile) {
3452 return TRI_MAYBE;
3453 }
3456 case REQ_RANGE_CITY:
3457 if (!context->city) {
3458 return TRI_MAYBE;
3459 }
3461 city_tile(context->city), ptile) {
3462 const struct terrain *pterrain = tile_terrain(ptile);
3463
3464 if (pterrain != T_UNKNOWN
3465 && terrain_type_terrain_class(pterrain) == pclass) {
3466 return TRI_YES;
3467 }
3469
3470 return TRI_NO;
3472 if (!context->city) {
3473 return TRI_MAYBE;
3474 }
3476 city_tile(context->city), ptile) {
3477 const struct terrain *pterrain = tile_terrain(ptile);
3478
3479 if (pterrain != T_UNKNOWN
3480 && terrain_type_terrain_class(pterrain) == pclass) {
3481 return TRI_YES;
3482 }
3484
3485 ret = TRI_NO;
3487 if (trade_partner == nullptr) {
3488 ret = TRI_MAYBE;
3489 } else {
3491 city_tile(trade_partner), ptile) {
3492 const struct terrain *pterrain = tile_terrain(ptile);
3493
3494 if (pterrain != T_UNKNOWN
3495 && terrain_type_terrain_class(pterrain) == pclass) {
3496 return TRI_YES;
3497 }
3499 }
3501
3502 return ret;
3504 case REQ_RANGE_PLAYER:
3505 case REQ_RANGE_TEAM:
3506 case REQ_RANGE_ALLIANCE:
3507 case REQ_RANGE_WORLD:
3508 case REQ_RANGE_LOCAL:
3509 case REQ_RANGE_COUNT:
3510 break;
3511 }
3512
3513 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3514
3515 return TRI_MAYBE;
3516}
3517
3518/**********************************************************************/
3526static enum fc_tristate
3528 const struct req_context *context,
3529 const struct req_context *other_context,
3530 const struct requirement *req)
3531{
3533 enum fc_tristate ret;
3534
3536
3538
3539 switch (req->range) {
3540 case REQ_RANGE_TILE:
3541 /* The requirement is fulfilled if the tile has a terrain with
3542 * correct flag. */
3543 if (!context->tile) {
3544 return TRI_MAYBE;
3545 }
3547 terrflag));
3549 if (!context->tile) {
3550 return TRI_MAYBE;
3551 }
3553 terrflag)
3555 terrflag));
3556 case REQ_RANGE_ADJACENT:
3557 if (!context->tile) {
3558 return TRI_MAYBE;
3559 }
3561 terrflag)
3563 terrflag));
3564 case REQ_RANGE_CITY:
3565 if (!context->city) {
3566 return TRI_MAYBE;
3567 }
3569 city_tile(context->city), ptile) {
3570 const struct terrain *pterrain = tile_terrain(ptile);
3571
3572 if (pterrain != T_UNKNOWN
3573 && terrain_has_flag(pterrain, terrflag)) {
3574 return TRI_YES;
3575 }
3577
3578 return TRI_NO;
3580 if (!context->city) {
3581 return TRI_MAYBE;
3582 }
3584 city_tile(context->city), ptile) {
3585 const struct terrain *pterrain = tile_terrain(ptile);
3586
3587 if (pterrain != T_UNKNOWN
3588 && terrain_has_flag(pterrain, terrflag)) {
3589 return TRI_YES;
3590 }
3592
3593 ret = TRI_NO;
3595 if (trade_partner == nullptr) {
3596 ret = TRI_MAYBE;
3597 } else {
3599 city_tile(trade_partner), ptile) {
3600 const struct terrain *pterrain = tile_terrain(ptile);
3601
3602 if (pterrain != T_UNKNOWN
3603 && terrain_has_flag(pterrain, terrflag)) {
3604 return TRI_YES;
3605 }
3607 }
3609
3610 return ret;
3612 case REQ_RANGE_PLAYER:
3613 case REQ_RANGE_TEAM:
3614 case REQ_RANGE_ALLIANCE:
3615 case REQ_RANGE_WORLD:
3616 case REQ_RANGE_LOCAL:
3617 case REQ_RANGE_COUNT:
3618 break;
3619 }
3620
3621 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3622
3623 return TRI_MAYBE;
3624}
3625
3626/**********************************************************************/
3634static enum fc_tristate
3636 const struct req_context *context,
3637 const struct req_context *other_context,
3638 const struct requirement *req)
3639{
3640 enum road_flag_id roadflag;
3641 enum fc_tristate ret;
3642
3644
3645 roadflag = req->source.value.roadflag;
3646
3647 switch (req->range) {
3648 case REQ_RANGE_LOCAL:
3649 {
3650 if (!context->extra) {
3651 return TRI_MAYBE;
3652 }
3653 struct road_type *r = extra_road_get(context->extra);
3654
3655 return BOOL_TO_TRISTATE(
3656 r && road_has_flag(r, roadflag)
3657 );
3658 }
3659 case REQ_RANGE_TILE:
3660 /* The requirement is filled if the tile has a road with correct flag. */
3661 if (!context->tile) {
3662 return TRI_MAYBE;
3663 }
3664 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3666 if (!context->tile) {
3667 return TRI_MAYBE;
3668 }
3669 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3671 roadflag));
3672 case REQ_RANGE_ADJACENT:
3673 if (!context->tile) {
3674 return TRI_MAYBE;
3675 }
3676 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3678 roadflag));
3679 case REQ_RANGE_CITY:
3680 if (!context->city) {
3681 return TRI_MAYBE;
3682 }
3684 city_tile(context->city), ptile) {
3685 if (tile_has_road_flag(ptile, roadflag)) {
3686 return TRI_YES;
3687 }
3689
3690 return TRI_NO;
3692 if (!context->city) {
3693 return TRI_MAYBE;
3694 }
3696 city_tile(context->city), ptile) {
3697 if (tile_has_road_flag(ptile, roadflag)) {
3698 return TRI_YES;
3699 }
3701
3702 ret = TRI_NO;
3704 if (trade_partner == nullptr) {
3705 ret = TRI_MAYBE;
3706 } else {
3708 city_tile(trade_partner), ptile) {
3709 if (tile_has_road_flag(ptile, roadflag)) {
3710 return TRI_YES;
3711 }
3713 }
3715
3716 return ret;
3718 case REQ_RANGE_PLAYER:
3719 case REQ_RANGE_TEAM:
3720 case REQ_RANGE_ALLIANCE:
3721 case REQ_RANGE_WORLD:
3722 case REQ_RANGE_COUNT:
3723 break;
3724 }
3725
3726 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3727
3728 return TRI_MAYBE;
3729}
3730
3731/**********************************************************************/
3739static enum fc_tristate
3741 const struct req_context *context,
3742 const struct req_context *other_context,
3743 const struct requirement *req)
3744{
3745 enum extra_flag_id extraflag;
3746 enum fc_tristate ret;
3747
3749
3750 extraflag = req->source.value.extraflag;
3751
3752 switch (req->range) {
3753 case REQ_RANGE_LOCAL:
3754 if (!context->extra) {
3755 return TRI_MAYBE;
3756 }
3757 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3758 case REQ_RANGE_TILE:
3759 /* The requirement is filled if the tile has an extra with correct flag. */
3760 if (!context->tile) {
3761 return TRI_MAYBE;
3762 }
3763 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3765 if (!context->tile) {
3766 return TRI_MAYBE;
3767 }
3768 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3769 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3770 case REQ_RANGE_ADJACENT:
3771 if (!context->tile) {
3772 return TRI_MAYBE;
3773 }
3774 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3775 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3776 case REQ_RANGE_CITY:
3777 if (!context->city) {
3778 return TRI_MAYBE;
3779 }
3781 city_tile(context->city), ptile) {
3782 if (tile_has_extra_flag(ptile, extraflag)) {
3783 return TRI_YES;
3784 }
3786
3787 return TRI_NO;
3789 if (!context->city) {
3790 return TRI_MAYBE;
3791 }
3793 city_tile(context->city), ptile) {
3794 if (tile_has_extra_flag(ptile, extraflag)) {
3795 return TRI_YES;
3796 }
3798
3799 ret = TRI_NO;
3801 if (trade_partner == nullptr) {
3802 ret = TRI_MAYBE;
3803 } else {
3805 city_tile(trade_partner), ptile) {
3806 if (tile_has_extra_flag(ptile, extraflag)) {
3807 return TRI_YES;
3808 }
3810 }
3812
3813 return ret;
3815 case REQ_RANGE_PLAYER:
3816 case REQ_RANGE_TEAM:
3817 case REQ_RANGE_ALLIANCE:
3818 case REQ_RANGE_WORLD:
3819 case REQ_RANGE_COUNT:
3820 break;
3821 }
3822
3823 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3824
3825 return TRI_MAYBE;
3826}
3827
3828/**********************************************************************/
3836static enum fc_tristate
3838 const struct req_context *context,
3839 const struct req_context *other_context,
3840 const struct requirement *req)
3841{
3843
3845
3847
3848 if (!context->tile) {
3849 return TRI_MAYBE;
3850 }
3851
3852 switch (req->range) {
3853 case REQ_RANGE_TILE:
3857 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
3858 case REQ_RANGE_CITY:
3861 case REQ_RANGE_PLAYER:
3862 case REQ_RANGE_TEAM:
3863 case REQ_RANGE_ALLIANCE:
3864 case REQ_RANGE_WORLD:
3865 case REQ_RANGE_LOCAL:
3866 case REQ_RANGE_COUNT:
3867 break;
3868 }
3869
3870 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3871
3872 return TRI_MAYBE;
3873}
3874
3875/**********************************************************************/
3883static enum fc_tristate
3885 const struct req_context *context,
3886 const struct req_context *other_context,
3887 const struct requirement *req)
3888{
3890
3891 if (context->player == nullptr) {
3892 return TRI_MAYBE;
3893 } else {
3895 == req->source.value.govern);
3896 }
3897}
3898
3899/**********************************************************************/
3907static enum fc_tristate
3909 const struct req_context *context,
3910 const struct req_context *other_context,
3911 const struct requirement *req)
3912{
3914
3915 if (context->player == nullptr) {
3916 return TRI_MAYBE;
3917 } else {
3919 req->source.value.govflag));
3920 }
3921}
3922
3923/**********************************************************************/
3931static enum fc_tristate
3933 const struct req_context *context,
3934 const struct req_context *other_context,
3935 const struct requirement *req)
3936{
3938
3939 if (context->player == nullptr) {
3940 return TRI_MAYBE;
3941 } else {
3942 return BOOL_TO_TRISTATE(context->player->style
3943 == req->source.value.style);
3944 }
3945}
3946
3947/**********************************************************************/
3955static enum fc_tristate
3957 const struct req_context *context,
3958 const struct req_context *other_context,
3959 const struct requirement *req)
3960{
3962
3963 switch (req->range) {
3964 case REQ_RANGE_WORLD:
3965 /* "None" does not count */
3966 return ((game.info.global_advance_count - 1)
3967 >= req->source.value.min_techs);
3968 case REQ_RANGE_PLAYER:
3969 if (context->player == nullptr) {
3970 return TRI_MAYBE;
3971 } else {
3972 /* "None" does not count */
3973 return BOOL_TO_TRISTATE(
3974 (research_get(context->player)->techs_researched - 1)
3975 >= req->source.value.min_techs
3976 );
3977 }
3978 default:
3979 return TRI_MAYBE;
3980 }
3981}
3982
3983/**********************************************************************/
3991static enum fc_tristate
3993 const struct req_context *context,
3994 const struct req_context *other_context,
3995 const struct requirement *req)
3996{
3998
3999 switch (req->range) {
4000 case REQ_RANGE_WORLD:
4002 if (research_get(plr)->future_tech
4003 >= req->source.value.future_techs) {
4004 return TRI_YES;
4005 }
4007
4008 return TRI_NO;
4009 case REQ_RANGE_PLAYER:
4010 if (context->player == nullptr) {
4011 return TRI_MAYBE;
4012 } else {
4014 >= req->source.value.future_techs);
4015 }
4016 default:
4017 return TRI_MAYBE;
4018 }
4019}
4020
4021/**********************************************************************/
4029static enum fc_tristate
4031 const struct req_context *context,
4032 const struct req_context *other_context,
4033 const struct requirement *req)
4034{
4036
4037 switch (req->range) {
4038 case REQ_RANGE_PLAYER:
4039 if (context->player == nullptr) {
4040 return TRI_MAYBE;
4041 } else {
4042 /* "None" does not count */
4043 return BOOL_TO_TRISTATE(
4044 city_list_size(context->player->cities)
4045 >= req->source.value.min_cities
4046 );
4047 }
4048 default:
4049 return TRI_MAYBE;
4050 }
4051}
4052
4053/**********************************************************************/
4061static enum fc_tristate
4063 const struct req_context *context,
4064 const struct req_context *other_context,
4065 const struct requirement *req)
4066{
4068
4069 if (context->player == nullptr) {
4070 return TRI_MAYBE;
4071 } else {
4072 return BOOL_TO_TRISTATE(is_ai(context->player)
4073 && context->player->ai_common.skill_level
4074 == req->source.value.ai_level);
4075 }
4076}
4077
4078/**********************************************************************/
4086static enum fc_tristate
4088 const struct req_context *context,
4089 const struct req_context *other_context,
4090 const struct requirement *req)
4091{
4092 const struct nation_type *nation;
4093
4095
4096 nation = req->source.value.nation;
4097
4098 switch (req->range) {
4099 case REQ_RANGE_PLAYER:
4100 if (context->player == nullptr) {
4101 return TRI_MAYBE;
4102 }
4103 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
4104 case REQ_RANGE_TEAM:
4105 case REQ_RANGE_ALLIANCE:
4106 if (context->player == nullptr) {
4107 return TRI_MAYBE;
4108 }
4109 players_iterate_alive(plr2) {
4110 if (players_in_same_range(context->player, plr2, req->range)) {
4111 if (nation_of_player(plr2) == nation) {
4112 return TRI_YES;
4113 }
4114 }
4116 return TRI_NO;
4117 case REQ_RANGE_WORLD:
4118 /* NB: if a player is ever removed outright from the game
4119 * (e.g. via /remove), rather than just dying, this 'survives'
4120 * requirement will stop being true for their nation.
4121 * create_command_newcomer() can also cause this to happen. */
4122 return BOOL_TO_TRISTATE(nation->player != nullptr
4123 && (req->survives || nation->player->is_alive));
4124 case REQ_RANGE_LOCAL:
4125 case REQ_RANGE_TILE:
4127 case REQ_RANGE_ADJACENT:
4128 case REQ_RANGE_CITY:
4131 case REQ_RANGE_COUNT:
4132 break;
4133 }
4134
4135 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4136
4137 return TRI_MAYBE;
4138}
4139
4140/**********************************************************************/
4148static enum fc_tristate
4150 const struct req_context *context,
4151 const struct req_context *other_context,
4152 const struct requirement *req)
4153{
4154 const struct nation_group *ngroup;
4155
4157
4159
4160 switch (req->range) {
4161 case REQ_RANGE_PLAYER:
4162 if (context->player == nullptr) {
4163 return TRI_MAYBE;
4164 }
4166 nation_of_player(context->player), ngroup));
4167 case REQ_RANGE_TEAM:
4168 case REQ_RANGE_ALLIANCE:
4169 case REQ_RANGE_WORLD:
4170 if (context->player == nullptr) {
4171 return TRI_MAYBE;
4172 }
4173 players_iterate_alive(plr2) {
4174 if (players_in_same_range(context->player, plr2, req->range)) {
4176 return TRI_YES;
4177 }
4178 }
4180 return TRI_NO;
4181 case REQ_RANGE_LOCAL:
4182 case REQ_RANGE_TILE:
4184 case REQ_RANGE_ADJACENT:
4185 case REQ_RANGE_CITY:
4188 case REQ_RANGE_COUNT:
4189 break;
4190 }
4191
4192 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4193
4194 return TRI_MAYBE;
4195}
4196
4197/**********************************************************************/
4205static enum fc_tristate
4207 const struct req_context *context,
4208 const struct req_context *other_context,
4209 const struct requirement *req)
4210{
4211 const struct nation_type *nationality;
4212 enum fc_tristate ret;
4213
4215
4216 nationality = req->source.value.nationality;
4217
4218 switch (req->range) {
4219 case REQ_RANGE_CITY:
4220 if (context->city == nullptr) {
4221 return TRI_MAYBE;
4222 }
4223 citizens_iterate(context->city, slot, count) {
4224 if (player_slot_get_player(slot)->nation == nationality) {
4225 return TRI_YES;
4226 }
4228
4229 return TRI_NO;
4231 if (context->city == nullptr) {
4232 return TRI_MAYBE;
4233 }
4234 citizens_iterate(context->city, slot, count) {
4235 if (player_slot_get_player(slot)->nation == nationality) {
4236 return TRI_YES;
4237 }
4239
4240 ret = TRI_NO;
4242 if (trade_partner == nullptr) {
4243 ret = TRI_MAYBE;
4244 } else {
4245 citizens_iterate(trade_partner, slot, count) {
4246 if (player_slot_get_player(slot)->nation == nationality) {
4247 return TRI_YES;
4248 }
4250 }
4252
4253 return ret;
4254 case REQ_RANGE_PLAYER:
4255 case REQ_RANGE_TEAM:
4256 case REQ_RANGE_ALLIANCE:
4257 case REQ_RANGE_WORLD:
4258 case REQ_RANGE_LOCAL:
4259 case REQ_RANGE_TILE:
4261 case REQ_RANGE_ADJACENT:
4263 case REQ_RANGE_COUNT:
4264 break;
4265 }
4266
4267 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4268
4269 return TRI_MAYBE;
4270}
4271
4272/**********************************************************************/
4280static enum fc_tristate
4282 const struct req_context *context,
4283 const struct req_context *other_context,
4284 const struct requirement *req)
4285{
4286 const struct nation_type *nation;
4287
4289
4290 nation = req->source.value.origowner;
4291
4292 switch (req->range) {
4293 case REQ_RANGE_CITY:
4294 if (context->city == nullptr || context->city->original == nullptr) {
4295 return TRI_MAYBE;
4296 }
4297 if (player_nation(context->city->original) == nation) {
4298 return TRI_YES;
4299 }
4300
4301 return TRI_NO;
4303 case REQ_RANGE_PLAYER:
4304 case REQ_RANGE_TEAM:
4305 case REQ_RANGE_ALLIANCE:
4306 case REQ_RANGE_WORLD:
4307 case REQ_RANGE_LOCAL:
4308 case REQ_RANGE_TILE:
4310 case REQ_RANGE_ADJACENT:
4312 case REQ_RANGE_COUNT:
4313 break;
4314 }
4315
4316 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4317
4318 return TRI_MAYBE;
4319}
4320
4321/**********************************************************************/
4325 const struct player *other_player,
4326 enum req_range range,
4327 int diplrel)
4328{
4329 switch (range) {
4330 case REQ_RANGE_PLAYER:
4331 if (target_player == nullptr) {
4332 return TRI_MAYBE;
4333 }
4335 case REQ_RANGE_TEAM:
4336 case REQ_RANGE_ALLIANCE:
4337 case REQ_RANGE_WORLD:
4338 if (target_player == nullptr) {
4339 return TRI_MAYBE;
4340 }
4341 players_iterate_alive(plr2) {
4343 if (is_diplrel_to_other(plr2, diplrel)) {
4344 return TRI_YES;
4345 }
4346 }
4348 return TRI_NO;
4349 case REQ_RANGE_LOCAL:
4350 if (target_player == nullptr || other_player == nullptr) {
4351 return TRI_MAYBE;
4352 }
4353 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
4354 case REQ_RANGE_TILE:
4356 case REQ_RANGE_ADJACENT:
4357 case REQ_RANGE_CITY:
4360 case REQ_RANGE_COUNT:
4361 break;
4362 }
4363
4364 fc_assert_msg(FALSE, "Invalid range %d.", range);
4365
4366 return TRI_MAYBE;
4367}
4368
4369/**********************************************************************/
4377static enum fc_tristate
4379 const struct req_context *context,
4380 const struct req_context *other_context,
4381 const struct requirement *req)
4382{
4384
4385 return is_diplrel_in_range(context->player, other_context->player,
4386 req->range, req->source.value.diplrel);
4387}
4388
4389/**********************************************************************/
4397static enum fc_tristate
4399 const struct req_context *context,
4400 const struct req_context *other_context,
4401 const struct requirement *req)
4402{
4404
4405 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4406 : nullptr,
4407 context->player,
4408 req->range,
4409 req->source.value.diplrel);
4410}
4411
4412/**********************************************************************/
4421static enum fc_tristate
4423 const struct req_context *context,
4424 const struct req_context *other_context,
4425 const struct requirement *req)
4426{
4428
4429 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4430 : nullptr,
4431 other_context->player,
4432 req->range,
4433 req->source.value.diplrel);
4434}
4435
4436/**********************************************************************/
4439static enum fc_tristate
4441 const struct player *other_player,
4442 enum req_range range,
4443 int diplrel)
4444{
4445 enum fc_tristate out = TRI_NO;
4446
4447 if (target_tile == nullptr) {
4448 return TRI_MAYBE;
4449 }
4450
4453 unit_owner(target_unit), other_player, range, diplrel);
4454
4457
4458 return out;
4459}
4460
4461/**********************************************************************/
4470static enum fc_tristate
4472 const struct req_context *context,
4473 const struct req_context *other_context,
4474 const struct requirement *req)
4475{
4477
4478 return is_diplrel_unitany_in_range(context->tile, context->player,
4479 req->range,
4480 req->source.value.diplrel);
4481}
4482
4483/**********************************************************************/
4492static enum fc_tristate
4494 const struct req_context *context,
4495 const struct req_context *other_context,
4496 const struct requirement *req)
4497{
4499
4501 req->range,
4502 req->source.value.diplrel);
4503}
4504
4505/**********************************************************************/
4513static enum fc_tristate
4515 const struct req_context *context,
4516 const struct req_context *other_context,
4517 const struct requirement *req)
4518{
4519 const struct unit_type *punittype;
4520
4522
4523 punittype = req->source.value.utype;
4524
4525 switch (req->range) {
4526 case REQ_RANGE_LOCAL:
4527 if (!context->unittype) {
4528 return TRI_MAYBE;
4529 }
4530 return BOOL_TO_TRISTATE(context->unittype == punittype);
4531 case REQ_RANGE_TILE:
4533 case REQ_RANGE_ADJACENT:
4534 if (context->tile == nullptr) {
4535 return TRI_MAYBE;
4536 }
4537
4538 unit_list_iterate(context->tile->units, punit) {
4539 if (punit->utype == punittype) {
4540 return TRI_YES;
4541 }
4543
4544 if (req->range == REQ_RANGE_TILE) {
4545 return TRI_NO;
4546 }
4547
4548 if (req->range == REQ_RANGE_CADJACENT) {
4551 if (punit->utype == punittype) {
4552 return TRI_YES;
4553 }
4556 } else {
4558
4561 if (punit->utype == punittype) {
4562 return TRI_YES;
4563 }
4566 }
4567
4568 return TRI_NO;
4569
4570 case REQ_RANGE_CITY:
4573 case REQ_RANGE_PLAYER:
4574 case REQ_RANGE_TEAM:
4575 case REQ_RANGE_ALLIANCE:
4576 case REQ_RANGE_WORLD:
4577 case REQ_RANGE_COUNT:
4579 break;
4580 }
4581
4582 return TRI_NO;
4583}
4584
4585/**********************************************************************/
4593static enum fc_tristate
4595 const struct req_context *context,
4596 const struct req_context *other_context,
4597 const struct requirement *req)
4598{
4599 enum unit_type_flag_id unitflag;
4600
4602
4603 unitflag = req->source.value.unitflag;
4604
4605 switch (req->range) {
4606 case REQ_RANGE_LOCAL:
4607 if (!context->unittype) {
4608 return TRI_MAYBE;
4609 }
4610 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4611 case REQ_RANGE_TILE:
4613 case REQ_RANGE_ADJACENT:
4614 if (context->tile == nullptr) {
4615 return TRI_MAYBE;
4616 }
4617
4618 unit_list_iterate(context->tile->units, punit) {
4619 if (unit_has_type_flag(punit, unitflag)) {
4620 return TRI_YES;
4621 }
4623
4624 if (req->range == REQ_RANGE_TILE) {
4625 return TRI_NO;
4626 }
4627
4628 if (req->range == REQ_RANGE_CADJACENT) {
4631 if (unit_has_type_flag(punit, unitflag)) {
4632 return TRI_YES;
4633 }
4636 } else {
4638
4641 if (unit_has_type_flag(punit, unitflag)) {
4642 return TRI_YES;
4643 }
4646 }
4647
4648 return TRI_NO;
4649
4650 case REQ_RANGE_CITY:
4653 case REQ_RANGE_PLAYER:
4654 case REQ_RANGE_TEAM:
4655 case REQ_RANGE_ALLIANCE:
4656 case REQ_RANGE_WORLD:
4657 case REQ_RANGE_COUNT:
4659 break;
4660 }
4661
4662 return TRI_NO;
4663}
4664
4665/**********************************************************************/
4673static enum fc_tristate
4675 const struct req_context *context,
4676 const struct req_context *other_context,
4677 const struct requirement *req)
4678{
4679 const struct unit_class *pclass;
4680
4682
4683 pclass = req->source.value.uclass;
4684
4685 switch (req->range) {
4686 case REQ_RANGE_LOCAL:
4687 if (!context->unittype) {
4688 return TRI_MAYBE;
4689 }
4690 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4691 case REQ_RANGE_TILE:
4693 case REQ_RANGE_ADJACENT:
4694 if (context->tile == nullptr) {
4695 return TRI_MAYBE;
4696 }
4697
4698 unit_list_iterate(context->tile->units, punit) {
4699 if (unit_class_get(punit) == pclass) {
4700 return TRI_YES;
4701 }
4703
4704 if (req->range == REQ_RANGE_TILE) {
4705 return TRI_NO;
4706 }
4707
4708 if (req->range == REQ_RANGE_CADJACENT) {
4711 if (unit_class_get(punit) == pclass) {
4712 return TRI_YES;
4713 }
4716 } else {
4718
4721 if (unit_class_get(punit) == pclass) {
4722 return TRI_YES;
4723 }
4726 }
4727
4728 return TRI_NO;
4729
4730 case REQ_RANGE_CITY:
4733 case REQ_RANGE_PLAYER:
4734 case REQ_RANGE_TEAM:
4735 case REQ_RANGE_ALLIANCE:
4736 case REQ_RANGE_WORLD:
4737 case REQ_RANGE_COUNT:
4739 break;
4740 }
4741
4742 return TRI_NO;
4743}
4744
4745/**********************************************************************/
4753static enum fc_tristate
4755 const struct req_context *context,
4756 const struct req_context *other_context,
4757 const struct requirement *req)
4758{
4760
4762
4764
4765 switch (req->range) {
4766 case REQ_RANGE_LOCAL:
4767 if (!context->unittype) {
4768 return TRI_MAYBE;
4769 }
4771 case REQ_RANGE_TILE:
4773 case REQ_RANGE_ADJACENT:
4774 if (context->tile == nullptr) {
4775 return TRI_MAYBE;
4776 }
4777
4778 unit_list_iterate(context->tile->units, punit) {
4780 return TRI_YES;
4781 }
4783
4784 if (req->range == REQ_RANGE_TILE) {
4785 return TRI_NO;
4786 }
4787
4788 if (req->range == REQ_RANGE_CADJACENT) {
4792 return TRI_YES;
4793 }
4796 } else {
4798
4802 return TRI_YES;
4803 }
4806 }
4807
4808 return TRI_NO;
4809
4810 case REQ_RANGE_CITY:
4813 case REQ_RANGE_PLAYER:
4814 case REQ_RANGE_TEAM:
4815 case REQ_RANGE_ALLIANCE:
4816 case REQ_RANGE_WORLD:
4817 case REQ_RANGE_COUNT:
4819 break;
4820 }
4821
4822 return TRI_NO;
4823}
4824
4825/**********************************************************************/
4833static enum fc_tristate
4835 const struct req_context *context,
4836 const struct req_context *other_context,
4837 const struct requirement *req)
4838{
4839 enum ustate_prop uprop;
4840
4842
4844
4846 "Unsupported range \"%s\"",
4847 req_range_name(req->range));
4848
4849 /* Could be asked with incomplete data.
4850 * is_req_active() will handle it based on prob_type. */
4851 if (context->unit == nullptr) {
4852 return TRI_MAYBE;
4853 }
4854
4855 switch (uprop) {
4856 case USP_TRANSPORTED:
4857 return BOOL_TO_TRISTATE(context->unit->transporter != nullptr);
4858 case USP_LIVABLE_TILE:
4859 return BOOL_TO_TRISTATE(
4861 unit_tile(context->unit)));
4862 break;
4863 case USP_TRANSPORTING:
4865 case USP_HAS_HOME_CITY:
4866 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
4867 case USP_NATIVE_TILE:
4868 return BOOL_TO_TRISTATE(
4870 unit_tile(context->unit)));
4871 break;
4872 case USP_NATIVE_EXTRA:
4873 return BOOL_TO_TRISTATE(
4875 unit_type_get(context->unit)));
4876 break;
4878 return BOOL_TO_TRISTATE(context->unit->moved);
4879 case USP_COUNT:
4880 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
4881 /* Invalid property is unknowable. */
4882 return TRI_NO;
4883 }
4884
4885 /* Should never be reached */
4886 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
4887
4888 return TRI_NO;
4889}
4890
4891/**********************************************************************/
4899static enum fc_tristate
4901 const struct req_context *context,
4902 const struct req_context *other_context,
4903 const struct requirement *req)
4904{
4905 enum unit_activity activity;
4906
4908
4909 activity = req->source.value.activity;
4910
4912 "Unsupported range \"%s\"",
4913 req_range_name(req->range));
4914
4915 if (context->unit == nullptr) {
4916 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
4917 * it's the zero value that context has by default - so many callers
4918 * who meant not to set specific activity actually have ACTIVITY_IDLE
4919 * instead of ACTIVITY_LAST */
4920 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
4921 return BOOL_TO_TRISTATE(activity == context->activity);
4922 }
4923
4924 /* Could be asked with incomplete data.
4925 * is_req_active() will handle it based on prob_type. */
4926 return TRI_MAYBE;
4927 }
4928
4929 switch (context->unit->activity) {
4930 case ACTIVITY_IDLE:
4931 case ACTIVITY_SENTRY:
4932 case ACTIVITY_GOTO:
4933 case ACTIVITY_EXPLORE:
4934 /* Seen as idle. */
4935 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
4936 default:
4937 /* Handled below. */
4938 break;
4939 }
4940
4941 return BOOL_TO_TRISTATE(context->unit->activity == activity);
4942}
4943
4944/**********************************************************************/
4952static enum fc_tristate
4954 const struct req_context *context,
4955 const struct req_context *other_context,
4956 const struct requirement *req)
4957{
4959
4960 if (context->unit == nullptr) {
4961 return TRI_MAYBE;
4962 } else {
4963 return BOOL_TO_TRISTATE(context->unit->veteran
4964 >= req->source.value.minveteran);
4965 }
4966}
4967
4968/**********************************************************************/
4976static enum fc_tristate
4978 const struct req_context *context,
4979 const struct req_context *other_context,
4980 const struct requirement *req)
4981{
4983
4984 if (context->unit == nullptr) {
4985 return TRI_MAYBE;
4986 } else {
4988 <= context->unit->moves_left);
4989 }
4990}
4991
4992/**********************************************************************/
5000static enum fc_tristate
5002 const struct req_context *context,
5003 const struct req_context *other_context,
5004 const struct requirement *req)
5005{
5007
5008 if (context->unit == nullptr) {
5009 return TRI_MAYBE;
5010 } else {
5012 <= context->unit->hp);
5013 }
5014}
5015
5016/**********************************************************************/
5024static enum fc_tristate
5026 const struct req_context *context,
5027 const struct req_context *other_context,
5028 const struct requirement *req)
5029{
5031
5032 switch (req->range) {
5033 case REQ_RANGE_LOCAL:
5034 if (context->unit == nullptr || !is_server()) {
5035 return TRI_MAYBE;
5036 } else {
5037 return BOOL_TO_TRISTATE(
5038 req->source.value.age <=
5039 game.info.turn - context->unit->birth_turn);
5040 }
5041 break;
5042 case REQ_RANGE_CITY:
5043 if (context->city == nullptr) {
5044 return TRI_MAYBE;
5045 } else {
5046 return BOOL_TO_TRISTATE(
5047 req->source.value.age <=
5048 game.info.turn - context->city->turn_founded);
5049 }
5050 break;
5051 case REQ_RANGE_PLAYER:
5052 if (context->player == nullptr) {
5053 return TRI_MAYBE;
5054 } else {
5055 return BOOL_TO_TRISTATE(req->source.value.age
5056 <= player_age(context->player));
5057 }
5058 break;
5059 default:
5060 return TRI_MAYBE;
5061 break;
5062 }
5063}
5064
5065/**********************************************************************/
5073static enum fc_tristate
5075 const struct req_context *context,
5076 const struct req_context *other_context,
5077 const struct requirement *req)
5078{
5080
5081 switch (req->range) {
5082 case REQ_RANGE_LOCAL:
5083 if (context->unit == nullptr || !is_server()) {
5084 return TRI_MAYBE;
5085 } else {
5086 return BOOL_TO_TRISTATE(
5087 req->source.value.form_age <=
5088 game.info.turn - context->unit->current_form_turn);
5089 }
5090 break;
5091 default:
5092 return TRI_MAYBE;
5093 break;
5094 }
5095}
5096
5097/**********************************************************************/
5101static inline enum fc_tristate
5103{
5105 bool whole_known;
5106
5107 if (cont > 0) {
5110
5111 if (actual_surrounder > 0) {
5112 return TRI_NO;
5113 }
5114 } else if (cont < 0) {
5117
5118 if (actual_surrounder < 0) {
5119 return TRI_NO;
5120 }
5121 } else {
5122 return TRI_MAYBE;
5123 }
5124
5125 if (actual_surrounder == 0 || surrounder == 0) {
5126 return TRI_MAYBE;
5127 } else if (actual_surrounder != surrounder) {
5128 return TRI_NO;
5129 } else if (!whole_known) {
5130 return TRI_MAYBE;
5131 } else {
5132 return TRI_YES;
5133 }
5134}
5135
5136/**********************************************************************/
5144static enum fc_tristate
5146 const struct req_context *context,
5147 const struct req_context *other_context,
5148 const struct requirement *req)
5149{
5151
5152 if (context->tile == nullptr || other_context->tile == nullptr) {
5153 /* Note: For some values, we might be able to give a definitive
5154 * TRI_NO answer even if one of the tiles is missing, but that's
5155 * probably not worth the added effort. */
5156 return TRI_MAYBE;
5157 }
5158
5159 switch (req->source.value.tilerel) {
5160 case TREL_SAME_TCLASS:
5161 if (tile_terrain(other_context->tile) == T_UNKNOWN) {
5162 return TRI_MAYBE;
5163 }
5165 || req->range == REQ_RANGE_CADJACENT
5166 || req->range == REQ_RANGE_ADJACENT),
5167 TRI_MAYBE,
5168 "Invalid range %d for tile relation \"%s\" req",
5170 {
5173 bool seen_unknown = FALSE;
5174 const struct terrain *terr;
5175
5176 if ((terr = tile_terrain(context->tile)) == T_UNKNOWN) {
5178 } else if (terrain_type_terrain_class(terr) == cls) {
5179 return TRUE;
5180 }
5181
5183 if ((terr = tile_terrain(adj_tile)) == T_UNKNOWN) {
5185 } else if (terrain_type_terrain_class(terr) == cls) {
5186 return TRUE;
5187 }
5189
5190 if (seen_unknown) {
5191 return TRI_MAYBE;
5192 } else {
5193 return TRI_NO;
5194 }
5195 }
5196 break;
5197 case TREL_SAME_REGION:
5198 if (tile_continent(other_context->tile) == 0) {
5199 return TRI_MAYBE;
5200 }
5202 || req->range == REQ_RANGE_CADJACENT
5203 || req->range == REQ_RANGE_ADJACENT),
5204 TRI_MAYBE,
5205 "Invalid range %d for tile relation \"%s\" req",
5207
5208 if (tile_continent(context->tile)
5209 == tile_continent(other_context->tile)) {
5210 return TRI_YES;
5211 } else {
5212 bool seen_unknown = (tile_continent(context->tile) == 0);
5214
5217
5218 if (adj_cont == cont) {
5219 return TRI_YES;
5220 } else if (adj_cont == 0) {
5222 }
5224
5225 if (seen_unknown) {
5226 return TRI_MAYBE;
5227 } else {
5228 return TRI_NO;
5229 }
5230 }
5231 break;
5233 if (tile_continent(context->tile) == 0
5234 || tile_continent(other_context->tile) == 0) {
5235 /* Note: We could still give a definitive TRI_NO answer if there are
5236 * too many different adjacent continents, but that's probably not
5237 * worth the added effort. */
5238 return TRI_MAYBE;
5239 }
5241 || req->range == REQ_RANGE_ADJACENT),
5242 TRI_MAYBE,
5243 "Invalid range %d for tile relation \"%s\" req",
5244 req->range,
5246
5247 {
5248 bool seen_unknown = FALSE;
5249 Continent_id cont = tile_continent(context->tile);
5251
5254
5255 if (adj_cont == 0) {
5257 } else if (adj_cont != cont && adj_cont != other_cont) {
5258 return TRI_NO;
5259 }
5261
5262 if (seen_unknown) {
5263 return TRI_MAYBE;
5264 } else {
5265 return TRI_YES;
5266 }
5267 }
5268 break;
5271 || req->range == REQ_RANGE_CADJACENT
5272 || req->range == REQ_RANGE_ADJACENT),
5273 TRI_MAYBE,
5274 "Invalid range %d for tile relation \"%s\" req",
5275 req->range,
5277
5278 {
5279 bool seen_maybe = FALSE;
5281
5283 wanted)) {
5284 case TRI_YES:
5285 return TRI_YES;
5286 case TRI_MAYBE:
5287 seen_maybe = TRUE;
5288 break;
5289 default:
5290 break;
5291 }
5292
5295 wanted)) {
5296 case TRI_YES:
5297 return TRI_YES;
5298 case TRI_MAYBE:
5299 seen_maybe = TRUE;
5300 break;
5301 default:
5302 break;
5303 }
5305
5306 if (seen_maybe) {
5307 return TRI_MAYBE;
5308 } else {
5309 return TRI_NO;
5310 }
5311 }
5312 break;
5313 default:
5314 break;
5315 }
5316
5318 "Illegal value %d for tile relationship requirement.",
5319 req->source.value.tilerel);
5320 return TRI_MAYBE;
5321}
5322
5323/**********************************************************************/
5326static bool is_city_in_tile(const struct tile *ptile,
5327 const struct city *pcity)
5328{
5329 if (pcity == nullptr) {
5330 return tile_city(ptile) != nullptr;
5331 } else {
5332 return is_city_center(pcity, ptile);
5333 }
5334}
5335
5336/**********************************************************************/
5344static enum fc_tristate
5346 const struct req_context *context,
5347 const struct req_context *other_context,
5348 const struct requirement *req)
5349{
5350 enum citytile_type citytile;
5351
5353
5354 citytile = req->source.value.citytile;
5355
5357 if (context->tile == nullptr) {
5358 return TRI_MAYBE;
5359 }
5360
5361 switch (citytile) {
5362 case CITYT_CENTER:
5363 switch (req->range) {
5364 case REQ_RANGE_TILE:
5366 context->city));
5368 if (is_city_in_tile(context->tile, context->city)) {
5369 return TRI_YES;
5370 }
5372 if (is_city_in_tile(adjc_tile, context->city)) {
5373 return TRI_YES;
5374 }
5376
5377 return TRI_NO;
5378 case REQ_RANGE_ADJACENT:
5379 if (is_city_in_tile(context->tile, context->city)) {
5380 return TRI_YES;
5381 }
5383 if (is_city_in_tile(adjc_tile, context->city)) {
5384 return TRI_YES;
5385 }
5387
5388 return TRI_NO;
5389 case REQ_RANGE_CITY:
5392 case REQ_RANGE_PLAYER:
5393 case REQ_RANGE_TEAM:
5394 case REQ_RANGE_ALLIANCE:
5395 case REQ_RANGE_WORLD:
5396 case REQ_RANGE_LOCAL:
5397 case REQ_RANGE_COUNT:
5398 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5399 break;
5400 }
5401
5402 return TRI_MAYBE;
5403 case CITYT_CLAIMED:
5404 switch (req->range) {
5405 case REQ_RANGE_TILE:
5406 return BOOL_TO_TRISTATE(context->tile->owner != nullptr);
5408 if (context->tile->owner != nullptr) {
5409 return TRI_YES;
5410 }
5412 if (adjc_tile->owner != nullptr) {
5413 return TRI_YES;
5414 }
5416
5417 return TRI_NO;
5418 case REQ_RANGE_ADJACENT:
5419 if (context->tile->owner != nullptr) {
5420 return TRI_YES;
5421 }
5423 if (adjc_tile->owner != nullptr) {
5424 return TRI_YES;
5425 }
5427
5428 return TRI_NO;
5429 case REQ_RANGE_CITY:
5432 case REQ_RANGE_PLAYER:
5433 case REQ_RANGE_TEAM:
5434 case REQ_RANGE_ALLIANCE:
5435 case REQ_RANGE_WORLD:
5436 case REQ_RANGE_LOCAL:
5437 case REQ_RANGE_COUNT:
5438 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5439 break;
5440 }
5441
5442 return TRI_MAYBE;
5443 case CITYT_EXTRAS_OWNED:
5444 switch (req->range) {
5445 case REQ_RANGE_TILE:
5446 return BOOL_TO_TRISTATE(context->tile->extras_owner != nullptr);
5448 if (context->tile->extras_owner != nullptr) {
5449 return TRI_YES;
5450 }
5452 if (adjc_tile->extras_owner != nullptr) {
5453 return TRI_YES;
5454 }
5456
5457 return TRI_NO;
5458 case REQ_RANGE_ADJACENT:
5459 if (context->tile->extras_owner != nullptr) {
5460 return TRI_YES;
5461 }
5463 if (adjc_tile->extras_owner != nullptr) {
5464 return TRI_YES;
5465 }
5467
5468 return TRI_NO;
5469 case REQ_RANGE_CITY:
5472 case REQ_RANGE_PLAYER:
5473 case REQ_RANGE_TEAM:
5474 case REQ_RANGE_ALLIANCE:
5475 case REQ_RANGE_WORLD:
5476 case REQ_RANGE_LOCAL:
5477 case REQ_RANGE_COUNT:
5478 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5479 break;
5480 }
5481
5482 return TRI_MAYBE;
5483 case CITYT_WORKED:
5484 switch (req->range) {
5485 case REQ_RANGE_TILE:
5486 return BOOL_TO_TRISTATE(context->tile->worked != nullptr);
5488 if (context->tile->worked != nullptr) {
5489 return TRI_YES;
5490 }
5492 if (adjc_tile->worked != nullptr) {
5493 return TRI_YES;
5494 }
5496
5497 return TRI_NO;
5498 case REQ_RANGE_ADJACENT:
5499 if (context->tile->worked != nullptr) {
5500 return TRI_YES;
5501 }
5503 if (adjc_tile->worked != nullptr) {
5504 return TRI_YES;
5505 }
5507
5508 return TRI_NO;
5509 case REQ_RANGE_CITY:
5512 case REQ_RANGE_PLAYER:
5513 case REQ_RANGE_TEAM:
5514 case REQ_RANGE_ALLIANCE:
5515 case REQ_RANGE_WORLD:
5516 case REQ_RANGE_LOCAL:
5517 case REQ_RANGE_COUNT:
5518 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5519 break;
5520 }
5521
5522 return TRI_MAYBE;
5524 {
5526 const struct tile *target_tile = context->tile, *cc_tile;
5527
5528 if (!context->city) {
5529 return TRI_MAYBE;
5530 }
5531 cc_tile = city_tile(context->city);
5532 if (!cc_tile) {
5533 /* Unplaced virtual city */
5534 return TRI_MAYBE;
5535 }
5537 /* Note: No special treatment of 0 == cc here*/
5538 switch (req->range) {
5539 case REQ_RANGE_TILE:
5542 if (tile_continent(target_tile) == cc) {
5543 return TRI_YES;
5544 }
5546 if (tile_continent(adjc_tile) == cc) {
5547 return TRI_YES;
5548 }
5550
5551 return TRI_NO;
5552 case REQ_RANGE_ADJACENT:
5553 if (tile_continent(target_tile) == cc) {
5554 return TRI_YES;
5555 }
5557 if (tile_continent(adjc_tile) == cc) {
5558 return TRI_YES;
5559 }
5561
5562 return TRI_NO;
5563 case REQ_RANGE_CITY:
5566 case REQ_RANGE_PLAYER:
5567 case REQ_RANGE_TEAM:
5568 case REQ_RANGE_ALLIANCE:
5569 case REQ_RANGE_WORLD:
5570 case REQ_RANGE_LOCAL:
5571 case REQ_RANGE_COUNT:
5572 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5573 break;
5574 }
5575 }
5576
5577 return TRI_MAYBE;
5579 {
5580 int n = 0;
5582 bool ukt = FALSE;
5583 const struct tile *target_tile = context->tile, *cc_tile;
5584
5585 if (!context->city) {
5586 return TRI_MAYBE;
5587 }
5588 cc_tile = city_tile(context->city);
5589 if (!cc_tile) {
5590 /* Unplaced virtual city */
5591 return TRI_MAYBE;
5592 }
5594 if (!cc) {
5595 /* Don't know the city center terrain class.
5596 * Maybe, the city floats? Even if the rules prohibit it... */
5597 return TRI_MAYBE;
5598 }
5601
5602 if (0 != tc) {
5603 bool seen = FALSE;
5604 int i = n;
5605
5606 if (tc == cc) {
5607 continue;
5608 }
5609 while (--i >= 0) {
5610 if (adjc_cont[i] == tc) {
5611 seen = TRUE;
5612 break;
5613 }
5614 }
5615 if (seen) {
5616 continue;
5617 }
5619 } else {
5620 /* Likely, it's a black tile in client and we don't know
5621 * We possibly can calculate, but keep it simple. */
5622 ukt = TRUE;
5623 }
5625 if (0 == n) {
5626 return ukt ? TRI_MAYBE : TRI_NO;
5627 }
5628
5629 switch (req->range) {
5630 case REQ_RANGE_TILE:
5631 {
5633
5634 if (cc == tc) {
5635 return TRI_NO;
5636 }
5637 if (0 == tc || ukt) {
5638 return TRI_MAYBE;
5639 }
5640 for (int i = 0; i < n; i++) {
5641 if (tc == adjc_cont[i]) {
5642 return TRI_YES;
5643 }
5644 }
5645 }
5646
5647 return TRI_NO;
5648 case REQ_RANGE_ADJACENT:
5649 if (ukt) {
5650 /* If ALL the tiles in range are on cc, we can say it's false */
5652 if (tile_continent(adjc_tile) != cc) {
5653 return TRI_MAYBE;
5654 }
5656
5657 return TRI_NO;
5658 } else {
5661
5662 if (0 == tc) {
5663 return TRI_MAYBE;
5664 }
5665 for (int i = 0; i < n; i++) {
5666 if (tc == adjc_cont[i]) {
5667 return TRI_YES;
5668 }
5669 }
5671 }
5672
5673 return TRI_NO;
5675 if (ukt) {
5676 /* If ALL the tiles in range are on cc, we can say it's false */
5678 if (tile_continent(cadjc_tile) != cc) {
5679 return TRI_MAYBE;
5680 }
5682 } else {
5685
5686 if (0 == tc) {
5687 return TRI_MAYBE;
5688 }
5689 for (int i = 0; i < n; i++) {
5690 if (tc == adjc_cont[i]) {
5691 return TRI_YES;
5692 }
5693 }
5695 }
5696
5697 return TRI_NO;
5698 case REQ_RANGE_CITY:
5701 case REQ_RANGE_PLAYER:
5702 case REQ_RANGE_TEAM:
5703 case REQ_RANGE_ALLIANCE:
5704 case REQ_RANGE_WORLD:
5705 case REQ_RANGE_LOCAL:
5706 case REQ_RANGE_COUNT:
5707 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5708 break;
5709 }
5710 }
5711
5712 return TRI_MAYBE;
5713 case CITYT_LAST:
5714 /* Handled below */
5715 break;
5716 }
5717
5718 /* Not implemented */
5719 log_error("is_req_active(): citytile %d not supported.",
5720 citytile);
5721 return TRI_MAYBE;
5722}
5723
5724/**********************************************************************/
5732static enum fc_tristate
5734 const struct req_context *context,
5735 const struct req_context *other_context,
5736 const struct requirement *req)
5737{
5738 enum citystatus_type citystatus;
5739
5741
5742 citystatus = req->source.value.citystatus;
5743
5744 if (context->city == nullptr) {
5745 return TRI_MAYBE;
5746 }
5747
5748 switch (citystatus) {
5750 switch (req->range) {
5751 case REQ_RANGE_CITY:
5752 if (context->city->original == nullptr) {
5753 return TRI_MAYBE;
5754 }
5755 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
5757 {
5758 enum fc_tristate ret;
5759
5760 if (city_owner(context->city) == context->city->original) {
5761 return TRI_YES;
5762 }
5763
5764 ret = TRI_NO;
5766 if (trade_partner == nullptr || trade_partner->original == nullptr) {
5767 ret = TRI_MAYBE;
5768 } else if (city_owner(trade_partner) == trade_partner->original) {
5769 return TRI_YES;
5770 }
5772
5773 return ret;
5774 }
5775 case REQ_RANGE_LOCAL:
5776 case REQ_RANGE_TILE:
5778 case REQ_RANGE_ADJACENT:
5780 case REQ_RANGE_PLAYER:
5781 case REQ_RANGE_TEAM:
5782 case REQ_RANGE_ALLIANCE:
5783 case REQ_RANGE_WORLD:
5784 case REQ_RANGE_COUNT:
5785 break;
5786 }
5787
5788 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
5789 req->range);
5790
5791 return TRI_MAYBE;
5792
5793 case CITYS_STARVED:
5794 switch (req->range) {
5795 case REQ_RANGE_CITY:
5796 return BOOL_TO_TRISTATE(context->city->had_famine);
5798 {
5799 enum fc_tristate ret;
5800
5801 if (context->city->had_famine) {
5802 return TRI_YES;
5803 }
5804
5805 ret = TRI_NO;
5807 if (trade_partner == nullptr) {
5808 ret = TRI_MAYBE;
5809 } else if (trade_partner->had_famine) {
5810 return TRI_YES;
5811 }
5813
5814 return ret;
5815 }
5816 case REQ_RANGE_LOCAL:
5817 case REQ_RANGE_TILE:
5819 case REQ_RANGE_ADJACENT:
5821 case REQ_RANGE_PLAYER:
5822 case REQ_RANGE_TEAM:
5823 case REQ_RANGE_ALLIANCE:
5824 case REQ_RANGE_WORLD:
5825 case REQ_RANGE_COUNT:
5826 break;
5827 }
5828
5829 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
5830 req->range);
5831
5832 return TRI_MAYBE;
5833
5834 case CITYS_DISORDER:
5835 switch (req->range) {
5836 case REQ_RANGE_CITY:
5837 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
5839 {
5840 enum fc_tristate ret;
5841
5842 if (context->city->anarchy > 0) {
5843 return TRI_YES;
5844 }
5845
5846 ret = TRI_NO;
5848 if (trade_partner == nullptr) {
5849 ret = TRI_MAYBE;
5850 } else if (trade_partner->anarchy > 0) {
5851 return TRI_YES;
5852 }
5854
5855 return ret;
5856 }
5857 case REQ_RANGE_LOCAL:
5858 case REQ_RANGE_TILE:
5860 case REQ_RANGE_ADJACENT:
5862 case REQ_RANGE_PLAYER:
5863 case REQ_RANGE_TEAM:
5864 case REQ_RANGE_ALLIANCE:
5865 case REQ_RANGE_WORLD:
5866 case REQ_RANGE_COUNT:
5867 break;
5868 }
5869
5870 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
5871 req->range);
5872
5873 return TRI_MAYBE;
5874
5875 case CITYS_CELEBRATION:
5876 switch (req->range) {
5877 case REQ_RANGE_CITY:
5878 return BOOL_TO_TRISTATE(context->city->rapture > 0);
5880 {
5881 enum fc_tristate ret;
5882
5883 if (context->city->rapture > 0) {
5884 return TRI_YES;
5885 }
5886
5887 ret = TRI_NO;
5889 if (trade_partner == nullptr) {
5890 ret = TRI_MAYBE;
5891 } else if (trade_partner->rapture > 0) {
5892 return TRI_YES;
5893 }
5895
5896 return ret;
5897 }
5898 case REQ_RANGE_LOCAL:
5899 case REQ_RANGE_TILE:
5901 case REQ_RANGE_ADJACENT:
5903 case REQ_RANGE_PLAYER:
5904 case REQ_RANGE_TEAM:
5905 case REQ_RANGE_ALLIANCE:
5906 case REQ_RANGE_WORLD:
5907 case REQ_RANGE_COUNT:
5908 break;
5909 }
5910
5911 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
5912 req->range);
5913
5914 return TRI_MAYBE;
5915
5916 case CITYS_TRANSFERRED:
5917 switch (req->range) {
5918 case REQ_RANGE_CITY:
5919 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
5921 {
5922 enum fc_tristate ret;
5923
5924 if (context->city->acquire_t != CACQ_FOUNDED) {
5925 return TRI_YES;
5926 }
5927
5928 ret = TRI_NO;
5930 if (trade_partner == nullptr) {
5931 ret = TRI_MAYBE;
5932 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
5933 return TRI_YES;
5934 }
5936
5937 return ret;
5938 }
5939 case REQ_RANGE_LOCAL:
5940 case REQ_RANGE_TILE:
5942 case REQ_RANGE_ADJACENT:
5944 case REQ_RANGE_PLAYER:
5945 case REQ_RANGE_TEAM:
5946 case REQ_RANGE_ALLIANCE:
5947 case REQ_RANGE_WORLD:
5948 case REQ_RANGE_COUNT:
5949 break;
5950 }
5951
5952 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
5953 req->range);
5954
5955 return TRI_MAYBE;
5956
5958 if (!is_server()) {
5959 /* Client has no idea. */
5960 return TRI_MAYBE;
5961 }
5962
5963 switch (req->range) {
5964 case REQ_RANGE_CITY:
5965 return BOOL_TO_TRISTATE(context->city->server.aarea != nullptr
5966 && context->city->server.aarea->capital);
5968 {
5969 enum fc_tristate ret;
5970
5971 if (context->city->server.aarea != nullptr
5972 && context->city->server.aarea->capital) {
5973 return TRI_YES;
5974 }
5975
5976 ret = TRI_NO;
5978 if (trade_partner == nullptr) {
5979 ret = TRI_MAYBE;
5980 } else if (trade_partner->server.aarea != nullptr
5981 && trade_partner->server.aarea->capital) {
5982 return TRI_YES;
5983 }
5985
5986 return ret;
5987 }
5988 case REQ_RANGE_LOCAL:
5989 case REQ_RANGE_TILE:
5991 case REQ_RANGE_ADJACENT:
5993 case REQ_RANGE_PLAYER:
5994 case REQ_RANGE_TEAM:
5995 case REQ_RANGE_ALLIANCE:
5996 case REQ_RANGE_WORLD:
5997 case REQ_RANGE_COUNT:
5998 break;
5999 }
6000
6001 fc_assert_msg(FALSE, "Invalid range %d for citystatus CapitalConnected.",
6002 req->range);
6003
6004 return TRI_MAYBE;
6005
6006 case CITYS_LAST:
6007 break;
6008 }
6009
6010 /* Not implemented */
6011 log_error("is_req_active(): citystatus %d not supported.",
6012 citystatus);
6013
6014 return TRI_MAYBE;
6015}
6016
6017/**********************************************************************/
6025static enum fc_tristate
6027 const struct req_context *context,
6028 const struct req_context *other_context,
6029 const struct requirement *req)
6030{
6032
6033 if (context->city == nullptr) {
6034 return TRI_MAYBE;
6035 } else {
6036 if (req->range == REQ_RANGE_TRADE_ROUTE) {
6037 enum fc_tristate ret;
6038
6039 if (city_size_get(context->city) >= req->source.value.minsize) {
6040 return TRI_YES;
6041 }
6042
6043 ret = TRI_NO;
6045 if (trade_partner == nullptr) {
6046 ret = TRI_MAYBE;
6047 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
6048 return TRI_YES;
6049 }
6051
6052 return ret;
6053 } else {
6055 >= req->source.value.minsize);
6056 }
6057 }
6058}
6059
6060/**********************************************************************/
6068static enum fc_tristate
6070 const struct req_context *context,
6071 const struct req_context *other_context,
6072 const struct requirement *req)
6073{
6074 const struct counter *count;
6075
6077
6078 count = req->source.value.counter;
6079
6080 if (context->city == nullptr) {
6081 return TRI_MAYBE;
6082 }
6083 return BOOL_TO_TRISTATE(count->checkpoint <=
6084 context->city->counter_values[
6085 counter_index(count)]);
6086}
6087
6088/**********************************************************************/
6096static enum fc_tristate
6098 const struct req_context *context,
6099 const struct req_context *other_context,
6100 const struct requirement *req)
6101{
6102 const struct achievement *achievement;
6103
6105
6107
6108 if (req->range == REQ_RANGE_WORLD) {
6110 } else if (context->player == nullptr) {
6111 return TRI_MAYBE;
6112 } else if (req->range == REQ_RANGE_ALLIANCE
6113 || req->range == REQ_RANGE_TEAM) {
6114 players_iterate_alive(plr2) {
6115 if (players_in_same_range(context->player, plr2, req->range)
6117 return TRI_YES;
6118 }
6120 return TRI_NO;
6121 } else if (req->range == REQ_RANGE_PLAYER) {
6123 return TRI_YES;
6124 } else {
6125 return TRI_NO;
6126 }
6127 }
6128
6129 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
6130
6131 return TRI_MAYBE;
6132}
6133
6134/**********************************************************************/
6142static enum fc_tristate
6144 const struct req_context *context,
6145 const struct req_context *other_context,
6146 const struct requirement *req)
6147{
6148 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
6149
6150 fc_assert_ret_val(req != nullptr, TRI_MAYBE);
6151 fc_assert(context != nullptr);
6152
6153 switch (req->source.kind) {
6154 case VUT_MINLATITUDE:
6155 min = req->source.value.latitude;
6156 break;
6157 case VUT_MAXLATITUDE:
6158 max = req->source.value.latitude;
6159 break;
6160 default:
6162 || req->source.kind == VUT_MAXLATITUDE);
6163 break;
6164 }
6165
6166 switch (req->range) {
6167 case REQ_RANGE_WORLD:
6169 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
6170
6171 case REQ_RANGE_TILE:
6172 if (context->tile == nullptr) {
6173 return TRI_MAYBE;
6174 } else {
6176
6178 }
6179
6181 if (context->tile == nullptr) {
6182 return TRI_MAYBE;
6183 }
6184
6187
6189 return TRI_YES;
6190 }
6192 return TRI_NO;
6193
6194 case REQ_RANGE_ADJACENT:
6195 if (!context->tile) {
6196 return TRI_MAYBE;
6197 }
6198
6201
6203 return TRI_YES;
6204 }
6206 return TRI_NO;
6207
6208 case REQ_RANGE_CITY:
6211 case REQ_RANGE_PLAYER:
6212 case REQ_RANGE_TEAM:
6213 case REQ_RANGE_ALLIANCE:
6214 case REQ_RANGE_LOCAL:
6215 case REQ_RANGE_COUNT:
6216 break;
6217 }
6218
6220 "Illegal range %d for latitude requirement.", req->range);
6221
6222 return TRI_MAYBE;
6223}
6224
6225/**********************************************************************/
6233static enum fc_tristate
6235 const struct req_context *context,
6236 const struct req_context *other_context,
6237 const struct requirement *req)
6238{
6240
6241 switch (req->range) {
6242 case REQ_RANGE_TILE:
6243 if (context->tile == nullptr || other_context->tile == nullptr) {
6244 return TRI_MAYBE;
6245 }
6246 return BOOL_TO_TRISTATE(
6248 <= req->source.value.distance_sq
6249 );
6250 default:
6251 break;
6252 }
6253
6255 "Illegal range %d for max squared distance requirement.",
6256 req->range);
6257
6258 return TRI_MAYBE;
6259}
6260
6261/**********************************************************************/
6269static enum fc_tristate
6271 const struct req_context *context,
6272 const struct req_context *other_context,
6273 const struct requirement *req)
6274{
6275 int max_tiles, min_tiles = 1;
6276
6278
6279 switch (req->range) {
6281 case REQ_RANGE_ADJACENT:
6282 if (context->tile == nullptr) {
6283 /* The tile itself is included in the range */
6284 max_tiles = 1 + ((req->range == REQ_RANGE_CADJACENT)
6285 ? nmap->num_cardinal_dirs
6286 : nmap->num_valid_dirs);
6287
6288 break;
6289 } else {
6290 Continent_id cont = tile_continent(context->tile);
6291
6292 /* Count how many adjacent tiles there actually are as we go along */
6293 max_tiles = 1;
6294
6297
6298 if (adj_cont == 0 || cont == 0) {
6299 max_tiles++;
6300 } else if (adj_cont == cont) {
6301 min_tiles++;
6302 max_tiles++;
6303 }
6305 }
6306 break;
6308 {
6309 Continent_id cont = context->tile ? tile_continent(context->tile) : 0;
6310
6313
6314 /* Note: We could come up with a better upper bound by subtracting
6315 * all other continent/ocean sizes, or all except the largest if we
6316 * don't know the tile.
6317 * We could even do a flood-fill count of the unknown area bordered
6318 * by known tiles of the continent.
6319 * Probably not worth the effort though. */
6320 max_tiles = nmap->xsize * nmap->ysize;
6321
6322 if (cont > 0) {
6323 min_tiles = nmap->continent_sizes[cont];
6324 if (is_whole_continent_known(cont)) {
6326 }
6327 } else if (cont < 0) {
6328 min_tiles = nmap->ocean_sizes[-cont];
6329 if (is_whole_ocean_known(-cont)) {
6331 }
6332 }
6333 }
6334 break;
6335 default:
6337 "Illegal range %d for max region tiles requirement.",
6338 req->range);
6339 return TRI_MAYBE;
6340 }
6341
6342 if (min_tiles > req->source.value.region_tiles) {
6343 return TRI_NO;
6344 } else if (max_tiles <= req->source.value.region_tiles) {
6345 return TRI_YES;
6346 }
6347 return TRI_MAYBE;
6348}
6349
6350/**********************************************************************/
6358static enum fc_tristate
6360 const struct req_context *context,
6361 const struct req_context *other_context,
6362 const struct requirement *req)
6363{
6365
6367}
6368
6369/**********************************************************************/
6377static enum fc_tristate
6379 const struct req_context *context,
6380 const struct req_context *other_context,
6381 const struct requirement *req)
6382{
6384
6386 >= req->source.value.mincalfrag);
6387}
6388
6389/**********************************************************************/
6397static enum fc_tristate
6399 const struct req_context *context,
6400 const struct req_context *other_context,
6401 const struct requirement *req)
6402{
6404
6405 return BOOL_TO_TRISTATE(
6407}
6408
6409/**********************************************************************/
6417static enum fc_tristate
6419 const struct req_context *context,
6420 const struct req_context *other_context,
6421 const struct requirement *req)
6422{
6424
6425 return BOOL_TO_TRISTATE(
6427}
6428
6429/**********************************************************************/
6437static enum fc_tristate
6439 const struct req_context *context,
6440 const struct req_context *other_context,
6441 const struct requirement *req)
6442{
6444
6446 req->source.value.ssetval));
6447}
6448
6449/* Not const for potential ruleset-related adjustment */
6452
6453 /* Alphabetical order of enum constant */
6519};
6520
6521/**********************************************************************/
6535 const struct req_context *other_context,
6536 const struct requirement *req,
6537 const enum req_problem_type prob_type)
6538{
6539 const struct civ_map *nmap = &(wld.map);
6541 req);
6542
6543 if (eval == TRI_MAYBE) {
6544 if (prob_type == RPT_POSSIBLE) {
6545 return TRUE;
6546 } else {
6547 return FALSE;
6548 }
6549 }
6550 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
6551}
6552
6553/**********************************************************************/
6562static
6564 const struct req_context *context,
6565 const struct req_context *other_context,
6566 const struct requirement *req)
6567{
6568 if (!context) {
6570 }
6571 if (!other_context) {
6573 }
6574
6575 if (req->source.kind >= VUT_COUNT) {
6576 log_error("tri_req_present(): invalid source kind %d.",
6577 req->source.kind);
6578 return TRI_NO;
6579 }
6580
6582
6583 return req_definitions[req->source.kind].cb(nmap, context,
6584 other_context, req);
6585}
6586
6587/**********************************************************************/
6597 const struct req_context *other_context,
6598 const struct requirement *req)
6599{
6600 const struct civ_map *nmap = &(wld.map);
6602
6603 if (!req->present) {
6604 if (TRI_NO == eval) {
6605 return TRI_YES;
6606 }
6607 if (TRI_YES == eval) {
6608 return TRI_NO;
6609 }
6610 }
6611
6612 return eval;
6613}
6614
6615/**********************************************************************/
6631 const struct req_context *other_context,
6632 const struct requirement_vector *reqs,
6633 const enum req_problem_type prob_type)
6634{
6637 return FALSE;
6638 }
6640
6641 return TRUE;
6642}
6643
6644/**********************************************************************/
6649 const enum req_range max_range,
6650 const struct req_context *context,
6651 const struct req_context *other_context,
6652 const struct requirement_vector *reqs,
6653 const enum req_problem_type prob_type)
6654{
6656 if (preq->range >= min_range && preq->range <= max_range) {
6658 return FALSE;
6659 }
6660 }
6662
6663 return TRUE;
6664}
6665
6666/**********************************************************************/
6672enum fc_tristate
6674 const struct req_context *context,
6675 const struct req_context *other_context,
6676 const struct requirement *req)
6677{
6678 /* FIXME: Doubles code from calendar.c */
6682 int fragment1 = fragment; /* If fragments don't advance */
6683 int year_inc, year_inc1;
6686 bool present, present1;
6687
6688 fc_assert(pass >= 0 && period >= 0);
6689 if (slowdown >= 3) {
6690 if (ypt > 1) {
6691 ypt = 1;
6692 }
6693 } else if (slowdown >= 2) {
6694 if (ypt > 2) {
6695 ypt = 2;
6696 }
6697 } else if (slowdown >= 1) {
6698 if (ypt > 5) {
6699 ypt = 5;
6700 }
6701 }
6702 year_inc = ypt * pass;
6705 int fragment_years;
6706
6707 fragment += fpt * pass;
6715 }
6717 if (year_inc + game.info.year >= 0) {
6718 year_inc++;
6719 year_inc1++;
6720 } else if (year_inc1 + game.info.year >= 0) {
6721 year_inc1++;
6722 }
6723 }
6724
6725 switch (req->source.kind) {
6726 case VUT_AGE:
6727 switch (req->range) {
6728 case REQ_RANGE_LOCAL:
6729 if (context->unit == nullptr || !is_server()) {
6730 return TRI_MAYBE;
6731 } else {
6732 int ua = game.info.turn + pass - context->unit->birth_turn;
6733
6734 present = req->source.value.age <= ua;
6735 present1 = req->source.value.age <= ua + period;
6736 }
6737 break;
6738 case REQ_RANGE_CITY:
6739 if (context->city == nullptr) {
6740 return TRI_MAYBE;
6741 } else {
6742 int ca = game.info.turn + pass - context->city->turn_founded;
6743
6744 present = req->source.value.age <= ca;
6745 present1 = req->source.value.age <= ca + period;
6746 }
6747 break;
6748 case REQ_RANGE_PLAYER:
6749 if (context->player == nullptr) {
6750 return TRI_MAYBE;
6751 } else {
6752 present = req->source.value.age
6753 <= player_age(context->player) + pass;
6754 present1 = req->source.value.age
6755 <= player_age(context->player) + pass + period;
6756 }
6757 break;
6758 default:
6759 return TRI_MAYBE;
6760 }
6761 break;
6762 case VUT_FORM_AGE:
6763 if (context->unit == nullptr || !is_server()) {
6764 return TRI_MAYBE;
6765 } else {
6766 int ua = game.info.turn + pass - context->unit->current_form_turn;
6767
6768 present = req->source.value.form_age <= ua;
6769 present1 = req->source.value.form_age <= ua + period;
6770 }
6771 break;
6772 case VUT_MINYEAR:
6773 present = game.info.year + year_inc >= req->source.value.minyear;
6775 break;
6776 case VUT_MINCALFRAG:
6778 /* Hope that the requirement is valid and fragments advance fine */
6779 return TRI_YES;
6780 }
6781 present = fragment >= req->source.value.mincalfrag;
6783 break;
6784 default:
6785 /* No special handling invented */
6786 return tri_req_active(context, other_context, req);
6787 }
6788 return BOOL_TO_TRISTATE(req->present
6789 ? present || present1 : !(present && present1));
6790}
6791
6792/**********************************************************************/
6798 (const struct req_context *context,
6799 const struct req_context *other_context,
6800 const struct requirement *req,
6801 void *data, int n_data)
6802{
6803 int i;
6804
6805 fc_assert_ret_val(data || n_data == 0, TRI_NO);
6806
6807 for (i = 0; i < n_data; i++) {
6808 if (are_requirements_contradictions(&((struct requirement *) data)[i],
6809 req)) {
6810 return TRI_NO;
6811 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
6812 return TRI_YES;
6813 }
6814 }
6815
6816 return tri_req_active(context, other_context, req);
6817}
6818
6819/**********************************************************************/
6825enum fc_tristate
6827 const struct req_context *other_context,
6828 const struct requirement_vector *reqs,
6831 void *data, int n_data)
6832{
6833 bool active = TRUE;
6834 bool certain = TRUE;
6835
6836 fc_assert_ret_val(tester != nullptr, TRI_NO);
6837
6840 data, n_data)) {
6841 case TRI_NO:
6842 active = FALSE;
6843 certain = TRUE;
6844 break;
6845 case TRI_YES:
6846 break;
6847 case TRI_MAYBE:
6848 certain = FALSE;
6849 if (maybe_reqs) {
6851 }
6852 break;
6853 default:
6855 active = FALSE;
6856 }
6857 if (!active) {
6858 break;
6859 }
6861
6862 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
6863}
6864
6865/**********************************************************************/
6875 const struct requirement *req)
6876{
6877 enum req_unchanging_status s;
6878 const struct civ_map *nmap = &(wld.map);
6879
6882 "Invalid source kind %d.", req->source.kind);
6884
6885 if (req->survives) {
6886 /* Special case for surviving requirements */
6887 /* Buildings may obsolete even here */
6888 if (VUT_IMPROVEMENT == req->source.kind) {
6889 const struct impr_type *b = req->source.value.building;
6890
6892 if (improvement_obsolete(context->player, b, context->city)) {
6893 /* FIXME: Sometimes can unobsolete, but considering it
6894 * may sometimes put the function on endless recursion */
6895 return REQUCH_ACT; /* Mostly about techs */
6896 } else {
6897 /* NOTE: May obsoletion reqs be unchanging? Hardly but why not. */
6898 return REQUCH_NO;
6899 }
6900 }
6901 }
6902 s = unchanging_present(nmap, s, context, req);
6903 if (s != REQUCH_NO) {
6904 return unchanging_noally(nmap, s, context, req);
6905 }
6906 } else {
6909
6910 if (cond) {
6911 return cond(nmap, s, context, req);
6912 }
6913 }
6914
6915 return s;
6916}
6917
6918/**********************************************************************/
6923 const struct req_context *other_context,
6924 const struct requirement *req,
6926{
6928
6929 if (REQUCH_NO != u) {
6930 /* Presence is precalculated */
6931 bool auto_present = (req->survives
6932 && !(VUT_IMPROVEMENT == req->source.kind
6936
6937 if (auto_present ? req->present
6939 /* Unchanging but does not block */
6940 return REQUCH_NO;
6941 }
6942 }
6943
6944 return u;
6945}
6946
6947/**********************************************************************/
6951bool is_req_in_vec(const struct requirement *req,
6952 const struct requirement_vector *vec)
6953{
6955 if (are_requirements_equal(req, preq)) {
6956 return TRUE;
6957 }
6959
6960 return FALSE;
6961}
6962
6963/**********************************************************************/
6971 enum universals_n kind)
6972{
6974 if (preq->present && preq->source.kind == kind) {
6975 return TRUE;
6976 }
6978 return FALSE;
6979}
6980
6981/**********************************************************************/
6990{
6991 switch (source->kind) {
6992 case VUT_ACTION:
6993 return !action_is_in_use(source->value.action);
6994 case VUT_UTFLAG:
6995 return !utype_flag_is_in_use(source->value.unitflag);
6996 case VUT_UCFLAG:
6997 return !uclass_flag_is_in_use(source->value.unitclassflag);
6998 case VUT_EXTRAFLAG:
6999 return !extra_flag_is_in_use(source->value.extraflag);
7000 case VUT_MINLATITUDE:
7001 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
7002 case VUT_MAXLATITUDE:
7003 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
7004 case VUT_COUNTER:
7005 case VUT_OTYPE:
7006 case VUT_SPECIALIST:
7007 case VUT_AI_LEVEL:
7008 case VUT_CITYTILE:
7009 case VUT_CITYSTATUS:
7010 case VUT_STYLE:
7011 case VUT_TOPO:
7012 case VUT_WRAP:
7013 case VUT_SERVERSETTING:
7014 case VUT_NATION:
7015 case VUT_NATIONGROUP:
7016 case VUT_ADVANCE:
7017 case VUT_TECHFLAG:
7018 case VUT_GOVERNMENT:
7019 case VUT_GOVFLAG:
7020 case VUT_ACHIEVEMENT:
7021 case VUT_IMPROVEMENT:
7022 case VUT_SITE:
7023 case VUT_IMPR_GENUS:
7024 case VUT_IMPR_FLAG:
7025 case VUT_PLAYER_FLAG:
7026 case VUT_PLAYER_STATE:
7027 case VUT_MINSIZE:
7028 case VUT_MINCULTURE:
7029 case VUT_MINFOREIGNPCT:
7030 case VUT_MINTECHS:
7031 case VUT_FUTURETECHS:
7032 case VUT_MINCITIES:
7033 case VUT_NATIONALITY:
7034 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
7035 case VUT_DIPLREL:
7036 case VUT_DIPLREL_TILE:
7037 case VUT_DIPLREL_TILE_O:
7042 case VUT_UTYPE:
7043 case VUT_UCLASS:
7044 case VUT_MINVETERAN:
7045 case VUT_UNITSTATE:
7046 case VUT_ACTIVITY:
7047 case VUT_MINMOVES:
7048 case VUT_MINHP:
7049 case VUT_AGE:
7050 case VUT_FORM_AGE:
7051 case VUT_ROADFLAG:
7052 case VUT_MINCALFRAG:
7053 case VUT_TERRAIN:
7054 case VUT_EXTRA:
7055 case VUT_GOOD:
7056 case VUT_TERRAINCLASS:
7057 case VUT_TERRFLAG:
7058 case VUT_TERRAINALTER:
7059 case VUT_MINYEAR:
7062 case VUT_TILE_REL:
7063 case VUT_NONE:
7064 case VUT_COUNT:
7065 /* Not implemented. */
7066 break;
7067 }
7068
7069 return FALSE;
7070}
7071
7072/**********************************************************************/
7081{
7082 /* Not known to be impossible to fulfill */
7083 return req->present && universal_never_there(&req->source);
7084}
7085
7086/**********************************************************************/
7095{
7098 return TRUE;
7099 }
7101
7102 /* Not known to be impossible to fulfill */
7103 return FALSE;
7104}
7105
7106/**********************************************************************/
7116 const struct requirement_vector *vec)
7117{
7118 if (vec) {
7119 return 0;
7120 } else {
7121 return -1;
7122 }
7123}
7124
7125/********************************************************************/
7134struct requirement_vector *
7136{
7137 fc_assert_ret_val(number == 0, nullptr);
7138
7139 return (struct requirement_vector *)parent_item;
7140}
7141
7142/**********************************************************************/
7153const char *req_vec_change_translation(const struct req_vec_change *change,
7155{
7156 const char *req_vec_description;
7157 static char buf[MAX_LEN_NAME * 3];
7158 struct astring astr;
7159
7160 fc_assert_ret_val(change, nullptr);
7162 nullptr);
7163
7164 /* Get rid of the previous. */
7165 buf[0] = '\0';
7166
7167 if (namer == nullptr) {
7168 /* TRANS: default description of a requirement vector
7169 * (used in ruledit) */
7170 req_vec_description = _("the requirement vector");
7171 } else {
7173 }
7174
7175 switch (change->operation) {
7176 case RVCO_REMOVE:
7177 fc_snprintf(buf, sizeof(buf),
7178 /* TRANS: remove a requirement from a requirement vector
7179 * (in ruledit).
7180 * The first %s is the operation.
7181 * The second %s is the requirement.
7182 * The third %s is a description of the requirement vector,
7183 * like "actor_reqs" */
7184 _("%s %s from %s"),
7186 req_to_fstring(&change->req, &astr),
7188 astr_free(&astr);
7189 break;
7190 case RVCO_APPEND:
7191 fc_snprintf(buf, sizeof(buf),
7192 /* TRANS: append a requirement to a requirement vector
7193 * (in ruledit).
7194 * The first %s is the operation.
7195 * The second %s is the requirement.
7196 * The third %s is a description of the requirement vector,
7197 * like "actor_reqs" */
7198 _("%s %s to %s"),
7200 req_to_fstring(&change->req, &astr),
7202 astr_free(&astr);
7203 break;
7204 case RVCO_NOOP:
7205 fc_snprintf(buf, sizeof(buf),
7206 /* TRANS: do nothing to a requirement vector (in ruledit).
7207 * The first %s is a description of the requirement vector,
7208 * like "actor_reqs" */
7209 _("Do nothing to %s"), req_vec_description);
7210 break;
7211 }
7212
7213 return buf;
7214}
7215
7216/**********************************************************************/
7229 const void *parent_item)
7230{
7231 struct requirement_vector *target
7232 = getter(parent_item, modification->vector_number);
7233 int i = 0;
7234
7235 switch (modification->operation) {
7236 case RVCO_APPEND:
7238 return TRUE;
7239 case RVCO_REMOVE:
7243 return TRUE;
7244 }
7245 i++;
7247 return FALSE;
7248 case RVCO_NOOP:
7249 return FALSE;
7250 }
7251
7252 return FALSE;
7253}
7254
7255/**********************************************************************/
7265struct req_vec_problem *
7267 const char *description,
7268 const char *description_translated)
7269{
7270 struct req_vec_problem *out;
7271 int i;
7272
7273 out = fc_malloc(sizeof(*out));
7274
7275 fc_strlcpy(out->description, description, sizeof(out->description));
7276 fc_strlcpy(out->description_translated, _(description_translated),
7277 sizeof(out->description_translated));
7278
7279 out->num_suggested_solutions = num_suggested_solutions;
7280 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
7281 * sizeof(struct req_vec_change));
7282 for (i = 0; i < out->num_suggested_solutions; i++) {
7283 /* No suggestions are ready yet. */
7284 out->suggested_solutions[i].operation = RVCO_NOOP;
7285 out->suggested_solutions[i].vector_number = -1;
7286 out->suggested_solutions[i].req.source.kind = VUT_NONE;
7287 }
7288
7289 return out;
7290}
7291
7292/**********************************************************************/
7302 const char *descr, ...)
7303{
7304 char description[500];
7305 char description_translated[500];
7306 va_list ap;
7307
7308 va_start(ap, descr);
7309 fc_vsnprintf(description, sizeof(description), descr, ap);
7310 va_end(ap);
7311
7312 va_start(ap, descr);
7314 _(descr), ap);
7315 va_end(ap);
7316
7319}
7320
7321/**********************************************************************/
7328{
7329 FC_FREE(issue->suggested_solutions);
7330 issue->num_suggested_solutions = 0;
7331
7332 FC_FREE(issue);
7333}
7334
7335/**********************************************************************/
7347struct req_vec_problem *
7350 const void *parent_item)
7351{
7352 int i, j;
7354
7355 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7356 /* No vector. */
7357 return nullptr;
7358 }
7359
7360 if (get_num == nullptr || parent_item == nullptr) {
7361 vec_num = 0;
7362 } else {
7363 vec_num = get_num(parent_item, vec);
7364 }
7365
7366 /* Look for contradictions */
7367 for (i = 0; i < requirement_vector_size(vec); i++) {
7368 struct requirement *preq = requirement_vector_get(vec, i);
7369 for (j = 0; j < requirement_vector_size(vec); j++) {
7370 struct requirement *nreq = requirement_vector_get(vec, j);
7371
7373 struct req_vec_problem *problem;
7374 struct astring astr;
7375 struct astring nastr;
7376
7378 N_("Requirements {%s} and {%s} contradict each other."),
7380
7381 astr_free(&astr);
7382 astr_free(&nastr);
7383
7384 /* The solution is to remove one of the contradictions. */
7385 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7386 problem->suggested_solutions[0].vector_number = vec_num;
7387 problem->suggested_solutions[0].req = *preq;
7388
7389 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7390 problem->suggested_solutions[1].vector_number = vec_num;
7391 problem->suggested_solutions[1].req = *nreq;
7392
7393 /* Only the first contradiction is reported. */
7394 return problem;
7395 }
7396 }
7397 }
7398
7399 return nullptr;
7400}
7401
7402/**********************************************************************/
7413struct req_vec_problem *
7416 const void *parent_item)
7417{
7418 /* Check for self contradictins. */
7420}
7421
7422/**********************************************************************/
7435struct req_vec_problem *
7438 const void *parent_item)
7439{
7440 int i;
7442 struct req_vec_problem *problem = nullptr;
7443
7444 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7445 /* No vector. */
7446 return nullptr;
7447 }
7448
7449 if (get_num == nullptr || parent_item == nullptr) {
7450 vec_num = 0;
7451 } else {
7452 vec_num = get_num(parent_item, vec);
7453 }
7454
7455 /* Look for contradictions */
7456 for (i = 0; i < requirement_vector_size(vec); i++) {
7457 struct requirement *preq = requirement_vector_get(vec, i);
7458
7459 if (universal_never_there(&preq->source)) {
7460 struct astring astr;
7461
7462 if (preq->present) {
7463 /* The requirement vector can never be fulfilled. Removing the
7464 * requirement makes it possible to fulfill it. This is a rule
7465 * change and shouldn't be "fixed" without thinking. Don't offer any
7466 * automatic solution to prevent mindless "fixes". */
7467 /* TRANS: Ruledit warns a user about an unused requirement vector
7468 * that never can be fulfilled because it asks for something that
7469 * never will be there. */
7470 if (problem == nullptr) {
7472 N_("Requirement {%s} requires %s but it will never be"
7473 " there."),
7475 astr_free(&astr);
7476 }
7477
7478 /* Continue to check if other problems have a solution proposal,
7479 * and prefer to return those. */
7480 continue;
7481 }
7482
7483 if (problem != nullptr) {
7484 /* Free previous one (one with no solution proposals) */
7486 }
7487
7489 N_("Requirement {%s} mentions %s but it will never be there."),
7491
7492 astr_free(&astr);
7493
7494 /* The solution is to remove the reference to the missing
7495 * universal. */
7496 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7497 problem->suggested_solutions[0].vector_number = vec_num;
7498 problem->suggested_solutions[0].req = *preq;
7499
7500 /* Only the first missing universal is reported. */
7501 return problem;
7502 }
7503 }
7504
7505 return problem;
7506}
7507
7508/**********************************************************************/
7521struct req_vec_problem *
7524 const void *parent_item)
7525{
7526 int i, j;
7528
7529 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7530 /* No vector. */
7531 return nullptr;
7532 }
7533
7534 if (get_num == nullptr || parent_item == nullptr) {
7535 vec_num = 0;
7536 } else {
7537 vec_num = get_num(parent_item, vec);
7538 }
7539
7540 /* Look for repeated requirements */
7541 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
7542 struct requirement *preq = requirement_vector_get(vec, i);
7543 for (j = i + 1; j < requirement_vector_size(vec); j++) {
7544 struct requirement *nreq = requirement_vector_get(vec, j);
7545
7547 struct req_vec_problem *problem;
7548 struct astring astr;
7549 struct astring nastr;
7550
7552 N_("Requirements {%s} and {%s} are the same."),
7554
7555 astr_free(&astr);
7556 astr_free(&nastr);
7557
7558 /* The solution is to remove one of the redundant requirements. */
7559 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7560 problem->suggested_solutions[0].vector_number = vec_num;
7561 problem->suggested_solutions[0].req = *preq;
7562
7563 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7564 problem->suggested_solutions[1].vector_number = vec_num;
7565 problem->suggested_solutions[1].req = *nreq;
7566
7567 /* Only the first redundancy is reported. */
7568 return problem;
7569 }
7570 }
7571 }
7572
7573 return nullptr;
7574}
7575
7576/**********************************************************************/
7588struct req_vec_problem *
7591 const void *parent_item)
7592{
7593 struct req_vec_problem *out;
7594
7596 if (out != nullptr) {
7597 /* A bug, not just a potential improvement */
7598 return out;
7599 }
7600
7601 /* Check if a universal that never will appear in the game is checked. */
7603 if (out != nullptr) {
7604 return out;
7605 }
7606
7607 /* Check if a requirement is redundant. */
7609 return out;
7610}
7611
7612/**********************************************************************/
7617 const struct universal *psource2)
7618{
7619 if (psource1->kind != psource2->kind) {
7620 return FALSE;
7621 }
7622 switch (psource1->kind) {
7623 case VUT_NONE:
7624 return TRUE;
7625 case VUT_COUNTER:
7626 return psource1->value.counter == psource2->value.counter;
7627 case VUT_ADVANCE:
7628 return psource1->value.advance == psource2->value.advance;
7629 case VUT_TECHFLAG:
7630 return psource1->value.techflag == psource2->value.techflag;
7631 case VUT_GOVERNMENT:
7632 return psource1->value.govern == psource2->value.govern;
7633 case VUT_GOVFLAG:
7634 return psource1->value.govflag == psource2->value.govflag;
7635 case VUT_ACHIEVEMENT:
7636 return psource1->value.achievement == psource2->value.achievement;
7637 case VUT_STYLE:
7638 return psource1->value.style == psource2->value.style;
7639 case VUT_IMPROVEMENT:
7640 case VUT_SITE:
7641 return psource1->value.building == psource2->value.building;
7642 case VUT_IMPR_GENUS:
7643 return psource1->value.impr_genus == psource2->value.impr_genus;
7644 case VUT_IMPR_FLAG:
7645 return psource1->value.impr_flag == psource2->value.impr_flag;
7646 case VUT_PLAYER_FLAG:
7647 return psource1->value.plr_flag == psource2->value.plr_flag;
7648 case VUT_PLAYER_STATE:
7649 return psource1->value.plrstate == psource2->value.plrstate;
7650 case VUT_EXTRA:
7651 return psource1->value.extra == psource2->value.extra;
7652 case VUT_GOOD:
7653 return psource1->value.good == psource2->value.good;
7654 case VUT_TERRAIN:
7655 return psource1->value.terrain == psource2->value.terrain;
7656 case VUT_TERRFLAG:
7657 return psource1->value.terrainflag == psource2->value.terrainflag;
7658 case VUT_NATION:
7659 return psource1->value.nation == psource2->value.nation;
7660 case VUT_NATIONGROUP:
7661 return psource1->value.nationgroup == psource2->value.nationgroup;
7662 case VUT_NATIONALITY:
7663 return psource1->value.nationality == psource2->value.nationality;
7664 case VUT_ORIGINAL_OWNER:
7665 return psource1->value.origowner == psource2->value.origowner;
7666 case VUT_DIPLREL:
7667 case VUT_DIPLREL_TILE:
7668 case VUT_DIPLREL_TILE_O:
7671 return psource1->value.diplrel == psource2->value.diplrel;
7672 case VUT_UTYPE:
7673 return psource1->value.utype == psource2->value.utype;
7674 case VUT_UTFLAG:
7675 return psource1->value.unitflag == psource2->value.unitflag;
7676 case VUT_UCLASS:
7677 return psource1->value.uclass == psource2->value.uclass;
7678 case VUT_UCFLAG:
7679 return psource1->value.unitclassflag == psource2->value.unitclassflag;
7680 case VUT_MINVETERAN:
7681 return psource1->value.minveteran == psource2->value.minveteran;
7682 case VUT_UNITSTATE:
7683 return psource1->value.unit_state == psource2->value.unit_state;
7684 case VUT_ACTIVITY:
7685 return psource1->value.activity == psource2->value.activity;
7686 case VUT_MINMOVES:
7687 return psource1->value.minmoves == psource2->value.minmoves;
7688 case VUT_MINHP:
7689 return psource1->value.min_hit_points == psource2->value.min_hit_points;
7690 case VUT_AGE:
7691 return psource1->value.age == psource2->value.age;
7692 case VUT_FORM_AGE:
7693 return psource1->value.form_age == psource2->value.form_age;
7694 case VUT_MINTECHS:
7695 return psource1->value.min_techs == psource2->value.min_techs;
7696 case VUT_FUTURETECHS:
7697 return psource1->value.future_techs == psource2->value.future_techs;
7698 case VUT_MINCITIES:
7699 return psource1->value.min_cities == psource2->value.min_cities;
7700 case VUT_ACTION:
7701 return (action_number(psource1->value.action)
7702 == action_number(psource2->value.action));
7703 case VUT_OTYPE:
7704 return psource1->value.outputtype == psource2->value.outputtype;
7705 case VUT_SPECIALIST:
7706 return psource1->value.specialist == psource2->value.specialist;
7707 case VUT_MINSIZE:
7708 return psource1->value.minsize == psource2->value.minsize;
7709 case VUT_MINCULTURE:
7710 return psource1->value.minculture == psource2->value.minculture;
7711 case VUT_MINFOREIGNPCT:
7712 return psource1->value.minforeignpct == psource2->value.minforeignpct;
7713 case VUT_AI_LEVEL:
7714 return psource1->value.ai_level == psource2->value.ai_level;
7716 return psource1->value.max_tile_total_units == psource2->value.max_tile_total_units;
7718 return psource1->value.max_tile_top_units == psource2->value.max_tile_top_units;
7719 case VUT_TERRAINCLASS:
7720 return psource1->value.terrainclass == psource2->value.terrainclass;
7721 case VUT_ROADFLAG:
7722 return psource1->value.roadflag == psource2->value.roadflag;
7723 case VUT_EXTRAFLAG:
7724 return psource1->value.extraflag == psource2->value.extraflag;
7725 case VUT_MINYEAR:
7726 return psource1->value.minyear == psource2->value.minyear;
7727 case VUT_MINCALFRAG:
7728 return psource1->value.mincalfrag == psource2->value.mincalfrag;
7729 case VUT_TOPO:
7730 return psource1->value.topo_property == psource2->value.topo_property;
7731 case VUT_WRAP:
7732 return psource1->value.wrap_property == psource2->value.wrap_property;
7733 case VUT_SERVERSETTING:
7734 return psource1->value.ssetval == psource2->value.ssetval;
7735 case VUT_TERRAINALTER:
7736 return psource1->value.terrainalter == psource2->value.terrainalter;
7737 case VUT_CITYTILE:
7738 return psource1->value.citytile == psource2->value.citytile;
7739 case VUT_CITYSTATUS:
7740 return psource1->value.citystatus == psource2->value.citystatus;
7741 case VUT_TILE_REL:
7742 return psource1->value.tilerel == psource2->value.tilerel;
7743 case VUT_MINLATITUDE:
7744 case VUT_MAXLATITUDE:
7745 return psource1->value.latitude == psource2->value.latitude;
7747 return psource1->value.distance_sq == psource2->value.distance_sq;
7749 return psource1->value.region_tiles == psource2->value.region_tiles;
7750 case VUT_COUNT:
7751 break;
7752 }
7753
7754 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
7755 return FALSE;
7756}
7757
7758/**********************************************************************/
7762const char *universal_rule_name(const struct universal *psource)
7763{
7764 static char buffer[10];
7765
7766 switch (psource->kind) {
7767 case VUT_NONE:
7768 return "(none)";
7769 case VUT_COUNTER:
7770 return counter_rule_name(psource->value.counter);
7771 case VUT_CITYTILE:
7772 return citytile_type_name(psource->value.citytile);
7773 case VUT_CITYSTATUS:
7774 return citystatus_type_name(psource->value.citystatus);
7775 case VUT_TILE_REL:
7776 return tilerel_type_name(psource->value.tilerel);
7777 case VUT_MINYEAR:
7778 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
7779
7780 return buffer;
7781 case VUT_MINCALFRAG:
7782 /* Rule name is 0-based number, not pretty name from ruleset */
7783 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
7784
7785 return buffer;
7786 case VUT_TOPO:
7787 return topo_flag_name(psource->value.topo_property);
7788 case VUT_WRAP:
7789 return wrap_flag_name(psource->value.wrap_property);
7790 case VUT_SERVERSETTING:
7791 return ssetv_rule_name(psource->value.ssetval);
7792 case VUT_ADVANCE:
7793 return advance_rule_name(psource->value.advance);
7794 case VUT_TECHFLAG:
7795 return tech_flag_id_name(psource->value.techflag);
7796 case VUT_GOVERNMENT:
7797 return government_rule_name(psource->value.govern);
7798 case VUT_GOVFLAG:
7799 return gov_flag_id_name(psource->value.govflag);
7800 case VUT_ACHIEVEMENT:
7801 return achievement_rule_name(psource->value.achievement);
7802 case VUT_STYLE:
7803 return style_rule_name(psource->value.style);
7804 case VUT_IMPROVEMENT:
7805 case VUT_SITE:
7806 return improvement_rule_name(psource->value.building);
7807 case VUT_IMPR_GENUS:
7808 return impr_genus_id_name(psource->value.impr_genus);
7809 case VUT_IMPR_FLAG:
7810 return impr_flag_id_name(psource->value.impr_flag);
7811 case VUT_PLAYER_FLAG:
7812 return plr_flag_id_name(psource->value.plr_flag);
7813 case VUT_PLAYER_STATE:
7814 return plrstate_type_name(psource->value.plrstate);
7815 case VUT_EXTRA:
7816 return extra_rule_name(psource->value.extra);
7817 case VUT_GOOD:
7818 return goods_rule_name(psource->value.good);
7819 case VUT_TERRAIN:
7820 return terrain_rule_name(psource->value.terrain);
7821 case VUT_TERRFLAG:
7822 return terrain_flag_id_name(psource->value.terrainflag);
7823 case VUT_NATION:
7824 return nation_rule_name(psource->value.nation);
7825 case VUT_NATIONGROUP:
7826 return nation_group_rule_name(psource->value.nationgroup);
7827 case VUT_DIPLREL:
7828 case VUT_DIPLREL_TILE:
7829 case VUT_DIPLREL_TILE_O:
7832 return diplrel_rule_name(psource->value.diplrel);
7833 case VUT_NATIONALITY:
7834 return nation_rule_name(psource->value.nationality);
7835 case VUT_ORIGINAL_OWNER:
7836 return nation_rule_name(psource->value.origowner);
7837 case VUT_UTYPE:
7838 return utype_rule_name(psource->value.utype);
7839 case VUT_UTFLAG:
7840 return unit_type_flag_id_name(psource->value.unitflag);
7841 case VUT_UCLASS:
7842 return uclass_rule_name(psource->value.uclass);
7843 case VUT_UCFLAG:
7844 return unit_class_flag_id_name(psource->value.unitclassflag);
7845 case VUT_MINVETERAN:
7846 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
7847
7848 return buffer;
7849 case VUT_UNITSTATE:
7850 return ustate_prop_name(psource->value.unit_state);
7851 case VUT_ACTIVITY:
7852 return unit_activity_name(psource->value.activity);
7853 case VUT_MINMOVES:
7854 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
7855
7856 return buffer;
7857 case VUT_MINHP:
7858 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
7859
7860 return buffer;
7861 case VUT_AGE:
7862 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
7863
7864 return buffer;
7865 case VUT_FORM_AGE:
7866 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
7867
7868 return buffer;
7869 case VUT_MINTECHS:
7870 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
7871
7872 return buffer;
7873 case VUT_FUTURETECHS:
7874 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.future_techs);
7875
7876 return buffer;
7877 case VUT_MINCITIES:
7878 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_cities);
7879
7880 return buffer;
7881 case VUT_ACTION:
7882 return action_rule_name(psource->value.action);
7883 case VUT_OTYPE:
7884 return get_output_identifier(psource->value.outputtype);
7885 case VUT_SPECIALIST:
7886 return specialist_rule_name(psource->value.specialist);
7887 case VUT_MINSIZE:
7888 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
7889
7890 return buffer;
7891 case VUT_MINCULTURE:
7892 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
7893
7894 return buffer;
7895 case VUT_MINFOREIGNPCT:
7896 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
7897
7898 return buffer;
7899 case VUT_AI_LEVEL:
7900 return ai_level_name(psource->value.ai_level);
7902 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_total_units);
7903 return buffer;
7905 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_top_units);
7906 return buffer;
7907 case VUT_TERRAINCLASS:
7908 return terrain_class_name(psource->value.terrainclass);
7909 case VUT_ROADFLAG:
7910 return road_flag_id_name(psource->value.roadflag);
7911 case VUT_EXTRAFLAG:
7912 return extra_flag_id_name(psource->value.extraflag);
7913 case VUT_TERRAINALTER:
7914 return terrain_alteration_name(psource->value.terrainalter);
7915 case VUT_MINLATITUDE:
7916 case VUT_MAXLATITUDE:
7917 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
7918
7919 return buffer;
7921 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.distance_sq);
7922
7923 return buffer;
7925 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.region_tiles);
7926
7927 return buffer;
7928 case VUT_COUNT:
7929 break;
7930 }
7931
7932 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
7933
7934 return nullptr;
7935}
7936
7937/**********************************************************************/
7946 char *buf, size_t bufsz)
7947{
7948 buf[0] = '\0'; /* to be safe. */
7949 switch (psource->kind) {
7950 case VUT_NONE:
7951 /* TRANS: missing value */
7952 fc_strlcat(buf, _("(none)"), bufsz);
7953 return buf;
7954 case VUT_ADVANCE:
7956 return buf;
7957 case VUT_COUNTER:
7959 return buf;
7960 case VUT_TECHFLAG:
7961 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
7962 tech_flag_id_translated_name(psource->value.techflag));
7963 return buf;
7964 case VUT_GOVERNMENT:
7966 bufsz);
7967 return buf;
7968 case VUT_GOVFLAG:
7969 cat_snprintf(buf, bufsz, _("\"%s\" gov"),
7970 gov_flag_id_translated_name(psource->value.govflag));
7971 return buf;
7972 case VUT_ACHIEVEMENT:
7974 bufsz);
7975 return buf;
7976 case VUT_STYLE:
7978 bufsz);
7979 return buf;
7980 case VUT_IMPROVEMENT:
7982 bufsz);
7983 return buf;
7984 case VUT_SITE:
7985 {
7986 char local_buf[1024];
7987
7988 fc_snprintf(local_buf, sizeof(local_buf), _("%s site"),
7989 improvement_name_translation(psource->value.building));
7991 }
7992
7993 return buf;
7994 case VUT_IMPR_GENUS:
7996 impr_genus_id_translated_name(psource->value.impr_genus),
7997 bufsz);
7998 return buf;
7999 case VUT_IMPR_FLAG:
8001 impr_flag_id_translated_name(psource->value.impr_flag),
8002 bufsz);
8003 return buf;
8004 case VUT_PLAYER_FLAG:
8006 plr_flag_id_translated_name(psource->value.plr_flag),
8007 bufsz);
8008 return buf;
8009 case VUT_PLAYER_STATE:
8011 plrstate_type_translated_name(psource->value.plrstate),
8012 bufsz);
8013 return buf;
8014 case VUT_EXTRA:
8016 return buf;
8017 case VUT_GOOD:
8019 return buf;
8020 case VUT_TERRAIN:
8022 return buf;
8023 case VUT_NATION:
8025 bufsz);
8026 return buf;
8027 case VUT_NATIONGROUP:
8029 bufsz);
8030 return buf;
8031 case VUT_NATIONALITY:
8032 cat_snprintf(buf, bufsz, _("%s citizens"),
8033 nation_adjective_translation(psource->value.nationality));
8034 return buf;
8035 case VUT_ORIGINAL_OWNER:
8036 /* TRANS: Keep short. City founding nation. */
8037 cat_snprintf(buf, bufsz, _("%s original owner"),
8038 nation_adjective_translation(psource->value.origowner));
8039 return buf;
8040 case VUT_DIPLREL:
8041 case VUT_DIPLREL_TILE:
8042 case VUT_DIPLREL_TILE_O:
8046 bufsz);
8047 return buf;
8048 case VUT_UTYPE:
8050 return buf;
8051 case VUT_UTFLAG:
8053 /* TRANS: Unit type flag */
8054 Q_("?utflag:\"%s\" units"),
8056 psource->value.unitflag));
8057 return buf;
8058 case VUT_UCLASS:
8060 /* TRANS: Unit class */
8061 _("%s units"),
8062 uclass_name_translation(psource->value.uclass));
8063 return buf;
8064 case VUT_UCFLAG:
8066 /* TRANS: Unit class flag */
8067 Q_("?ucflag:\"%s\" units"),
8069 psource->value.unitclassflag));
8070 return buf;
8071 case VUT_MINVETERAN:
8072 /* FIXME */
8073 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
8074 psource->value.minveteran);
8075 return buf;
8076 case VUT_UNITSTATE:
8077 switch (psource->value.unit_state) {
8078 case USP_TRANSPORTED:
8079 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
8080 cat_snprintf(buf, bufsz, _("Transported"));
8081 break;
8082 case USP_LIVABLE_TILE:
8084 /* TRANS: unit state. (appears in strings like
8085 * "Missile+On livable tile") */
8086 _("On livable tile"));
8087 break;
8088 case USP_TRANSPORTING:
8089 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
8090 cat_snprintf(buf, bufsz, _("Transporting"));
8091 break;
8092 case USP_HAS_HOME_CITY:
8093 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
8094 cat_snprintf(buf, bufsz, _("Has a home city"));
8095 break;
8096 case USP_NATIVE_TILE:
8098 /* TRANS: unit state. (appears in strings like
8099 * "Missile+On native tile") */
8100 _("On native tile"));
8101 break;
8102 case USP_NATIVE_EXTRA:
8104 /* TRANS: unit state. (appears in strings like
8105 * "Missile+In native extra") */
8106 _("In native extra"));
8107 break;
8109 /* TRANS: unit state. (appears in strings like
8110 * "Missile+Has moved this turn") */
8111 cat_snprintf(buf, bufsz, _("Has moved this turn"));
8112 break;
8113 case USP_COUNT:
8114 fc_assert_msg(psource->value.unit_state != USP_COUNT,
8115 "Invalid unit state property.");
8116 break;
8117 }
8118 return buf;
8119 case VUT_ACTIVITY:
8120 cat_snprintf(buf, bufsz, _("%s activity"),
8121 Q_(unit_activity_name(psource->value.activity)));
8122 return buf;
8123 case VUT_MINMOVES:
8124 /* TRANS: Minimum unit movement points left for requirement to be met
8125 * (%s is a string like "1" or "2 1/3") */
8126 cat_snprintf(buf, bufsz, _("%s MP"),
8127 move_points_text(psource->value.minmoves, TRUE));
8128 return buf;
8129 case VUT_MINHP:
8130 /* TRANS: HP = hit points */
8131 cat_snprintf(buf, bufsz, _("%d HP"),
8132 psource->value.min_hit_points);
8133 return buf;
8134 case VUT_AGE:
8135 cat_snprintf(buf, bufsz, _("Age %d"),
8136 psource->value.age);
8137 return buf;
8138 case VUT_FORM_AGE:
8139 cat_snprintf(buf, bufsz, _("Form age %d"),
8140 psource->value.form_age);
8141 return buf;
8142 case VUT_MINTECHS:
8143 cat_snprintf(buf, bufsz, _("%d Techs"),
8144 psource->value.min_techs);
8145 return buf;
8146 case VUT_FUTURETECHS:
8147 cat_snprintf(buf, bufsz, _("%d Future techs"),
8148 psource->value.future_techs);
8149 return buf;
8150 case VUT_MINCITIES:
8151 cat_snprintf(buf, bufsz, _("%d Cities"),
8152 psource->value.min_cities);
8153 return buf;
8154 case VUT_ACTION:
8156 bufsz);
8157 return buf;
8158 case VUT_OTYPE:
8159 /* FIXME */
8160 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
8161 return buf;
8162 case VUT_SPECIALIST:
8164 bufsz);
8165 return buf;
8166 case VUT_MINSIZE:
8167 cat_snprintf(buf, bufsz, _("Size %d"),
8168 psource->value.minsize);
8169 return buf;
8170 case VUT_MINCULTURE:
8171 cat_snprintf(buf, bufsz, _("Culture %d"),
8172 psource->value.minculture);
8173 return buf;
8174 case VUT_MINFOREIGNPCT:
8175 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
8176 psource->value.minforeignpct);
8177 return buf;
8178 case VUT_AI_LEVEL:
8179 /* TRANS: "Hard AI" */
8180 cat_snprintf(buf, bufsz, _("%s AI"),
8181 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
8182 return buf;
8184 /* TRANS: here <= means 'less than or equal' */
8185 cat_snprintf(buf, bufsz, PL_("<=%d total unit",
8186 "<=%d total units",
8187 psource->value.max_tile_total_units),
8188 psource->value.max_tile_total_units);
8189 return buf;
8191 /* TRANS: here <= means 'less than or equal' */
8192 cat_snprintf(buf, bufsz, PL_("<=%d unit",
8193 "<=%d units", psource->value.max_tile_top_units),
8194 psource->value.max_tile_top_units);
8195 return buf;
8196 case VUT_TERRAINCLASS:
8197 /* TRANS: Terrain class: "Land terrain" */
8198 cat_snprintf(buf, bufsz, _("%s terrain"),
8199 terrain_class_name_translation(psource->value.terrainclass));
8200 return buf;
8201 case VUT_TERRFLAG:
8203 /* TRANS: Terrain flag */
8204 Q_("?terrflag:\"%s\" terrain"),
8206 psource->value.terrainflag));
8207 return buf;
8208 case VUT_ROADFLAG:
8210 /* TRANS: Road flag */
8211 Q_("?roadflag:\"%s\" road"),
8212 road_flag_id_translated_name(psource->value.roadflag));
8213 return buf;
8214 case VUT_EXTRAFLAG:
8216 /* TRANS: Extra flag */
8217 Q_("?extraflag:\"%s\" extra"),
8218 extra_flag_id_translated_name(psource->value.extraflag));
8219 return buf;
8220 case VUT_MINYEAR:
8221 cat_snprintf(buf, bufsz, _("After %s"),
8222 textyear(psource->value.minyear));
8223 return buf;
8224 case VUT_MINCALFRAG:
8225 /* TRANS: here >= means 'greater than or equal'.
8226 * %s identifies a calendar fragment (may be bare number). */
8227 cat_snprintf(buf, bufsz, _(">=%s"),
8228 textcalfrag(psource->value.mincalfrag));
8229 return buf;
8230 case VUT_TOPO:
8231 /* TRANS: topology flag name ("Hex", "ISO") */
8232 cat_snprintf(buf, bufsz, _("%s map"),
8233 _(topo_flag_name(psource->value.topo_property)));
8234 return buf;
8235 case VUT_WRAP:
8236 /* TRANS: wrap flag name ("WrapX", "WrapY") */
8237 cat_snprintf(buf, bufsz, _("%s map"),
8238 _(wrap_flag_name(psource->value.wrap_property)));
8239 return buf;
8240 case VUT_SERVERSETTING:
8242 bufsz);
8243 return buf;
8244 case VUT_TERRAINALTER:
8245 /* TRANS: "Irrigation possible" */
8246 cat_snprintf(buf, bufsz, _("%s possible"),
8247 Q_(terrain_alteration_name(psource->value.terrainalter)));
8248 return buf;
8249 case VUT_CITYTILE:
8250 switch (psource->value.citytile) {
8251 case CITYT_CENTER:
8252 fc_strlcat(buf, _("City center"), bufsz);
8253 break;
8254 case CITYT_CLAIMED:
8255 fc_strlcat(buf, _("Tile claimed"), bufsz);
8256 break;
8257 case CITYT_EXTRAS_OWNED:
8258 fc_strlcat(buf, _("Extras owned"), bufsz);
8259 break;
8260 case CITYT_WORKED:
8261 fc_strlcat(buf, _("Worked tile"), bufsz);
8262 break;
8264 fc_strlcat(buf, _("Same continent tile"), bufsz);
8265 break;
8267 /* TRANS: Short for "a tile of other terrain class mass near city" */
8268 fc_strlcat(buf, _("Port reachable tile"), bufsz);
8269 break;
8270 case CITYT_LAST:
8271 fc_assert(psource->value.citytile != CITYT_LAST);
8272 fc_strlcat(buf, "error", bufsz);
8273 break;
8274 }
8275 return buf;
8276 case VUT_CITYSTATUS:
8277 switch (psource->value.citystatus) {
8279 fc_strlcat(buf, _("Owned by original"), bufsz);
8280 break;
8281 case CITYS_STARVED:
8282 fc_strlcat(buf, _("Starved"), bufsz);
8283 break;
8284 case CITYS_DISORDER:
8285 fc_strlcat(buf, _("Disorder"), bufsz);
8286 break;
8287 case CITYS_CELEBRATION:
8288 fc_strlcat(buf, _("Celebration"), bufsz);
8289 break;
8290 case CITYS_TRANSFERRED:
8291 /* TRANS: CityStatus value - city has changed hands */
8292 fc_strlcat(buf, _("Transferred"), bufsz);
8293 break;
8295 fc_strlcat(buf, _("CapitalConnected"), bufsz);
8296 break;
8297 case CITYS_LAST:
8298 fc_assert(psource->value.citystatus != CITYS_LAST);
8299 fc_strlcat(buf, "error", bufsz);
8300 break;
8301 }
8302 return buf;
8303 case VUT_TILE_REL:
8304 switch (psource->value.tilerel) {
8305 case TREL_SAME_TCLASS:
8306 fc_strlcat(buf, _("Same terrain class"), bufsz);
8307 break;
8308 case TREL_SAME_REGION:
8309 fc_strlcat(buf, _("Same continent/ocean"), bufsz);
8310 break;
8312 fc_strlcat(buf, _("Only other continent/ocean"), bufsz);
8313 break;
8315 fc_strlcat(buf, _("Lake/island surrounded"), bufsz);
8316 break;
8317 case TREL_COUNT:
8318 fc_assert(psource->value.tilerel != TREL_COUNT);
8319 fc_strlcat(buf, "error", bufsz);
8320 break;
8321 }
8322 return buf;
8323 case VUT_MINLATITUDE:
8324 /* TRANS: here >= means 'greater than or equal'. */
8325 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
8326 psource->value.latitude);
8327 return buf;
8328 case VUT_MAXLATITUDE:
8329 /* TRANS: here <= means 'less than or equal'. */
8330 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
8331 psource->value.latitude);
8332 return buf;
8334 /* TRANS: here <= means 'less than or equal'. */
8335 cat_snprintf(buf, bufsz, _("Squared distance <= %d"),
8336 psource->value.distance_sq);
8337 return buf;
8339 cat_snprintf(buf, bufsz, _("%d or fewer region tiles"),
8340 psource->value.region_tiles);
8341 return buf;
8342 case VUT_COUNT:
8343 break;
8344 }
8345
8346 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8347 return buf;
8348}
8349
8350/**********************************************************************/
8354{
8355 return universals_n_name(psource->kind);
8356}
8357
8358/**********************************************************************/
8362 const struct universal *target)
8363{
8364 switch (target->kind) {
8365 case VUT_IMPROVEMENT:
8366 case VUT_SITE:
8367 return impr_build_shield_cost(pcity, target->value.building);
8368 case VUT_UTYPE:
8369 return utype_build_shield_cost(pcity, nullptr, target->value.utype);
8370 default:
8371 break;
8372 }
8373 return FC_INFINITY;
8374}
8375
8376/**********************************************************************/
8382 const struct universal *to_replace,
8383 const struct universal *replacement)
8384{
8385 bool changed = FALSE;
8386
8389 preq->source = *replacement;
8390 changed = TRUE;
8391 }
8393
8394 return changed;
8395}
8396
8397/**********************************************************************/
8402 const struct requirement_vector *reqs,
8403 const struct universal *psource)
8404{
8407 return TRUE;
8408 }
8410
8411 return FALSE;
8412}
8413
8414/**********************************************************************/
8425 struct universal *unis,
8426 size_t n_unis)
8427{
8428 int i;
8429
8430 for (i = 0; i < n_unis; i++) {
8432 /* This universal makes it impossible to fulfill the specified
8433 * requirement vector */
8434 return TRUE;
8435 }
8436 }
8437
8438 /* No specified universal is known to guarantee that the requirement
8439 * vector never will be fulfilled. */
8440 return FALSE;
8441}
8442
8443/**********************************************************************/
8459 struct universal *unis,
8460 size_t n_unis)
8461{
8463 int i;
8465
8466 for (i = 0; i < n_unis; i++) {
8467 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
8468 case ITF_NO:
8469 case ITF_YES:
8470 /* this req matched this source */
8472 break;
8473 case ITF_NOT_APPLICABLE:
8474 /* Not a mention. */
8475 break;
8476 }
8477 }
8478
8480 /* A requirement not relevant to any of the specified universals was
8481 * found in the requirement vector. */
8482 return FALSE;
8483 }
8485
8486 /* No requirement not relevant to any of the specified universals was
8487 * found in the requirement vector. */
8488 return TRUE;
8489}
8490
8491/**********************************************************************/
8494enum req_item_found
8496 const struct universal *source)
8497{
8500 "No req item found function for %s",
8502
8503 return (*universal_found_function[source->kind])(preq, source);
8504}
8505
8506/**********************************************************************/
8517 const struct requirement_vector *reqs,
8518 const struct universal *source)
8519{
8520 bool necessary = FALSE;
8521
8524 "No req item found function for %s",
8526
8528 switch ((*universal_found_function[source->kind])(preq, source)) {
8529 case ITF_NOT_APPLICABLE:
8530 continue;
8531 case ITF_NO:
8532 if (preq->present) {
8533 return FALSE;
8534 }
8535 break;
8536 case ITF_YES:
8537 if (preq->present) {
8538 necessary = TRUE;
8539 } else {
8540 return FALSE;
8541 }
8542 break;
8543 }
8545
8546 return (!check_necessary || necessary);
8547}
8548
8549/**********************************************************************/
8554 const struct universal *source)
8555{
8556 switch (universal_fulfills_requirement(req, source)) {
8557 case ITF_NOT_APPLICABLE:
8558 return FALSE;
8559 case ITF_NO:
8560 case ITF_YES:
8561 return TRUE;
8562 }
8563
8564 log_error("Unhandled item_found value");
8565 return FALSE;
8566}
8567
8568/**********************************************************************/
8572 const struct universal *source)
8573{
8574 fc_assert(source->value.nation);
8575
8576 switch (preq->source.kind) {
8577 case VUT_NATION:
8578 return preq->source.value.nation == source->value.nation ? ITF_YES
8579 : ITF_NO;
8580 case VUT_NATIONGROUP:
8581 return nation_is_in_group(source->value.nation,
8582 preq->source.value.nationgroup) ? ITF_YES
8583 : ITF_NO;
8584 default:
8585 break;
8586 }
8587
8588 return ITF_NOT_APPLICABLE;
8589}
8590
8591/**********************************************************************/
8595 const struct universal *source)
8596{
8597 fc_assert(source->value.govern);
8598
8599 if (preq->source.kind == VUT_GOVERNMENT) {
8600 return preq->source.value.govern == source->value.govern ? ITF_YES
8601 : ITF_NO;
8602 } else if (preq->source.kind == VUT_GOVFLAG) {
8603 return BV_ISSET(source->value.govern->flags, preq->source.value.govflag)
8604 ? ITF_YES : ITF_NO;
8605 }
8606
8607 return ITF_NOT_APPLICABLE;
8608}
8609
8610/**********************************************************************/
8614 const struct universal *source)
8615{
8616 fc_assert(source->value.min_cities);
8617
8618 if (preq->source.kind == VUT_MINCITIES) {
8619 return preq->source.value.min_cities <= source->value.min_cities ? ITF_YES
8620 : ITF_NO;
8621 }
8622
8623 return ITF_NOT_APPLICABLE;
8624}
8625
8626/**********************************************************************/
8630 const struct universal *source)
8631{
8632 fc_assert(source->value.building);
8633
8634 /* We only ever return ITF_YES, because requiring a different
8635 * improvement does not mean that the improvement under consideration
8636 * cannot fulfill the requirements. This is necessary to allow
8637 * requirement vectors to specify multiple required improvements. */
8638
8639 switch (preq->source.kind) {
8640 case VUT_IMPROVEMENT:
8641 case VUT_SITE:
8642 if (source->value.building == preq->source.value.building) {
8643 return ITF_YES;
8644 }
8645 break;
8646 case VUT_IMPR_GENUS:
8647 if (source->value.building->genus == preq->source.value.impr_genus) {
8648 return ITF_YES;
8649 }
8650 break;
8651 case VUT_IMPR_FLAG:
8652 if (improvement_has_flag(source->value.building,
8653 preq->source.value.impr_flag)) {
8654 return ITF_YES;
8655 }
8656 break;
8657 default:
8658 break;
8659 }
8660
8661 return ITF_NOT_APPLICABLE;
8662}
8663
8664/**********************************************************************/
8668 const struct universal *source)
8669{
8670 fc_assert(source->value.uclass);
8671
8672 switch (preq->source.kind) {
8673 case VUT_UCLASS:
8674 return source->value.uclass == preq->source.value.uclass ? ITF_YES
8675 : ITF_NO;
8676 case VUT_UCFLAG:
8677 return uclass_has_flag(source->value.uclass,
8678 preq->source.value.unitclassflag) ? ITF_YES
8679 : ITF_NO;
8680
8681 default:
8682 /* Not found and not relevant. */
8683 return ITF_NOT_APPLICABLE;
8684 };
8685}
8686
8687/**********************************************************************/
8691 const struct universal *source)
8692{
8693 fc_assert(source->value.utype);
8694
8695 switch (preq->source.kind) {
8696 case VUT_UTYPE:
8697 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
8698 case VUT_UCLASS:
8699 return utype_class(source->value.utype) == preq->source.value.uclass
8700 ? ITF_YES : ITF_NO;
8701 case VUT_UTFLAG:
8702 return utype_has_flag(source->value.utype,
8703 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
8704 case VUT_UCFLAG:
8705 return uclass_has_flag(utype_class(source->value.utype),
8706 preq->source.value.unitclassflag) ? ITF_YES
8707 : ITF_NO;
8708 default:
8709 /* Not found and not relevant. */
8710 return ITF_NOT_APPLICABLE;
8711 };
8712}
8713
8714/**********************************************************************/
8717static enum req_item_found
8719 const struct universal *source)
8720{
8723
8724 switch (preq->source.kind) {
8725 case VUT_ACTIVITY:
8726 return source->value.activity == preq->source.value.activity ? ITF_YES
8727 : ITF_NO;
8728 default:
8729 /* Not found and not relevant. */
8730 return ITF_NOT_APPLICABLE;
8731 };
8732}
8733
8734/**********************************************************************/
8738 const struct universal *source)
8739{
8740 fc_assert(source->value.terrain);
8741
8742 switch (preq->source.kind) {
8743 case VUT_TERRAIN:
8744 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
8745 case VUT_TERRAINCLASS:
8746 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
8747 ? ITF_YES : ITF_NO;
8748 case VUT_TERRFLAG:
8749 return terrain_has_flag(source->value.terrain,
8750 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
8751 case VUT_TERRAINALTER:
8752 return (terrain_can_support_alteration(source->value.terrain,
8753 preq->source.value.terrainalter)
8754 ? ITF_YES : ITF_NO);
8755 default:
8756 /* Not found and not relevant. */
8757 return ITF_NOT_APPLICABLE;
8758 };
8759}
8760
8761/**********************************************************************/
8765 const struct universal *source)
8766{
8769
8770 switch (preq->source.kind) {
8771 case VUT_CITYTILE:
8772 return (source->value.citytile == preq->source.value.citytile
8773 ? ITF_YES
8774 /* The presence of one tile state doesn't block another */
8776 default:
8777 /* Not found and not relevant. */
8778 return ITF_NOT_APPLICABLE;
8779 };
8780}
8781
8782/**********************************************************************/
8786 const struct universal *source)
8787{
8788 fc_assert(source->value.extra);
8789
8790 switch (preq->source.kind) {
8791 case VUT_EXTRA:
8792 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
8793 case VUT_EXTRAFLAG:
8794 return extra_has_flag(source->value.extra,
8795 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
8796 case VUT_ROADFLAG:
8797 {
8798 struct road_type *r = extra_road_get(source->value.extra);
8799 return r && road_has_flag(r, preq->source.value.roadflag)
8800 ? ITF_YES : ITF_NO;
8801 }
8802 default:
8803 /* Not found and not relevant. */
8804 return ITF_NOT_APPLICABLE;
8805 }
8806}
8807
8808/**********************************************************************/
8812 const struct universal *source)
8813{
8814 fc_assert(source->value.action);
8815
8816 if (preq->source.kind == VUT_ACTION) {
8817 return preq->source.value.action == source->value.action ? ITF_YES
8818 : ITF_NO;
8819 }
8820
8821 return ITF_NOT_APPLICABLE;
8822}
8823
8824/**********************************************************************/
8828 const struct universal *source)
8829{
8831 || source->kind == VUT_DIPLREL_TILE
8832 || source->kind == VUT_DIPLREL_TILE_O
8833 || source->kind == VUT_DIPLREL_UNITANY
8834 || source->kind == VUT_DIPLREL_UNITANY_O),
8836
8837 if (preq->source.kind == source->kind) {
8838 if (preq->source.value.diplrel == source->value.diplrel) {
8839 /* The diplrel itself. */
8840 return ITF_YES;
8841 }
8842 if (preq->source.value.diplrel == DRO_FOREIGN
8843 && source->value.diplrel < DS_LAST) {
8844 /* All diplstate_type values are to foreigners. */
8845 return ITF_YES;
8846 }
8847 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
8848 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
8849 /* A real embassy is an embassy. */
8850 return ITF_YES;
8851 }
8852 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
8853 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
8854 /* A real embassy is an embassy. */
8855 return ITF_YES;
8856 }
8857 if (preq->source.value.diplrel < DS_LAST
8858 && source->value.diplrel < DS_LAST
8859 && preq->range == REQ_RANGE_LOCAL) {
8860 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
8861 ITF_YES);
8862 /* Can only have one diplstate_type to a specific player. */
8863 return ITF_NO;
8864 }
8865 /* Can't say this diplrel blocks the other diplrel. */
8866 return ITF_NOT_APPLICABLE;
8867 }
8868
8869 /* Not relevant. */
8870 return ITF_NOT_APPLICABLE;
8871}
8872
8873/**********************************************************************/
8877 const struct universal *source)
8878{
8879 switch (preq->source.kind) {
8880 case VUT_OTYPE:
8881 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
8882 : ITF_NO;
8883 default:
8884 /* Not found and not relevant. */
8885 return ITF_NOT_APPLICABLE;
8886 }
8887}
8888
8889/**********************************************************************/
8893 const struct universal *source)
8894{
8895 if (preq->range != REQ_RANGE_LOCAL) {
8896 return ITF_NOT_APPLICABLE;
8897 }
8898
8899 if (preq->source.kind == VUT_UNITSTATE) {
8900 switch (source->value.unit_state) {
8901 case USP_TRANSPORTED:
8902 case USP_TRANSPORTING:
8903 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
8904 case USP_LIVABLE_TILE:
8905 case USP_NATIVE_TILE:
8906 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
8907 * UTYF_COAST_STRICT. */
8908 case USP_HAS_HOME_CITY:
8909 case USP_NATIVE_EXTRA:
8911 if (source->value.unit_state == preq->source.value.unit_state) {
8912 /* The other unit states doesn't contradict */
8913 return ITF_YES;
8914 }
8915 break;
8916 case USP_COUNT:
8917 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
8919 }
8920 }
8921
8922 /* Not found and not relevant. */
8923 return ITF_NOT_APPLICABLE;
8924}
8925
8926/**********************************************************************/
8951
8952/**********************************************************************/
8960int requirement_kind_ereq(const int value,
8961 const enum req_range range,
8962 const bool present,
8963 const int max_value)
8964{
8965 /* The enumerators in each range starts with present for every possible
8966 * value followed by !present for every possible value. */
8967 const int pres_start = (present ? 0 : max_value);
8968
8969 /* The enumerators for every range follows all the positions of the
8970 * previous range(s). */
8971 const int range_start = ((max_value - 1) * 2) * range;
8972
8973 return range_start + pres_start + value;
8974}
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
struct achievement * achievement_by_number(int id)
int achievement_number(const struct achievement *pach)
const char * achievement_rule_name(struct achievement *pach)
struct achievement * achievement_by_rule_name(const char *name)
const char * achievement_name_translation(struct achievement *pach)
bool achievement_claimed(const struct achievement *pach)
const char * action_name_translation(const struct action *paction)
Definition actions.c:1251
bool action_is_in_use(struct action *paction)
Definition actions.c:5899
struct action * action_by_rule_name(const char *name)
Definition actions.c:1100
const char * action_rule_name(const struct action *action)
Definition actions.c:1237
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1260
int action_number(const struct action *action)
Definition actions.c:1229
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define ACTION_NONE
Definition actions.h:59
void astr_free(struct astring *astr)
Definition astring.c:148
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:251
void astr_init(struct astring *astr)
Definition astring.c:139
#define n
Definition astring.c:77
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
const char * textcalfrag(int frag)
Definition calendar.c:101
const char * textyear(int year)
Definition calendar.c:121
citizens citizens_nation_foreign(const struct city *pcity)
Definition citizens.c:91
#define citizens_iterate_end
Definition citizens.h:54
#define citizens_iterate(_pcity, _pslot, _nationality)
Definition citizens.h:48
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:1240
Output_type_id output_type_by_identifier(const char *id)
Definition city.c:647
const char * get_output_identifier(Output_type_id output)
Definition city.c:619
const char * get_output_name(Output_type_id output)
Definition city.c:629
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
#define city_tile(_pcity_)
Definition city.h:564
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
#define city_owner(_pcity_)
Definition city.h:563
static bool is_city_center(const struct city *pcity, const struct tile *ptile)
Definition city.h:869
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:228
#define city_tile_iterate_end
Definition city.h:236
#define city_built_iterate(_pcity, _p)
Definition city.h:835
#define city_built_iterate_end
Definition city.h:841
char * incite_cost
Definition comments.c:76
int counter_index(const struct counter *pcount)
Definition counters.c:174
const char * counter_name_translation(const struct counter *counter)
Definition counters.c:157
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:115
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:165
struct counter * counter_by_id(int id)
Definition counters.c:82
int counter_id(struct counter *pcount)
Definition counters.c:105
int city_culture(const struct city *pcity)
Definition culture.c:29
int player_culture(const struct player *plr)
Definition culture.c:49
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:56
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:57
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
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 int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
struct @22::@23 reqs
int get_world_bonus(enum effect_type effect_type)
Definition effects.c:812
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
bool extra_flag_is_in_use(enum extra_flag_id id)
Definition extras.c:1001
bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:904
bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:884
bool is_extra_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:379
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:875
bool is_extra_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:363
struct extra_type * extra_by_number(int id)
Definition extras.c:183
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:194
#define extra_road_get(_e_)
Definition extras.h:191
static bool is_server(void)
int Tech_type_id
Definition fc_types.h:237
req_problem_type
Definition fc_types.h:513
@ RPT_POSSIBLE
Definition fc_types.h:514
#define MAX_LEN_NAME
Definition fc_types.h:67
@ VC_SPACERACE
Definition fc_types.h:964
@ O_LAST
Definition fc_types.h:102
signed short Continent_id
Definition fc_types.h:232
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
const char * government_name_translation(const struct government *pgovern)
Definition government.c:145
struct government * government_by_number(const Government_type_id gov)
Definition government.c:105
struct government * government_of_player(const struct player *pplayer)
Definition government.c:116
Government_type_id government_number(const struct government *pgovern)
Definition government.c:93
const char * government_rule_name(const struct government *pgovern)
Definition government.c:135
struct government * government_by_rule_name(const char *name)
Definition government.c:57
struct city * owner
Definition citydlg.c:226
static GtkWidget * source
Definition gotodlg.c:58
GType type
Definition repodlgs.c:1313
static const int bufsz
Definition helpdlg.c:70
struct impr_type * improvement_by_number(const Impr_type_id id)
bool great_wonder_is_built(const struct impr_type *pimprove)
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
bool wonder_is_built(const struct player *pplayer, const struct impr_type *pimprove)
Impr_type_id improvement_number(const struct impr_type *pimprove)
bool can_improvement_go_obsolete(const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
struct city * city_from_wonder(const struct player *pplayer, const struct impr_type *pimprove)
int impr_build_shield_cost(const struct city *pcity, const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
bool improvement_obsolete(const struct player *pplayer, const struct impr_type *pimprove, const struct city *pcity)
bool improvement_has_flag(const struct impr_type *pimprove, enum impr_flag_id flag)
struct impr_type * improvement_by_rule_name(const char *name)
const char * improvement_name_translation(const struct impr_type *pimprove)
bool great_wonder_is_available(const struct impr_type *pimprove)
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition log.h:209
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:686
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:1067
int map_signed_latitude(const struct tile *ptile)
Definition map.c:1692
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:1076
int get_island_surrounder(Continent_id id)
Definition map.c:842
int get_lake_surrounder(Continent_id id)
Definition map.c:875
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:699
#define current_topo_has_flag(flag)
Definition map.h:43
#define range_adjc_iterate(nmap, center_tile, range, itr_tile)
Definition map.h:498
#define MAP_MAX_LATITUDE
Definition map.h:602
#define adjc_iterate_end
Definition map.h:430
#define MAP_MAX_REAL_LATITUDE(_nmap)
Definition map.h:614
#define range_adjc_iterate_end
Definition map.h:501
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:388
#define cardinal_adjc_iterate_end
Definition map.h:456
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:425
#define is_whole_continent_known(cont)
Definition map.h:78
#define square_iterate_end
Definition map.h:391
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:452
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:398
#define current_wrap_has_flag(flag)
Definition map.h:46
#define is_whole_ocean_known(ocean)
Definition map.h:82
#define MAP_MIN_REAL_LATITUDE(_nmap)
Definition map.h:616
#define circle_iterate_end
Definition map.h:401
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
const char * move_points_text(int mp, bool reduce)
Definition movement.c:1048
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:350
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:362
struct nation_group * nation_group_by_rule_name(const char *name)
Definition nation.c:1055
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:505
const char * nation_adjective_translation(const struct nation_type *pnation)
Definition nation.c:149
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:493
const char * nation_group_rule_name(const struct nation_group *pgroup)
Definition nation.c:1117
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:458
bool nation_is_in_group(const struct nation_type *pnation, const struct nation_group *pgroup)
Definition nation.c:1138
const char * nation_group_name_translation(const struct nation_group *pgroup)
Definition nation.c:1128
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
struct nation_group * nation_group_by_number(int id)
Definition nation.c:1038
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:984
#define NO_NATION_SELECTED
Definition nation.h:30
bool player_knows_techs_with_flag(const struct player *pplayer, enum tech_flag_id flag)
Definition player.c:1336
bool player_has_state(const struct player *pplayer, enum plrstate_type state)
Definition player.c:2012
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Definition player.c:1837
int diplrel_by_rule_name(const char *value)
Definition player.c:1593
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1488
bool is_diplrel_to_other(const struct player *pplayer, int diplrel)
Definition player.c:1574
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:2004
const char * diplrel_name_translation(int value)
Definition player.c:1639
bool is_diplrel_between(const struct player *player1, const struct player *player2, int diplrel)
Definition player.c:1524
int player_age(const struct player *pplayer)
Definition player.c:961
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1417
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:439
const char * diplrel_rule_name(int value)
Definition player.c:1627
#define players_iterate_end
Definition player.h:542
#define players_iterate(_pplayer)
Definition player.h:537
#define player_nation(_plr_)
Definition player.h:408
#define is_ai(plr)
Definition player.h:232
#define players_iterate_alive_end
Definition player.h:552
#define players_iterate_alive(_pplayer)
Definition player.h:547
static enum req_item_found terrain_type_found(const struct requirement *preq, const struct universal *source)
bool universal_never_there(const struct universal *source)
static enum fc_tristate is_unitclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unitflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_relevant_to_requirement(const struct requirement *req, const struct universal *source)
static enum fc_tristate is_futuretechs_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define EXTRACT_INFO(req)
bool is_req_in_vec(const struct requirement *req, const struct requirement_vector *vec)
int universal_build_shield_cost(const struct city *pcity, const struct universal *target)
static enum fc_tristate is_terrainflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found city_tile_found(const struct requirement *preq, const struct universal *source)
struct req_vec_problem * req_vec_get_first_contradiction(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static universal_found universal_found_function[VUT_COUNT]
static enum req_unchanging_status unchanging_local(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
#define REQUC_CITYSTATUS
const struct req_context * req_context_empty(void)
static enum fc_tristate is_action_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found unit_type_found(const struct requirement *preq, const struct universal *source)
void universal_extraction(const struct universal *source, int *kind, int *value)
static int num_player_buildings(const struct player *pplayer, const struct impr_type *building)
static enum fc_tristate is_tech_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_none_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static int num_continent_buildings(const struct player *pplayer, int continent, const struct impr_type *building)
static enum fc_tristate is_minveteran_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * req_to_fstring(const struct requirement *req, struct astring *astr)
static enum fc_tristate is_counter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
req_vec_num_in_item req_vec_vector_number(const void *parent_item, const struct requirement_vector *vec)
static bool present_implies_not_present(const struct requirement *req1, const struct requirement *req2)
enum fc_tristate tri_req_active(const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct requirement_vector * req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
bool universal_fulfills_requirements(bool check_necessary, const struct requirement_vector *reqs, const struct universal *source)
static bool activity_is_valid_in_requirement(enum unit_activity act)
enum fc_tristate tri_reqs_cb_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, struct requirement_vector *maybe_reqs, req_tester_cb tester, void *data, int n_data)
static enum fc_tristate is_minsize_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_ai_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_noally(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_max_distance_sq_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_vec_change_apply(const struct req_vec_change *modification, requirement_vector_by_number getter, const void *parent_item)
void universal_copy(struct universal *dst, const struct universal *src)
static enum fc_tristate is_minculture_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_building(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_terrain_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_requirements_equal(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_minforeignpct_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_minyear_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found extra_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_buildingflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_in_range(const struct tile *target_tile, const struct player *other_player, enum req_range range, int diplrel)
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
struct requirement req_from_str(const char *type, const char *range, bool survives, bool present, bool quiet, const char *value)
struct req_vec_problem * req_vec_suggest_repair(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum fc_tristate is_wrap_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void universal_value_from_str(struct universal *source, const char *value)
static enum fc_tristate is_buildingflag_in_city(const struct city *pcity, enum impr_flag_id flag)
static enum fc_tristate is_latitude_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_get_values(const struct requirement *req, int *type, int *range, bool *survives, bool *present, bool *quiet, int *value)
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
static enum fc_tristate is_nationality_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * universal_rule_name(const struct universal *psource)
static enum req_unchanging_status unchanging_present(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
bool universal_replace_in_req_vec(struct requirement_vector *reqs, const struct universal *to_replace, const struct universal *replacement)
static enum req_item_found action_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_minmovefrags_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_requirements_contradictions(const struct requirement *req1, const struct requirement *req2)
#define REQUC_IMPR
struct req_vec_problem * req_vec_problem_new(int num_suggested_solutions, const char *descr,...)
static enum fc_tristate is_buildinggenus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_in_range(const struct player *target_player, const struct player *other_player, enum req_range range, int diplrel)
static enum fc_tristate is_mintechs_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
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)
static enum fc_tristate is_originalowner_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool are_bounds_contradictions(int bound1, bool is_upper1, int bound2, bool is_upper2)
static enum fc_tristate is_diplrel_tile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_legal_in_requirement(const struct universal *univ)
enum fc_tristate default_tester_cb(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, void *data, int n_data)
static enum fc_tristate tri_req_present(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
int requirement_kind_ereq(const int value, const enum req_range range, const bool present, const int max_value)
static enum fc_tristate is_achievement_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_vec_problem_free(struct req_vec_problem *issue)
static struct req_def req_definitions[VUT_COUNT]
static bool impr_contra_flag(const struct requirement *impr_req, const struct requirement *flag_req)
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)
static enum req_item_found improvement_found(const struct requirement *preq, const struct universal *source)
struct req_vec_problem * req_vec_get_first_missing_univ(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum req_item_found mincities_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_extraflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum req_unchanging_status is_req_preventing(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, enum req_problem_type prob_type)
static enum fc_tristate is_plr_state_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool players_in_same_range(const struct player *pplayer1, const struct player *pplayer2, enum req_range range)
struct requirement * req_vec_first_contradiction_in_vec(const struct requirement *req, const struct requirement_vector *vec)
enum req_item_found(* universal_found)(const struct requirement *, const struct universal *)
static enum fc_tristate is_terrainclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct universal universal_by_number(const enum universals_n kind, const int value)
static enum fc_tristate is_roadflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum req_item_found universal_fulfills_requirement(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_building_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_reqs_active_ranges(const enum req_range min_range, const enum req_range max_range, const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
static enum fc_tristate is_gov_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_tile_o_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_good_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unitstate_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool city_center_contra(const struct requirement *cc_req, const struct requirement *ct_req)
static enum req_item_found ustate_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_terrainalter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unittype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_vec_wants_type(const struct requirement_vector *reqs, enum universals_n kind)
static int num_world_buildings_total(const struct impr_type *building)
static enum req_unchanging_status unchanging_citytile(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum req_item_found output_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_citystatus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_tile_rel_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct req_vec_problem * req_vec_get_first_redundant_req(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum fc_tristate is_mincities_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool is_city_in_tile(const struct tile *ptile, const struct city *pcity)
bool does_req_contradicts_reqs(const struct requirement *req, const struct requirement_vector *vec)
static enum req_item_found government_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate does_region_surrounder_match(Continent_id cont, Continent_id surrounder)
static enum fc_tristate is_extra_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_world(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_mincalfrag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_maxtopunitsontile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_activity_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
static enum fc_tristate is_max_region_tiles_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct req_vec_problem * req_vec_problem_new_transl(int num_suggested_solutions, const char *description, const char *description_translated)
static enum fc_tristate is_nationgroup_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define REQUC_NALLY
static enum req_item_found unit_activity_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_minhitpoints_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum fc_tristate tri_req_active_turns(int pass, int period, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_outputtype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define REQUC_LOCAL
bool universals_say_everything(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
static enum fc_tristate is_unitclassflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found nation_found(const struct requirement *preq, const struct universal *source)
#define REQUC_WORLD
static enum fc_tristate is_govflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * universal_type_rule_name(const struct universal *psource)
#define REQUC_PRESENT
static enum fc_tristate is_maxtotalunitsontile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void universal_found_functions_init(void)
static enum fc_tristate is_style_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found unit_class_found(const struct requirement *preq, const struct universal *source)
#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind)
int universal_number(const struct universal *source)
static enum fc_tristate is_techflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_mentioned_by_requirements(const struct requirement_vector *reqs, const struct universal *psource)
#define REQUC_CITYTILE
static enum fc_tristate is_citytile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found diplrel_found(const struct requirement *preq, const struct universal *source)
bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
bool req_implies_req(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_specialist_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_copy(struct requirement *dst, const struct requirement *src)
enum req_unchanging_status is_req_unchanging(const struct req_context *context, const struct requirement *req)
static bool player_has_ever_built(const struct player *pplayer, const struct impr_type *building)
enum fc_tristate(* is_req_active_cb)(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool nation_contra_group(const struct requirement *nation_req, const struct requirement *group_req)
static enum fc_tristate is_serversetting_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_plr_flag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_nation_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_is_impossible_to_fulfill(const struct requirement *req)
static bool are_tiles_in_range(const struct tile *tile1, const struct tile *tile2, enum req_range range)
static bool are_requirements_opposites(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_form_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static int num_world_buildings(const struct impr_type *building)
static enum req_unchanging_status unchanging_citystatus(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_topology_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_o_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
struct universal universal_by_rule_name(const char *kind, const char *value)
bool universals_mean_unfulfilled(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
struct req_vec_problem * req_vec_suggest_improvement(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static bool impr_contra_genus(const struct requirement *impr_req, const struct requirement *genus_req)
enum fc_tristate(* req_tester_cb)(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, void *data, int n_data)
#define requirement_diplrel_ereq(_id_, _range_, _present_)
signed char req_vec_num_in_item
req_vec_num_in_item a requirement vectors number in an item.
req_vec_num_in_item(* requirement_vector_number)(const void *parent_item, const struct requirement_vector *vec)
const char *(* requirement_vector_namer)(req_vec_num_in_item number)
#define universal_is_mentioned_by_requirement(preq, psource)
enum req_unchanging_status(* req_unchanging_cond_cb)(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
#define requirement_vector_iterate_end
struct universal universal_by_number(const enum universals_n kind, const int value)
struct requirement_vector *(* requirement_vector_by_number)(const void *parent_item, req_vec_num_in_item number)
#define requirement_vector_iterate(req_vec, preq)
req_item_found
@ ITF_NO
@ ITF_YES
@ ITF_NOT_APPLICABLE
req_unchanging_status
@ REQUCH_ACT
@ REQUCH_NO
@ REQUCH_SCRIPTS
@ REQUCH_YES
@ REQUCH_HACK
@ REQUCH_CTRL
struct research * research_get(const struct player *pplayer)
Definition research.c:130
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:622
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Definition road.c:416
bool is_road_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:446
bool is_road_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:425
bool ssetv_setting_has_value(ssetv val)
ssetv ssetv_by_rule_name(const char *name)
const char * ssetv_rule_name(ssetv val)
const char * ssetv_human_readable(ssetv val, bool present)
#define SSETV_NONE
enum fc_tristate fc_tristate_or(enum fc_tristate one, enum fc_tristate two)
Definition shared.c:143
fc_tristate
Definition shared.h:46
@ TRI_YES
Definition shared.h:46
@ TRI_NO
Definition shared.h:46
@ TRI_MAYBE
Definition shared.h:46
#define BOOL_TO_TRISTATE(tri)
Definition shared.h:47
#define FC_INFINITY
Definition shared.h:36
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c:123
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:110
Specialist_type_id specialist_number(const struct specialist *sp)
Definition specialist.c:100
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:157
const char * specialist_plural_translation(const struct specialist *sp)
Definition specialist.c:166
Definition city.h:318
struct packet_game_info info
Definition game.h:89
struct packet_calendar_info calendar
Definition game.h:90
int checkpoint
Definition counters.h:33
bv_gov_flags flags
Definition government.h:67
struct player * player
Definition nation.h:118
bool global_advances[A_LAST]
bool is_alive
Definition player.h:268
enum req_unchanging_status unchanging
req_unchanging_cond_cb unchanging_cond
const is_req_active_cb cb
req_vec_num_in_item vector_number
enum req_vec_change_operation operation
struct requirement req
char description[500]
char description_translated[500]
enum req_range range
struct universal source
Tech_type_id researching
Definition research.h:52
int future_tech
Definition research.h:42
int techs_researched
Definition research.h:42
Definition tile.h:50
struct tile * tile
Definition unit.h:142
const struct unit_type * utype
Definition unit.h:141
enum universals_n kind
Definition fc_types.h:593
universals_u value
Definition fc_types.h:592
struct civ_map map
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
struct nation_style * style_by_number(int id)
Definition style.c:88
const char * style_name_translation(const struct nation_style *pstyle)
Definition style.c:99
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:108
int style_number(const struct nation_style *pstyle)
Definition style.c:68
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:822
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define bool
Definition support.h:71
#define fc__fallthrough
Definition support.h:119
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag)
Definition tech.c:216
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:300
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:309
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:189
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:616
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:595
const char * terrain_class_name_translation(enum terrain_class tclass)
Definition terrain.c:665
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:241
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:158
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Definition terrain.c:677
bool is_terrain_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:331
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:250
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:586
bool is_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:462
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:149
bool is_terrain_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:442
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:352
#define T_UNKNOWN
Definition terrain.h:62
#define terrain_has_flag(terr, flag)
Definition terrain.h:176
bool tile_has_extra_flag(const struct tile *ptile, enum extra_flag_id flag)
Definition tile.c:887
bool tile_has_native_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:325
bool tile_has_road_flag(const struct tile *ptile, enum road_flag_id flag)
Definition tile.c:869
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_terrain(_tile)
Definition tile.h:115
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#define tile_owner(_tile)
Definition tile.h:97
bool goods_can_be_provided(const struct city *pcity, const struct goods_type *pgood, const struct unit *punit)
Goods_type_id goods_number(const struct goods_type *pgood)
bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
const char * goods_name_translation(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
#define trade_partners_iterate_end
#define trade_partners_iterate(c, p)
const struct unit_type * utype
Definition fc_types.h:535
int region_tiles
Definition fc_types.h:582
struct nation_style * style
Definition fc_types.h:539
enum ai_level ai_level
Definition fc_types.h:543
struct specialist * specialist
Definition fc_types.h:532
enum impr_genus_id impr_genus
Definition fc_types.h:567
enum citytile_type citytile
Definition fc_types.h:544
struct nation_group * nationgroup
Definition fc_types.h:538
struct extra_type * extra
Definition fc_types.h:536
enum wrap_flag wrap_property
Definition fc_types.h:585
enum plrstate_type plrstate
Definition fc_types.h:546
enum tilerel_type tilerel
Definition fc_types.h:547
struct nation_type * nation
Definition fc_types.h:529
int terrainclass
Definition fc_types.h:554
int unitclassflag
Definition fc_types.h:557
struct government * govern
Definition fc_types.h:527
struct nation_type * origowner
Definition fc_types.h:531
enum impr_flag_id impr_flag
Definition fc_types.h:568
int terrainalter
Definition fc_types.h:555
enum citystatus_type citystatus
Definition fc_types.h:545
int minforeignpct
Definition fc_types.h:550
const struct impr_type * building
Definition fc_types.h:528
int max_tile_total_units
Definition fc_types.h:571
int max_tile_top_units
Definition fc_types.h:572
struct achievement * achievement
Definition fc_types.h:537
ssetv ssetval
Definition fc_types.h:586
struct advance * advance
Definition fc_types.h:525
enum unit_activity activity
Definition fc_types.h:566
struct goods_type * good
Definition fc_types.h:541
struct terrain * terrain
Definition fc_types.h:533
int terrainflag
Definition fc_types.h:559
enum ustate_prop unit_state
Definition fc_types.h:565
Output_type_id outputtype
Definition fc_types.h:553
int distance_sq
Definition fc_types.h:581
enum topo_flag topo_property
Definition fc_types.h:584
struct counter * counter
Definition fc_types.h:526
int min_hit_points
Definition fc_types.h:574
struct unit_class * uclass
Definition fc_types.h:534
struct nation_type * nationality
Definition fc_types.h:530
struct action * action
Definition fc_types.h:540
int future_techs
Definition fc_types.h:578
enum plr_flag_id plr_flag
Definition fc_types.h:569
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1847
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2529
#define unit_tile(_pu)
Definition unit.h:407
#define unit_owner(_pu)
Definition unit.h:406
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const char * uclass_name_translation(const struct unit_class *pclass)
Definition unittype.c:1658
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126
bool unit_has_class_flag(const struct unit *punit, enum unit_class_flag_id flag)
Definition unittype.c:1675
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1793
bool uclass_flag_is_in_use(enum unit_class_flag_id ucflag)
Definition unittype.c:3013
struct unit_class * uclass_by_number(const Unit_Class_id id)
Definition unittype.c:2506
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1604
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2530
struct unit_type * utype_by_number(const Unit_type_id id)
Definition unittype.c:114
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:215
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1667
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:102
struct unit_class * unit_class_by_rule_name(const char *s)
Definition unittype.c:1810
bool utype_flag_is_in_use(enum unit_type_flag_id uflag)
Definition unittype.c:3032
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1463
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2497
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1586
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:773
#define utype_class(_t_)
Definition unittype.h:756
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
bool victory_enabled(enum victory_condition_type victory)
Definition victory.c:26