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 "tiledef.h"
44#include "victory.h" /* victory_enabled() */
45
46#include "requirements.h"
47
52
53/* get 'struct thr_req_data_list' and related functions: */
54#define SPECLIST_TAG thr_req_data
55#define SPECLIST_TYPE struct thr_req_data
56#include "speclist.h"
57
58#define thr_req_data_list_iterate(trlist, ptrdata) \
59 TYPED_LIST_ITERATE(struct thr_req_data, trlist, ptrdata)
60#define thr_req_data_list_iterate_end LIST_ITERATE_END
61
64
65/************************************************************************
66 Container for req_item_found functions
67************************************************************************/
68typedef enum req_item_found (*universal_found)(const struct requirement *,
69 const struct universal *);
71
72static
74 const struct req_context *context,
75 const struct req_context *other_context,
76 const struct requirement *req);
77
78/* Function pointer for requirement-type-specific is_req_active handlers */
79typedef enum fc_tristate
80(*is_req_active_cb)(const struct civ_map *nmap,
81 const struct req_context *context,
82 const struct req_context *other_context,
83 const struct requirement *req);
84
85static inline bool are_tiles_in_range(const struct tile *tile1,
86 const struct tile *tile2,
87 enum req_range range);
88
89/**********************************************************************/
94static enum req_unchanging_status
96 enum req_unchanging_status def,
97 const struct req_context *context,
98 const struct requirement *req)
99{
100 return req->range == REQ_RANGE_LOCAL ? REQUCH_YES : def;
101}
102#define REQUC_LOCAL unchanging_local
103
104/**********************************************************************/
107static enum req_unchanging_status
109 enum req_unchanging_status def,
110 const struct req_context *context,
111 const struct requirement *req)
112{
113 if (TRI_YES != tri_req_present(nmap, context, nullptr, req)) {
114 return REQUCH_NO;
115 }
116 return def;
117}
118#define REQUC_PRESENT unchanging_present
119
120/**********************************************************************/
123static enum req_unchanging_status
125 enum req_unchanging_status def,
126 const struct req_context *context,
127 const struct requirement *req)
128{
129 return
131 context, req);
132}
133#define REQUC_WORLD unchanging_world
134
135/**********************************************************************/
139static enum req_unchanging_status
141 enum req_unchanging_status def,
142 const struct req_context *context,
143 const struct requirement *req)
144{
145 if (REQ_RANGE_ALLIANCE == req->range
146 || REQ_RANGE_TEAM == req->range) {
147 struct requirement preq;
148
149 req_copy(&preq, req);
150 preq.range = REQ_RANGE_PLAYER;
151 if (TRI_YES != tri_req_present(nmap, context, nullptr, &preq)) {
152 return REQ_RANGE_TEAM == req->range ? REQUCH_ACT : REQUCH_NO;
153 }
154 }
155 return def;
156}
157#define REQUC_NALLY unchanging_noally
158
159/**********************************************************************/
162static enum req_unchanging_status
164 enum req_unchanging_status def,
165 const struct req_context *context,
166 const struct requirement *req)
167{
171 && context->city != nullptr && context->tile != nullptr
172 && city_tile(context->city) != nullptr
174 req->range))){
175 /* Cities don't move, and most reqs are present on city center */
176 return REQUCH_YES;
177 }
178 return def;
179}
180#define REQUC_CITYTILE unchanging_citytile
181
182/**********************************************************************/
185static enum req_unchanging_status
187 enum req_unchanging_status def,
188 const struct req_context *context,
189 const struct requirement *req)
190{
192
193 if (REQ_RANGE_CITY == req->range
196 return REQUCH_CTRL;
197 }
198
199 return def;
200}
201#define REQUC_CITYSTATUS unchanging_citystatus
202
203/**********************************************************************/
208static enum req_unchanging_status
210 enum req_unchanging_status def,
211 const struct req_context *context,
212 const struct requirement *req)
213{
214 const struct impr_type *b = req->source.value.building;
215
217 || VUT_SITE == req->source.kind, REQUCH_NO);
218 if (REQ_RANGE_LOCAL == req->range) {
219 /* Likely, won't be questioned for an obsolete building */
220 return REQUCH_YES;
221 }
222
223 if (req->source.kind == VUT_IMPROVEMENT
224 && improvement_obsolete(context->player, b, context->city)) {
225 /* FIXME: Sometimes can unobsolete, but considering it
226 * may sometimes put the function on endless recursion */
227 return REQUCH_ACT; /* Mostly about techs */
228 }
229 if (is_great_wonder(b)) {
232 && (req->range <= REQ_RANGE_CITY && TRI_YES
233 == tri_req_present(nmap, context, nullptr, req)))) {
234 /* If the wonder stays somewhere, it may either remain there
235 * or be destroyed. If it is destroyed, it is nowhere. */
236 return REQUCH_SCRIPTS;
237 }
238 }
239 return def;
240}
241#define REQUC_IMPR unchanging_building
242
248
249/**********************************************************************/
252static void thr_exit_cb(void)
253{
255
258 if (fc_threads_equal(self, data->thr_id)) {
260 free(data);
261 break;
262 }
265}
266
267/**********************************************************************/
276
277/**********************************************************************/
285
286/**********************************************************************/
294 const char *value)
295{
296 struct universal source;
297
299 if (!universals_n_is_valid(source.kind)) {
300 return source;
301 }
302
304
305 return source;
306}
307
308/**********************************************************************/
313{
314 return unit_activity_is_valid(act)
315 && act != ACTIVITY_SENTRY
316 && act != ACTIVITY_GOTO
317 && act != ACTIVITY_EXPLORE;
318}
319
320/**********************************************************************/
325{
326 if (univ->kind == VUT_ACTIVITY) {
328 }
329
330 return TRUE;
331}
332
333/**********************************************************************/
338{
339 /* Finally scan the value string based on the type of the source. */
340 switch (source->kind) {
341 case VUT_NONE:
342 return;
343 case VUT_ADVANCE:
344 source->value.advance = advance_by_rule_name(value);
345 if (source->value.advance != nullptr) {
346 return;
347 }
348 break;
349 case VUT_TECHFLAG:
350 source->value.techflag
352 if (tech_flag_id_is_valid(source->value.techflag)) {
353 return;
354 }
355 break;
356 case VUT_GOVERNMENT:
357 source->value.govern = government_by_rule_name(value);
358 if (source->value.govern != nullptr) {
359 return;
360 }
361 break;
362 case VUT_GOVFLAG:
364 if (gov_flag_id_is_valid(source->value.govflag)) {
365 return;
366 }
367 break;
368 case VUT_ACHIEVEMENT:
369 source->value.achievement = achievement_by_rule_name(value);
370 if (source->value.achievement != nullptr) {
371 return;
372 }
373 break;
374 case VUT_STYLE:
375 source->value.style = style_by_rule_name(value);
376 if (source->value.style != nullptr) {
377 return;
378 }
379 break;
380 case VUT_IMPROVEMENT:
381 case VUT_SITE:
382 source->value.building = improvement_by_rule_name(value);
383 if (source->value.building != nullptr) {
384 return;
385 }
386 break;
387 case VUT_IMPR_GENUS:
388 source->value.impr_genus = impr_genus_id_by_name(value, fc_strcasecmp);
389 if (impr_genus_id_is_valid(source->value.impr_genus)) {
390 return;
391 }
392 break;
393 case VUT_IMPR_FLAG:
394 source->value.impr_flag = impr_flag_id_by_name(value, fc_strcasecmp);
395 if (impr_flag_id_is_valid(source->value.impr_flag)) {
396 return;
397 }
398 break;
399 case VUT_PLAYER_FLAG:
400 source->value.plr_flag = plr_flag_id_by_name(value, fc_strcasecmp);
401 if (plr_flag_id_is_valid(source->value.plr_flag)) {
402 return;
403 }
404 break;
405 case VUT_EXTRA:
406 source->value.extra = extra_type_by_rule_name(value);
407 if (source->value.extra != nullptr) {
408 return;
409 }
410 break;
411 case VUT_TILEDEF:
413 source->value.tiledef = tiledef_by_rule_name(value);
414 if (source->value.tiledef != nullptr) {
415 return;
416 }
417 break;
418 case VUT_GOOD:
419 source->value.good = goods_by_rule_name(value);
420 if (source->value.good != nullptr) {
421 return;
422 }
423 break;
424 case VUT_TERRAIN:
425 source->value.terrain = terrain_by_rule_name(value);
426 if (source->value.terrain != T_UNKNOWN) {
427 return;
428 }
429 break;
430 case VUT_TERRFLAG:
431 source->value.terrainflag
433 if (terrain_flag_id_is_valid(source->value.terrainflag)) {
434 return;
435 }
436 break;
437 case VUT_NATION:
438 source->value.nation = nation_by_rule_name(value);
439 if (source->value.nation != NO_NATION_SELECTED) {
440 return;
441 }
442 break;
443 case VUT_NATIONGROUP:
444 source->value.nationgroup = nation_group_by_rule_name(value);
445 if (source->value.nationgroup != nullptr) {
446 return;
447 }
448 break;
449 case VUT_NATIONALITY:
450 source->value.nationality = nation_by_rule_name(value);
451 if (source->value.nationality != NO_NATION_SELECTED) {
452 return;
453 }
454 break;
456 source->value.origowner = nation_by_rule_name(value);
457 if (source->value.origowner != NO_NATION_SELECTED) {
458 return;
459 }
460 break;
461 case VUT_DIPLREL:
462 case VUT_DIPLREL_TILE:
466 source->value.diplrel = diplrel_by_rule_name(value);
467 if (source->value.diplrel != diplrel_other_invalid()) {
468 return;
469 }
470 break;
471 case VUT_UTYPE:
472 source->value.utype = unit_type_by_rule_name(value);
473 if (source->value.utype) {
474 return;
475 }
476 break;
477 case VUT_UTFLAG:
479 if (unit_type_flag_id_is_valid(source->value.unitflag)) {
480 return;
481 }
482 break;
483 case VUT_UCLASS:
484 source->value.uclass = unit_class_by_rule_name(value);
485 if (source->value.uclass) {
486 return;
487 }
488 break;
489 case VUT_UCFLAG:
490 source->value.unitclassflag
492 if (unit_class_flag_id_is_valid(source->value.unitclassflag)) {
493 return;
494 }
495 break;
496 case VUT_MINVETERAN:
497 source->value.minveteran = atoi(value);
498 if (source->value.minveteran > 0) {
499 return;
500 }
501 break;
502 case VUT_UNITSTATE:
503 source->value.unit_state = ustate_prop_by_name(value, fc_strcasecmp);
504 if (ustate_prop_is_valid(source->value.unit_state)) {
505 return;
506 }
507 break;
508 case VUT_ACTIVITY:
510 if (activity_is_valid_in_requirement(source->value.activity)) {
511 return;
512 }
513 break;
514 case VUT_MINMOVES:
515 source->value.minmoves = atoi(value);
516 if (source->value.minmoves > 0) {
517 return;
518 }
519 break;
520 case VUT_MINHP:
521 source->value.min_hit_points = atoi(value);
522 if (source->value.min_hit_points > 0) {
523 return;
524 }
525 break;
526 case VUT_AGE:
527 source->value.age = atoi(value);
528 if (source->value.age > 0) {
529 return;
530 }
531 break;
532 case VUT_FORM_AGE:
533 source->value.form_age = atoi(value);
534 if (source->value.form_age > 0) {
535 return;
536 }
537 break;
538 case VUT_MINTECHS:
539 source->value.min_techs = atoi(value);
540 if (source->value.min_techs > 0) {
541 return;
542 }
543 break;
544 case VUT_FUTURETECHS:
545 source->value.future_techs = atoi(value);
546 if (source->value.future_techs > 0) {
547 return;
548 }
549 break;
550 case VUT_MINCITIES:
551 source->value.min_cities = atoi(value);
552 if (source->value.min_cities > 0) {
553 return;
554 }
555 break;
556 case VUT_ACTION:
557 source->value.action = action_by_rule_name(value);
558 if (source->value.action != nullptr) {
559 return;
560 }
561 break;
562 case VUT_OTYPE:
563 source->value.outputtype = output_type_by_identifier(value);
564 if (source->value.outputtype != O_LAST) {
565 return;
566 }
567 break;
568 case VUT_SPECIALIST:
569 source->value.specialist = specialist_by_rule_name(value);
570 if (source->value.specialist) {
571 return;
572 }
573 break;
574 case VUT_MINSIZE:
575 source->value.minsize = atoi(value);
576 if (source->value.minsize > 0) {
577 return;
578 }
579 break;
580 case VUT_MINCULTURE:
581 source->value.minculture = atoi(value);
582 if (source->value.minculture > 0) {
583 return;
584 }
585 break;
587 source->value.minforeignpct = atoi(value);
588 if (source->value.minforeignpct > 0) {
589 return;
590 }
591 break;
592 case VUT_AI_LEVEL:
593 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
594 if (ai_level_is_valid(source->value.ai_level)) {
595 return;
596 }
597 break;
599 source->value.max_tile_total_units = atoi(value);
600 if (0 <= source->value.max_tile_total_units) {
601 return;
602 }
603 break;
605 source->value.max_tile_top_units = atoi(value);
606 if (0 <= source->value.max_tile_top_units) {
607 return;
608 }
609 break;
610 case VUT_TERRAINCLASS:
611 source->value.terrainclass
613 if (terrain_class_is_valid(source->value.terrainclass)) {
614 return;
615 }
616 break;
617 case VUT_ROADFLAG:
619 if (road_flag_id_is_valid(source->value.roadflag)) {
620 return;
621 }
622 break;
623 case VUT_EXTRAFLAG:
624 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
625 if (extra_flag_id_is_valid(source->value.extraflag)) {
626 return;
627 }
628 break;
629 case VUT_MINYEAR:
630 source->value.minyear = atoi(value);
631 return;
632 case VUT_MINCALFRAG:
633 /* Rule names are 0-based numbers, not pretty names from ruleset */
634 source->value.mincalfrag = atoi(value);
635 if (source->value.mincalfrag >= 0) {
636 /* More range checking done later, in sanity_check_req_individual() */
637 return;
638 }
639 break;
640 case VUT_TOPO:
641 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
642 if (topo_flag_is_valid(source->value.topo_property)) {
643 return;
644 }
645 break;
646 case VUT_WRAP:
647 source->value.wrap_property = wrap_flag_by_name(value, fc_strcasecmp);
648 if (wrap_flag_is_valid(source->value.wrap_property)) {
649 return;
650 }
651 break;
653 source->value.ssetval = ssetv_by_rule_name(value);
654 if (source->value.ssetval != SSETV_NONE) {
655 return;
656 }
657 break;
658 case VUT_TERRAINALTER:
659 source->value.terrainalter
661 if (terrain_alteration_is_valid(source->value.terrainalter)) {
662 return;
663 }
664 break;
665 case VUT_CITYTILE:
667 if (source->value.citytile != CITYT_LAST) {
668 return;
669 }
670 break;
671 case VUT_CITYSTATUS:
673 if (source->value.citystatus != CITYS_LAST) {
674 return;
675 }
676 break;
677 case VUT_PLAYER_STATE:
679 if (source->value.plrstate != PLRS_LAST) {
680 return;
681 }
682 break;
683 case VUT_MINLATITUDE:
684 case VUT_MAXLATITUDE:
685 source->value.latitude = atoi(value);
686 if (source->value.latitude >= -MAP_MAX_LATITUDE
687 && source->value.latitude <= MAP_MAX_LATITUDE) {
688 return;
689 }
690 break;
691 case VUT_COUNTER:
692 source->value.counter = counter_by_rule_name(value);
693 if (source->value.counter != nullptr) {
694 return;
695 }
696 break;
698 source->value.distance_sq = atoi(value);
699 if (0 <= source->value.distance_sq) {
700 return;
701 }
702 break;
704 source->value.region_tiles = atoi(value);
705 if (0 < source->value.region_tiles) {
706 return;
707 }
708 break;
709 case VUT_TILE_REL:
711 if (source->value.tilerel != TREL_COUNT) {
712 return;
713 }
714 break;
715 case VUT_COUNT:
716 break;
717 }
718
719 /* If we reach here there's been an error. */
721}
722
723/**********************************************************************/
730{
731 struct universal source;
732
733 source.kind = kind;
734
735 switch (source.kind) {
736 case VUT_NONE:
737 /* Avoid compiler warning about uninitialized source.value */
738 source.value.advance = nullptr;
739
740 return source;
741 case VUT_ADVANCE:
742 source.value.advance = advance_by_number(value);
743 if (source.value.advance != nullptr) {
744 return source;
745 }
746 break;
747 case VUT_TECHFLAG:
748 source.value.techflag = value;
749 return source;
750 case VUT_GOVERNMENT:
752 if (source.value.govern != nullptr) {
753 return source;
754 }
755 break;
756 case VUT_GOVFLAG:
757 source.value.govflag = value;
758 return source;
759 case VUT_ACHIEVEMENT:
761 if (source.value.achievement != nullptr) {
762 return source;
763 }
764 break;
765 case VUT_STYLE:
766 source.value.style = style_by_number(value);
767 if (source.value.style != nullptr) {
768 return source;
769 }
770 break;
771 case VUT_IMPROVEMENT:
772 case VUT_SITE:
773 source.value.building = improvement_by_number(value);
774 if (source.value.building != nullptr) {
775 return source;
776 }
777 break;
778 case VUT_IMPR_GENUS:
779 source.value.impr_genus = value;
780 return source;
781 case VUT_IMPR_FLAG:
782 source.value.impr_flag = value;
783 return source;
784 case VUT_PLAYER_FLAG:
785 source.value.plr_flag = value;
786 return source;
787 case VUT_EXTRA:
789 return source;
790 case VUT_TILEDEF:
792 source.value.tiledef = tiledef_by_number(value);
793 return source;
794 case VUT_GOOD:
795 source.value.good = goods_by_number(value);
796 return source;
797 case VUT_TERRAIN:
798 source.value.terrain = terrain_by_number(value);
799 if (source.value.terrain != nullptr) {
800 return source;
801 }
802 break;
803 case VUT_TERRFLAG:
804 source.value.terrainflag = value;
805 return source;
806 case VUT_NATION:
808 if (source.value.nation != nullptr) {
809 return source;
810 }
811 break;
812 case VUT_NATIONGROUP:
813 source.value.nationgroup = nation_group_by_number(value);
814 if (source.value.nationgroup != nullptr) {
815 return source;
816 }
817 break;
818 case VUT_DIPLREL:
819 case VUT_DIPLREL_TILE:
823 source.value.diplrel = value;
824 if (source.value.diplrel != diplrel_other_invalid()) {
825 return source;
826 }
827 break;
828 case VUT_NATIONALITY:
830 if (source.value.nationality != nullptr) {
831 return source;
832 }
833 break;
835 source.value.origowner = nation_by_number(value);
836 if (source.value.origowner != nullptr) {
837 return source;
838 }
839 break;
840 case VUT_UTYPE:
841 source.value.utype = utype_by_number(value);
842 if (source.value.utype != nullptr) {
843 return source;
844 }
845 break;
846 case VUT_UTFLAG:
847 source.value.unitflag = value;
848 return source;
849 case VUT_UCLASS:
851 if (source.value.uclass != nullptr) {
852 return source;
853 }
854 break;
855 case VUT_UCFLAG:
856 source.value.unitclassflag = value;
857 return source;
858 case VUT_MINVETERAN:
859 source.value.minveteran = value;
860 return source;
861 case VUT_UNITSTATE:
862 source.value.unit_state = value;
863 return source;
864 case VUT_ACTIVITY:
865 source.value.activity = value;
866 return source;
867 case VUT_MINMOVES:
868 source.value.minmoves = value;
869 return source;
870 case VUT_MINHP:
872 return source;
873 case VUT_AGE:
874 source.value.age = value;
875 return source;
876 case VUT_FORM_AGE:
877 source.value.form_age = value;
878 return source;
879 case VUT_MINTECHS:
880 source.value.min_techs = value;
881 return source;
882 case VUT_FUTURETECHS:
883 source.value.future_techs = value;
884 return source;
885 case VUT_MINCITIES:
886 source.value.min_cities = value;
887 return source;
888 case VUT_ACTION:
890 if (source.value.action != nullptr) {
891 return source;
892 }
893 break;
894 case VUT_OTYPE:
895 source.value.outputtype = value;
896 return source;
897 case VUT_SPECIALIST:
899 return source;
900 case VUT_MINSIZE:
901 source.value.minsize = value;
902 return source;
903 case VUT_MINCULTURE:
904 source.value.minculture = value;
905 return source;
907 source.value.minforeignpct = value;
908 return source;
909 case VUT_AI_LEVEL:
910 source.value.ai_level = value;
911 return source;
914 return source;
917 return source;
918 case VUT_TERRAINCLASS:
919 source.value.terrainclass = value;
920 return source;
921 case VUT_ROADFLAG:
922 source.value.roadflag = value;
923 return source;
924 case VUT_EXTRAFLAG:
925 source.value.extraflag = value;
926 return source;
927 case VUT_MINYEAR:
928 source.value.minyear = value;
929 return source;
930 case VUT_MINCALFRAG:
931 source.value.mincalfrag = value;
932 return source;
933 case VUT_TOPO:
934 source.value.topo_property = value;
935 return source;
936 case VUT_WRAP:
937 source.value.wrap_property = value;
938 return source;
940 source.value.ssetval = value;
941 return source;
942 case VUT_TERRAINALTER:
943 source.value.terrainalter = value;
944 return source;
945 case VUT_CITYTILE:
946 source.value.citytile = value;
947 return source;
948 case VUT_CITYSTATUS:
949 source.value.citystatus = value;
950 return source;
951 case VUT_PLAYER_STATE:
952 source.value.plrstate = value;
953 return source;
954 case VUT_COUNTER:
956 return source;
957 case VUT_MINLATITUDE:
958 case VUT_MAXLATITUDE:
959 source.value.latitude = value;
960 return source;
962 source.value.distance_sq = value;
963 return source;
965 source.value.region_tiles = value;
966 return source;
967 case VUT_TILE_REL:
968 source.value.tilerel = value;
969 return source;
970 case VUT_COUNT:
971 break;
972 }
973
974 /* If we reach here there's been an error. */
976 /* Avoid compiler warning about uninitialized source.value */
977 source.value.advance = nullptr;
978
979 return source;
980}
981
982/**********************************************************************/
985void universal_copy(struct universal *dst, const struct universal *src)
986{
987 dst->value = src->value;
988 dst->kind = src->kind;
989}
990
991/**********************************************************************/
996 int *kind, int *value)
997{
998 *kind = source->kind;
1000}
1001
1002/**********************************************************************/
1006{
1007 switch (source->kind) {
1008 case VUT_NONE:
1009 return 0;
1010 case VUT_ADVANCE:
1011 return advance_number(source->value.advance);
1012 case VUT_TECHFLAG:
1013 return source->value.techflag;
1014 case VUT_GOVERNMENT:
1015 return government_number(source->value.govern);
1016 case VUT_GOVFLAG:
1017 return source->value.govflag;
1018 case VUT_ACHIEVEMENT:
1019 return achievement_number(source->value.achievement);
1020 case VUT_STYLE:
1021 return style_number(source->value.style);
1022 case VUT_IMPROVEMENT:
1023 case VUT_SITE:
1024 return improvement_number(source->value.building);
1025 case VUT_IMPR_GENUS:
1026 return source->value.impr_genus;
1027 case VUT_IMPR_FLAG:
1028 return source->value.impr_flag;
1029 case VUT_PLAYER_FLAG:
1030 return source->value.plr_flag;
1031 case VUT_EXTRA:
1032 return extra_number(source->value.extra);
1033 case VUT_TILEDEF:
1035 return tiledef_number(source->value.tiledef);
1036 case VUT_GOOD:
1037 return goods_number(source->value.good);
1038 case VUT_TERRAIN:
1039 return terrain_number(source->value.terrain);
1040 case VUT_TERRFLAG:
1041 return source->value.terrainflag;
1042 case VUT_NATION:
1043 return nation_number(source->value.nation);
1044 case VUT_NATIONGROUP:
1045 return nation_group_number(source->value.nationgroup);
1046 case VUT_NATIONALITY:
1047 return nation_number(source->value.nationality);
1048 case VUT_ORIGINAL_OWNER:
1049 return nation_number(source->value.origowner);
1050 case VUT_DIPLREL:
1051 case VUT_DIPLREL_TILE:
1052 case VUT_DIPLREL_TILE_O:
1055 return source->value.diplrel;
1056 case VUT_UTYPE:
1057 return utype_number(source->value.utype);
1058 case VUT_UTFLAG:
1059 return source->value.unitflag;
1060 case VUT_UCLASS:
1061 return uclass_number(source->value.uclass);
1062 case VUT_UCFLAG:
1063 return source->value.unitclassflag;
1064 case VUT_MINVETERAN:
1065 return source->value.minveteran;
1066 case VUT_UNITSTATE:
1067 return source->value.unit_state;
1068 case VUT_ACTIVITY:
1069 return source->value.activity;
1070 case VUT_MINMOVES:
1071 return source->value.minmoves;
1072 case VUT_MINHP:
1073 return source->value.min_hit_points;
1074 case VUT_AGE:
1075 return source->value.age;
1076 case VUT_FORM_AGE:
1077 return source->value.form_age;
1078 case VUT_MINTECHS:
1079 return source->value.min_techs;
1080 case VUT_FUTURETECHS:
1081 return source->value.future_techs;
1082 case VUT_MINCITIES:
1083 return source->value.min_cities;
1084 case VUT_ACTION:
1085 return action_number(source->value.action);
1086 case VUT_OTYPE:
1087 return source->value.outputtype;
1088 case VUT_SPECIALIST:
1089 return specialist_number(source->value.specialist);
1090 case VUT_MINSIZE:
1091 return source->value.minsize;
1092 case VUT_MINCULTURE:
1093 return source->value.minculture;
1094 case VUT_MINFOREIGNPCT:
1095 return source->value.minforeignpct;
1096 case VUT_AI_LEVEL:
1097 return source->value.ai_level;
1099 return source->value.max_tile_total_units;
1101 return source->value.max_tile_top_units;
1102 case VUT_TERRAINCLASS:
1103 return source->value.terrainclass;
1104 case VUT_ROADFLAG:
1105 return source->value.roadflag;
1106 case VUT_EXTRAFLAG:
1107 return source->value.extraflag;
1108 case VUT_MINYEAR:
1109 return source->value.minyear;
1110 case VUT_MINCALFRAG:
1111 return source->value.mincalfrag;
1112 case VUT_TOPO:
1113 return source->value.topo_property;
1114 case VUT_WRAP:
1115 return source->value.wrap_property;
1116 case VUT_SERVERSETTING:
1117 return source->value.ssetval;
1118 case VUT_TERRAINALTER:
1119 return source->value.terrainalter;
1120 case VUT_CITYTILE:
1121 return source->value.citytile;
1122 case VUT_CITYSTATUS:
1123 return source->value.citystatus;
1124 case VUT_PLAYER_STATE:
1125 return source->value.plrstate;
1126 case VUT_COUNTER:
1127 return counter_id(source->value.counter);
1128 case VUT_MINLATITUDE:
1129 case VUT_MAXLATITUDE:
1130 return source->value.latitude;
1132 return source->value.distance_sq;
1134 return source->value.region_tiles;
1135 case VUT_TILE_REL:
1136 return source->value.tilerel;
1137 case VUT_COUNT:
1138 break;
1139 }
1140
1141 /* If we reach here there's been an error. */
1142 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
1143 source->kind);
1144 return 0;
1145}
1146
1147
1148/**********************************************************************/
1152{
1153 static const struct req_context empty = {};
1154 return &empty;
1155}
1156
1157
1158/**********************************************************************/
1166const char *req_to_fstring(const struct requirement *req,
1167 struct astring *astr)
1168{
1169 astr_init(astr);
1170
1171 astr_set(astr, "%s%s %s %s%s",
1172 req->survives ? "surviving " : "",
1173 req_range_name(req->range),
1175 req->present ? "" : "!",
1177
1178 return astr_str(astr);
1179}
1180
1181/**********************************************************************/
1189 bool survives, bool present, bool quiet,
1190 const char *value)
1191{
1192 struct requirement req;
1193 bool invalid;
1194 const char *error = nullptr;
1195
1196 req.source = universal_by_rule_name(type, value);
1197
1199 if (invalid) {
1200 error = "bad type or name";
1201 } else {
1202 /* Scan the range string to find the range. If no range is given a
1203 * default fallback is used rather than giving an error. */
1204 if (range != nullptr) {
1206 if (!req_range_is_valid(req.range)) {
1207 invalid = TRUE;
1208 }
1209 } else {
1210 switch (req.source.kind) {
1211 case VUT_NONE:
1212 case VUT_COUNT:
1213 break;
1214 case VUT_IMPROVEMENT:
1215 case VUT_SITE:
1216 case VUT_IMPR_GENUS:
1217 case VUT_IMPR_FLAG:
1218 case VUT_UTYPE:
1219 case VUT_UTFLAG:
1220 case VUT_UCLASS:
1221 case VUT_UCFLAG:
1222 case VUT_MINVETERAN:
1223 case VUT_UNITSTATE:
1224 case VUT_ACTIVITY:
1225 case VUT_MINMOVES:
1226 case VUT_MINHP:
1227 case VUT_AGE:
1228 case VUT_FORM_AGE:
1229 case VUT_ACTION:
1230 case VUT_OTYPE:
1231 case VUT_SPECIALIST:
1232 case VUT_DIPLREL_TILE_O:
1234 req.range = REQ_RANGE_LOCAL;
1235 break;
1236 case VUT_EXTRA:
1237 case VUT_TILEDEF:
1238 case VUT_ROADFLAG:
1239 case VUT_EXTRAFLAG:
1240 /* Keep old behavior */
1241 req.range = REQ_RANGE_TILE;
1242 break;
1243 case VUT_TERRAIN:
1244 case VUT_TERRFLAG:
1245 case VUT_TERRAINCLASS:
1246 case VUT_TERRAINALTER:
1247 case VUT_CITYTILE:
1250 case VUT_MINLATITUDE:
1251 case VUT_MAXLATITUDE:
1253 req.range = REQ_RANGE_TILE;
1254 break;
1255 case VUT_COUNTER:
1256 case VUT_MINSIZE:
1257 case VUT_MINCULTURE:
1258 case VUT_MINFOREIGNPCT:
1259 case VUT_NATIONALITY:
1260 case VUT_ORIGINAL_OWNER:
1261 case VUT_CITYSTATUS:
1262 case VUT_GOOD:
1264 req.range = REQ_RANGE_CITY;
1265 break;
1266 case VUT_GOVERNMENT:
1267 case VUT_GOVFLAG:
1268 case VUT_ACHIEVEMENT:
1269 case VUT_STYLE:
1270 case VUT_ADVANCE:
1271 case VUT_TECHFLAG:
1272 case VUT_NATION:
1273 case VUT_NATIONGROUP:
1274 case VUT_DIPLREL:
1275 case VUT_DIPLREL_TILE:
1277 case VUT_AI_LEVEL:
1278 case VUT_PLAYER_FLAG:
1279 case VUT_PLAYER_STATE:
1280 case VUT_MINCITIES:
1281 case VUT_FUTURETECHS:
1282 req.range = REQ_RANGE_PLAYER;
1283 break;
1284 case VUT_MINYEAR:
1285 case VUT_MINCALFRAG:
1286 case VUT_TOPO:
1287 case VUT_WRAP:
1288 case VUT_MINTECHS:
1289 case VUT_SERVERSETTING:
1290 req.range = REQ_RANGE_WORLD;
1291 break;
1294 break;
1295 case VUT_TILE_REL:
1296 req.range = REQ_RANGE_TILE;
1298 /* Not available at Tile range */
1300 }
1301 break;
1302 }
1303 }
1304
1305 req.survives = survives;
1306 req.present = present;
1307 req.quiet = quiet;
1308
1309 /* These checks match what combinations are supported inside
1310 * is_req_active(). However, it's only possible to do basic checks,
1311 * not anything that might depend on the rest of the ruleset which
1312 * might not have been loaded yet. */
1313 switch (req.source.kind) {
1314 case VUT_TERRAIN:
1315 case VUT_TERRAINCLASS:
1316 case VUT_TERRFLAG:
1317 invalid = (req.range != REQ_RANGE_TILE
1318 && req.range != REQ_RANGE_CADJACENT
1319 && req.range != REQ_RANGE_ADJACENT
1320 && req.range != REQ_RANGE_CITY
1321 && req.range != REQ_RANGE_TRADE_ROUTE);
1322 break;
1323 case VUT_EXTRA:
1324 case VUT_ROADFLAG:
1325 case VUT_EXTRAFLAG:
1327 break;
1328 case VUT_TILEDEF:
1330 || req.range == REQ_RANGE_LOCAL);
1331 break;
1332 case VUT_ACHIEVEMENT:
1333 case VUT_MINTECHS:
1334 case VUT_FUTURETECHS:
1335 invalid = (req.range < REQ_RANGE_PLAYER);
1336 break;
1337 case VUT_ADVANCE:
1338 case VUT_TECHFLAG:
1340 && req.range != REQ_RANGE_LOCAL);
1341 break;
1342 case VUT_GOVERNMENT:
1343 case VUT_GOVFLAG:
1344 case VUT_AI_LEVEL:
1345 case VUT_STYLE:
1346 case VUT_MINCITIES:
1347 invalid = (req.range != REQ_RANGE_PLAYER);
1348 break;
1349 case VUT_MINSIZE:
1350 case VUT_MINFOREIGNPCT:
1351 case VUT_NATIONALITY:
1352 case VUT_CITYSTATUS:
1353 invalid = (req.range != REQ_RANGE_CITY
1354 && req.range != REQ_RANGE_TRADE_ROUTE);
1355 break;
1356 case VUT_GOOD:
1357 case VUT_ORIGINAL_OWNER:
1359 invalid = (req.range != REQ_RANGE_CITY);
1360 break;
1361 case VUT_MINCULTURE:
1362 invalid = (req.range != REQ_RANGE_CITY
1364 && req.range != REQ_RANGE_PLAYER
1365 && req.range != REQ_RANGE_TEAM
1366 && req.range != REQ_RANGE_ALLIANCE
1367 && req.range != REQ_RANGE_WORLD);
1368 break;
1369 case VUT_DIPLREL:
1370 invalid = (req.range != REQ_RANGE_LOCAL
1371 && req.range != REQ_RANGE_PLAYER
1372 && req.range != REQ_RANGE_TEAM
1373 && req.range != REQ_RANGE_ALLIANCE
1374 && req.range != REQ_RANGE_WORLD)
1375 /* Non local foreign makes no sense. */
1376 || (req.source.value.diplrel == DRO_FOREIGN
1377 && req.range != REQ_RANGE_LOCAL);
1378 break;
1379 case VUT_DIPLREL_TILE:
1380 invalid = (req.range != REQ_RANGE_LOCAL
1381 && req.range != REQ_RANGE_PLAYER
1382 && req.range != REQ_RANGE_TEAM
1383 && req.range != REQ_RANGE_ALLIANCE)
1384 /* Non local foreign makes no sense. */
1385 || (req.source.value.diplrel == DRO_FOREIGN
1386 && req.range != REQ_RANGE_LOCAL);
1387 break;
1388 case VUT_DIPLREL_TILE_O:
1389 invalid = (req.range != REQ_RANGE_LOCAL);
1390 break;
1392 invalid = (req.range != REQ_RANGE_LOCAL
1393 && req.range != REQ_RANGE_PLAYER
1394 && req.range != REQ_RANGE_TEAM
1395 && req.range != REQ_RANGE_ALLIANCE)
1396 /* Non local foreign makes no sense. */
1397 || (req.source.value.diplrel == DRO_FOREIGN
1398 && req.range != REQ_RANGE_LOCAL);
1399 break;
1401 invalid = (req.range != REQ_RANGE_LOCAL);
1402 break;
1403 case VUT_NATION:
1404 case VUT_NATIONGROUP:
1406 && req.range != REQ_RANGE_TEAM
1407 && req.range != REQ_RANGE_ALLIANCE
1408 && req.range != REQ_RANGE_WORLD);
1409 break;
1410 case VUT_MINVETERAN:
1411 case VUT_UNITSTATE:
1412 case VUT_ACTIVITY:
1413 case VUT_MINMOVES:
1414 case VUT_MINHP:
1415 case VUT_ACTION:
1416 case VUT_OTYPE:
1417 case VUT_SPECIALIST:
1418 invalid = (req.range != REQ_RANGE_LOCAL);
1419 break;
1420 case VUT_UTYPE:
1421 case VUT_UTFLAG:
1422 case VUT_UCLASS:
1423 case VUT_UCFLAG:
1424 invalid = (req.range != REQ_RANGE_LOCAL
1425 && req.range != REQ_RANGE_TILE
1426 && req.range != REQ_RANGE_CADJACENT
1427 && req.range != REQ_RANGE_ADJACENT);
1428 break;
1429 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1431 invalid = (req.range != REQ_RANGE_TILE);
1432 break;
1433 case VUT_CITYTILE:
1436 invalid = (req.range != REQ_RANGE_TILE
1437 && req.range != REQ_RANGE_CADJACENT
1438 && req.range != REQ_RANGE_ADJACENT);
1439 break;
1440 case VUT_MINLATITUDE:
1441 case VUT_MAXLATITUDE:
1442 invalid = (req.range != REQ_RANGE_TILE
1443 && req.range != REQ_RANGE_CADJACENT
1444 && req.range != REQ_RANGE_ADJACENT
1445 && req.range != REQ_RANGE_WORLD)
1446 /* Avoid redundancy at tile range: no negated requirements
1447 * that could be emulated by a present requirement of the
1448 * other type */
1449 || (req.range == REQ_RANGE_TILE && !req.present);
1450 break;
1451 case VUT_MINYEAR:
1452 case VUT_MINCALFRAG:
1453 case VUT_TOPO:
1454 case VUT_WRAP:
1455 case VUT_SERVERSETTING:
1456 invalid = (req.range != REQ_RANGE_WORLD);
1457 break;
1458 case VUT_AGE:
1459 /* FIXME: Could support TRADE_ROUTE, TEAM, etc */
1460 invalid = (req.range != REQ_RANGE_LOCAL
1461 && req.range != REQ_RANGE_CITY
1462 && req.range != REQ_RANGE_PLAYER);
1463 break;
1464 case VUT_FORM_AGE:
1465 invalid = (req.range != REQ_RANGE_LOCAL);
1466 break;
1467 case VUT_IMPR_GENUS:
1468 /* TODO: Support other ranges too. */
1469 invalid = (req.range != REQ_RANGE_LOCAL);
1470 break;
1471 case VUT_IMPR_FLAG:
1472 invalid = (req.range != REQ_RANGE_LOCAL
1473 && req.range != REQ_RANGE_TILE
1474 && req.range != REQ_RANGE_CITY);
1475 break;
1476 case VUT_COUNTER:
1477 invalid = req.range != REQ_RANGE_CITY;
1478 break;
1479 case VUT_PLAYER_FLAG:
1480 case VUT_PLAYER_STATE:
1481 invalid = (req.range != REQ_RANGE_PLAYER);
1482 break;
1485 && req.range != REQ_RANGE_CADJACENT
1486 && req.range != REQ_RANGE_ADJACENT);
1487 break;
1488 case VUT_TILE_REL:
1490 && req.range != REQ_RANGE_CADJACENT
1491 && req.range != REQ_RANGE_TILE)
1492 /* TREL_ONLY_OTHER_REGION not supported at Tile range */
1494 && req.range == REQ_RANGE_TILE);
1495 break;
1496 case VUT_IMPROVEMENT:
1497 case VUT_SITE:
1498 /* Valid ranges depend on the building genus (wonder/improvement),
1499 * which might not have been loaded from the ruleset yet.
1500 * So we allow anything here, and do a proper check once ruleset
1501 * loading is complete, in sanity_check_req_individual(). */
1502 case VUT_NONE:
1503 invalid = FALSE;
1504 break;
1505 case VUT_COUNT:
1506 break;
1507 }
1508 if (invalid) {
1509 error = "bad range";
1510 }
1511 }
1512
1513 if (!invalid) {
1514 /* Check 'survives'. */
1515 switch (req.source.kind) {
1516 case VUT_IMPROVEMENT:
1517 case VUT_SITE:
1518 /* See buildings_in_range(). */
1520 break;
1521 case VUT_NATION:
1522 case VUT_ADVANCE:
1524 break;
1525 case VUT_COUNTER:
1526 case VUT_IMPR_GENUS:
1527 case VUT_IMPR_FLAG:
1528 case VUT_PLAYER_FLAG:
1529 case VUT_PLAYER_STATE:
1530 case VUT_GOVERNMENT:
1531 case VUT_GOVFLAG:
1532 case VUT_TERRAIN:
1533 case VUT_UTYPE:
1534 case VUT_UTFLAG:
1535 case VUT_UCLASS:
1536 case VUT_UCFLAG:
1537 case VUT_MINVETERAN:
1538 case VUT_UNITSTATE:
1539 case VUT_ACTIVITY:
1540 case VUT_MINMOVES:
1541 case VUT_MINHP:
1542 case VUT_AGE:
1543 case VUT_FORM_AGE:
1544 case VUT_ACTION:
1545 case VUT_OTYPE:
1546 case VUT_SPECIALIST:
1547 case VUT_MINSIZE:
1548 case VUT_MINCULTURE:
1549 case VUT_MINFOREIGNPCT:
1550 case VUT_AI_LEVEL:
1551 case VUT_TERRAINCLASS:
1552 case VUT_MINYEAR:
1553 case VUT_MINCALFRAG:
1554 case VUT_TOPO:
1555 case VUT_WRAP:
1556 case VUT_SERVERSETTING:
1557 case VUT_TERRAINALTER:
1558 case VUT_CITYTILE:
1559 case VUT_CITYSTATUS:
1560 case VUT_TERRFLAG:
1561 case VUT_NATIONALITY:
1562 case VUT_ORIGINAL_OWNER:
1563 case VUT_ROADFLAG:
1564 case VUT_EXTRAFLAG:
1565 case VUT_EXTRA:
1566 case VUT_TILEDEF:
1568 case VUT_GOOD:
1569 case VUT_TECHFLAG:
1570 case VUT_ACHIEVEMENT:
1571 case VUT_NATIONGROUP:
1572 case VUT_STYLE:
1573 case VUT_DIPLREL:
1574 case VUT_DIPLREL_TILE:
1575 case VUT_DIPLREL_TILE_O:
1580 case VUT_MINTECHS:
1581 case VUT_FUTURETECHS:
1582 case VUT_MINCITIES:
1583 case VUT_MINLATITUDE:
1584 case VUT_MAXLATITUDE:
1587 case VUT_TILE_REL:
1588 /* Most requirements don't support 'survives'. */
1589 invalid = survives;
1590 break;
1591 case VUT_NONE:
1592 case VUT_COUNT:
1593 break;
1594 }
1595 if (invalid) {
1596 error = "bad 'survives'";
1597 }
1598 }
1599
1600 if (invalid) {
1601 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1602 type, range, survives ? "survives" : "",
1603 present ? "present" : "", value, error);
1605 }
1606
1607 return req;
1608}
1609
1610/**********************************************************************/
1616 int value)
1617{
1618 struct requirement req;
1619
1620 req.source = universal_by_number(type, value);
1621 req.range = range;
1622 req.survives = survives;
1623 req.present = present;
1624 req.quiet = quiet;
1625
1626 return req;
1627}
1628
1629/**********************************************************************/
1633void req_get_values(const struct requirement *req,
1634 int *type, int *range,
1635 bool *survives, bool *present, bool *quiet,
1636 int *value)
1637{
1638 universal_extraction(&req->source, type, value);
1639 *range = req->range;
1640 *survives = req->survives;
1641 *present = req->present;
1642 *quiet = req->quiet;
1643}
1644
1645/**********************************************************************/
1648void req_copy(struct requirement *dst, const struct requirement *src)
1649{
1650 universal_copy(&(dst->source), &(src->source));
1651 dst->range = src->range;
1652 dst->survives = src->survives;
1653 dst->present = src->present;
1654 dst->quiet = src->quiet;
1655}
1656
1657/**********************************************************************/
1661bool are_requirements_equal(const struct requirement *req1,
1662 const struct requirement *req2)
1663{
1664 return (are_universals_equal(&req1->source, &req2->source)
1665 && req1->range == req2->range
1666 && req1->survives == req2->survives
1667 && req1->present == req2->present);
1668}
1669
1670/**********************************************************************/
1673static bool are_requirements_opposites(const struct requirement *req1,
1674 const struct requirement *req2)
1675{
1676 return (are_universals_equal(&req1->source, &req2->source)
1677 && req1->range == req2->range
1678 && req1->survives == req2->survives
1679 && req1->present != req2->present);
1680}
1681
1682/**********************************************************************/
1686static bool impr_contra_genus(const struct requirement *impr_req,
1687 const struct requirement *genus_req)
1688{
1689 /* The input is sane. */
1691 || impr_req->source.kind == VUT_SITE, FALSE);
1693
1694 if (impr_req->range == REQ_RANGE_LOCAL
1695 && genus_req->range == REQ_RANGE_LOCAL) {
1696 /* Applies to the same target building. */
1697
1698 if (impr_req->present && !genus_req->present) {
1699 /* The target building can't not have the genus it has. */
1700 return (impr_req->source.value.building->genus
1701 == genus_req->source.value.impr_genus);
1702 }
1703
1704 if (impr_req->present && genus_req->present) {
1705 /* The target building can't have another genus than it has. */
1706 return (impr_req->source.value.building->genus
1707 != genus_req->source.value.impr_genus);
1708 }
1709 }
1710
1711 /* No special knowledge. */
1712 return FALSE;
1713}
1714
1715/**********************************************************************/
1719static bool impr_contra_flag(const struct requirement *impr_req,
1720 const struct requirement *flag_req)
1721{
1722 /* The input is sane. */
1724 || impr_req->source.kind == VUT_SITE, FALSE);
1726
1727 if (impr_req->range == REQ_RANGE_LOCAL
1728 && flag_req->range == REQ_RANGE_LOCAL) {
1729 /* Applies to the same target building. */
1730
1731 if (impr_req->present && !flag_req->present) {
1732 /* The target building can't not have the flag it has. */
1733 return improvement_has_flag(impr_req->source.value.building,
1734 flag_req->source.value.impr_flag);
1735 }
1736
1737 if (impr_req->present && flag_req->present) {
1738 /* The target building can't have another flag than it has. */
1739 return !improvement_has_flag(impr_req->source.value.building,
1740 flag_req->source.value.impr_flag);
1741 }
1742 }
1743
1744 /* No special knowledge. */
1745 return FALSE;
1746}
1747
1748/**********************************************************************/
1753 const struct requirement *group_req)
1754{
1755 /* The input is sane. */
1756 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1758
1759 if (nation_req->range == REQ_RANGE_PLAYER
1760 && group_req->range == REQ_RANGE_PLAYER) {
1761 /* Applies to the same target building. */
1762
1763 if (nation_req->present && !group_req->present) {
1764 /* The target nation can't be in the group. */
1765 return nation_is_in_group(nation_req->source.value.nation,
1766 group_req->source.value.nationgroup);
1767 }
1768 }
1769
1770 /* No special knowledge. */
1771 return FALSE;
1772}
1773
1774/**********************************************************************/
1778static bool city_center_contra(const struct requirement *cc_req,
1779 const struct requirement *ct_req)
1780{
1781 /* The input is sane. */
1782 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1783 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1784
1785 if (cc_req->source.value.citytile == CITYT_CENTER
1786 && cc_req->present && cc_req->range <= ct_req->range) {
1787 switch (ct_req->source.value.citytile) {
1788 case CITYT_CENTER:
1789 case CITYT_CLAIMED:
1790 case CITYT_EXTRAS_OWNED:
1791 case CITYT_WORKED:
1793 /* Should be always on city center */
1794 return !ct_req->present;
1796 /* Handled later */
1797 break;
1798 case CITYT_LAST:
1799 /* Error */
1800 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1801 }
1802 }
1803 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1804 || cc_req->source.value.citytile == CITYT_CENTER)
1805 && ct_req->source.value.citytile
1807 && REQ_RANGE_TILE == cc_req->range
1808 && REQ_RANGE_TILE == ct_req->range) {
1809 /* Can't coexist */
1810 return cc_req->present ? ct_req->present : !ct_req->present;
1811 }
1812
1813 return FALSE;
1814}
1815
1816/**********************************************************************/
1821static bool present_implies_not_present(const struct requirement *req1,
1822 const struct requirement *req2)
1823{
1824 const struct requirement *absent, *present;
1825
1826 if (req1->present == req2->present) {
1827 /* Can't use the knowledge in universal_found_function when both are
1828 * required to be absent or when both are required to be present.
1829 * It is no contradiction to require !Spy unit and !Missile unit class.
1830 * It is no contradiction to require River and Irrigation at the same
1831 * tile. */
1832 return FALSE;
1833 }
1834
1835 if (req1->present) {
1836 absent = req2;
1837 present = req1;
1838 } else {
1839 absent = req1;
1840 present = req2;
1841 }
1842
1843 if (!universal_found_function[present->source.kind]) {
1844 /* No knowledge to exploit. */
1845 return FALSE;
1846 }
1847
1848 if (present->range != absent->range) {
1849 /* Larger ranges are not always strict supersets of smaller ranges.
1850 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1851 * but not in Trade Route. */
1852 return FALSE;
1853 }
1854
1856 &present->source);
1857}
1858
1859/**********************************************************************/
1862bool req_implies_req(const struct requirement *req1,
1863 const struct requirement *req2)
1864{
1865 struct requirement nreq2;
1866
1867 req_copy(&nreq2, req2);
1868 nreq2.present = !nreq2.present;
1870}
1871
1872/**********************************************************************/
1877static inline bool are_bounds_contradictions(int bound1, bool is_upper1,
1878 int bound2, bool is_upper2)
1879{
1880 /* If the bounds are on opposite sides, and one is inclusive, the other
1881 * exclusive, the number of values that satisfy both bounds is exactly
1882 * their difference, (upper bound) - (lower bound).
1883 * The bounds contradict each other iff this difference is 0 or less,
1884 * i.e. iff (upper bound) <= (lower bound) */
1885 if (is_upper1 && !is_upper2) {
1886 return bound1 <= bound2;
1887 } else if (!is_upper1 && is_upper2) {
1888 return bound1 >= bound2;
1889 }
1890 /* Both are upper or both are lower ~> no contradiction possible */
1891 return FALSE;
1892}
1893
1894/**********************************************************************/
1902 const struct requirement *req2)
1903{
1904 if (are_requirements_opposites(req1, req2)) {
1905 /* The exact opposite. */
1906 return TRUE;
1907 }
1908
1909 if (present_implies_not_present(req1, req2)) {
1910 return TRUE;
1911 }
1912
1913 switch (req1->source.kind) {
1914 case VUT_IMPROVEMENT:
1915 case VUT_SITE:
1916 if (req2->source.kind == VUT_IMPR_GENUS) {
1917 return impr_contra_genus(req1, req2);
1918 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1919 return impr_contra_flag(req1, req2);
1920 } else if (req2->source.kind == VUT_CITYTILE
1921 && req2->source.value.citytile == CITYT_CENTER
1922 && REQ_RANGE_TILE == req2->range
1923 && REQ_RANGE_TILE == req1->range
1924 && req1->present) {
1925 /* A building must be in a city */
1926 return !req2->present;
1927 }
1928
1929 /* No special knowledge. */
1930 return FALSE;
1931 case VUT_IMPR_GENUS:
1932 if (req2->source.kind == VUT_IMPROVEMENT
1933 || req2->source.kind == VUT_SITE) {
1934 return impr_contra_genus(req2, req1);
1935 }
1936
1937 /* No special knowledge. */
1938 return FALSE;
1939 case VUT_IMPR_FLAG:
1940 if (req2->source.kind == VUT_IMPROVEMENT
1941 || req2->source.kind == VUT_SITE) {
1942 return impr_contra_flag(req2, req1);
1943 }
1944
1945 /* No special knowledge. */
1946 return FALSE;
1947 case VUT_DIPLREL:
1948 case VUT_DIPLREL_TILE:
1949 case VUT_DIPLREL_TILE_O:
1952 if (req2->source.kind != req1->source.kind) {
1953 /* Finding contradictions across requirement kinds aren't supported
1954 * for DiplRel requirements. */
1955 return FALSE;
1956 } else {
1957 /* Use the special knowledge about DiplRel requirements to find
1958 * contradictions. */
1959
1961 int req2_pos;
1962
1965 req2->range,
1966 req2->present);
1967
1968 return BV_ISSET(req1_contra, req2_pos);
1969 }
1970 break;
1971 case VUT_MINMOVES:
1972 if (req2->source.kind != VUT_MINMOVES) {
1973 /* Finding contradictions across requirement kinds aren't supported
1974 * for MinMoveFrags requirements. */
1975 return FALSE;
1976 }
1978 req1->source.value.minmoves, !req1->present,
1979 req2->source.value.minmoves, !req2->present);
1980 case VUT_MINLATITUDE:
1981 case VUT_MAXLATITUDE:
1982 if (req2->source.kind != VUT_MINLATITUDE
1983 && req2->source.kind != VUT_MAXLATITUDE) {
1984 /* Finding contradictions across requirement kinds other than each
1985 * other is not supported for MinLatitude and MaxLatitude. */
1986 return FALSE;
1987 } else {
1988 /* For a contradiction, we need
1989 * - a minimum (present MinLatitude or negated MaxLatitude)
1990 * - a maximum (negated MinLatitude or present MaxLatitude)
1991 * - the maximum to be less than the minimum
1992 * - a requirement at the larger range that applies to the entire
1993 * range (i.e. a negated requirement, unless the range is Tile)
1994 * Otherwise, the two requirements could still be fulfilled
1995 * simultaneously by different tiles in the range */
1996
1997 /* Initial values beyond the boundaries to avoid edge cases */
1998 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
2000
2001#define EXTRACT_INFO(req) \
2002 if (req->present) { \
2003 if (req->source.kind == VUT_MINLATITUDE) { \
2004 /* present MinLatitude */ \
2005 minimum = MAX(minimum, req->source.value.latitude); \
2006 } else { \
2007 /* present MaxLatitude */ \
2008 maximum = MIN(maximum, req->source.value.latitude); \
2009 } \
2010 } else { \
2011 covered_range = MAX(covered_range, req->range); \
2012 if (req->source.kind == VUT_MINLATITUDE) { \
2013 /* negated MinLatitude */ \
2014 maximum = MIN(maximum, req->source.value.latitude - 1); \
2015 } else { \
2016 /* negated MaxLatitude */ \
2017 minimum = MAX(minimum, req->source.value.latitude + 1); \
2018 } \
2019 }
2020
2021 EXTRACT_INFO(req1);
2022 EXTRACT_INFO(req2);
2023
2024#undef EXTRACT_INFO
2025
2026 return (maximum < minimum
2027 && covered_range >= req1->range
2028 && covered_range >= req2->range);
2029 }
2030 break;
2031 case VUT_NATION:
2032 if (req2->source.kind == VUT_NATIONGROUP) {
2033 return nation_contra_group(req1, req2);
2034 }
2035
2036 /* No special knowledge. */
2037 return FALSE;
2038 break;
2039 case VUT_NATIONGROUP:
2040 if (req2->source.kind == VUT_NATION) {
2041 return nation_contra_group(req2, req1);
2042 }
2043
2044 /* No special knowledge. */
2045 return FALSE;
2046 break;
2047 case VUT_CITYTILE:
2048 if (req2->source.kind == VUT_CITYTILE) {
2049 return city_center_contra(req1, req2)
2050 || city_center_contra(req2, req1);
2051 } else if (req1->source.value.citytile == CITYT_CENTER
2052 && (req2->source.kind == VUT_IMPROVEMENT
2053 || req2->source.kind == VUT_SITE)
2054 && REQ_RANGE_TILE == req2->range
2055 && REQ_RANGE_TILE == req1->range
2056 && req2->present) {
2057 /* A building must be in a city */
2058 return !req1->present;
2059 }
2060
2061 return FALSE;
2063 if (req2->source.kind != VUT_MAX_DISTANCE_SQ) {
2064 /* Finding contradictions across requirement kinds isn't supported
2065 * for MaxDistanceSq requirements. */
2066 return FALSE;
2067 }
2069 req1->source.value.distance_sq, req1->present,
2070 req2->source.value.distance_sq, req2->present);
2072 if (req2->source.kind != VUT_MAX_REGION_TILES) {
2073 /* Finding contradictions across requirement kinds isn't supported
2074 * for MaxRegionTiles requirements. */
2075 return FALSE;
2076 } else if (req1->range != req2->range) {
2077 /* FIXME: Finding contradictions across ranges not yet supported.
2078 * In particular, a max at a small range and a min at a larger range
2079 * needs extra work to figure out. */
2080 return FALSE;
2081 }
2083 req1->source.value.region_tiles, req1->present,
2084 req2->source.value.region_tiles, req2->present);
2085 case VUT_TILE_REL:
2086 if (req2->source.kind != VUT_TILE_REL) {
2087 /* Finding contradictions across requirement kinds isn't supported
2088 * for TileRel requirements. */
2089 return FALSE;
2090 }
2091 if (req1->source.value.tilerel == req2->source.value.tilerel) {
2092 /* Same requirement at different ranges. Note that same range is
2093 * already covered by are_requirements_opposites() above. */
2094 switch (req1->source.value.tilerel) {
2095 case TREL_SAME_TCLASS:
2096 case TREL_SAME_REGION:
2098 /* Negated req at larger range contradicts present req at
2099 * smaller range. */
2100 if (req1->range > req2->range) {
2101 return !req1->present && req2->present;
2102 } else {
2103 return req1->present && !req2->present;
2104 }
2105 break;
2107 /* Present req at larger range contradicts negated req at
2108 * smaller range */
2109 if (req1->range > req2->range) {
2110 return req1->present && !req2->present;
2111 } else {
2112 return !req1->present && req2->present;
2113 }
2114 break;
2115 default:
2116 return FALSE;
2117 }
2118 }
2120 && req2->source.value.tilerel == TREL_SAME_REGION) {
2121 /* Same region at any range implies same terrain class at that range
2122 * and any larger range ~> contradicts negated */
2123 return (!req1->present && req2->present
2124 && (req1->range >= req2->range));
2125 } else if (req2->source.value.tilerel == TREL_SAME_TCLASS
2126 && req1->source.value.tilerel == TREL_SAME_REGION) {
2127 /* Same as above */
2128 return (req1->present && !req2->present
2129 && (req1->range <= req2->range));
2130 } else if (req1->source.value.tilerel == TREL_REGION_SURROUNDED
2132 const struct requirement *surr, *other;
2134 surr = req1;
2135 other = req2;
2136 } else {
2137 surr = req2;
2138 other = req1;
2139 }
2140 if (surr->present && surr->range == REQ_RANGE_TILE) {
2141 /* Target tile must be part of a surrounded region
2142 * ~> not the same terrain class
2143 * ~> not the same region
2144 * ~> not touched by a third region */
2145 switch (other->source.value.tilerel) {
2146 case TREL_SAME_TCLASS:
2147 case TREL_SAME_REGION:
2148 return (other->present && other->range == REQ_RANGE_TILE);
2150 return (!other->present);
2151 default:
2152 break;
2153 }
2154 }
2155 }
2156 /* No further contradictions we can detect */
2157 return FALSE;
2158 default:
2159 /* No special knowledge exists. The requirements aren't the exact
2160 * opposite of each other per the initial check. */
2161 return FALSE;
2162 }
2163}
2164
2165/**********************************************************************/
2173struct requirement *
2175 const struct requirement_vector *vec)
2176{
2177 /* If the requirement is contradicted by any requirement in the vector it
2178 * contradicts the entire requirement vector. */
2181 return preq;
2182 }
2184
2185 /* Not a single requirement in the requirement vector is contradicted to be
2186 * the specified requirement. */
2187 return nullptr;
2188}
2189
2190/**********************************************************************/
2195 const struct requirement_vector *vec)
2196{
2197 return req_vec_first_contradiction_in_vec(req, vec) != nullptr;
2198}
2199
2200/**********************************************************************/
2203static inline bool are_tiles_in_range(const struct tile *tile1,
2204 const struct tile *tile2,
2205 enum req_range range)
2206{
2207 switch (range) {
2208 case REQ_RANGE_ADJACENT:
2210 return TRUE;
2211 }
2213 case REQ_RANGE_TILE:
2214 return same_pos(tile1, tile2);
2216 return map_distance(tile1, tile2) <= 1;
2217 case REQ_RANGE_CITY:
2219 case REQ_RANGE_LOCAL:
2221 case REQ_RANGE_PLAYER:
2222 case REQ_RANGE_TEAM:
2223 case REQ_RANGE_ALLIANCE:
2224 case REQ_RANGE_WORLD:
2225 case REQ_RANGE_COUNT:
2226 /* Invalid */
2228 }
2229 return FALSE;
2230}
2231
2232/**********************************************************************/
2235static inline bool players_in_same_range(const struct player *pplayer1,
2236 const struct player *pplayer2,
2237 enum req_range range)
2238{
2239 switch (range) {
2240 case REQ_RANGE_WORLD:
2241 return TRUE;
2242 case REQ_RANGE_ALLIANCE:
2244 case REQ_RANGE_TEAM:
2246 case REQ_RANGE_PLAYER:
2247 return pplayer1 == pplayer2;
2250 case REQ_RANGE_CITY:
2251 case REQ_RANGE_ADJACENT:
2253 case REQ_RANGE_TILE:
2254 case REQ_RANGE_LOCAL:
2255 case REQ_RANGE_COUNT:
2256 break;
2257 }
2258
2259 fc_assert_msg(FALSE, "Invalid range %d.", range);
2260 return FALSE;
2261}
2262
2263#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
2264{ \
2265 fc_assert_ret_val(req != nullptr, TRI_MAYBE); \
2266 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
2267 fc_assert(context != nullptr); \
2268 fc_assert(other_context != nullptr); \
2269}
2270
2271/**********************************************************************/
2279static enum fc_tristate
2281 const struct req_context *context,
2282 const struct req_context *other_context,
2283 const struct requirement *req)
2284{
2286
2287 return TRI_YES;
2288}
2289
2290/**********************************************************************/
2294static int num_world_buildings_total(const struct impr_type *building)
2295{
2296 if (is_great_wonder(building)) {
2297 return (great_wonder_is_built(building)
2298 || great_wonder_is_destroyed(building) ? 1 : 0);
2299 } else {
2300 log_error("World-ranged requirements are only supported for wonders.");
2301 return 0;
2302 }
2303}
2304
2305/**********************************************************************/
2308static int num_world_buildings(const struct impr_type *building)
2309{
2310 if (is_great_wonder(building)) {
2311 return (great_wonder_is_built(building) ? 1 : 0);
2312 } else {
2313 log_error("World-ranged requirements are only supported for wonders.");
2314 return 0;
2315 }
2316}
2317
2318/**********************************************************************/
2329static bool player_has_ever_built(const struct player *pplayer,
2330 const struct impr_type *building)
2331{
2332 if (is_wonder(building)) {
2333 return (wonder_is_built(pplayer, building)
2334 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2335 } else {
2336 log_error("Player-ranged requirements are only supported for wonders.");
2337 return FALSE;
2338 }
2339}
2340
2341/**********************************************************************/
2344static int num_player_buildings(const struct player *pplayer,
2345 const struct impr_type *building)
2346{
2347 if (is_wonder(building)) {
2348 return (wonder_is_built(pplayer, building) ? 1 : 0);
2349 } else {
2350 log_error("Player-ranged requirements are only supported for wonders.");
2351 return 0;
2352 }
2353}
2354
2355/**********************************************************************/
2358static int num_continent_buildings(const struct player *pplayer,
2359 int continent,
2360 const struct impr_type *building)
2361{
2362 if (is_wonder(building)) {
2363 const struct city *pcity;
2364
2365 pcity = city_from_wonder(pplayer, building);
2366 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2367 return 1;
2368 }
2369 } else {
2370 log_error("Island-ranged requirements are only supported for wonders.");
2371 }
2372 return 0;
2373}
2374
2375/**********************************************************************/
2383static enum fc_tristate
2385 const struct req_context *context,
2386 const struct req_context *other_context,
2387 const struct requirement *req)
2388{
2389 const struct impr_type *building;
2390
2391 /* Can't use this assertion, as both VUT_IMPROVEMENT and VUT_SITE
2392 * are handled here. */
2393 /* IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT); */
2394
2395 building = req->source.value.building;
2396
2397 /* Check if it's certain that the building is obsolete given the
2398 * specification we have */
2399 if (req->source.kind == VUT_IMPROVEMENT
2400 && improvement_obsolete(context->player, building, context->city)) {
2401 return TRI_NO;
2402 }
2403
2404 if (req->survives) {
2405
2406 /* Check whether condition has ever held, using cached information. */
2407 switch (req->range) {
2408 case REQ_RANGE_WORLD:
2409 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2410 case REQ_RANGE_ALLIANCE:
2411 case REQ_RANGE_TEAM:
2412 if (context->player == nullptr) {
2413 return TRI_MAYBE;
2414 }
2415 players_iterate_alive(plr2) {
2416 if (players_in_same_range(context->player, plr2, req->range)
2417 && player_has_ever_built(plr2, building)) {
2418 return TRI_YES;
2419 }
2421 return TRI_NO;
2422 case REQ_RANGE_PLAYER:
2423 if (context->player == nullptr) {
2424 return TRI_MAYBE;
2425 }
2427 building));
2430 case REQ_RANGE_CITY:
2431 case REQ_RANGE_LOCAL:
2432 case REQ_RANGE_TILE:
2434 case REQ_RANGE_ADJACENT:
2435 /* There is no sources cache for this. */
2436 log_error("Surviving requirements are only supported at "
2437 "World/Alliance/Team/Player ranges.");
2438 return TRI_NO;
2439 case REQ_RANGE_COUNT:
2440 break;
2441 }
2442
2443 } else {
2444
2445 /* Non-surviving requirement. */
2446 switch (req->range) {
2447 case REQ_RANGE_WORLD:
2448 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2449 case REQ_RANGE_ALLIANCE:
2450 case REQ_RANGE_TEAM:
2451 if (context->player == nullptr) {
2452 return TRI_MAYBE;
2453 }
2454 players_iterate_alive(plr2) {
2455 if (players_in_same_range(context->player, plr2, req->range)
2456 && num_player_buildings(plr2, building) > 0) {
2457 return TRI_YES;
2458 }
2460 return TRI_NO;
2461 case REQ_RANGE_PLAYER:
2462 if (context->player == nullptr) {
2463 return TRI_MAYBE;
2464 }
2466 building)
2467 > 0);
2469 /* At present, "Continent" effects can affect only
2470 * cities and units in cities. */
2471 if (context->player && context->city) {
2472 int continent = tile_continent(context->city->tile);
2474 continent, building)
2475 > 0);
2476 } else {
2477 return TRI_MAYBE;
2478 }
2480 if (context->city) {
2481 if (city_has_building(context->city, building)) {
2482 return TRI_YES;
2483 } else {
2484 enum fc_tristate ret = TRI_NO;
2485
2487 if (trade_partner == nullptr) {
2488 ret = TRI_MAYBE;
2489 } else if (city_has_building(trade_partner, building)) {
2490 return TRI_YES;
2491 }
2493
2494 return ret;
2495 }
2496 } else {
2497 return TRI_MAYBE;
2498 }
2499 case REQ_RANGE_CITY:
2500 if (context->city) {
2501 return BOOL_TO_TRISTATE(city_has_building(context->city, building));
2502 } else {
2503 return TRI_MAYBE;
2504 }
2505 case REQ_RANGE_LOCAL:
2506 if (context->building) {
2507 if (context->building == building) {
2508 return TRI_YES;
2509 } else {
2510 return TRI_NO;
2511 }
2512 } else {
2513 /* TODO: Other local targets */
2514 return TRI_MAYBE;
2515 }
2516 case REQ_RANGE_TILE:
2517 if (context->tile) {
2518 const struct city *pcity = tile_city(context->tile);
2519
2520 if (pcity) {
2521 return BOOL_TO_TRISTATE(city_has_building(pcity, building));
2522 } else {
2523 return TRI_NO;
2524 }
2525 } else {
2526 return TRI_MAYBE;
2527 }
2529 case REQ_RANGE_ADJACENT:
2530 case REQ_RANGE_COUNT:
2531 break;
2532 }
2533
2534 }
2535
2536 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2537 return TRI_NO;
2538}
2539
2540/**********************************************************************/
2548static enum fc_tristate
2550 const struct req_context *context,
2551 const struct req_context *other_context,
2552 const struct requirement *req)
2553{
2555
2556 return (context->building ? BOOL_TO_TRISTATE(
2557 context->building->genus
2558 == req->source.value.impr_genus)
2559 : TRI_MAYBE);
2560}
2561
2562/**********************************************************************/
2566 enum impr_flag_id flag)
2567{
2568 struct player *owner;
2569
2570 if (pcity == nullptr) {
2571 return TRI_MAYBE;
2572 }
2573
2575 city_built_iterate(pcity, impr) {
2576 if (improvement_has_flag(impr, flag)
2577 && !improvement_obsolete(owner, impr, pcity)) {
2578 return TRI_YES;
2579 }
2581
2582 return TRI_NO;
2583}
2584
2585/**********************************************************************/
2593static enum fc_tristate
2595 const struct req_context *context,
2596 const struct req_context *other_context,
2597 const struct requirement *req)
2598{
2600
2601 switch (req->range) {
2602 case REQ_RANGE_LOCAL:
2603 return (context->building
2605 req->source.value.impr_flag))
2606 : TRI_MAYBE);
2607 case REQ_RANGE_CITY:
2609 case REQ_RANGE_TILE:
2610 if (context->tile == nullptr) {
2611 return TRI_MAYBE;
2612 }
2614 req->source.value.impr_flag);
2616 case REQ_RANGE_ADJACENT:
2619 case REQ_RANGE_PLAYER:
2620 case REQ_RANGE_ALLIANCE:
2621 case REQ_RANGE_TEAM:
2622 case REQ_RANGE_WORLD:
2623 case REQ_RANGE_COUNT:
2624 break;
2625 }
2626
2627 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2628
2629 return TRI_MAYBE;
2630}
2631
2632/**********************************************************************/
2640static enum fc_tristate
2642 const struct req_context *context,
2643 const struct req_context *other_context,
2644 const struct requirement *req)
2645{
2647
2648 switch (req->range) {
2649 case REQ_RANGE_PLAYER:
2650 return (context->player != nullptr
2652 req->source.value.plr_flag))
2653 : TRI_MAYBE);
2654 case REQ_RANGE_LOCAL:
2655 case REQ_RANGE_CITY:
2656 case REQ_RANGE_TILE:
2658 case REQ_RANGE_ADJACENT:
2661 case REQ_RANGE_ALLIANCE:
2662 case REQ_RANGE_TEAM:
2663 case REQ_RANGE_WORLD:
2664 case REQ_RANGE_COUNT:
2665 break;
2666 }
2667
2668 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2669
2670 return TRI_MAYBE;
2671}
2672
2673/**********************************************************************/
2681static enum fc_tristate
2683 const struct req_context *context,
2684 const struct req_context *other_context,
2685 const struct requirement *req)
2686{
2688
2689 switch (req->range) {
2690 case REQ_RANGE_PLAYER:
2691 return (context->player != nullptr
2693 req->source.value.plrstate))
2694 : TRI_MAYBE);
2695 case REQ_RANGE_LOCAL:
2696 case REQ_RANGE_CITY:
2697 case REQ_RANGE_TILE:
2699 case REQ_RANGE_ADJACENT:
2702 case REQ_RANGE_ALLIANCE:
2703 case REQ_RANGE_TEAM:
2704 case REQ_RANGE_WORLD:
2705 case REQ_RANGE_COUNT:
2706 break;
2707 }
2708
2709 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2710
2711 return TRI_MAYBE;
2712}
2713
2714/**********************************************************************/
2722static enum fc_tristate
2724 const struct req_context *context,
2725 const struct req_context *other_context,
2726 const struct requirement *req)
2727{
2728 Tech_type_id tech;
2729
2731
2732 tech = advance_number(req->source.value.advance);
2733
2734 if (req->survives) {
2737 }
2738
2739 /* Not a 'surviving' requirement. */
2740 switch (req->range) {
2741 case REQ_RANGE_PLAYER:
2742 if (context->player != nullptr) {
2744 (research_get(context->player), tech));
2745 } else {
2746 return TRI_MAYBE;
2747 }
2748 case REQ_RANGE_TEAM:
2749 case REQ_RANGE_ALLIANCE:
2750 case REQ_RANGE_WORLD:
2751 if (context->player == nullptr) {
2752 return TRI_MAYBE;
2753 }
2754 players_iterate_alive(plr2) {
2755 if (players_in_same_range(context->player, plr2, req->range)) {
2756 if (research_invention_state(research_get(plr2), tech)
2757 == TECH_KNOWN) {
2758 return TRI_YES;
2759 }
2760 }
2762
2763 return TRI_NO;
2764 case REQ_RANGE_LOCAL:
2765 if (context->player == nullptr) {
2766 return TRI_MAYBE;
2767 }
2768 if (research_get(context->player)->researching == tech) {
2769 return TRI_YES;
2770 }
2771 return TRI_NO;
2772 case REQ_RANGE_TILE:
2774 case REQ_RANGE_ADJACENT:
2775 case REQ_RANGE_CITY:
2778 case REQ_RANGE_COUNT:
2779 break;
2780 }
2781
2782 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2783
2784 return TRI_MAYBE;
2785}
2786
2787/**********************************************************************/
2795static enum fc_tristate
2797 const struct req_context *context,
2798 const struct req_context *other_context,
2799 const struct requirement *req)
2800{
2801 enum tech_flag_id techflag;
2802
2804
2805 techflag = req->source.value.techflag;
2806
2807 switch (req->range) {
2808 case REQ_RANGE_PLAYER:
2809 if (context->player != nullptr) {
2811 techflag));
2812 } else {
2813 return TRI_MAYBE;
2814 }
2815 break;
2816 case REQ_RANGE_TEAM:
2817 case REQ_RANGE_ALLIANCE:
2818 if (context->player == nullptr) {
2819 return TRI_MAYBE;
2820 }
2821 players_iterate_alive(plr2) {
2822 if (players_in_same_range(context->player, plr2, req->range)
2823 && player_knows_techs_with_flag(plr2, techflag)) {
2824 return TRI_YES;
2825 }
2827 return TRI_NO;
2828 case REQ_RANGE_WORLD:
2829 players_iterate(pplayer) {
2830 if (player_knows_techs_with_flag(pplayer, techflag)) {
2831 return TRI_YES;
2832 }
2834
2835 return TRI_NO;
2836 case REQ_RANGE_LOCAL:
2837 if (context->player == nullptr) {
2838 return TRI_MAYBE;
2839 }
2840 if (advance_has_flag(research_get(context->player)->researching, techflag)) {
2841 return TRI_YES;
2842 }
2843 return TRI_NO;
2844 case REQ_RANGE_TILE:
2846 case REQ_RANGE_ADJACENT:
2847 case REQ_RANGE_CITY:
2850 case REQ_RANGE_COUNT:
2851 break;
2852 }
2853
2854 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2855
2856 return TRI_MAYBE;
2857}
2858
2859/**********************************************************************/
2867static enum fc_tristate
2869 const struct req_context *context,
2870 const struct req_context *other_context,
2871 const struct requirement *req)
2872{
2873 int minculture;
2874
2876
2877 minculture = req->source.value.minculture;
2878
2879 switch (req->range) {
2880 case REQ_RANGE_CITY:
2881 if (!context->city) {
2882 return TRI_MAYBE;
2883 }
2884 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2886 if (!context->city) {
2887 return TRI_MAYBE;
2888 }
2889 if (city_culture(context->city) >= minculture) {
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 if (city_culture(trade_partner) >= minculture) {
2898 return TRI_YES;
2899 }
2901
2902 return ret;
2903 }
2904 case REQ_RANGE_PLAYER:
2905 case REQ_RANGE_TEAM:
2906 case REQ_RANGE_ALLIANCE:
2907 case REQ_RANGE_WORLD:
2908 if (context->player == nullptr) {
2909 return TRI_MAYBE;
2910 }
2911 players_iterate_alive(plr2) {
2912 if (players_in_same_range(context->player, plr2, req->range)) {
2913 if (player_culture(plr2) >= minculture) {
2914 return TRI_YES;
2915 }
2916 }
2918 return TRI_NO;
2919 case REQ_RANGE_LOCAL:
2920 case REQ_RANGE_TILE:
2922 case REQ_RANGE_ADJACENT:
2924 case REQ_RANGE_COUNT:
2925 break;
2926 }
2927
2928 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2929
2930 return TRI_MAYBE;
2931}
2932
2933/**********************************************************************/
2941static enum fc_tristate
2943 const struct req_context *context,
2944 const struct req_context *other_context,
2945 const struct requirement *req)
2946{
2948
2950
2952
2953 switch (req->range) {
2954 case REQ_RANGE_CITY:
2955 if (!context->city) {
2956 return TRI_MAYBE;
2957 }
2959 / city_size_get(context->city);
2962 if (!context->city) {
2963 return TRI_MAYBE;
2964 }
2966 / city_size_get(context->city);
2968 return TRI_YES;
2969 } else {
2970 enum fc_tristate ret = TRI_NO;
2971
2973 if (trade_partner == nullptr) {
2974 ret = TRI_MAYBE;
2975 } else {
2979 return TRI_YES;
2980 }
2981 }
2983
2984 return ret;
2985 }
2986 case REQ_RANGE_PLAYER:
2987 case REQ_RANGE_TEAM:
2988 case REQ_RANGE_ALLIANCE:
2989 case REQ_RANGE_WORLD:
2990 case REQ_RANGE_LOCAL:
2991 case REQ_RANGE_TILE:
2993 case REQ_RANGE_ADJACENT:
2995 case REQ_RANGE_COUNT:
2996 break;
2997 }
2998
2999 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3000
3001 return TRI_MAYBE;
3002}
3003
3004/**********************************************************************/
3012static enum fc_tristate
3014 const struct req_context *context,
3015 const struct req_context *other_context,
3016 const struct requirement *req)
3017{
3018 int max_units;
3019
3021
3023
3024 /* TODO: If can't see V_INVIS -> TRI_MAYBE */
3025 switch (req->range) {
3026 case REQ_RANGE_TILE:
3027 if (!context->tile) {
3028 return TRI_MAYBE;
3029 }
3030 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
3032 if (!context->tile) {
3033 return TRI_MAYBE;
3034 }
3035 if (unit_list_size(context->tile->units) <= max_units) {
3036 return TRI_YES;
3037 }
3039 if (unit_list_size(adjc_tile->units) <= max_units) {
3040 return TRI_YES;
3041 }
3043 return TRI_NO;
3044 case REQ_RANGE_ADJACENT:
3045 if (!context->tile) {
3046 return TRI_MAYBE;
3047 }
3048 if (unit_list_size(context->tile->units) <= max_units) {
3049 return TRI_YES;
3050 }
3052 if (unit_list_size(adjc_tile->units) <= max_units) {
3053 return TRI_YES;
3054 }
3056 return TRI_NO;
3057 case REQ_RANGE_CITY:
3060 case REQ_RANGE_PLAYER:
3061 case REQ_RANGE_TEAM:
3062 case REQ_RANGE_ALLIANCE:
3063 case REQ_RANGE_WORLD:
3064 case REQ_RANGE_LOCAL:
3065 case REQ_RANGE_COUNT:
3066 break;
3067 }
3068
3069 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3070
3071 return TRI_MAYBE;
3072}
3073
3074
3075/**********************************************************************/
3083static enum fc_tristate
3085 const struct req_context *context,
3086 const struct req_context *other_context,
3087 const struct requirement *req)
3088{
3089 int max_units;
3090 int count;
3091
3093
3095
3096 /* TODO: If can't see V_INVIS -> TRI_MAYBE */
3097 switch (req->range) {
3098 case REQ_RANGE_TILE:
3099 if (!context->tile) {
3100 return TRI_MAYBE;
3101 }
3102 count = 0;
3103 unit_list_iterate(context->tile->units, punit) {
3104 if (!unit_transported(punit)) {
3105 count++;
3106 }
3108 return BOOL_TO_TRISTATE(count <= max_units);
3110 if (!context->tile) {
3111 return TRI_MAYBE;
3112 }
3113 count = 0;
3114 unit_list_iterate(context->tile->units, punit) {
3115 if (!unit_transported(punit)) {
3116 count++;
3117 }
3119 if (count <= max_units) {
3120 return TRI_YES;
3121 }
3123 count = 0;
3125 if (!unit_transported(punit)) {
3126 count++;
3127 }
3129 if (count <= max_units) {
3130 return TRI_YES;
3131 }
3133
3134 return TRI_NO;
3135 case REQ_RANGE_ADJACENT:
3136 if (!context->tile) {
3137 return TRI_MAYBE;
3138 }
3139 count = 0;
3140 unit_list_iterate(context->tile->units, punit) {
3141 if (!unit_transported(punit)) {
3142 count++;
3143 }
3145 if (count <= max_units) {
3146 return TRI_YES;
3147 }
3149 count = 0;
3151 if (!unit_transported(punit)) {
3152 count++;
3153 }
3155 if (count <= max_units) {
3156 return TRI_YES;
3157 }
3159 return TRI_NO;
3160 case REQ_RANGE_CITY:
3163 case REQ_RANGE_PLAYER:
3164 case REQ_RANGE_TEAM:
3165 case REQ_RANGE_ALLIANCE:
3166 case REQ_RANGE_WORLD:
3167 case REQ_RANGE_LOCAL:
3168 case REQ_RANGE_COUNT:
3169 break;
3170 }
3171
3172 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3173
3174 return TRI_MAYBE;
3175}
3176
3177/**********************************************************************/
3185static enum fc_tristate
3187 const struct req_context *context,
3188 const struct req_context *other_context,
3189 const struct requirement *req)
3190{
3191 const struct extra_type *pextra;
3192 enum fc_tristate ret;
3193
3195
3196 pextra = req->source.value.extra;
3197
3198 switch (req->range) {
3199 case REQ_RANGE_LOCAL:
3200 if (!context->extra) {
3201 return TRI_MAYBE;
3202 }
3203 return BOOL_TO_TRISTATE(context->extra == pextra);
3204 case REQ_RANGE_TILE:
3205 /* The requirement is filled if the tile has extra of requested type. */
3206 if (!context->tile) {
3207 return TRI_MAYBE;
3208 }
3209 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
3211 if (!context->tile) {
3212 return TRI_MAYBE;
3213 }
3214 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
3215 || is_extra_card_near(nmap, context->tile, pextra));
3216 case REQ_RANGE_ADJACENT:
3217 if (!context->tile) {
3218 return TRI_MAYBE;
3219 }
3220 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
3221 || is_extra_near_tile(nmap, context->tile, pextra));
3222 case REQ_RANGE_CITY:
3223 if (!context->city) {
3224 return TRI_MAYBE;
3225 }
3227 city_tile(context->city), ptile) {
3228 if (tile_has_extra(ptile, pextra)) {
3229 return TRI_YES;
3230 }
3232
3233 return TRI_NO;
3234
3236 if (!context->city) {
3237 return TRI_MAYBE;
3238 }
3240 city_tile(context->city), ptile) {
3241 if (tile_has_extra(ptile, pextra)) {
3242 return TRI_YES;
3243 }
3245
3246 ret = TRI_NO;
3248 if (trade_partner == nullptr) {
3249 ret = TRI_MAYBE;
3250 } else {
3252 city_tile(trade_partner), ptile) {
3253 if (tile_has_extra(ptile, pextra)) {
3254 return TRI_YES;
3255 }
3257 }
3259
3260 return ret;
3261
3263 case REQ_RANGE_PLAYER:
3264 case REQ_RANGE_TEAM:
3265 case REQ_RANGE_ALLIANCE:
3266 case REQ_RANGE_WORLD:
3267 case REQ_RANGE_COUNT:
3268 break;
3269 }
3270
3271 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3272
3273 return TRI_MAYBE;
3274}
3275
3276/**********************************************************************/
3284static enum fc_tristate
3286 const struct req_context *context,
3287 const struct req_context *other_context,
3288 const struct requirement *req)
3289{
3290 const struct tiledef *ptdef;
3291 enum fc_tristate ret;
3292
3294
3295 ptdef = req->source.value.tiledef;
3296
3297 switch (req->range) {
3298 case REQ_RANGE_TILE:
3299 /* The requirement is filled if the tile has tiledef of requested type. */
3300 if (!context->tile) {
3301 return TRI_MAYBE;
3302 }
3305 if (!context->tile) {
3306 return TRI_MAYBE;
3307 }
3310 case REQ_RANGE_ADJACENT:
3311 if (!context->tile) {
3312 return TRI_MAYBE;
3313 }
3316 case REQ_RANGE_CITY:
3317 if (!context->city) {
3318 return TRI_MAYBE;
3319 }
3321 city_tile(context->city), ptile) {
3322 if (tile_matches_tiledef(ptdef, ptile)) {
3323 return TRI_YES;
3324 }
3326
3327 return TRI_NO;
3328
3330 if (!context->city) {
3331 return TRI_MAYBE;
3332 }
3334 city_tile(context->city), ptile) {
3335 if (tile_matches_tiledef(ptdef, ptile)) {
3336 return TRI_YES;
3337 }
3339
3340 ret = TRI_NO;
3342 if (trade_partner == nullptr) {
3343 ret = TRI_MAYBE;
3344 } else {
3346 city_tile(trade_partner), ptile) {
3347 if (tile_matches_tiledef(ptdef, ptile)) {
3348 return TRI_YES;
3349 }
3351 }
3353
3354 return ret;
3355
3356 case REQ_RANGE_LOCAL:
3358 case REQ_RANGE_PLAYER:
3359 case REQ_RANGE_TEAM:
3360 case REQ_RANGE_ALLIANCE:
3361 case REQ_RANGE_WORLD:
3362 case REQ_RANGE_COUNT:
3363 break;
3364 }
3365
3366 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3367
3368 return TRI_MAYBE;
3369}
3370
3371/**********************************************************************/
3379static enum fc_tristate
3381 const struct req_context *context,
3382 const struct req_context *other_context,
3383 const struct requirement *req)
3384{
3386
3387 if (!is_server()) {
3388 /* Client does not know about access areas */
3389 return TRI_MAYBE;
3390 }
3391
3392 if (req->range == REQ_RANGE_CITY) {
3393 if (context->city == nullptr
3394 || context->city->server.aarea == nullptr) {
3395 return TRI_MAYBE;
3396 }
3397
3398 if (BV_ISSET(context->city->server.aarea->tiledefs,
3400 return TRI_YES;
3401 }
3402
3403 return TRI_NO;
3404 }
3405
3406 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3407
3408 return TRI_MAYBE;
3409}
3410
3411/**********************************************************************/
3419static enum fc_tristate
3421 const struct req_context *context,
3422 const struct req_context *other_context,
3423 const struct requirement *req)
3424{
3425 const struct goods_type *pgood;
3426
3428
3429 pgood = req->source.value.good;
3430
3431 switch (req->range) {
3432 case REQ_RANGE_LOCAL:
3433 case REQ_RANGE_CITY:
3434 /* The requirement is filled if the city imports good of requested type. */
3435 if (!context->city) {
3436 return TRI_MAYBE;
3437 }
3441 nullptr)));
3442 case REQ_RANGE_TILE:
3444 case REQ_RANGE_ADJACENT:
3447 case REQ_RANGE_PLAYER:
3448 case REQ_RANGE_TEAM:
3449 case REQ_RANGE_ALLIANCE:
3450 case REQ_RANGE_WORLD:
3451 case REQ_RANGE_COUNT:
3452 break;
3453 }
3454
3455 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3456
3457 return TRI_MAYBE;
3458}
3459
3460/**********************************************************************/
3468static enum fc_tristate
3470 const struct req_context *context,
3471 const struct req_context *other_context,
3472 const struct requirement *req)
3473{
3475
3476 if (context->action) {
3477 return BOOL_TO_TRISTATE(action_number(context->action)
3478 == action_number(req->source.value.action));
3479 }
3480
3481 if (context->unit != nullptr && context->unit->action != ACTION_NONE) {
3482 log_normal("Unit action %s", action_id_rule_name(context->unit->action));
3483 return BOOL_TO_TRISTATE(context->unit->action
3484 == action_number(req->source.value.action));
3485 }
3486
3487 return TRI_NO;
3488}
3489
3490/**********************************************************************/
3498static enum fc_tristate
3500 const struct req_context *context,
3501 const struct req_context *other_context,
3502 const struct requirement *req)
3503{
3505
3506 return BOOL_TO_TRISTATE(context->output
3507 && context->output->index
3508 == req->source.value.outputtype);
3509}
3510
3511/**********************************************************************/
3519static enum fc_tristate
3521 const struct req_context *context,
3522 const struct req_context *other_context,
3523 const struct requirement *req)
3524{
3526
3527 return BOOL_TO_TRISTATE(context->specialist
3528 && context->specialist
3529 == req->source.value.specialist);
3530}
3531
3532/**********************************************************************/
3540static enum fc_tristate
3542 const struct req_context *context,
3543 const struct req_context *other_context,
3544 const struct requirement *req)
3545{
3546 const struct terrain *pterrain;
3547
3549
3550 pterrain = req->source.value.terrain;
3551
3552 switch (req->range) {
3553 case REQ_RANGE_TILE:
3554 /* The requirement is filled if the tile has the terrain. */
3555 if (!context->tile) {
3556 return TRI_MAYBE;
3557 }
3558 return pterrain && tile_terrain(context->tile) == pterrain;
3560 if (!context->tile) {
3561 return TRI_MAYBE;
3562 }
3563 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
3564 case REQ_RANGE_ADJACENT:
3565 if (!context->tile) {
3566 return TRI_MAYBE;
3567 }
3568 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
3569 case REQ_RANGE_CITY:
3570 if (!context->city) {
3571 return TRI_MAYBE;
3572 }
3573 if (pterrain != nullptr) {
3575 city_tile(context->city), ptile) {
3576 if (tile_terrain(ptile) == pterrain) {
3577 return TRI_YES;
3578 }
3580 }
3581 return TRI_NO;
3583 if (!context->city) {
3584 return TRI_MAYBE;
3585 }
3586 if (pterrain != nullptr) {
3587 enum fc_tristate ret;
3588
3590 city_tile(context->city), ptile) {
3591 if (tile_terrain(ptile) == pterrain) {
3592 return TRI_YES;
3593 }
3595
3596 ret = TRI_NO;
3598 if (trade_partner == nullptr) {
3599 ret = TRI_MAYBE;
3600 } else {
3602 city_tile(trade_partner), ptile) {
3603 if (tile_terrain(ptile) == pterrain) {
3604 return TRI_YES;
3605 }
3607 }
3609
3610 return ret;
3611 }
3612
3613 return TRI_MAYBE;
3615 case REQ_RANGE_PLAYER:
3616 case REQ_RANGE_TEAM:
3617 case REQ_RANGE_ALLIANCE:
3618 case REQ_RANGE_WORLD:
3619 case REQ_RANGE_LOCAL:
3620 case REQ_RANGE_COUNT:
3621 break;
3622 }
3623
3624 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3625
3626 return TRI_MAYBE;
3627}
3628
3629/**********************************************************************/
3637static enum fc_tristate
3639 const struct req_context *context,
3640 const struct req_context *other_context,
3641 const struct requirement *req)
3642{
3643 enum terrain_class pclass;
3644 enum fc_tristate ret;
3645
3647
3649
3650 switch (req->range) {
3651 case REQ_RANGE_TILE:
3652 /* The requirement is filled if the tile has the terrain of correct class. */
3653 if (!context->tile) {
3654 return TRI_MAYBE;
3655 }
3658 if (!context->tile) {
3659 return TRI_MAYBE;
3660 }
3663 case REQ_RANGE_ADJACENT:
3664 if (!context->tile) {
3665 return TRI_MAYBE;
3666 }
3669 case REQ_RANGE_CITY:
3670 if (!context->city) {
3671 return TRI_MAYBE;
3672 }
3674 city_tile(context->city), ptile) {
3675 const struct terrain *pterrain = tile_terrain(ptile);
3676
3677 if (pterrain != T_UNKNOWN
3678 && terrain_type_terrain_class(pterrain) == pclass) {
3679 return TRI_YES;
3680 }
3682
3683 return TRI_NO;
3685 if (!context->city) {
3686 return TRI_MAYBE;
3687 }
3689 city_tile(context->city), ptile) {
3690 const struct terrain *pterrain = tile_terrain(ptile);
3691
3692 if (pterrain != T_UNKNOWN
3693 && terrain_type_terrain_class(pterrain) == pclass) {
3694 return TRI_YES;
3695 }
3697
3698 ret = TRI_NO;
3700 if (trade_partner == nullptr) {
3701 ret = TRI_MAYBE;
3702 } else {
3704 city_tile(trade_partner), ptile) {
3705 const struct terrain *pterrain = tile_terrain(ptile);
3706
3707 if (pterrain != T_UNKNOWN
3708 && terrain_type_terrain_class(pterrain) == pclass) {
3709 return TRI_YES;
3710 }
3712 }
3714
3715 return ret;
3717 case REQ_RANGE_PLAYER:
3718 case REQ_RANGE_TEAM:
3719 case REQ_RANGE_ALLIANCE:
3720 case REQ_RANGE_WORLD:
3721 case REQ_RANGE_LOCAL:
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{
3746 enum fc_tristate ret;
3747
3749
3751
3752 switch (req->range) {
3753 case REQ_RANGE_TILE:
3754 /* The requirement is fulfilled if the tile has a terrain with
3755 * correct flag. */
3756 if (!context->tile) {
3757 return TRI_MAYBE;
3758 }
3760 terrflag));
3762 if (!context->tile) {
3763 return TRI_MAYBE;
3764 }
3766 terrflag)
3768 terrflag));
3769 case REQ_RANGE_ADJACENT:
3770 if (!context->tile) {
3771 return TRI_MAYBE;
3772 }
3774 terrflag)
3776 terrflag));
3777 case REQ_RANGE_CITY:
3778 if (!context->city) {
3779 return TRI_MAYBE;
3780 }
3782 city_tile(context->city), ptile) {
3783 const struct terrain *pterrain = tile_terrain(ptile);
3784
3785 if (pterrain != T_UNKNOWN
3786 && terrain_has_flag(pterrain, terrflag)) {
3787 return TRI_YES;
3788 }
3790
3791 return TRI_NO;
3793 if (!context->city) {
3794 return TRI_MAYBE;
3795 }
3797 city_tile(context->city), ptile) {
3798 const struct terrain *pterrain = tile_terrain(ptile);
3799
3800 if (pterrain != T_UNKNOWN
3801 && terrain_has_flag(pterrain, terrflag)) {
3802 return TRI_YES;
3803 }
3805
3806 ret = TRI_NO;
3808 if (trade_partner == nullptr) {
3809 ret = TRI_MAYBE;
3810 } else {
3812 city_tile(trade_partner), ptile) {
3813 const struct terrain *pterrain = tile_terrain(ptile);
3814
3815 if (pterrain != T_UNKNOWN
3816 && terrain_has_flag(pterrain, terrflag)) {
3817 return TRI_YES;
3818 }
3820 }
3822
3823 return ret;
3825 case REQ_RANGE_PLAYER:
3826 case REQ_RANGE_TEAM:
3827 case REQ_RANGE_ALLIANCE:
3828 case REQ_RANGE_WORLD:
3829 case REQ_RANGE_LOCAL:
3830 case REQ_RANGE_COUNT:
3831 break;
3832 }
3833
3834 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3835
3836 return TRI_MAYBE;
3837}
3838
3839/**********************************************************************/
3847static enum fc_tristate
3849 const struct req_context *context,
3850 const struct req_context *other_context,
3851 const struct requirement *req)
3852{
3853 enum road_flag_id roadflag;
3854 enum fc_tristate ret;
3855
3857
3858 roadflag = req->source.value.roadflag;
3859
3860 switch (req->range) {
3861 case REQ_RANGE_LOCAL:
3862 {
3863 if (!context->extra) {
3864 return TRI_MAYBE;
3865 }
3866 struct road_type *r = extra_road_get(context->extra);
3867
3868 return BOOL_TO_TRISTATE(
3869 r && road_has_flag(r, roadflag)
3870 );
3871 }
3872 case REQ_RANGE_TILE:
3873 /* The requirement is filled if the tile has a road with correct flag. */
3874 if (!context->tile) {
3875 return TRI_MAYBE;
3876 }
3877 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3879 if (!context->tile) {
3880 return TRI_MAYBE;
3881 }
3882 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3884 roadflag));
3885 case REQ_RANGE_ADJACENT:
3886 if (!context->tile) {
3887 return TRI_MAYBE;
3888 }
3889 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3891 roadflag));
3892 case REQ_RANGE_CITY:
3893 if (!context->city) {
3894 return TRI_MAYBE;
3895 }
3897 city_tile(context->city), ptile) {
3898 if (tile_has_road_flag(ptile, roadflag)) {
3899 return TRI_YES;
3900 }
3902
3903 return TRI_NO;
3905 if (!context->city) {
3906 return TRI_MAYBE;
3907 }
3909 city_tile(context->city), ptile) {
3910 if (tile_has_road_flag(ptile, roadflag)) {
3911 return TRI_YES;
3912 }
3914
3915 ret = TRI_NO;
3917 if (trade_partner == nullptr) {
3918 ret = TRI_MAYBE;
3919 } else {
3921 city_tile(trade_partner), ptile) {
3922 if (tile_has_road_flag(ptile, roadflag)) {
3923 return TRI_YES;
3924 }
3926 }
3928
3929 return ret;
3931 case REQ_RANGE_PLAYER:
3932 case REQ_RANGE_TEAM:
3933 case REQ_RANGE_ALLIANCE:
3934 case REQ_RANGE_WORLD:
3935 case REQ_RANGE_COUNT:
3936 break;
3937 }
3938
3939 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3940
3941 return TRI_MAYBE;
3942}
3943
3944/**********************************************************************/
3952static enum fc_tristate
3954 const struct req_context *context,
3955 const struct req_context *other_context,
3956 const struct requirement *req)
3957{
3958 enum extra_flag_id extraflag;
3959 enum fc_tristate ret;
3960
3962
3963 extraflag = req->source.value.extraflag;
3964
3965 switch (req->range) {
3966 case REQ_RANGE_LOCAL:
3967 if (!context->extra) {
3968 return TRI_MAYBE;
3969 }
3970 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3971 case REQ_RANGE_TILE:
3972 /* The requirement is filled if the tile has an extra with correct flag. */
3973 if (!context->tile) {
3974 return TRI_MAYBE;
3975 }
3976 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3978 if (!context->tile) {
3979 return TRI_MAYBE;
3980 }
3981 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3982 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3983 case REQ_RANGE_ADJACENT:
3984 if (!context->tile) {
3985 return TRI_MAYBE;
3986 }
3987 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3988 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3989 case REQ_RANGE_CITY:
3990 if (!context->city) {
3991 return TRI_MAYBE;
3992 }
3994 city_tile(context->city), ptile) {
3995 if (tile_has_extra_flag(ptile, extraflag)) {
3996 return TRI_YES;
3997 }
3999
4000 return TRI_NO;
4002 if (!context->city) {
4003 return TRI_MAYBE;
4004 }
4006 city_tile(context->city), ptile) {
4007 if (tile_has_extra_flag(ptile, extraflag)) {
4008 return TRI_YES;
4009 }
4011
4012 ret = TRI_NO;
4014 if (trade_partner == nullptr) {
4015 ret = TRI_MAYBE;
4016 } else {
4018 city_tile(trade_partner), ptile) {
4019 if (tile_has_extra_flag(ptile, extraflag)) {
4020 return TRI_YES;
4021 }
4023 }
4025
4026 return ret;
4028 case REQ_RANGE_PLAYER:
4029 case REQ_RANGE_TEAM:
4030 case REQ_RANGE_ALLIANCE:
4031 case REQ_RANGE_WORLD:
4032 case REQ_RANGE_COUNT:
4033 break;
4034 }
4035
4036 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4037
4038 return TRI_MAYBE;
4039}
4040
4041/**********************************************************************/
4049static enum fc_tristate
4051 const struct req_context *context,
4052 const struct req_context *other_context,
4053 const struct requirement *req)
4054{
4056
4058
4060
4061 if (!context->tile) {
4062 return TRI_MAYBE;
4063 }
4064
4065 switch (req->range) {
4066 case REQ_RANGE_TILE:
4070 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
4071 case REQ_RANGE_CITY:
4074 case REQ_RANGE_PLAYER:
4075 case REQ_RANGE_TEAM:
4076 case REQ_RANGE_ALLIANCE:
4077 case REQ_RANGE_WORLD:
4078 case REQ_RANGE_LOCAL:
4079 case REQ_RANGE_COUNT:
4080 break;
4081 }
4082
4083 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4084
4085 return TRI_MAYBE;
4086}
4087
4088/**********************************************************************/
4096static enum fc_tristate
4098 const struct req_context *context,
4099 const struct req_context *other_context,
4100 const struct requirement *req)
4101{
4103
4104 if (context->player == nullptr) {
4105 return TRI_MAYBE;
4106 } else {
4108 == req->source.value.govern);
4109 }
4110}
4111
4112/**********************************************************************/
4120static enum fc_tristate
4122 const struct req_context *context,
4123 const struct req_context *other_context,
4124 const struct requirement *req)
4125{
4127
4128 if (context->player == nullptr) {
4129 return TRI_MAYBE;
4130 } else {
4132 req->source.value.govflag));
4133 }
4134}
4135
4136/**********************************************************************/
4144static enum fc_tristate
4146 const struct req_context *context,
4147 const struct req_context *other_context,
4148 const struct requirement *req)
4149{
4151
4152 if (context->player == nullptr) {
4153 return TRI_MAYBE;
4154 } else {
4155 return BOOL_TO_TRISTATE(context->player->style
4156 == req->source.value.style);
4157 }
4158}
4159
4160/**********************************************************************/
4168static enum fc_tristate
4170 const struct req_context *context,
4171 const struct req_context *other_context,
4172 const struct requirement *req)
4173{
4175
4176 switch (req->range) {
4177 case REQ_RANGE_WORLD:
4178 /* "None" does not count */
4179 return ((game.info.global_advance_count - 1)
4180 >= req->source.value.min_techs);
4181 case REQ_RANGE_PLAYER:
4182 if (context->player == nullptr) {
4183 return TRI_MAYBE;
4184 } else {
4185 /* "None" does not count */
4186 return BOOL_TO_TRISTATE(
4187 (research_get(context->player)->techs_researched - 1)
4188 >= req->source.value.min_techs
4189 );
4190 }
4191 default:
4192 return TRI_MAYBE;
4193 }
4194}
4195
4196/**********************************************************************/
4204static enum fc_tristate
4206 const struct req_context *context,
4207 const struct req_context *other_context,
4208 const struct requirement *req)
4209{
4211
4212 switch (req->range) {
4213 case REQ_RANGE_WORLD:
4215 if (research_get(plr)->future_tech
4216 >= req->source.value.future_techs) {
4217 return TRI_YES;
4218 }
4220
4221 return TRI_NO;
4222 case REQ_RANGE_PLAYER:
4223 if (context->player == nullptr) {
4224 return TRI_MAYBE;
4225 } else {
4227 >= req->source.value.future_techs);
4228 }
4229 default:
4230 return TRI_MAYBE;
4231 }
4232}
4233
4234/**********************************************************************/
4242static enum fc_tristate
4244 const struct req_context *context,
4245 const struct req_context *other_context,
4246 const struct requirement *req)
4247{
4249
4250 switch (req->range) {
4251 case REQ_RANGE_PLAYER:
4252 if (context->player == nullptr) {
4253 return TRI_MAYBE;
4254 } else {
4255 /* "None" does not count */
4256 return BOOL_TO_TRISTATE(
4257 city_list_size(context->player->cities)
4258 >= req->source.value.min_cities
4259 );
4260 }
4261 default:
4262 return TRI_MAYBE;
4263 }
4264}
4265
4266/**********************************************************************/
4274static enum fc_tristate
4276 const struct req_context *context,
4277 const struct req_context *other_context,
4278 const struct requirement *req)
4279{
4281
4282 if (context->player == nullptr) {
4283 return TRI_MAYBE;
4284 } else {
4285 return BOOL_TO_TRISTATE(is_ai(context->player)
4286 && context->player->ai_common.skill_level
4287 == req->source.value.ai_level);
4288 }
4289}
4290
4291/**********************************************************************/
4299static enum fc_tristate
4301 const struct req_context *context,
4302 const struct req_context *other_context,
4303 const struct requirement *req)
4304{
4305 const struct nation_type *nation;
4306
4308
4309 nation = req->source.value.nation;
4310
4311 switch (req->range) {
4312 case REQ_RANGE_PLAYER:
4313 if (context->player == nullptr) {
4314 return TRI_MAYBE;
4315 }
4316 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
4317 case REQ_RANGE_TEAM:
4318 case REQ_RANGE_ALLIANCE:
4319 if (context->player == nullptr) {
4320 return TRI_MAYBE;
4321 }
4322 players_iterate_alive(plr2) {
4323 if (players_in_same_range(context->player, plr2, req->range)) {
4324 if (nation_of_player(plr2) == nation) {
4325 return TRI_YES;
4326 }
4327 }
4329 return TRI_NO;
4330 case REQ_RANGE_WORLD:
4331 /* NB: if a player is ever removed outright from the game
4332 * (e.g. via /remove), rather than just dying, this 'survives'
4333 * requirement will stop being true for their nation.
4334 * create_command_newcomer() can also cause this to happen. */
4335 return BOOL_TO_TRISTATE(nation->player != nullptr
4336 && (req->survives || nation->player->is_alive));
4337 case REQ_RANGE_LOCAL:
4338 case REQ_RANGE_TILE:
4340 case REQ_RANGE_ADJACENT:
4341 case REQ_RANGE_CITY:
4344 case REQ_RANGE_COUNT:
4345 break;
4346 }
4347
4348 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4349
4350 return TRI_MAYBE;
4351}
4352
4353/**********************************************************************/
4361static enum fc_tristate
4363 const struct req_context *context,
4364 const struct req_context *other_context,
4365 const struct requirement *req)
4366{
4367 const struct nation_group *ngroup;
4368
4370
4372
4373 switch (req->range) {
4374 case REQ_RANGE_PLAYER:
4375 if (context->player == nullptr) {
4376 return TRI_MAYBE;
4377 }
4379 nation_of_player(context->player), ngroup));
4380 case REQ_RANGE_TEAM:
4381 case REQ_RANGE_ALLIANCE:
4382 case REQ_RANGE_WORLD:
4383 if (context->player == nullptr) {
4384 return TRI_MAYBE;
4385 }
4386 players_iterate_alive(plr2) {
4387 if (players_in_same_range(context->player, plr2, req->range)) {
4389 return TRI_YES;
4390 }
4391 }
4393 return TRI_NO;
4394 case REQ_RANGE_LOCAL:
4395 case REQ_RANGE_TILE:
4397 case REQ_RANGE_ADJACENT:
4398 case REQ_RANGE_CITY:
4401 case REQ_RANGE_COUNT:
4402 break;
4403 }
4404
4405 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4406
4407 return TRI_MAYBE;
4408}
4409
4410/**********************************************************************/
4418static enum fc_tristate
4420 const struct req_context *context,
4421 const struct req_context *other_context,
4422 const struct requirement *req)
4423{
4424 const struct nation_type *nationality;
4425 enum fc_tristate ret;
4426
4428
4429 nationality = req->source.value.nationality;
4430
4431 switch (req->range) {
4432 case REQ_RANGE_CITY:
4433 if (context->city == nullptr) {
4434 return TRI_MAYBE;
4435 }
4436 citizens_iterate(context->city, slot, count) {
4437 if (player_slot_get_player(slot)->nation == nationality) {
4438 return TRI_YES;
4439 }
4441
4442 return TRI_NO;
4444 if (context->city == nullptr) {
4445 return TRI_MAYBE;
4446 }
4447 citizens_iterate(context->city, slot, count) {
4448 if (player_slot_get_player(slot)->nation == nationality) {
4449 return TRI_YES;
4450 }
4452
4453 ret = TRI_NO;
4455 if (trade_partner == nullptr) {
4456 ret = TRI_MAYBE;
4457 } else {
4458 citizens_iterate(trade_partner, slot, count) {
4459 if (player_slot_get_player(slot)->nation == nationality) {
4460 return TRI_YES;
4461 }
4463 }
4465
4466 return ret;
4467 case REQ_RANGE_PLAYER:
4468 case REQ_RANGE_TEAM:
4469 case REQ_RANGE_ALLIANCE:
4470 case REQ_RANGE_WORLD:
4471 case REQ_RANGE_LOCAL:
4472 case REQ_RANGE_TILE:
4474 case REQ_RANGE_ADJACENT:
4476 case REQ_RANGE_COUNT:
4477 break;
4478 }
4479
4480 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4481
4482 return TRI_MAYBE;
4483}
4484
4485/**********************************************************************/
4493static enum fc_tristate
4495 const struct req_context *context,
4496 const struct req_context *other_context,
4497 const struct requirement *req)
4498{
4499 const struct nation_type *nation;
4500
4502
4503 nation = req->source.value.origowner;
4504
4505 switch (req->range) {
4506 case REQ_RANGE_CITY:
4507 if (context->city == nullptr || context->city->original == nullptr) {
4508 return TRI_MAYBE;
4509 }
4510 if (player_nation(context->city->original) == nation) {
4511 return TRI_YES;
4512 }
4513
4514 return TRI_NO;
4516 case REQ_RANGE_PLAYER:
4517 case REQ_RANGE_TEAM:
4518 case REQ_RANGE_ALLIANCE:
4519 case REQ_RANGE_WORLD:
4520 case REQ_RANGE_LOCAL:
4521 case REQ_RANGE_TILE:
4523 case REQ_RANGE_ADJACENT:
4525 case REQ_RANGE_COUNT:
4526 break;
4527 }
4528
4529 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4530
4531 return TRI_MAYBE;
4532}
4533
4534/**********************************************************************/
4538 const struct player *other_player,
4539 enum req_range range,
4540 int diplrel)
4541{
4542 switch (range) {
4543 case REQ_RANGE_PLAYER:
4544 if (target_player == nullptr) {
4545 return TRI_MAYBE;
4546 }
4548 case REQ_RANGE_TEAM:
4549 case REQ_RANGE_ALLIANCE:
4550 case REQ_RANGE_WORLD:
4551 if (target_player == nullptr) {
4552 return TRI_MAYBE;
4553 }
4554 players_iterate_alive(plr2) {
4556 if (is_diplrel_to_other(plr2, diplrel)) {
4557 return TRI_YES;
4558 }
4559 }
4561 return TRI_NO;
4562 case REQ_RANGE_LOCAL:
4563 if (target_player == nullptr || other_player == nullptr) {
4564 return TRI_MAYBE;
4565 }
4566 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
4567 case REQ_RANGE_TILE:
4569 case REQ_RANGE_ADJACENT:
4570 case REQ_RANGE_CITY:
4573 case REQ_RANGE_COUNT:
4574 break;
4575 }
4576
4577 fc_assert_msg(FALSE, "Invalid range %d.", range);
4578
4579 return TRI_MAYBE;
4580}
4581
4582/**********************************************************************/
4590static enum fc_tristate
4592 const struct req_context *context,
4593 const struct req_context *other_context,
4594 const struct requirement *req)
4595{
4597
4598 return is_diplrel_in_range(context->player, other_context->player,
4599 req->range, req->source.value.diplrel);
4600}
4601
4602/**********************************************************************/
4610static enum fc_tristate
4612 const struct req_context *context,
4613 const struct req_context *other_context,
4614 const struct requirement *req)
4615{
4617
4618 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4619 : nullptr,
4620 context->player,
4621 req->range,
4622 req->source.value.diplrel);
4623}
4624
4625/**********************************************************************/
4634static enum fc_tristate
4636 const struct req_context *context,
4637 const struct req_context *other_context,
4638 const struct requirement *req)
4639{
4641
4642 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4643 : nullptr,
4644 other_context->player,
4645 req->range,
4646 req->source.value.diplrel);
4647}
4648
4649/**********************************************************************/
4652static enum fc_tristate
4654 const struct player *other_player,
4655 enum req_range range,
4656 int diplrel)
4657{
4658 enum fc_tristate out = TRI_NO;
4659
4660 if (target_tile == nullptr) {
4661 return TRI_MAYBE;
4662 }
4663
4666 unit_owner(target_unit), other_player, range, diplrel);
4667
4670
4671 return out;
4672}
4673
4674/**********************************************************************/
4683static enum fc_tristate
4685 const struct req_context *context,
4686 const struct req_context *other_context,
4687 const struct requirement *req)
4688{
4690
4691 return is_diplrel_unitany_in_range(context->tile, context->player,
4692 req->range,
4693 req->source.value.diplrel);
4694}
4695
4696/**********************************************************************/
4705static enum fc_tristate
4707 const struct req_context *context,
4708 const struct req_context *other_context,
4709 const struct requirement *req)
4710{
4712
4714 req->range,
4715 req->source.value.diplrel);
4716}
4717
4718/**********************************************************************/
4726static enum fc_tristate
4728 const struct req_context *context,
4729 const struct req_context *other_context,
4730 const struct requirement *req)
4731{
4732 const struct unit_type *punittype;
4733
4735
4736 punittype = req->source.value.utype;
4737
4738 switch (req->range) {
4739 case REQ_RANGE_LOCAL:
4740 if (!context->unittype) {
4741 return TRI_MAYBE;
4742 }
4743 return BOOL_TO_TRISTATE(context->unittype == punittype);
4744 case REQ_RANGE_TILE:
4746 case REQ_RANGE_ADJACENT:
4747 if (context->tile == nullptr) {
4748 return TRI_MAYBE;
4749 }
4750
4751 unit_list_iterate(context->tile->units, punit) {
4752 if (punit->utype == punittype) {
4753 return TRI_YES;
4754 }
4756
4757 if (req->range == REQ_RANGE_TILE) {
4758 return TRI_NO;
4759 }
4760
4761 if (req->range == REQ_RANGE_CADJACENT) {
4764 if (punit->utype == punittype) {
4765 return TRI_YES;
4766 }
4769 } else {
4771
4774 if (punit->utype == punittype) {
4775 return TRI_YES;
4776 }
4779 }
4780
4781 return TRI_NO;
4782
4783 case REQ_RANGE_CITY:
4786 case REQ_RANGE_PLAYER:
4787 case REQ_RANGE_TEAM:
4788 case REQ_RANGE_ALLIANCE:
4789 case REQ_RANGE_WORLD:
4790 case REQ_RANGE_COUNT:
4792 break;
4793 }
4794
4795 return TRI_NO;
4796}
4797
4798/**********************************************************************/
4806static enum fc_tristate
4808 const struct req_context *context,
4809 const struct req_context *other_context,
4810 const struct requirement *req)
4811{
4812 enum unit_type_flag_id unitflag;
4813
4815
4816 unitflag = req->source.value.unitflag;
4817
4818 switch (req->range) {
4819 case REQ_RANGE_LOCAL:
4820 if (!context->unittype) {
4821 return TRI_MAYBE;
4822 }
4823 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4824 case REQ_RANGE_TILE:
4826 case REQ_RANGE_ADJACENT:
4827 if (context->tile == nullptr) {
4828 return TRI_MAYBE;
4829 }
4830
4831 unit_list_iterate(context->tile->units, punit) {
4832 if (unit_has_type_flag(punit, unitflag)) {
4833 return TRI_YES;
4834 }
4836
4837 if (req->range == REQ_RANGE_TILE) {
4838 return TRI_NO;
4839 }
4840
4841 if (req->range == REQ_RANGE_CADJACENT) {
4844 if (unit_has_type_flag(punit, unitflag)) {
4845 return TRI_YES;
4846 }
4849 } else {
4851
4854 if (unit_has_type_flag(punit, unitflag)) {
4855 return TRI_YES;
4856 }
4859 }
4860
4861 return TRI_NO;
4862
4863 case REQ_RANGE_CITY:
4866 case REQ_RANGE_PLAYER:
4867 case REQ_RANGE_TEAM:
4868 case REQ_RANGE_ALLIANCE:
4869 case REQ_RANGE_WORLD:
4870 case REQ_RANGE_COUNT:
4872 break;
4873 }
4874
4875 return TRI_NO;
4876}
4877
4878/**********************************************************************/
4886static enum fc_tristate
4888 const struct req_context *context,
4889 const struct req_context *other_context,
4890 const struct requirement *req)
4891{
4892 const struct unit_class *pclass;
4893
4895
4896 pclass = req->source.value.uclass;
4897
4898 switch (req->range) {
4899 case REQ_RANGE_LOCAL:
4900 if (!context->unittype) {
4901 return TRI_MAYBE;
4902 }
4903 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4904 case REQ_RANGE_TILE:
4906 case REQ_RANGE_ADJACENT:
4907 if (context->tile == nullptr) {
4908 return TRI_MAYBE;
4909 }
4910
4911 unit_list_iterate(context->tile->units, punit) {
4912 if (unit_class_get(punit) == pclass) {
4913 return TRI_YES;
4914 }
4916
4917 if (req->range == REQ_RANGE_TILE) {
4918 return TRI_NO;
4919 }
4920
4921 if (req->range == REQ_RANGE_CADJACENT) {
4924 if (unit_class_get(punit) == pclass) {
4925 return TRI_YES;
4926 }
4929 } else {
4931
4934 if (unit_class_get(punit) == pclass) {
4935 return TRI_YES;
4936 }
4939 }
4940
4941 return TRI_NO;
4942
4943 case REQ_RANGE_CITY:
4946 case REQ_RANGE_PLAYER:
4947 case REQ_RANGE_TEAM:
4948 case REQ_RANGE_ALLIANCE:
4949 case REQ_RANGE_WORLD:
4950 case REQ_RANGE_COUNT:
4952 break;
4953 }
4954
4955 return TRI_NO;
4956}
4957
4958/**********************************************************************/
4966static enum fc_tristate
4968 const struct req_context *context,
4969 const struct req_context *other_context,
4970 const struct requirement *req)
4971{
4973
4975
4977
4978 switch (req->range) {
4979 case REQ_RANGE_LOCAL:
4980 if (!context->unittype) {
4981 return TRI_MAYBE;
4982 }
4984 case REQ_RANGE_TILE:
4986 case REQ_RANGE_ADJACENT:
4987 if (context->tile == nullptr) {
4988 return TRI_MAYBE;
4989 }
4990
4991 unit_list_iterate(context->tile->units, punit) {
4993 return TRI_YES;
4994 }
4996
4997 if (req->range == REQ_RANGE_TILE) {
4998 return TRI_NO;
4999 }
5000
5001 if (req->range == REQ_RANGE_CADJACENT) {
5005 return TRI_YES;
5006 }
5009 } else {
5011
5015 return TRI_YES;
5016 }
5019 }
5020
5021 return TRI_NO;
5022
5023 case REQ_RANGE_CITY:
5026 case REQ_RANGE_PLAYER:
5027 case REQ_RANGE_TEAM:
5028 case REQ_RANGE_ALLIANCE:
5029 case REQ_RANGE_WORLD:
5030 case REQ_RANGE_COUNT:
5032 break;
5033 }
5034
5035 return TRI_NO;
5036}
5037
5038/**********************************************************************/
5046static enum fc_tristate
5048 const struct req_context *context,
5049 const struct req_context *other_context,
5050 const struct requirement *req)
5051{
5052 enum ustate_prop uprop;
5053
5055
5057
5059 "Unsupported range \"%s\"",
5060 req_range_name(req->range));
5061
5062 /* Could be asked with incomplete data.
5063 * is_req_active() will handle it based on prob_type. */
5064 if (context->unit == nullptr) {
5065 return TRI_MAYBE;
5066 }
5067
5068 switch (uprop) {
5069 case USP_TRANSPORTED:
5070 return BOOL_TO_TRISTATE(context->unit->transporter != nullptr);
5071 case USP_LIVABLE_TILE:
5072 return BOOL_TO_TRISTATE(
5074 unit_tile(context->unit)));
5075 break;
5076 case USP_TRANSPORTING:
5078 case USP_HAS_HOME_CITY:
5079 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
5080 case USP_NATIVE_TILE:
5081 return BOOL_TO_TRISTATE(
5083 unit_tile(context->unit)));
5084 break;
5085 case USP_NATIVE_EXTRA:
5086 return BOOL_TO_TRISTATE(
5088 unit_type_get(context->unit)));
5089 break;
5091 return BOOL_TO_TRISTATE(context->unit->moved);
5092 case USP_COUNT:
5093 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
5094 /* Invalid property is unknowable. */
5095 return TRI_NO;
5096 }
5097
5098 /* Should never be reached */
5099 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
5100
5101 return TRI_NO;
5102}
5103
5104/**********************************************************************/
5112static enum fc_tristate
5114 const struct req_context *context,
5115 const struct req_context *other_context,
5116 const struct requirement *req)
5117{
5118 enum unit_activity activity;
5119
5121
5122 activity = req->source.value.activity;
5123
5125 "Unsupported range \"%s\"",
5126 req_range_name(req->range));
5127
5128 if (context->unit == nullptr) {
5129 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
5130 * it's the zero value that context has by default - so many callers
5131 * who meant not to set specific activity actually have ACTIVITY_IDLE
5132 * instead of ACTIVITY_LAST */
5133 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
5134 return BOOL_TO_TRISTATE(activity == context->activity);
5135 }
5136
5137 /* Could be asked with incomplete data.
5138 * is_req_active() will handle it based on prob_type. */
5139 return TRI_MAYBE;
5140 }
5141
5142 switch (context->unit->activity) {
5143 case ACTIVITY_IDLE:
5144 case ACTIVITY_SENTRY:
5145 case ACTIVITY_GOTO:
5146 case ACTIVITY_EXPLORE:
5147 /* Seen as idle. */
5148 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
5149 default:
5150 /* Handled below. */
5151 break;
5152 }
5153
5154 return BOOL_TO_TRISTATE(context->unit->activity == activity);
5155}
5156
5157/**********************************************************************/
5165static enum fc_tristate
5167 const struct req_context *context,
5168 const struct req_context *other_context,
5169 const struct requirement *req)
5170{
5172
5173 if (context->unit == nullptr) {
5174 return TRI_MAYBE;
5175 } else {
5176 return BOOL_TO_TRISTATE(context->unit->veteran
5177 >= req->source.value.minveteran);
5178 }
5179}
5180
5181/**********************************************************************/
5189static enum fc_tristate
5191 const struct req_context *context,
5192 const struct req_context *other_context,
5193 const struct requirement *req)
5194{
5196
5197 if (context->unit == nullptr) {
5198 return TRI_MAYBE;
5199 } else {
5201 <= context->unit->moves_left);
5202 }
5203}
5204
5205/**********************************************************************/
5213static enum fc_tristate
5215 const struct req_context *context,
5216 const struct req_context *other_context,
5217 const struct requirement *req)
5218{
5220
5221 if (context->unit == nullptr) {
5222 return TRI_MAYBE;
5223 } else {
5225 <= context->unit->hp);
5226 }
5227}
5228
5229/**********************************************************************/
5237static enum fc_tristate
5239 const struct req_context *context,
5240 const struct req_context *other_context,
5241 const struct requirement *req)
5242{
5244
5245 switch (req->range) {
5246 case REQ_RANGE_LOCAL:
5247 if (context->unit == nullptr || !is_server()) {
5248 return TRI_MAYBE;
5249 } else {
5250 return BOOL_TO_TRISTATE(
5251 req->source.value.age <=
5252 game.info.turn - context->unit->birth_turn);
5253 }
5254 break;
5255 case REQ_RANGE_CITY:
5256 if (context->city == nullptr) {
5257 return TRI_MAYBE;
5258 } else {
5259 return BOOL_TO_TRISTATE(
5260 req->source.value.age <=
5261 game.info.turn - context->city->turn_founded);
5262 }
5263 break;
5264 case REQ_RANGE_PLAYER:
5265 if (context->player == nullptr) {
5266 return TRI_MAYBE;
5267 } else {
5268 return BOOL_TO_TRISTATE(req->source.value.age
5269 <= player_age(context->player));
5270 }
5271 break;
5272 default:
5273 return TRI_MAYBE;
5274 break;
5275 }
5276}
5277
5278/**********************************************************************/
5286static enum fc_tristate
5288 const struct req_context *context,
5289 const struct req_context *other_context,
5290 const struct requirement *req)
5291{
5293
5294 switch (req->range) {
5295 case REQ_RANGE_LOCAL:
5296 if (context->unit == nullptr || !is_server()) {
5297 return TRI_MAYBE;
5298 } else {
5299 return BOOL_TO_TRISTATE(
5300 req->source.value.form_age <=
5301 game.info.turn - context->unit->current_form_turn);
5302 }
5303 break;
5304 default:
5305 return TRI_MAYBE;
5306 break;
5307 }
5308}
5309
5310/**********************************************************************/
5314static inline enum fc_tristate
5316{
5318 bool whole_known;
5319
5320 if (cont > 0) {
5323
5324 if (actual_surrounder > 0) {
5325 return TRI_NO;
5326 }
5327 } else if (cont < 0) {
5330
5331 if (actual_surrounder < 0) {
5332 return TRI_NO;
5333 }
5334 } else {
5335 return TRI_MAYBE;
5336 }
5337
5338 if (actual_surrounder == 0 || surrounder == 0) {
5339 return TRI_MAYBE;
5340 } else if (actual_surrounder != surrounder) {
5341 return TRI_NO;
5342 } else if (!whole_known) {
5343 return TRI_MAYBE;
5344 } else {
5345 return TRI_YES;
5346 }
5347}
5348
5349/**********************************************************************/
5357static enum fc_tristate
5359 const struct req_context *context,
5360 const struct req_context *other_context,
5361 const struct requirement *req)
5362{
5364
5365 if (context->tile == nullptr || other_context->tile == nullptr) {
5366 /* Note: For some values, we might be able to give a definitive
5367 * TRI_NO answer even if one of the tiles is missing, but that's
5368 * probably not worth the added effort. */
5369 return TRI_MAYBE;
5370 }
5371
5372 switch (req->source.value.tilerel) {
5373 case TREL_SAME_TCLASS:
5374 if (tile_terrain(other_context->tile) == T_UNKNOWN) {
5375 return TRI_MAYBE;
5376 }
5378 || req->range == REQ_RANGE_CADJACENT
5379 || req->range == REQ_RANGE_ADJACENT),
5380 TRI_MAYBE,
5381 "Invalid range %d for tile relation \"%s\" req",
5383 {
5386 bool seen_unknown = FALSE;
5387 const struct terrain *terr;
5388
5389 if ((terr = tile_terrain(context->tile)) == T_UNKNOWN) {
5391 } else if (terrain_type_terrain_class(terr) == cls) {
5392 return TRUE;
5393 }
5394
5396 if ((terr = tile_terrain(adj_tile)) == T_UNKNOWN) {
5398 } else if (terrain_type_terrain_class(terr) == cls) {
5399 return TRUE;
5400 }
5402
5403 if (seen_unknown) {
5404 return TRI_MAYBE;
5405 } else {
5406 return TRI_NO;
5407 }
5408 }
5409 break;
5410 case TREL_SAME_REGION:
5411 if (tile_continent(other_context->tile) == 0) {
5412 return TRI_MAYBE;
5413 }
5415 || req->range == REQ_RANGE_CADJACENT
5416 || req->range == REQ_RANGE_ADJACENT),
5417 TRI_MAYBE,
5418 "Invalid range %d for tile relation \"%s\" req",
5420
5421 if (tile_continent(context->tile)
5422 == tile_continent(other_context->tile)) {
5423 return TRI_YES;
5424 } else {
5425 bool seen_unknown = (tile_continent(context->tile) == 0);
5427
5430
5431 if (adj_cont == cont) {
5432 return TRI_YES;
5433 } else if (adj_cont == 0) {
5435 }
5437
5438 if (seen_unknown) {
5439 return TRI_MAYBE;
5440 } else {
5441 return TRI_NO;
5442 }
5443 }
5444 break;
5446 if (tile_continent(context->tile) == 0
5447 || tile_continent(other_context->tile) == 0) {
5448 /* Note: We could still give a definitive TRI_NO answer if there are
5449 * too many different adjacent continents, but that's probably not
5450 * worth the added effort. */
5451 return TRI_MAYBE;
5452 }
5454 || req->range == REQ_RANGE_ADJACENT),
5455 TRI_MAYBE,
5456 "Invalid range %d for tile relation \"%s\" req",
5457 req->range,
5459
5460 {
5461 bool seen_unknown = FALSE;
5462 Continent_id cont = tile_continent(context->tile);
5464
5467
5468 if (adj_cont == 0) {
5470 } else if (adj_cont != cont && adj_cont != other_cont) {
5471 return TRI_NO;
5472 }
5474
5475 if (seen_unknown) {
5476 return TRI_MAYBE;
5477 } else {
5478 return TRI_YES;
5479 }
5480 }
5481 break;
5484 || req->range == REQ_RANGE_CADJACENT
5485 || req->range == REQ_RANGE_ADJACENT),
5486 TRI_MAYBE,
5487 "Invalid range %d for tile relation \"%s\" req",
5488 req->range,
5490
5491 {
5492 bool seen_maybe = FALSE;
5494
5496 wanted)) {
5497 case TRI_YES:
5498 return TRI_YES;
5499 case TRI_MAYBE:
5500 seen_maybe = TRUE;
5501 break;
5502 default:
5503 break;
5504 }
5505
5508 wanted)) {
5509 case TRI_YES:
5510 return TRI_YES;
5511 case TRI_MAYBE:
5512 seen_maybe = TRUE;
5513 break;
5514 default:
5515 break;
5516 }
5518
5519 if (seen_maybe) {
5520 return TRI_MAYBE;
5521 } else {
5522 return TRI_NO;
5523 }
5524 }
5525 break;
5526 default:
5527 break;
5528 }
5529
5531 "Illegal value %d for tile relationship requirement.",
5532 req->source.value.tilerel);
5533 return TRI_MAYBE;
5534}
5535
5536/**********************************************************************/
5539static bool is_city_in_tile(const struct tile *ptile,
5540 const struct city *pcity)
5541{
5542 if (pcity == nullptr) {
5543 return tile_city(ptile) != nullptr;
5544 } else {
5545 return is_city_center(pcity, ptile);
5546 }
5547}
5548
5549/**********************************************************************/
5557static enum fc_tristate
5559 const struct req_context *context,
5560 const struct req_context *other_context,
5561 const struct requirement *req)
5562{
5563 enum citytile_type citytile;
5564
5566
5567 citytile = req->source.value.citytile;
5568
5570 if (context->tile == nullptr) {
5571 return TRI_MAYBE;
5572 }
5573
5574 switch (citytile) {
5575 case CITYT_CENTER:
5576 switch (req->range) {
5577 case REQ_RANGE_TILE:
5579 context->city));
5581 if (is_city_in_tile(context->tile, context->city)) {
5582 return TRI_YES;
5583 }
5585 if (is_city_in_tile(adjc_tile, context->city)) {
5586 return TRI_YES;
5587 }
5589
5590 return TRI_NO;
5591 case REQ_RANGE_ADJACENT:
5592 if (is_city_in_tile(context->tile, context->city)) {
5593 return TRI_YES;
5594 }
5596 if (is_city_in_tile(adjc_tile, context->city)) {
5597 return TRI_YES;
5598 }
5600
5601 return TRI_NO;
5602 case REQ_RANGE_CITY:
5605 case REQ_RANGE_PLAYER:
5606 case REQ_RANGE_TEAM:
5607 case REQ_RANGE_ALLIANCE:
5608 case REQ_RANGE_WORLD:
5609 case REQ_RANGE_LOCAL:
5610 case REQ_RANGE_COUNT:
5611 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5612 break;
5613 }
5614
5615 return TRI_MAYBE;
5616 case CITYT_CLAIMED:
5617 switch (req->range) {
5618 case REQ_RANGE_TILE:
5619 return BOOL_TO_TRISTATE(context->tile->owner != nullptr);
5621 if (context->tile->owner != nullptr) {
5622 return TRI_YES;
5623 }
5625 if (adjc_tile->owner != nullptr) {
5626 return TRI_YES;
5627 }
5629
5630 return TRI_NO;
5631 case REQ_RANGE_ADJACENT:
5632 if (context->tile->owner != nullptr) {
5633 return TRI_YES;
5634 }
5636 if (adjc_tile->owner != nullptr) {
5637 return TRI_YES;
5638 }
5640
5641 return TRI_NO;
5642 case REQ_RANGE_CITY:
5645 case REQ_RANGE_PLAYER:
5646 case REQ_RANGE_TEAM:
5647 case REQ_RANGE_ALLIANCE:
5648 case REQ_RANGE_WORLD:
5649 case REQ_RANGE_LOCAL:
5650 case REQ_RANGE_COUNT:
5651 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5652 break;
5653 }
5654
5655 return TRI_MAYBE;
5656 case CITYT_EXTRAS_OWNED:
5657 switch (req->range) {
5658 case REQ_RANGE_TILE:
5659 return BOOL_TO_TRISTATE(context->tile->extras_owner != nullptr);
5661 if (context->tile->extras_owner != nullptr) {
5662 return TRI_YES;
5663 }
5665 if (adjc_tile->extras_owner != nullptr) {
5666 return TRI_YES;
5667 }
5669
5670 return TRI_NO;
5671 case REQ_RANGE_ADJACENT:
5672 if (context->tile->extras_owner != nullptr) {
5673 return TRI_YES;
5674 }
5676 if (adjc_tile->extras_owner != nullptr) {
5677 return TRI_YES;
5678 }
5680
5681 return TRI_NO;
5682 case REQ_RANGE_CITY:
5685 case REQ_RANGE_PLAYER:
5686 case REQ_RANGE_TEAM:
5687 case REQ_RANGE_ALLIANCE:
5688 case REQ_RANGE_WORLD:
5689 case REQ_RANGE_LOCAL:
5690 case REQ_RANGE_COUNT:
5691 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5692 break;
5693 }
5694
5695 return TRI_MAYBE;
5696 case CITYT_WORKED:
5697 switch (req->range) {
5698 case REQ_RANGE_TILE:
5699 return BOOL_TO_TRISTATE(context->tile->worked != nullptr);
5701 if (context->tile->worked != nullptr) {
5702 return TRI_YES;
5703 }
5705 if (adjc_tile->worked != nullptr) {
5706 return TRI_YES;
5707 }
5709
5710 return TRI_NO;
5711 case REQ_RANGE_ADJACENT:
5712 if (context->tile->worked != nullptr) {
5713 return TRI_YES;
5714 }
5716 if (adjc_tile->worked != nullptr) {
5717 return TRI_YES;
5718 }
5720
5721 return TRI_NO;
5722 case REQ_RANGE_CITY:
5725 case REQ_RANGE_PLAYER:
5726 case REQ_RANGE_TEAM:
5727 case REQ_RANGE_ALLIANCE:
5728 case REQ_RANGE_WORLD:
5729 case REQ_RANGE_LOCAL:
5730 case REQ_RANGE_COUNT:
5731 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5732 break;
5733 }
5734
5735 return TRI_MAYBE;
5737 {
5739 const struct tile *target_tile = context->tile, *cc_tile;
5740
5741 if (!context->city) {
5742 return TRI_MAYBE;
5743 }
5744 cc_tile = city_tile(context->city);
5745 if (!cc_tile) {
5746 /* Unplaced virtual city */
5747 return TRI_MAYBE;
5748 }
5750 /* Note: No special treatment of 0 == cc here*/
5751 switch (req->range) {
5752 case REQ_RANGE_TILE:
5755 if (tile_continent(target_tile) == cc) {
5756 return TRI_YES;
5757 }
5759 if (tile_continent(adjc_tile) == cc) {
5760 return TRI_YES;
5761 }
5763
5764 return TRI_NO;
5765 case REQ_RANGE_ADJACENT:
5766 if (tile_continent(target_tile) == cc) {
5767 return TRI_YES;
5768 }
5770 if (tile_continent(adjc_tile) == cc) {
5771 return TRI_YES;
5772 }
5774
5775 return TRI_NO;
5776 case REQ_RANGE_CITY:
5779 case REQ_RANGE_PLAYER:
5780 case REQ_RANGE_TEAM:
5781 case REQ_RANGE_ALLIANCE:
5782 case REQ_RANGE_WORLD:
5783 case REQ_RANGE_LOCAL:
5784 case REQ_RANGE_COUNT:
5785 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5786 break;
5787 }
5788 }
5789
5790 return TRI_MAYBE;
5792 {
5793 int n = 0;
5795 bool ukt = FALSE;
5796 const struct tile *target_tile = context->tile, *cc_tile;
5797
5798 if (!context->city) {
5799 return TRI_MAYBE;
5800 }
5801 cc_tile = city_tile(context->city);
5802 if (!cc_tile) {
5803 /* Unplaced virtual city */
5804 return TRI_MAYBE;
5805 }
5807 if (!cc) {
5808 /* Don't know the city center terrain class.
5809 * Maybe, the city floats? Even if the rules prohibit it... */
5810 return TRI_MAYBE;
5811 }
5814
5815 if (0 != tc) {
5816 bool seen = FALSE;
5817 int i = n;
5818
5819 if (tc == cc) {
5820 continue;
5821 }
5822 while (--i >= 0) {
5823 if (adjc_cont[i] == tc) {
5824 seen = TRUE;
5825 break;
5826 }
5827 }
5828 if (seen) {
5829 continue;
5830 }
5832 } else {
5833 /* Likely, it's a black tile in client and we don't know
5834 * We possibly can calculate, but keep it simple. */
5835 ukt = TRUE;
5836 }
5838 if (0 == n) {
5839 return ukt ? TRI_MAYBE : TRI_NO;
5840 }
5841
5842 switch (req->range) {
5843 case REQ_RANGE_TILE:
5844 {
5846
5847 if (cc == tc) {
5848 return TRI_NO;
5849 }
5850 if (0 == tc || ukt) {
5851 return TRI_MAYBE;
5852 }
5853 for (int i = 0; i < n; i++) {
5854 if (tc == adjc_cont[i]) {
5855 return TRI_YES;
5856 }
5857 }
5858 }
5859
5860 return TRI_NO;
5861 case REQ_RANGE_ADJACENT:
5862 if (ukt) {
5863 /* If ALL the tiles in range are on cc, we can say it's false */
5865 if (tile_continent(adjc_tile) != cc) {
5866 return TRI_MAYBE;
5867 }
5869
5870 return TRI_NO;
5871 } else {
5874
5875 if (0 == tc) {
5876 return TRI_MAYBE;
5877 }
5878 for (int i = 0; i < n; i++) {
5879 if (tc == adjc_cont[i]) {
5880 return TRI_YES;
5881 }
5882 }
5884 }
5885
5886 return TRI_NO;
5888 if (ukt) {
5889 /* If ALL the tiles in range are on cc, we can say it's false */
5891 if (tile_continent(cadjc_tile) != cc) {
5892 return TRI_MAYBE;
5893 }
5895 } else {
5898
5899 if (0 == tc) {
5900 return TRI_MAYBE;
5901 }
5902 for (int i = 0; i < n; i++) {
5903 if (tc == adjc_cont[i]) {
5904 return TRI_YES;
5905 }
5906 }
5908 }
5909
5910 return TRI_NO;
5911 case REQ_RANGE_CITY:
5914 case REQ_RANGE_PLAYER:
5915 case REQ_RANGE_TEAM:
5916 case REQ_RANGE_ALLIANCE:
5917 case REQ_RANGE_WORLD:
5918 case REQ_RANGE_LOCAL:
5919 case REQ_RANGE_COUNT:
5920 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5921 break;
5922 }
5923 }
5924
5925 return TRI_MAYBE;
5926 case CITYT_LAST:
5927 /* Handled below */
5928 break;
5929 }
5930
5931 /* Not implemented */
5932 log_error("is_req_active(): citytile %d not supported.",
5933 citytile);
5934 return TRI_MAYBE;
5935}
5936
5937/**********************************************************************/
5945static enum fc_tristate
5947 const struct req_context *context,
5948 const struct req_context *other_context,
5949 const struct requirement *req)
5950{
5951 enum citystatus_type citystatus;
5952
5954
5955 citystatus = req->source.value.citystatus;
5956
5957 if (context->city == nullptr) {
5958 return TRI_MAYBE;
5959 }
5960
5961 switch (citystatus) {
5963 switch (req->range) {
5964 case REQ_RANGE_CITY:
5965 if (context->city->original == nullptr) {
5966 return TRI_MAYBE;
5967 }
5968 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
5970 {
5971 enum fc_tristate ret;
5972
5973 if (city_owner(context->city) == context->city->original) {
5974 return TRI_YES;
5975 }
5976
5977 ret = TRI_NO;
5979 if (trade_partner == nullptr || trade_partner->original == nullptr) {
5980 ret = TRI_MAYBE;
5981 } else if (city_owner(trade_partner) == trade_partner->original) {
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 OwnedByOriginal.",
6002 req->range);
6003
6004 return TRI_MAYBE;
6005
6006 case CITYS_STARVED:
6007 switch (req->range) {
6008 case REQ_RANGE_CITY:
6009 return BOOL_TO_TRISTATE(context->city->had_famine);
6011 {
6012 enum fc_tristate ret;
6013
6014 if (context->city->had_famine) {
6015 return TRI_YES;
6016 }
6017
6018 ret = TRI_NO;
6020 if (trade_partner == nullptr) {
6021 ret = TRI_MAYBE;
6022 } else if (trade_partner->had_famine) {
6023 return TRI_YES;
6024 }
6026
6027 return ret;
6028 }
6029 case REQ_RANGE_LOCAL:
6030 case REQ_RANGE_TILE:
6032 case REQ_RANGE_ADJACENT:
6034 case REQ_RANGE_PLAYER:
6035 case REQ_RANGE_TEAM:
6036 case REQ_RANGE_ALLIANCE:
6037 case REQ_RANGE_WORLD:
6038 case REQ_RANGE_COUNT:
6039 break;
6040 }
6041
6042 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
6043 req->range);
6044
6045 return TRI_MAYBE;
6046
6047 case CITYS_DISORDER:
6048 switch (req->range) {
6049 case REQ_RANGE_CITY:
6050 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
6052 {
6053 enum fc_tristate ret;
6054
6055 if (context->city->anarchy > 0) {
6056 return TRI_YES;
6057 }
6058
6059 ret = TRI_NO;
6061 if (trade_partner == nullptr) {
6062 ret = TRI_MAYBE;
6063 } else if (trade_partner->anarchy > 0) {
6064 return TRI_YES;
6065 }
6067
6068 return ret;
6069 }
6070 case REQ_RANGE_LOCAL:
6071 case REQ_RANGE_TILE:
6073 case REQ_RANGE_ADJACENT:
6075 case REQ_RANGE_PLAYER:
6076 case REQ_RANGE_TEAM:
6077 case REQ_RANGE_ALLIANCE:
6078 case REQ_RANGE_WORLD:
6079 case REQ_RANGE_COUNT:
6080 break;
6081 }
6082
6083 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
6084 req->range);
6085
6086 return TRI_MAYBE;
6087
6088 case CITYS_CELEBRATION:
6089 switch (req->range) {
6090 case REQ_RANGE_CITY:
6091 return BOOL_TO_TRISTATE(context->city->rapture > 0);
6093 {
6094 enum fc_tristate ret;
6095
6096 if (context->city->rapture > 0) {
6097 return TRI_YES;
6098 }
6099
6100 ret = TRI_NO;
6102 if (trade_partner == nullptr) {
6103 ret = TRI_MAYBE;
6104 } else if (trade_partner->rapture > 0) {
6105 return TRI_YES;
6106 }
6108
6109 return ret;
6110 }
6111 case REQ_RANGE_LOCAL:
6112 case REQ_RANGE_TILE:
6114 case REQ_RANGE_ADJACENT:
6116 case REQ_RANGE_PLAYER:
6117 case REQ_RANGE_TEAM:
6118 case REQ_RANGE_ALLIANCE:
6119 case REQ_RANGE_WORLD:
6120 case REQ_RANGE_COUNT:
6121 break;
6122 }
6123
6124 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
6125 req->range);
6126
6127 return TRI_MAYBE;
6128
6129 case CITYS_TRANSFERRED:
6130 switch (req->range) {
6131 case REQ_RANGE_CITY:
6132 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
6134 {
6135 enum fc_tristate ret;
6136
6137 if (context->city->acquire_t != CACQ_FOUNDED) {
6138 return TRI_YES;
6139 }
6140
6141 ret = TRI_NO;
6143 if (trade_partner == nullptr) {
6144 ret = TRI_MAYBE;
6145 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
6146 return TRI_YES;
6147 }
6149
6150 return ret;
6151 }
6152 case REQ_RANGE_LOCAL:
6153 case REQ_RANGE_TILE:
6155 case REQ_RANGE_ADJACENT:
6157 case REQ_RANGE_PLAYER:
6158 case REQ_RANGE_TEAM:
6159 case REQ_RANGE_ALLIANCE:
6160 case REQ_RANGE_WORLD:
6161 case REQ_RANGE_COUNT:
6162 break;
6163 }
6164
6165 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
6166 req->range);
6167
6168 return TRI_MAYBE;
6169
6171 if (!is_server()) {
6172 /* Client has no idea. */
6173 return TRI_MAYBE;
6174 }
6175
6176 switch (req->range) {
6177 case REQ_RANGE_CITY:
6178 return BOOL_TO_TRISTATE(context->city->server.aarea != nullptr
6179 && context->city->server.aarea->capital);
6181 {
6182 enum fc_tristate ret;
6183
6184 if (context->city->server.aarea != nullptr
6185 && context->city->server.aarea->capital) {
6186 return TRI_YES;
6187 }
6188
6189 ret = TRI_NO;
6191 if (trade_partner == nullptr) {
6192 ret = TRI_MAYBE;
6193 } else if (trade_partner->server.aarea != nullptr
6194 && trade_partner->server.aarea->capital) {
6195 return TRI_YES;
6196 }
6198
6199 return ret;
6200 }
6201 case REQ_RANGE_LOCAL:
6202 case REQ_RANGE_TILE:
6204 case REQ_RANGE_ADJACENT:
6206 case REQ_RANGE_PLAYER:
6207 case REQ_RANGE_TEAM:
6208 case REQ_RANGE_ALLIANCE:
6209 case REQ_RANGE_WORLD:
6210 case REQ_RANGE_COUNT:
6211 break;
6212 }
6213
6214 fc_assert_msg(FALSE, "Invalid range %d for citystatus CapitalConnected.",
6215 req->range);
6216
6217 return TRI_MAYBE;
6218
6219 case CITYS_LAST:
6220 break;
6221 }
6222
6223 /* Not implemented */
6224 log_error("is_req_active(): citystatus %d not supported.",
6225 citystatus);
6226
6227 return TRI_MAYBE;
6228}
6229
6230/**********************************************************************/
6238static enum fc_tristate
6240 const struct req_context *context,
6241 const struct req_context *other_context,
6242 const struct requirement *req)
6243{
6245
6246 if (context->city == nullptr) {
6247 return TRI_MAYBE;
6248 } else {
6249 if (req->range == REQ_RANGE_TRADE_ROUTE) {
6250 enum fc_tristate ret;
6251
6252 if (city_size_get(context->city) >= req->source.value.minsize) {
6253 return TRI_YES;
6254 }
6255
6256 ret = TRI_NO;
6258 if (trade_partner == nullptr) {
6259 ret = TRI_MAYBE;
6260 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
6261 return TRI_YES;
6262 }
6264
6265 return ret;
6266 } else {
6268 >= req->source.value.minsize);
6269 }
6270 }
6271}
6272
6273/**********************************************************************/
6281static enum fc_tristate
6283 const struct req_context *context,
6284 const struct req_context *other_context,
6285 const struct requirement *req)
6286{
6287 const struct counter *count;
6288
6290
6291 count = req->source.value.counter;
6292
6293 if (context->city == nullptr) {
6294 return TRI_MAYBE;
6295 }
6296 return BOOL_TO_TRISTATE(count->checkpoint <=
6297 context->city->counter_values[
6298 counter_index(count)]);
6299}
6300
6301/**********************************************************************/
6309static enum fc_tristate
6311 const struct req_context *context,
6312 const struct req_context *other_context,
6313 const struct requirement *req)
6314{
6315 const struct achievement *achievement;
6316
6318
6320
6321 if (req->range == REQ_RANGE_WORLD) {
6323 } else if (context->player == nullptr) {
6324 return TRI_MAYBE;
6325 } else if (req->range == REQ_RANGE_ALLIANCE
6326 || req->range == REQ_RANGE_TEAM) {
6327 players_iterate_alive(plr2) {
6328 if (players_in_same_range(context->player, plr2, req->range)
6330 return TRI_YES;
6331 }
6333 return TRI_NO;
6334 } else if (req->range == REQ_RANGE_PLAYER) {
6336 return TRI_YES;
6337 } else {
6338 return TRI_NO;
6339 }
6340 }
6341
6342 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
6343
6344 return TRI_MAYBE;
6345}
6346
6347/**********************************************************************/
6355static enum fc_tristate
6357 const struct req_context *context,
6358 const struct req_context *other_context,
6359 const struct requirement *req)
6360{
6361 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
6362
6363 fc_assert_ret_val(req != nullptr, TRI_MAYBE);
6364 fc_assert(context != nullptr);
6365
6366 switch (req->source.kind) {
6367 case VUT_MINLATITUDE:
6368 min = req->source.value.latitude;
6369 break;
6370 case VUT_MAXLATITUDE:
6371 max = req->source.value.latitude;
6372 break;
6373 default:
6375 || req->source.kind == VUT_MAXLATITUDE);
6376 break;
6377 }
6378
6379 switch (req->range) {
6380 case REQ_RANGE_WORLD:
6382 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
6383
6384 case REQ_RANGE_TILE:
6385 if (context->tile == nullptr) {
6386 return TRI_MAYBE;
6387 } else {
6389
6391 }
6392
6394 if (context->tile == nullptr) {
6395 return TRI_MAYBE;
6396 }
6397
6400
6402 return TRI_YES;
6403 }
6405 return TRI_NO;
6406
6407 case REQ_RANGE_ADJACENT:
6408 if (!context->tile) {
6409 return TRI_MAYBE;
6410 }
6411
6414
6416 return TRI_YES;
6417 }
6419 return TRI_NO;
6420
6421 case REQ_RANGE_CITY:
6424 case REQ_RANGE_PLAYER:
6425 case REQ_RANGE_TEAM:
6426 case REQ_RANGE_ALLIANCE:
6427 case REQ_RANGE_LOCAL:
6428 case REQ_RANGE_COUNT:
6429 break;
6430 }
6431
6433 "Illegal range %d for latitude requirement.", req->range);
6434
6435 return TRI_MAYBE;
6436}
6437
6438/**********************************************************************/
6446static enum fc_tristate
6448 const struct req_context *context,
6449 const struct req_context *other_context,
6450 const struct requirement *req)
6451{
6453
6454 switch (req->range) {
6455 case REQ_RANGE_TILE:
6456 if (context->tile == nullptr || other_context->tile == nullptr) {
6457 return TRI_MAYBE;
6458 }
6459 return BOOL_TO_TRISTATE(
6461 <= req->source.value.distance_sq
6462 );
6463 default:
6464 break;
6465 }
6466
6468 "Illegal range %d for max squared distance requirement.",
6469 req->range);
6470
6471 return TRI_MAYBE;
6472}
6473
6474/**********************************************************************/
6482static enum fc_tristate
6484 const struct req_context *context,
6485 const struct req_context *other_context,
6486 const struct requirement *req)
6487{
6488 int max_tiles, min_tiles = 1;
6489
6491
6492 switch (req->range) {
6494 case REQ_RANGE_ADJACENT:
6495 if (context->tile == nullptr) {
6496 /* The tile itself is included in the range */
6497 max_tiles = 1 + ((req->range == REQ_RANGE_CADJACENT)
6498 ? nmap->num_cardinal_dirs
6499 : nmap->num_valid_dirs);
6500
6501 break;
6502 } else {
6503 Continent_id cont = tile_continent(context->tile);
6504
6505 /* Count how many adjacent tiles there actually are as we go along */
6506 max_tiles = 1;
6507
6510
6511 if (adj_cont == 0 || cont == 0) {
6512 max_tiles++;
6513 } else if (adj_cont == cont) {
6514 min_tiles++;
6515 max_tiles++;
6516 }
6518 }
6519 break;
6521 {
6522 Continent_id cont = context->tile ? tile_continent(context->tile) : 0;
6523
6526
6527 /* Note: We could come up with a better upper bound by subtracting
6528 * all other continent/ocean sizes, or all except the largest if we
6529 * don't know the tile.
6530 * We could even do a flood-fill count of the unknown area bordered
6531 * by known tiles of the continent.
6532 * Probably not worth the effort though. */
6533 max_tiles = nmap->xsize * nmap->ysize;
6534
6535 if (cont > 0) {
6536 min_tiles = nmap->continent_sizes[cont];
6537 if (is_whole_continent_known(cont)) {
6539 }
6540 } else if (cont < 0) {
6541 min_tiles = nmap->ocean_sizes[-cont];
6542 if (is_whole_ocean_known(-cont)) {
6544 }
6545 }
6546 }
6547 break;
6548 default:
6550 "Illegal range %d for max region tiles requirement.",
6551 req->range);
6552 return TRI_MAYBE;
6553 }
6554
6555 if (min_tiles > req->source.value.region_tiles) {
6556 return TRI_NO;
6557 } else if (max_tiles <= req->source.value.region_tiles) {
6558 return TRI_YES;
6559 }
6560 return TRI_MAYBE;
6561}
6562
6563/**********************************************************************/
6571static enum fc_tristate
6573 const struct req_context *context,
6574 const struct req_context *other_context,
6575 const struct requirement *req)
6576{
6578
6580}
6581
6582/**********************************************************************/
6590static enum fc_tristate
6592 const struct req_context *context,
6593 const struct req_context *other_context,
6594 const struct requirement *req)
6595{
6597
6599 >= req->source.value.mincalfrag);
6600}
6601
6602/**********************************************************************/
6610static enum fc_tristate
6612 const struct req_context *context,
6613 const struct req_context *other_context,
6614 const struct requirement *req)
6615{
6617
6618 return BOOL_TO_TRISTATE(
6620}
6621
6622/**********************************************************************/
6630static enum fc_tristate
6632 const struct req_context *context,
6633 const struct req_context *other_context,
6634 const struct requirement *req)
6635{
6637
6638 return BOOL_TO_TRISTATE(
6640}
6641
6642/**********************************************************************/
6650static enum fc_tristate
6652 const struct req_context *context,
6653 const struct req_context *other_context,
6654 const struct requirement *req)
6655{
6657
6659 req->source.value.ssetval));
6660}
6661
6662/* Not const for potential ruleset-related adjustment */
6665
6666 /* Alphabetical order of enum constant */
6734};
6735
6736/**********************************************************************/
6750 const struct req_context *other_context,
6751 const struct requirement *req,
6752 const enum req_problem_type prob_type)
6753{
6754 const struct civ_map *nmap = &(wld.map);
6755 enum fc_tristate eval;
6757 struct thr_req_data *trdata = nullptr;
6758
6761 if (fc_threads_equal(self, data->thr_id)) {
6762 trdata = data;
6763 }
6765
6766 if (trdata == nullptr) {
6767 trdata = fc_malloc(sizeof(struct thr_req_data));
6768 trdata->thr_id = self;
6770 }
6772
6774
6775 if (eval == TRI_MAYBE) {
6776 if (prob_type == RPT_POSSIBLE) {
6777 return TRUE;
6778 } else {
6779 return FALSE;
6780 }
6781 }
6782
6783 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
6784}
6785
6786/**********************************************************************/
6795static
6797 const struct req_context *context,
6798 const struct req_context *other_context,
6799 const struct requirement *req)
6800{
6801 if (!context) {
6803 }
6804 if (!other_context) {
6806 }
6807
6808 if (req->source.kind >= VUT_COUNT) {
6809 log_error("tri_req_present(): invalid source kind %d.",
6810 req->source.kind);
6811 return TRI_NO;
6812 }
6813
6815
6816 return req_definitions[req->source.kind].cb(nmap, context,
6817 other_context, req);
6818}
6819
6820/**********************************************************************/
6830 const struct req_context *other_context,
6831 const struct requirement *req)
6832{
6833 const struct civ_map *nmap = &(wld.map);
6835
6836 if (!req->present) {
6837 if (TRI_NO == eval) {
6838 return TRI_YES;
6839 }
6840 if (TRI_YES == eval) {
6841 return TRI_NO;
6842 }
6843 }
6844
6845 return eval;
6846}
6847
6848/**********************************************************************/
6864 const struct req_context *other_context,
6865 const struct requirement_vector *reqs,
6866 const enum req_problem_type prob_type)
6867{
6870 return FALSE;
6871 }
6873
6874 return TRUE;
6875}
6876
6877/**********************************************************************/
6882 const enum req_range max_range,
6883 const struct req_context *context,
6884 const struct req_context *other_context,
6885 const struct requirement_vector *reqs,
6886 const enum req_problem_type prob_type)
6887{
6889 if (preq->range >= min_range && preq->range <= max_range) {
6891 return FALSE;
6892 }
6893 }
6895
6896 return TRUE;
6897}
6898
6899/**********************************************************************/
6905enum fc_tristate
6907 const struct req_context *context,
6908 const struct req_context *other_context,
6909 const struct requirement *req)
6910{
6911 /* FIXME: Doubles code from calendar.c */
6915 int fragment1 = fragment; /* If fragments don't advance */
6916 int year_inc, year_inc1;
6919 bool present, present1;
6920
6921 fc_assert(pass >= 0 && period >= 0);
6922 if (slowdown >= 3) {
6923 if (ypt > 1) {
6924 ypt = 1;
6925 }
6926 } else if (slowdown >= 2) {
6927 if (ypt > 2) {
6928 ypt = 2;
6929 }
6930 } else if (slowdown >= 1) {
6931 if (ypt > 5) {
6932 ypt = 5;
6933 }
6934 }
6935 year_inc = ypt * pass;
6938 int fragment_years;
6939
6940 fragment += fpt * pass;
6948 }
6950 if (year_inc + game.info.year >= 0) {
6951 year_inc++;
6952 year_inc1++;
6953 } else if (year_inc1 + game.info.year >= 0) {
6954 year_inc1++;
6955 }
6956 }
6957
6958 switch (req->source.kind) {
6959 case VUT_AGE:
6960 switch (req->range) {
6961 case REQ_RANGE_LOCAL:
6962 if (context->unit == nullptr || !is_server()) {
6963 return TRI_MAYBE;
6964 } else {
6965 int ua = game.info.turn + pass - context->unit->birth_turn;
6966
6967 present = req->source.value.age <= ua;
6968 present1 = req->source.value.age <= ua + period;
6969 }
6970 break;
6971 case REQ_RANGE_CITY:
6972 if (context->city == nullptr) {
6973 return TRI_MAYBE;
6974 } else {
6975 int ca = game.info.turn + pass - context->city->turn_founded;
6976
6977 present = req->source.value.age <= ca;
6978 present1 = req->source.value.age <= ca + period;
6979 }
6980 break;
6981 case REQ_RANGE_PLAYER:
6982 if (context->player == nullptr) {
6983 return TRI_MAYBE;
6984 } else {
6985 present = req->source.value.age
6986 <= player_age(context->player) + pass;
6987 present1 = req->source.value.age
6988 <= player_age(context->player) + pass + period;
6989 }
6990 break;
6991 default:
6992 return TRI_MAYBE;
6993 }
6994 break;
6995 case VUT_FORM_AGE:
6996 if (context->unit == nullptr || !is_server()) {
6997 return TRI_MAYBE;
6998 } else {
6999 int ua = game.info.turn + pass - context->unit->current_form_turn;
7000
7001 present = req->source.value.form_age <= ua;
7002 present1 = req->source.value.form_age <= ua + period;
7003 }
7004 break;
7005 case VUT_MINYEAR:
7006 present = game.info.year + year_inc >= req->source.value.minyear;
7008 break;
7009 case VUT_MINCALFRAG:
7011 /* Hope that the requirement is valid and fragments advance fine */
7012 return TRI_YES;
7013 }
7014 present = fragment >= req->source.value.mincalfrag;
7016 break;
7017 default:
7018 /* No special handling invented */
7019 return tri_req_active(context, other_context, req);
7020 }
7021 return BOOL_TO_TRISTATE(req->present
7022 ? present || present1 : !(present && present1));
7023}
7024
7025/**********************************************************************/
7031 (const struct req_context *context,
7032 const struct req_context *other_context,
7033 const struct requirement *req,
7034 void *data, int n_data)
7035{
7036 int i;
7037
7038 fc_assert_ret_val(data || n_data == 0, TRI_NO);
7039
7040 for (i = 0; i < n_data; i++) {
7041 if (are_requirements_contradictions(&((struct requirement *) data)[i],
7042 req)) {
7043 return TRI_NO;
7044 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
7045 return TRI_YES;
7046 }
7047 }
7048
7049 return tri_req_active(context, other_context, req);
7050}
7051
7052/**********************************************************************/
7058enum fc_tristate
7060 const struct req_context *other_context,
7061 const struct requirement_vector *reqs,
7064 void *data, int n_data)
7065{
7066 bool active = TRUE;
7067 bool certain = TRUE;
7068
7069 fc_assert_ret_val(tester != nullptr, TRI_NO);
7070
7073 data, n_data)) {
7074 case TRI_NO:
7075 active = FALSE;
7076 certain = TRUE;
7077 break;
7078 case TRI_YES:
7079 break;
7080 case TRI_MAYBE:
7081 certain = FALSE;
7082 if (maybe_reqs) {
7084 }
7085 break;
7086 default:
7088 active = FALSE;
7089 }
7090 if (!active) {
7091 break;
7092 }
7094
7095 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
7096}
7097
7098/**********************************************************************/
7108 const struct requirement *req)
7109{
7110 enum req_unchanging_status s;
7111 const struct civ_map *nmap = &(wld.map);
7112
7115 "Invalid source kind %d.", req->source.kind);
7117
7118 if (req->survives) {
7119 /* Special case for surviving requirements */
7120 /* Buildings may obsolete even here */
7121 if (VUT_IMPROVEMENT == req->source.kind) {
7122 const struct impr_type *b = req->source.value.building;
7123
7125 if (improvement_obsolete(context->player, b, context->city)) {
7126 /* FIXME: Sometimes can unobsolete, but considering it
7127 * may sometimes put the function on endless recursion */
7128 return REQUCH_ACT; /* Mostly about techs */
7129 } else {
7130 /* NOTE: May obsoletion reqs be unchanging? Hardly but why not. */
7131 return REQUCH_NO;
7132 }
7133 }
7134 }
7135 s = unchanging_present(nmap, s, context, req);
7136 if (s != REQUCH_NO) {
7137 return unchanging_noally(nmap, s, context, req);
7138 }
7139 } else {
7142
7143 if (cond) {
7144 return cond(nmap, s, context, req);
7145 }
7146 }
7147
7148 return s;
7149}
7150
7151/**********************************************************************/
7156 const struct req_context *other_context,
7157 const struct requirement *req,
7159{
7161
7162 if (REQUCH_NO != u) {
7163 /* Presence is precalculated */
7164 bool auto_present = (req->survives
7165 && !(VUT_IMPROVEMENT == req->source.kind
7169
7170 if (auto_present ? req->present
7172 /* Unchanging but does not block */
7173 return REQUCH_NO;
7174 }
7175 }
7176
7177 return u;
7178}
7179
7180/**********************************************************************/
7184bool is_req_in_vec(const struct requirement *req,
7185 const struct requirement_vector *vec)
7186{
7188 if (are_requirements_equal(req, preq)) {
7189 return TRUE;
7190 }
7192
7193 return FALSE;
7194}
7195
7196/**********************************************************************/
7204 enum universals_n kind)
7205{
7207 if (preq->present && preq->source.kind == kind) {
7208 return TRUE;
7209 }
7211 return FALSE;
7212}
7213
7214/**********************************************************************/
7223{
7224 switch (source->kind) {
7225 case VUT_ACTION:
7226 return !action_is_in_use(source->value.action);
7227 case VUT_UTFLAG:
7228 return !utype_flag_is_in_use(source->value.unitflag);
7229 case VUT_UCFLAG:
7230 return !uclass_flag_is_in_use(source->value.unitclassflag);
7231 case VUT_EXTRAFLAG:
7232 return !extra_flag_is_in_use(source->value.extraflag);
7233 case VUT_MINLATITUDE:
7234 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
7235 case VUT_MAXLATITUDE:
7236 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
7237 case VUT_COUNTER:
7238 case VUT_OTYPE:
7239 case VUT_SPECIALIST:
7240 case VUT_AI_LEVEL:
7241 case VUT_CITYTILE:
7242 case VUT_CITYSTATUS:
7243 case VUT_STYLE:
7244 case VUT_TOPO:
7245 case VUT_WRAP:
7246 case VUT_SERVERSETTING:
7247 case VUT_NATION:
7248 case VUT_NATIONGROUP:
7249 case VUT_ADVANCE:
7250 case VUT_TECHFLAG:
7251 case VUT_GOVERNMENT:
7252 case VUT_GOVFLAG:
7253 case VUT_ACHIEVEMENT:
7254 case VUT_IMPROVEMENT:
7255 case VUT_SITE:
7256 case VUT_IMPR_GENUS:
7257 case VUT_IMPR_FLAG:
7258 case VUT_PLAYER_FLAG:
7259 case VUT_PLAYER_STATE:
7260 case VUT_MINSIZE:
7261 case VUT_MINCULTURE:
7262 case VUT_MINFOREIGNPCT:
7263 case VUT_MINTECHS:
7264 case VUT_FUTURETECHS:
7265 case VUT_MINCITIES:
7266 case VUT_NATIONALITY:
7267 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
7268 case VUT_DIPLREL:
7269 case VUT_DIPLREL_TILE:
7270 case VUT_DIPLREL_TILE_O:
7275 case VUT_UTYPE:
7276 case VUT_UCLASS:
7277 case VUT_MINVETERAN:
7278 case VUT_UNITSTATE:
7279 case VUT_ACTIVITY:
7280 case VUT_MINMOVES:
7281 case VUT_MINHP:
7282 case VUT_AGE:
7283 case VUT_FORM_AGE:
7284 case VUT_ROADFLAG:
7285 case VUT_MINCALFRAG:
7286 case VUT_TERRAIN:
7287 case VUT_EXTRA:
7288 case VUT_TILEDEF:
7290 case VUT_GOOD:
7291 case VUT_TERRAINCLASS:
7292 case VUT_TERRFLAG:
7293 case VUT_TERRAINALTER:
7294 case VUT_MINYEAR:
7297 case VUT_TILE_REL:
7298 case VUT_NONE:
7299 case VUT_COUNT:
7300 /* Not implemented. */
7301 break;
7302 }
7303
7304 return FALSE;
7305}
7306
7307/**********************************************************************/
7316{
7317 /* Not known to be impossible to fulfill */
7318 return req->present && universal_never_there(&req->source);
7319}
7320
7321/**********************************************************************/
7330{
7333 return TRUE;
7334 }
7336
7337 /* Not known to be impossible to fulfill */
7338 return FALSE;
7339}
7340
7341/**********************************************************************/
7351 const struct requirement_vector *vec)
7352{
7353 if (vec) {
7354 return 0;
7355 } else {
7356 return -1;
7357 }
7358}
7359
7360/********************************************************************/
7369struct requirement_vector *
7371{
7372 fc_assert_ret_val(number == 0, nullptr);
7373
7374 return (struct requirement_vector *)parent_item;
7375}
7376
7377/**********************************************************************/
7388const char *req_vec_change_translation(const struct req_vec_change *change,
7390{
7391 const char *req_vec_description;
7392 static char buf[MAX_LEN_NAME * 3];
7393 struct astring astr;
7394
7395 fc_assert_ret_val(change, nullptr);
7397 nullptr);
7398
7399 /* Get rid of the previous. */
7400 buf[0] = '\0';
7401
7402 if (namer == nullptr) {
7403 /* TRANS: default description of a requirement vector
7404 * (used in ruledit) */
7405 req_vec_description = _("the requirement vector");
7406 } else {
7408 }
7409
7410 switch (change->operation) {
7411 case RVCO_REMOVE:
7412 fc_snprintf(buf, sizeof(buf),
7413 /* TRANS: remove a requirement from a requirement vector
7414 * (in ruledit).
7415 * The first %s is the operation.
7416 * The second %s is the requirement.
7417 * The third %s is a description of the requirement vector,
7418 * like "actor_reqs" */
7419 _("%s %s from %s"),
7421 req_to_fstring(&change->req, &astr),
7423 astr_free(&astr);
7424 break;
7425 case RVCO_APPEND:
7426 fc_snprintf(buf, sizeof(buf),
7427 /* TRANS: append a requirement to a requirement vector
7428 * (in ruledit).
7429 * The first %s is the operation.
7430 * The second %s is the requirement.
7431 * The third %s is a description of the requirement vector,
7432 * like "actor_reqs" */
7433 _("%s %s to %s"),
7435 req_to_fstring(&change->req, &astr),
7437 astr_free(&astr);
7438 break;
7439 case RVCO_NOOP:
7440 fc_snprintf(buf, sizeof(buf),
7441 /* TRANS: do nothing to a requirement vector (in ruledit).
7442 * The first %s is a description of the requirement vector,
7443 * like "actor_reqs" */
7444 _("Do nothing to %s"), req_vec_description);
7445 break;
7446 }
7447
7448 return buf;
7449}
7450
7451/**********************************************************************/
7464 const void *parent_item)
7465{
7466 struct requirement_vector *target
7467 = getter(parent_item, modification->vector_number);
7468 int i = 0;
7469
7470 switch (modification->operation) {
7471 case RVCO_APPEND:
7473 return TRUE;
7474 case RVCO_REMOVE:
7478 return TRUE;
7479 }
7480 i++;
7482 return FALSE;
7483 case RVCO_NOOP:
7484 return FALSE;
7485 }
7486
7487 return FALSE;
7488}
7489
7490/**********************************************************************/
7500struct req_vec_problem *
7502 const char *description,
7503 const char *description_translated)
7504{
7505 struct req_vec_problem *out;
7506 int i;
7507
7508 out = fc_malloc(sizeof(*out));
7509
7510 fc_strlcpy(out->description, description, sizeof(out->description));
7511 fc_strlcpy(out->description_translated, _(description_translated),
7512 sizeof(out->description_translated));
7513
7514 out->num_suggested_solutions = num_suggested_solutions;
7515 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
7516 * sizeof(struct req_vec_change));
7517 for (i = 0; i < out->num_suggested_solutions; i++) {
7518 /* No suggestions are ready yet. */
7519 out->suggested_solutions[i].operation = RVCO_NOOP;
7520 out->suggested_solutions[i].vector_number = -1;
7521 out->suggested_solutions[i].req.source.kind = VUT_NONE;
7522 }
7523
7524 return out;
7525}
7526
7527/**********************************************************************/
7537 const char *descr, ...)
7538{
7539 char description[500];
7540 char description_translated[500];
7541 va_list ap;
7542
7543 va_start(ap, descr);
7544 fc_vsnprintf(description, sizeof(description), descr, ap);
7545 va_end(ap);
7546
7547 va_start(ap, descr);
7549 _(descr), ap);
7550 va_end(ap);
7551
7554}
7555
7556/**********************************************************************/
7563{
7564 FC_FREE(issue->suggested_solutions);
7565 issue->num_suggested_solutions = 0;
7566
7567 FC_FREE(issue);
7568}
7569
7570/**********************************************************************/
7582struct req_vec_problem *
7585 const void *parent_item)
7586{
7587 int i, j;
7589
7590 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7591 /* No vector. */
7592 return nullptr;
7593 }
7594
7595 if (get_num == nullptr || parent_item == nullptr) {
7596 vec_num = 0;
7597 } else {
7598 vec_num = get_num(parent_item, vec);
7599 }
7600
7601 /* Look for contradictions */
7602 for (i = 0; i < requirement_vector_size(vec); i++) {
7603 struct requirement *preq = requirement_vector_get(vec, i);
7604 for (j = 0; j < requirement_vector_size(vec); j++) {
7605 struct requirement *nreq = requirement_vector_get(vec, j);
7606
7608 struct req_vec_problem *problem;
7609 struct astring astr;
7610 struct astring nastr;
7611
7613 N_("Requirements {%s} and {%s} contradict each other."),
7615
7616 astr_free(&astr);
7617 astr_free(&nastr);
7618
7619 /* The solution is to remove one of the contradictions. */
7620 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7621 problem->suggested_solutions[0].vector_number = vec_num;
7622 problem->suggested_solutions[0].req = *preq;
7623
7624 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7625 problem->suggested_solutions[1].vector_number = vec_num;
7626 problem->suggested_solutions[1].req = *nreq;
7627
7628 /* Only the first contradiction is reported. */
7629 return problem;
7630 }
7631 }
7632 }
7633
7634 return nullptr;
7635}
7636
7637/**********************************************************************/
7648struct req_vec_problem *
7651 const void *parent_item)
7652{
7653 /* Check for self contradictins. */
7655}
7656
7657/**********************************************************************/
7670struct req_vec_problem *
7673 const void *parent_item)
7674{
7675 int i;
7677 struct req_vec_problem *problem = nullptr;
7678
7679 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7680 /* No vector. */
7681 return nullptr;
7682 }
7683
7684 if (get_num == nullptr || parent_item == nullptr) {
7685 vec_num = 0;
7686 } else {
7687 vec_num = get_num(parent_item, vec);
7688 }
7689
7690 /* Look for contradictions */
7691 for (i = 0; i < requirement_vector_size(vec); i++) {
7692 struct requirement *preq = requirement_vector_get(vec, i);
7693
7694 if (universal_never_there(&preq->source)) {
7695 struct astring astr;
7696
7697 if (preq->present) {
7698 /* The requirement vector can never be fulfilled. Removing the
7699 * requirement makes it possible to fulfill it. This is a rule
7700 * change and shouldn't be "fixed" without thinking. Don't offer any
7701 * automatic solution to prevent mindless "fixes". */
7702 /* TRANS: Ruledit warns a user about an unused requirement vector
7703 * that never can be fulfilled because it asks for something that
7704 * never will be there. */
7705 if (problem == nullptr) {
7707 N_("Requirement {%s} requires %s but it will never be"
7708 " there."),
7710 astr_free(&astr);
7711 }
7712
7713 /* Continue to check if other problems have a solution proposal,
7714 * and prefer to return those. */
7715 continue;
7716 }
7717
7718 if (problem != nullptr) {
7719 /* Free previous one (one with no solution proposals) */
7721 }
7722
7724 N_("Requirement {%s} mentions %s but it will never be there."),
7726
7727 astr_free(&astr);
7728
7729 /* The solution is to remove the reference to the missing
7730 * universal. */
7731 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7732 problem->suggested_solutions[0].vector_number = vec_num;
7733 problem->suggested_solutions[0].req = *preq;
7734
7735 /* Only the first missing universal is reported. */
7736 return problem;
7737 }
7738 }
7739
7740 return problem;
7741}
7742
7743/**********************************************************************/
7756struct req_vec_problem *
7759 const void *parent_item)
7760{
7761 int i, j;
7763
7764 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7765 /* No vector. */
7766 return nullptr;
7767 }
7768
7769 if (get_num == nullptr || parent_item == nullptr) {
7770 vec_num = 0;
7771 } else {
7772 vec_num = get_num(parent_item, vec);
7773 }
7774
7775 /* Look for repeated requirements */
7776 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
7777 struct requirement *preq = requirement_vector_get(vec, i);
7778 for (j = i + 1; j < requirement_vector_size(vec); j++) {
7779 struct requirement *nreq = requirement_vector_get(vec, j);
7780
7782 struct req_vec_problem *problem;
7783 struct astring astr;
7784 struct astring nastr;
7785
7787 N_("Requirements {%s} and {%s} are the same."),
7789
7790 astr_free(&astr);
7791 astr_free(&nastr);
7792
7793 /* The solution is to remove one of the redundant requirements. */
7794 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7795 problem->suggested_solutions[0].vector_number = vec_num;
7796 problem->suggested_solutions[0].req = *preq;
7797
7798 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7799 problem->suggested_solutions[1].vector_number = vec_num;
7800 problem->suggested_solutions[1].req = *nreq;
7801
7802 /* Only the first redundancy is reported. */
7803 return problem;
7804 }
7805 }
7806 }
7807
7808 return nullptr;
7809}
7810
7811/**********************************************************************/
7823struct req_vec_problem *
7826 const void *parent_item)
7827{
7828 struct req_vec_problem *out;
7829
7831 if (out != nullptr) {
7832 /* A bug, not just a potential improvement */
7833 return out;
7834 }
7835
7836 /* Check if a universal that never will appear in the game is checked. */
7838 if (out != nullptr) {
7839 return out;
7840 }
7841
7842 /* Check if a requirement is redundant. */
7844 return out;
7845}
7846
7847/**********************************************************************/
7852 const struct universal *psource2)
7853{
7854 if (psource1->kind != psource2->kind) {
7855 return FALSE;
7856 }
7857 switch (psource1->kind) {
7858 case VUT_NONE:
7859 return TRUE;
7860 case VUT_COUNTER:
7861 return psource1->value.counter == psource2->value.counter;
7862 case VUT_ADVANCE:
7863 return psource1->value.advance == psource2->value.advance;
7864 case VUT_TECHFLAG:
7865 return psource1->value.techflag == psource2->value.techflag;
7866 case VUT_GOVERNMENT:
7867 return psource1->value.govern == psource2->value.govern;
7868 case VUT_GOVFLAG:
7869 return psource1->value.govflag == psource2->value.govflag;
7870 case VUT_ACHIEVEMENT:
7871 return psource1->value.achievement == psource2->value.achievement;
7872 case VUT_STYLE:
7873 return psource1->value.style == psource2->value.style;
7874 case VUT_IMPROVEMENT:
7875 case VUT_SITE:
7876 return psource1->value.building == psource2->value.building;
7877 case VUT_IMPR_GENUS:
7878 return psource1->value.impr_genus == psource2->value.impr_genus;
7879 case VUT_IMPR_FLAG:
7880 return psource1->value.impr_flag == psource2->value.impr_flag;
7881 case VUT_PLAYER_FLAG:
7882 return psource1->value.plr_flag == psource2->value.plr_flag;
7883 case VUT_PLAYER_STATE:
7884 return psource1->value.plrstate == psource2->value.plrstate;
7885 case VUT_EXTRA:
7886 return psource1->value.extra == psource2->value.extra;
7887 case VUT_TILEDEF:
7889 return psource1->value.tiledef == psource2->value.tiledef;
7890 case VUT_GOOD:
7891 return psource1->value.good == psource2->value.good;
7892 case VUT_TERRAIN:
7893 return psource1->value.terrain == psource2->value.terrain;
7894 case VUT_TERRFLAG:
7895 return psource1->value.terrainflag == psource2->value.terrainflag;
7896 case VUT_NATION:
7897 return psource1->value.nation == psource2->value.nation;
7898 case VUT_NATIONGROUP:
7899 return psource1->value.nationgroup == psource2->value.nationgroup;
7900 case VUT_NATIONALITY:
7901 return psource1->value.nationality == psource2->value.nationality;
7902 case VUT_ORIGINAL_OWNER:
7903 return psource1->value.origowner == psource2->value.origowner;
7904 case VUT_DIPLREL:
7905 case VUT_DIPLREL_TILE:
7906 case VUT_DIPLREL_TILE_O:
7909 return psource1->value.diplrel == psource2->value.diplrel;
7910 case VUT_UTYPE:
7911 return psource1->value.utype == psource2->value.utype;
7912 case VUT_UTFLAG:
7913 return psource1->value.unitflag == psource2->value.unitflag;
7914 case VUT_UCLASS:
7915 return psource1->value.uclass == psource2->value.uclass;
7916 case VUT_UCFLAG:
7917 return psource1->value.unitclassflag == psource2->value.unitclassflag;
7918 case VUT_MINVETERAN:
7919 return psource1->value.minveteran == psource2->value.minveteran;
7920 case VUT_UNITSTATE:
7921 return psource1->value.unit_state == psource2->value.unit_state;
7922 case VUT_ACTIVITY:
7923 return psource1->value.activity == psource2->value.activity;
7924 case VUT_MINMOVES:
7925 return psource1->value.minmoves == psource2->value.minmoves;
7926 case VUT_MINHP:
7927 return psource1->value.min_hit_points == psource2->value.min_hit_points;
7928 case VUT_AGE:
7929 return psource1->value.age == psource2->value.age;
7930 case VUT_FORM_AGE:
7931 return psource1->value.form_age == psource2->value.form_age;
7932 case VUT_MINTECHS:
7933 return psource1->value.min_techs == psource2->value.min_techs;
7934 case VUT_FUTURETECHS:
7935 return psource1->value.future_techs == psource2->value.future_techs;
7936 case VUT_MINCITIES:
7937 return psource1->value.min_cities == psource2->value.min_cities;
7938 case VUT_ACTION:
7939 return (action_number(psource1->value.action)
7940 == action_number(psource2->value.action));
7941 case VUT_OTYPE:
7942 return psource1->value.outputtype == psource2->value.outputtype;
7943 case VUT_SPECIALIST:
7944 return psource1->value.specialist == psource2->value.specialist;
7945 case VUT_MINSIZE:
7946 return psource1->value.minsize == psource2->value.minsize;
7947 case VUT_MINCULTURE:
7948 return psource1->value.minculture == psource2->value.minculture;
7949 case VUT_MINFOREIGNPCT:
7950 return psource1->value.minforeignpct == psource2->value.minforeignpct;
7951 case VUT_AI_LEVEL:
7952 return psource1->value.ai_level == psource2->value.ai_level;
7954 return psource1->value.max_tile_total_units == psource2->value.max_tile_total_units;
7956 return psource1->value.max_tile_top_units == psource2->value.max_tile_top_units;
7957 case VUT_TERRAINCLASS:
7958 return psource1->value.terrainclass == psource2->value.terrainclass;
7959 case VUT_ROADFLAG:
7960 return psource1->value.roadflag == psource2->value.roadflag;
7961 case VUT_EXTRAFLAG:
7962 return psource1->value.extraflag == psource2->value.extraflag;
7963 case VUT_MINYEAR:
7964 return psource1->value.minyear == psource2->value.minyear;
7965 case VUT_MINCALFRAG:
7966 return psource1->value.mincalfrag == psource2->value.mincalfrag;
7967 case VUT_TOPO:
7968 return psource1->value.topo_property == psource2->value.topo_property;
7969 case VUT_WRAP:
7970 return psource1->value.wrap_property == psource2->value.wrap_property;
7971 case VUT_SERVERSETTING:
7972 return psource1->value.ssetval == psource2->value.ssetval;
7973 case VUT_TERRAINALTER:
7974 return psource1->value.terrainalter == psource2->value.terrainalter;
7975 case VUT_CITYTILE:
7976 return psource1->value.citytile == psource2->value.citytile;
7977 case VUT_CITYSTATUS:
7978 return psource1->value.citystatus == psource2->value.citystatus;
7979 case VUT_TILE_REL:
7980 return psource1->value.tilerel == psource2->value.tilerel;
7981 case VUT_MINLATITUDE:
7982 case VUT_MAXLATITUDE:
7983 return psource1->value.latitude == psource2->value.latitude;
7985 return psource1->value.distance_sq == psource2->value.distance_sq;
7987 return psource1->value.region_tiles == psource2->value.region_tiles;
7988 case VUT_COUNT:
7989 break;
7990 }
7991
7992 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
7993 return FALSE;
7994}
7995
7996/**********************************************************************/
8000const char *universal_rule_name(const struct universal *psource)
8001{
8002 static char buffer[10];
8003
8004 switch (psource->kind) {
8005 case VUT_NONE:
8006 return "(none)";
8007 case VUT_COUNTER:
8008 return counter_rule_name(psource->value.counter);
8009 case VUT_CITYTILE:
8010 return citytile_type_name(psource->value.citytile);
8011 case VUT_CITYSTATUS:
8012 return citystatus_type_name(psource->value.citystatus);
8013 case VUT_TILE_REL:
8014 return tilerel_type_name(psource->value.tilerel);
8015 case VUT_MINYEAR:
8016 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
8017
8018 return buffer;
8019 case VUT_MINCALFRAG:
8020 /* Rule name is 0-based number, not pretty name from ruleset */
8021 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
8022
8023 return buffer;
8024 case VUT_TOPO:
8025 return topo_flag_name(psource->value.topo_property);
8026 case VUT_WRAP:
8027 return wrap_flag_name(psource->value.wrap_property);
8028 case VUT_SERVERSETTING:
8029 return ssetv_rule_name(psource->value.ssetval);
8030 case VUT_ADVANCE:
8031 return advance_rule_name(psource->value.advance);
8032 case VUT_TECHFLAG:
8033 return tech_flag_id_name(psource->value.techflag);
8034 case VUT_GOVERNMENT:
8035 return government_rule_name(psource->value.govern);
8036 case VUT_GOVFLAG:
8037 return gov_flag_id_name(psource->value.govflag);
8038 case VUT_ACHIEVEMENT:
8039 return achievement_rule_name(psource->value.achievement);
8040 case VUT_STYLE:
8041 return style_rule_name(psource->value.style);
8042 case VUT_IMPROVEMENT:
8043 case VUT_SITE:
8044 return improvement_rule_name(psource->value.building);
8045 case VUT_IMPR_GENUS:
8046 return impr_genus_id_name(psource->value.impr_genus);
8047 case VUT_IMPR_FLAG:
8048 return impr_flag_id_name(psource->value.impr_flag);
8049 case VUT_PLAYER_FLAG:
8050 return plr_flag_id_name(psource->value.plr_flag);
8051 case VUT_PLAYER_STATE:
8052 return plrstate_type_name(psource->value.plrstate);
8053 case VUT_EXTRA:
8054 return extra_rule_name(psource->value.extra);
8055 case VUT_TILEDEF:
8057 return tiledef_rule_name(psource->value.tiledef);
8058 case VUT_GOOD:
8059 return goods_rule_name(psource->value.good);
8060 case VUT_TERRAIN:
8061 return terrain_rule_name(psource->value.terrain);
8062 case VUT_TERRFLAG:
8063 return terrain_flag_id_name(psource->value.terrainflag);
8064 case VUT_NATION:
8065 return nation_rule_name(psource->value.nation);
8066 case VUT_NATIONGROUP:
8067 return nation_group_rule_name(psource->value.nationgroup);
8068 case VUT_DIPLREL:
8069 case VUT_DIPLREL_TILE:
8070 case VUT_DIPLREL_TILE_O:
8073 return diplrel_rule_name(psource->value.diplrel);
8074 case VUT_NATIONALITY:
8075 return nation_rule_name(psource->value.nationality);
8076 case VUT_ORIGINAL_OWNER:
8077 return nation_rule_name(psource->value.origowner);
8078 case VUT_UTYPE:
8079 return utype_rule_name(psource->value.utype);
8080 case VUT_UTFLAG:
8081 return unit_type_flag_id_name(psource->value.unitflag);
8082 case VUT_UCLASS:
8083 return uclass_rule_name(psource->value.uclass);
8084 case VUT_UCFLAG:
8085 return unit_class_flag_id_name(psource->value.unitclassflag);
8086 case VUT_MINVETERAN:
8087 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
8088
8089 return buffer;
8090 case VUT_UNITSTATE:
8091 return ustate_prop_name(psource->value.unit_state);
8092 case VUT_ACTIVITY:
8093 return unit_activity_name(psource->value.activity);
8094 case VUT_MINMOVES:
8095 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
8096
8097 return buffer;
8098 case VUT_MINHP:
8099 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
8100
8101 return buffer;
8102 case VUT_AGE:
8103 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
8104
8105 return buffer;
8106 case VUT_FORM_AGE:
8107 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
8108
8109 return buffer;
8110 case VUT_MINTECHS:
8111 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
8112
8113 return buffer;
8114 case VUT_FUTURETECHS:
8115 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.future_techs);
8116
8117 return buffer;
8118 case VUT_MINCITIES:
8119 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_cities);
8120
8121 return buffer;
8122 case VUT_ACTION:
8123 return action_rule_name(psource->value.action);
8124 case VUT_OTYPE:
8125 return get_output_identifier(psource->value.outputtype);
8126 case VUT_SPECIALIST:
8127 return specialist_rule_name(psource->value.specialist);
8128 case VUT_MINSIZE:
8129 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
8130
8131 return buffer;
8132 case VUT_MINCULTURE:
8133 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
8134
8135 return buffer;
8136 case VUT_MINFOREIGNPCT:
8137 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
8138
8139 return buffer;
8140 case VUT_AI_LEVEL:
8141 return ai_level_name(psource->value.ai_level);
8143 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_total_units);
8144 return buffer;
8146 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_top_units);
8147 return buffer;
8148 case VUT_TERRAINCLASS:
8149 return terrain_class_name(psource->value.terrainclass);
8150 case VUT_ROADFLAG:
8151 return road_flag_id_name(psource->value.roadflag);
8152 case VUT_EXTRAFLAG:
8153 return extra_flag_id_name(psource->value.extraflag);
8154 case VUT_TERRAINALTER:
8155 return terrain_alteration_name(psource->value.terrainalter);
8156 case VUT_MINLATITUDE:
8157 case VUT_MAXLATITUDE:
8158 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
8159
8160 return buffer;
8162 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.distance_sq);
8163
8164 return buffer;
8166 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.region_tiles);
8167
8168 return buffer;
8169 case VUT_COUNT:
8170 break;
8171 }
8172
8173 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8174
8175 return nullptr;
8176}
8177
8178/**********************************************************************/
8187 char *buf, size_t bufsz)
8188{
8189 buf[0] = '\0'; /* to be safe. */
8190 switch (psource->kind) {
8191 case VUT_NONE:
8192 /* TRANS: missing value */
8193 fc_strlcat(buf, _("(none)"), bufsz);
8194 return buf;
8195 case VUT_ADVANCE:
8197 return buf;
8198 case VUT_COUNTER:
8200 return buf;
8201 case VUT_TECHFLAG:
8202 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
8203 tech_flag_id_translated_name(psource->value.techflag));
8204 return buf;
8205 case VUT_GOVERNMENT:
8207 bufsz);
8208 return buf;
8209 case VUT_GOVFLAG:
8210 cat_snprintf(buf, bufsz, _("\"%s\" gov"),
8211 gov_flag_id_translated_name(psource->value.govflag));
8212 return buf;
8213 case VUT_ACHIEVEMENT:
8215 bufsz);
8216 return buf;
8217 case VUT_STYLE:
8219 bufsz);
8220 return buf;
8221 case VUT_IMPROVEMENT:
8223 bufsz);
8224 return buf;
8225 case VUT_SITE:
8226 {
8227 char local_buf[1024];
8228
8229 fc_snprintf(local_buf, sizeof(local_buf), _("%s site"),
8230 improvement_name_translation(psource->value.building));
8232 }
8233
8234 return buf;
8235 case VUT_IMPR_GENUS:
8237 impr_genus_id_translated_name(psource->value.impr_genus),
8238 bufsz);
8239 return buf;
8240 case VUT_IMPR_FLAG:
8242 impr_flag_id_translated_name(psource->value.impr_flag),
8243 bufsz);
8244 return buf;
8245 case VUT_PLAYER_FLAG:
8247 plr_flag_id_translated_name(psource->value.plr_flag),
8248 bufsz);
8249 return buf;
8250 case VUT_PLAYER_STATE:
8252 plrstate_type_translated_name(psource->value.plrstate),
8253 bufsz);
8254 return buf;
8255 case VUT_EXTRA:
8257 return buf;
8258 case VUT_TILEDEF:
8261 return buf;
8262 case VUT_GOOD:
8264 return buf;
8265 case VUT_TERRAIN:
8267 return buf;
8268 case VUT_NATION:
8270 bufsz);
8271 return buf;
8272 case VUT_NATIONGROUP:
8274 bufsz);
8275 return buf;
8276 case VUT_NATIONALITY:
8277 cat_snprintf(buf, bufsz, _("%s citizens"),
8278 nation_adjective_translation(psource->value.nationality));
8279 return buf;
8280 case VUT_ORIGINAL_OWNER:
8281 /* TRANS: Keep short. City founding nation. */
8282 cat_snprintf(buf, bufsz, _("%s original owner"),
8283 nation_adjective_translation(psource->value.origowner));
8284 return buf;
8285 case VUT_DIPLREL:
8286 case VUT_DIPLREL_TILE:
8287 case VUT_DIPLREL_TILE_O:
8291 bufsz);
8292 return buf;
8293 case VUT_UTYPE:
8295 return buf;
8296 case VUT_UTFLAG:
8298 /* TRANS: Unit type flag */
8299 Q_("?utflag:\"%s\" units"),
8301 psource->value.unitflag));
8302 return buf;
8303 case VUT_UCLASS:
8305 /* TRANS: Unit class */
8306 _("%s units"),
8307 uclass_name_translation(psource->value.uclass));
8308 return buf;
8309 case VUT_UCFLAG:
8311 /* TRANS: Unit class flag */
8312 Q_("?ucflag:\"%s\" units"),
8314 psource->value.unitclassflag));
8315 return buf;
8316 case VUT_MINVETERAN:
8317 /* FIXME */
8318 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
8319 psource->value.minveteran);
8320 return buf;
8321 case VUT_UNITSTATE:
8322 switch (psource->value.unit_state) {
8323 case USP_TRANSPORTED:
8324 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
8325 cat_snprintf(buf, bufsz, _("Transported"));
8326 break;
8327 case USP_LIVABLE_TILE:
8329 /* TRANS: unit state. (appears in strings like
8330 * "Missile+On livable tile") */
8331 _("On livable tile"));
8332 break;
8333 case USP_TRANSPORTING:
8334 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
8335 cat_snprintf(buf, bufsz, _("Transporting"));
8336 break;
8337 case USP_HAS_HOME_CITY:
8338 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
8339 cat_snprintf(buf, bufsz, _("Has a home city"));
8340 break;
8341 case USP_NATIVE_TILE:
8343 /* TRANS: unit state. (appears in strings like
8344 * "Missile+On native tile") */
8345 _("On native tile"));
8346 break;
8347 case USP_NATIVE_EXTRA:
8349 /* TRANS: unit state. (appears in strings like
8350 * "Missile+In native extra") */
8351 _("In native extra"));
8352 break;
8354 /* TRANS: unit state. (appears in strings like
8355 * "Missile+Has moved this turn") */
8356 cat_snprintf(buf, bufsz, _("Has moved this turn"));
8357 break;
8358 case USP_COUNT:
8359 fc_assert_msg(psource->value.unit_state != USP_COUNT,
8360 "Invalid unit state property.");
8361 break;
8362 }
8363 return buf;
8364 case VUT_ACTIVITY:
8365 cat_snprintf(buf, bufsz, _("%s activity"),
8366 Q_(unit_activity_name(psource->value.activity)));
8367 return buf;
8368 case VUT_MINMOVES:
8369 /* TRANS: Minimum unit movement points left for requirement to be met
8370 * (%s is a string like "1" or "2 1/3") */
8371 cat_snprintf(buf, bufsz, _("%s MP"),
8372 move_points_text(psource->value.minmoves, TRUE));
8373 return buf;
8374 case VUT_MINHP:
8375 /* TRANS: HP = hit points */
8376 cat_snprintf(buf, bufsz, _("%d HP"),
8377 psource->value.min_hit_points);
8378 return buf;
8379 case VUT_AGE:
8380 cat_snprintf(buf, bufsz, _("Age %d"),
8381 psource->value.age);
8382 return buf;
8383 case VUT_FORM_AGE:
8384 cat_snprintf(buf, bufsz, _("Form age %d"),
8385 psource->value.form_age);
8386 return buf;
8387 case VUT_MINTECHS:
8388 cat_snprintf(buf, bufsz, _("%d Techs"),
8389 psource->value.min_techs);
8390 return buf;
8391 case VUT_FUTURETECHS:
8392 cat_snprintf(buf, bufsz, _("%d Future techs"),
8393 psource->value.future_techs);
8394 return buf;
8395 case VUT_MINCITIES:
8396 cat_snprintf(buf, bufsz, _("%d Cities"),
8397 psource->value.min_cities);
8398 return buf;
8399 case VUT_ACTION:
8401 bufsz);
8402 return buf;
8403 case VUT_OTYPE:
8404 /* FIXME */
8405 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
8406 return buf;
8407 case VUT_SPECIALIST:
8409 bufsz);
8410 return buf;
8411 case VUT_MINSIZE:
8412 cat_snprintf(buf, bufsz, _("Size %d"),
8413 psource->value.minsize);
8414 return buf;
8415 case VUT_MINCULTURE:
8416 cat_snprintf(buf, bufsz, _("Culture %d"),
8417 psource->value.minculture);
8418 return buf;
8419 case VUT_MINFOREIGNPCT:
8420 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
8421 psource->value.minforeignpct);
8422 return buf;
8423 case VUT_AI_LEVEL:
8424 /* TRANS: "Hard AI" */
8425 cat_snprintf(buf, bufsz, _("%s AI"),
8426 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
8427 return buf;
8429 /* TRANS: here <= means 'less than or equal' */
8430 cat_snprintf(buf, bufsz, PL_("<=%d total unit",
8431 "<=%d total units",
8432 psource->value.max_tile_total_units),
8433 psource->value.max_tile_total_units);
8434 return buf;
8436 /* TRANS: here <= means 'less than or equal' */
8437 cat_snprintf(buf, bufsz, PL_("<=%d unit",
8438 "<=%d units", psource->value.max_tile_top_units),
8439 psource->value.max_tile_top_units);
8440 return buf;
8441 case VUT_TERRAINCLASS:
8442 /* TRANS: Terrain class: "Land terrain" */
8443 cat_snprintf(buf, bufsz, _("%s terrain"),
8444 terrain_class_name_translation(psource->value.terrainclass));
8445 return buf;
8446 case VUT_TERRFLAG:
8448 /* TRANS: Terrain flag */
8449 Q_("?terrflag:\"%s\" terrain"),
8451 psource->value.terrainflag));
8452 return buf;
8453 case VUT_ROADFLAG:
8455 /* TRANS: Road flag */
8456 Q_("?roadflag:\"%s\" road"),
8457 road_flag_id_translated_name(psource->value.roadflag));
8458 return buf;
8459 case VUT_EXTRAFLAG:
8461 /* TRANS: Extra flag */
8462 Q_("?extraflag:\"%s\" extra"),
8463 extra_flag_id_translated_name(psource->value.extraflag));
8464 return buf;
8465 case VUT_MINYEAR:
8466 cat_snprintf(buf, bufsz, _("After %s"),
8467 textyear(psource->value.minyear));
8468 return buf;
8469 case VUT_MINCALFRAG:
8470 /* TRANS: here >= means 'greater than or equal'.
8471 * %s identifies a calendar fragment (may be bare number). */
8472 cat_snprintf(buf, bufsz, _(">=%s"),
8473 textcalfrag(psource->value.mincalfrag));
8474 return buf;
8475 case VUT_TOPO:
8476 /* TRANS: topology flag name ("Hex", "ISO") */
8477 cat_snprintf(buf, bufsz, _("%s map"),
8478 _(topo_flag_name(psource->value.topo_property)));
8479 return buf;
8480 case VUT_WRAP:
8481 /* TRANS: wrap flag name ("WrapX", "WrapY") */
8482 cat_snprintf(buf, bufsz, _("%s map"),
8483 _(wrap_flag_name(psource->value.wrap_property)));
8484 return buf;
8485 case VUT_SERVERSETTING:
8487 bufsz);
8488 return buf;
8489 case VUT_TERRAINALTER:
8490 /* TRANS: "Irrigation possible" */
8491 cat_snprintf(buf, bufsz, _("%s possible"),
8492 Q_(terrain_alteration_name(psource->value.terrainalter)));
8493 return buf;
8494 case VUT_CITYTILE:
8495 switch (psource->value.citytile) {
8496 case CITYT_CENTER:
8497 fc_strlcat(buf, _("City center"), bufsz);
8498 break;
8499 case CITYT_CLAIMED:
8500 fc_strlcat(buf, _("Tile claimed"), bufsz);
8501 break;
8502 case CITYT_EXTRAS_OWNED:
8503 fc_strlcat(buf, _("Extras owned"), bufsz);
8504 break;
8505 case CITYT_WORKED:
8506 fc_strlcat(buf, _("Worked tile"), bufsz);
8507 break;
8509 fc_strlcat(buf, _("Same continent tile"), bufsz);
8510 break;
8512 /* TRANS: Short for "a tile of other terrain class mass near city" */
8513 fc_strlcat(buf, _("Port reachable tile"), bufsz);
8514 break;
8515 case CITYT_LAST:
8516 fc_assert(psource->value.citytile != CITYT_LAST);
8517 fc_strlcat(buf, "error", bufsz);
8518 break;
8519 }
8520 return buf;
8521 case VUT_CITYSTATUS:
8522 switch (psource->value.citystatus) {
8524 fc_strlcat(buf, _("Owned by original"), bufsz);
8525 break;
8526 case CITYS_STARVED:
8527 fc_strlcat(buf, _("Starved"), bufsz);
8528 break;
8529 case CITYS_DISORDER:
8530 fc_strlcat(buf, _("Disorder"), bufsz);
8531 break;
8532 case CITYS_CELEBRATION:
8533 fc_strlcat(buf, _("Celebration"), bufsz);
8534 break;
8535 case CITYS_TRANSFERRED:
8536 /* TRANS: CityStatus value - city has changed hands */
8537 fc_strlcat(buf, _("Transferred"), bufsz);
8538 break;
8540 fc_strlcat(buf, _("CapitalConnected"), bufsz);
8541 break;
8542 case CITYS_LAST:
8543 fc_assert(psource->value.citystatus != CITYS_LAST);
8544 fc_strlcat(buf, "error", bufsz);
8545 break;
8546 }
8547 return buf;
8548 case VUT_TILE_REL:
8549 switch (psource->value.tilerel) {
8550 case TREL_SAME_TCLASS:
8551 fc_strlcat(buf, _("Same terrain class"), bufsz);
8552 break;
8553 case TREL_SAME_REGION:
8554 fc_strlcat(buf, _("Same continent/ocean"), bufsz);
8555 break;
8557 fc_strlcat(buf, _("Only other continent/ocean"), bufsz);
8558 break;
8560 fc_strlcat(buf, _("Lake/island surrounded"), bufsz);
8561 break;
8562 case TREL_COUNT:
8563 fc_assert(psource->value.tilerel != TREL_COUNT);
8564 fc_strlcat(buf, "error", bufsz);
8565 break;
8566 }
8567 return buf;
8568 case VUT_MINLATITUDE:
8569 /* TRANS: here >= means 'greater than or equal'. */
8570 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
8571 psource->value.latitude);
8572 return buf;
8573 case VUT_MAXLATITUDE:
8574 /* TRANS: here <= means 'less than or equal'. */
8575 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
8576 psource->value.latitude);
8577 return buf;
8579 /* TRANS: here <= means 'less than or equal'. */
8580 cat_snprintf(buf, bufsz, _("Squared distance <= %d"),
8581 psource->value.distance_sq);
8582 return buf;
8584 cat_snprintf(buf, bufsz, _("%d or fewer region tiles"),
8585 psource->value.region_tiles);
8586 return buf;
8587 case VUT_COUNT:
8588 break;
8589 }
8590
8591 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8592 return buf;
8593}
8594
8595/**********************************************************************/
8599{
8600 return universals_n_name(psource->kind);
8601}
8602
8603/**********************************************************************/
8607 const struct universal *target)
8608{
8609 switch (target->kind) {
8610 case VUT_IMPROVEMENT:
8611 case VUT_SITE:
8612 return impr_build_shield_cost(pcity, target->value.building);
8613 case VUT_UTYPE:
8614 return utype_build_shield_cost(pcity, nullptr, target->value.utype);
8615 default:
8616 break;
8617 }
8618 return FC_INFINITY;
8619}
8620
8621/**********************************************************************/
8627 const struct universal *to_replace,
8628 const struct universal *replacement)
8629{
8630 bool changed = FALSE;
8631
8634 preq->source = *replacement;
8635 changed = TRUE;
8636 }
8638
8639 return changed;
8640}
8641
8642/**********************************************************************/
8647 const struct requirement_vector *reqs,
8648 const struct universal *psource)
8649{
8652 return TRUE;
8653 }
8655
8656 return FALSE;
8657}
8658
8659/**********************************************************************/
8670 struct universal *unis,
8671 size_t n_unis)
8672{
8673 int i;
8674
8675 for (i = 0; i < n_unis; i++) {
8677 /* This universal makes it impossible to fulfill the specified
8678 * requirement vector */
8679 return TRUE;
8680 }
8681 }
8682
8683 /* No specified universal is known to guarantee that the requirement
8684 * vector never will be fulfilled. */
8685 return FALSE;
8686}
8687
8688/**********************************************************************/
8704 struct universal *unis,
8705 size_t n_unis)
8706{
8708 int i;
8710
8711 for (i = 0; i < n_unis; i++) {
8712 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
8713 case ITF_NO:
8714 case ITF_YES:
8715 /* this req matched this source */
8717 break;
8718 case ITF_NOT_APPLICABLE:
8719 /* Not a mention. */
8720 break;
8721 }
8722 }
8723
8725 /* A requirement not relevant to any of the specified universals was
8726 * found in the requirement vector. */
8727 return FALSE;
8728 }
8730
8731 /* No requirement not relevant to any of the specified universals was
8732 * found in the requirement vector. */
8733 return TRUE;
8734}
8735
8736/**********************************************************************/
8739enum req_item_found
8741 const struct universal *source)
8742{
8745 "No req item found function for %s",
8747
8748 return (*universal_found_function[source->kind])(preq, source);
8749}
8750
8751/**********************************************************************/
8762 const struct requirement_vector *reqs,
8763 const struct universal *source)
8764{
8765 bool necessary = FALSE;
8766
8769 "No req item found function for %s",
8771
8773 switch ((*universal_found_function[source->kind])(preq, source)) {
8774 case ITF_NOT_APPLICABLE:
8775 continue;
8776 case ITF_NO:
8777 if (preq->present) {
8778 return FALSE;
8779 }
8780 break;
8781 case ITF_YES:
8782 if (preq->present) {
8783 necessary = TRUE;
8784 } else {
8785 return FALSE;
8786 }
8787 break;
8788 }
8790
8791 return (!check_necessary || necessary);
8792}
8793
8794/**********************************************************************/
8799 const struct universal *source)
8800{
8801 switch (universal_fulfills_requirement(req, source)) {
8802 case ITF_NOT_APPLICABLE:
8803 return FALSE;
8804 case ITF_NO:
8805 case ITF_YES:
8806 return TRUE;
8807 }
8808
8809 log_error("Unhandled item_found value");
8810 return FALSE;
8811}
8812
8813/**********************************************************************/
8817 const struct universal *source)
8818{
8819 fc_assert(source->value.nation);
8820
8821 switch (preq->source.kind) {
8822 case VUT_NATION:
8823 return preq->source.value.nation == source->value.nation ? ITF_YES
8824 : ITF_NO;
8825 case VUT_NATIONGROUP:
8826 return nation_is_in_group(source->value.nation,
8827 preq->source.value.nationgroup) ? ITF_YES
8828 : ITF_NO;
8829 default:
8830 break;
8831 }
8832
8833 return ITF_NOT_APPLICABLE;
8834}
8835
8836/**********************************************************************/
8840 const struct universal *source)
8841{
8842 fc_assert(source->value.govern);
8843
8844 if (preq->source.kind == VUT_GOVERNMENT) {
8845 return preq->source.value.govern == source->value.govern ? ITF_YES
8846 : ITF_NO;
8847 } else if (preq->source.kind == VUT_GOVFLAG) {
8848 return BV_ISSET(source->value.govern->flags, preq->source.value.govflag)
8849 ? ITF_YES : ITF_NO;
8850 }
8851
8852 return ITF_NOT_APPLICABLE;
8853}
8854
8855/**********************************************************************/
8859 const struct universal *source)
8860{
8861 fc_assert(source->value.min_cities);
8862
8863 if (preq->source.kind == VUT_MINCITIES) {
8864 return preq->source.value.min_cities <= source->value.min_cities ? ITF_YES
8865 : ITF_NO;
8866 }
8867
8868 return ITF_NOT_APPLICABLE;
8869}
8870
8871/**********************************************************************/
8875 const struct universal *source)
8876{
8877 fc_assert(source->value.building);
8878
8879 /* We only ever return ITF_YES, because requiring a different
8880 * improvement does not mean that the improvement under consideration
8881 * cannot fulfill the requirements. This is necessary to allow
8882 * requirement vectors to specify multiple required improvements. */
8883
8884 switch (preq->source.kind) {
8885 case VUT_IMPROVEMENT:
8886 case VUT_SITE:
8887 if (source->value.building == preq->source.value.building) {
8888 return ITF_YES;
8889 }
8890 break;
8891 case VUT_IMPR_GENUS:
8892 if (source->value.building->genus == preq->source.value.impr_genus) {
8893 return ITF_YES;
8894 }
8895 break;
8896 case VUT_IMPR_FLAG:
8897 if (improvement_has_flag(source->value.building,
8898 preq->source.value.impr_flag)) {
8899 return ITF_YES;
8900 }
8901 break;
8902 default:
8903 break;
8904 }
8905
8906 return ITF_NOT_APPLICABLE;
8907}
8908
8909/**********************************************************************/
8913 const struct universal *source)
8914{
8915 fc_assert(source->value.uclass);
8916
8917 switch (preq->source.kind) {
8918 case VUT_UCLASS:
8919 return source->value.uclass == preq->source.value.uclass ? ITF_YES
8920 : ITF_NO;
8921 case VUT_UCFLAG:
8922 return uclass_has_flag(source->value.uclass,
8923 preq->source.value.unitclassflag) ? ITF_YES
8924 : ITF_NO;
8925
8926 default:
8927 /* Not found and not relevant. */
8928 return ITF_NOT_APPLICABLE;
8929 };
8930}
8931
8932/**********************************************************************/
8936 const struct universal *source)
8937{
8938 fc_assert(source->value.utype);
8939
8940 switch (preq->source.kind) {
8941 case VUT_UTYPE:
8942 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
8943 case VUT_UCLASS:
8944 return utype_class(source->value.utype) == preq->source.value.uclass
8945 ? ITF_YES : ITF_NO;
8946 case VUT_UTFLAG:
8947 return utype_has_flag(source->value.utype,
8948 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
8949 case VUT_UCFLAG:
8950 return uclass_has_flag(utype_class(source->value.utype),
8951 preq->source.value.unitclassflag) ? ITF_YES
8952 : ITF_NO;
8953 default:
8954 /* Not found and not relevant. */
8955 return ITF_NOT_APPLICABLE;
8956 };
8957}
8958
8959/**********************************************************************/
8962static enum req_item_found
8964 const struct universal *source)
8965{
8968
8969 switch (preq->source.kind) {
8970 case VUT_ACTIVITY:
8971 return source->value.activity == preq->source.value.activity ? ITF_YES
8972 : ITF_NO;
8973 default:
8974 /* Not found and not relevant. */
8975 return ITF_NOT_APPLICABLE;
8976 };
8977}
8978
8979/**********************************************************************/
8983 const struct universal *source)
8984{
8985 fc_assert(source->value.terrain);
8986
8987 switch (preq->source.kind) {
8988 case VUT_TERRAIN:
8989 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
8990 case VUT_TERRAINCLASS:
8991 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
8992 ? ITF_YES : ITF_NO;
8993 case VUT_TERRFLAG:
8994 return terrain_has_flag(source->value.terrain,
8995 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
8996 case VUT_TERRAINALTER:
8997 return (terrain_can_support_alteration(source->value.terrain,
8998 preq->source.value.terrainalter)
8999 ? ITF_YES : ITF_NO);
9000 default:
9001 /* Not found and not relevant. */
9002 return ITF_NOT_APPLICABLE;
9003 };
9004}
9005
9006/**********************************************************************/
9010 const struct universal *source)
9011{
9014
9015 switch (preq->source.kind) {
9016 case VUT_CITYTILE:
9017 return (source->value.citytile == preq->source.value.citytile
9018 ? ITF_YES
9019 /* The presence of one tile state doesn't block another */
9021 default:
9022 /* Not found and not relevant. */
9023 return ITF_NOT_APPLICABLE;
9024 };
9025}
9026
9027/**********************************************************************/
9033 const struct universal *source)
9034{
9035 fc_assert(source->value.extra);
9036
9037 switch (preq->source.kind) {
9038 case VUT_EXTRA:
9039 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
9040 case VUT_EXTRAFLAG:
9041 return extra_has_flag(source->value.extra,
9042 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
9043 case VUT_ROADFLAG:
9044 {
9045 struct road_type *r = extra_road_get(source->value.extra);
9046 return r && road_has_flag(r, preq->source.value.roadflag)
9047 ? ITF_YES : ITF_NO;
9048 }
9049 default:
9050 /* Not found and not relevant. */
9051 return ITF_NOT_APPLICABLE;
9052 }
9053}
9054
9055/**********************************************************************/
9059 const struct universal *source)
9060{
9061 fc_assert(source->value.action);
9062
9063 if (preq->source.kind == VUT_ACTION) {
9064 return preq->source.value.action == source->value.action ? ITF_YES
9065 : ITF_NO;
9066 }
9067
9068 return ITF_NOT_APPLICABLE;
9069}
9070
9071/**********************************************************************/
9075 const struct universal *source)
9076{
9078 || source->kind == VUT_DIPLREL_TILE
9079 || source->kind == VUT_DIPLREL_TILE_O
9080 || source->kind == VUT_DIPLREL_UNITANY
9081 || source->kind == VUT_DIPLREL_UNITANY_O),
9083
9084 if (preq->source.kind == source->kind) {
9085 if (preq->source.value.diplrel == source->value.diplrel) {
9086 /* The diplrel itself. */
9087 return ITF_YES;
9088 }
9089 if (preq->source.value.diplrel == DRO_FOREIGN
9090 && source->value.diplrel < DS_LAST) {
9091 /* All diplstate_type values are to foreigners. */
9092 return ITF_YES;
9093 }
9094 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
9095 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
9096 /* A real embassy is an embassy. */
9097 return ITF_YES;
9098 }
9099 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
9100 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
9101 /* A real embassy is an embassy. */
9102 return ITF_YES;
9103 }
9104 if (preq->source.value.diplrel < DS_LAST
9105 && source->value.diplrel < DS_LAST
9106 && preq->range == REQ_RANGE_LOCAL) {
9107 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
9108 ITF_YES);
9109 /* Can only have one diplstate_type to a specific player. */
9110 return ITF_NO;
9111 }
9112 /* Can't say this diplrel blocks the other diplrel. */
9113 return ITF_NOT_APPLICABLE;
9114 }
9115
9116 /* Not relevant. */
9117 return ITF_NOT_APPLICABLE;
9118}
9119
9120/**********************************************************************/
9124 const struct universal *source)
9125{
9126 switch (preq->source.kind) {
9127 case VUT_OTYPE:
9128 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
9129 : ITF_NO;
9130 default:
9131 /* Not found and not relevant. */
9132 return ITF_NOT_APPLICABLE;
9133 }
9134}
9135
9136/**********************************************************************/
9140 const struct universal *source)
9141{
9142 if (preq->range != REQ_RANGE_LOCAL) {
9143 return ITF_NOT_APPLICABLE;
9144 }
9145
9146 if (preq->source.kind == VUT_UNITSTATE) {
9147 switch (source->value.unit_state) {
9148 case USP_TRANSPORTED:
9149 case USP_TRANSPORTING:
9150 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
9151 case USP_LIVABLE_TILE:
9152 case USP_NATIVE_TILE:
9153 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
9154 * UTYF_COAST_STRICT. */
9155 case USP_HAS_HOME_CITY:
9156 case USP_NATIVE_EXTRA:
9158 if (source->value.unit_state == preq->source.value.unit_state) {
9159 /* The other unit states doesn't contradict */
9160 return ITF_YES;
9161 }
9162 break;
9163 case USP_COUNT:
9164 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
9166 }
9167 }
9168
9169 /* Not found and not relevant. */
9170 return ITF_NOT_APPLICABLE;
9171}
9172
9173/**********************************************************************/
9198
9199/**********************************************************************/
9207int requirement_kind_ereq(const int value,
9208 const enum req_range range,
9209 const bool present,
9210 const int max_value)
9211{
9212 /* The enumerators in each range starts with present for every possible
9213 * value followed by !present for every possible value. */
9214 const int pres_start = (present ? 0 : max_value);
9215
9216 /* The enumerators for every range follows all the positions of the
9217 * previous range(s). */
9218 const int range_start = ((max_value - 1) * 2) * range;
9219
9220 return range_start + pres_start + value;
9221}
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:5910
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:1280
Output_type_id output_type_by_identifier(const char *id)
Definition city.c:650
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:630
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
#define city_tile(_pcity_)
Definition city.h:565
static citizens city_size_get(const struct city *pcity)
Definition city.h:570
#define city_owner(_pcity_)
Definition city.h:564
static bool is_city_center(const struct city *pcity, const struct tile *ptile)
Definition city.h:870
#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:836
#define city_built_iterate_end
Definition city.h:842
static struct ai_type * self
Definition classicai.c:46
char * incite_cost
Definition comments.c:77
int counter_index(const struct counter *pcount)
Definition counters.c:176
const char * counter_name_translation(const struct counter *counter)
Definition counters.c:158
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:116
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:166
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:238
req_problem_type
Definition fc_types.h:514
@ RPT_POSSIBLE
Definition fc_types.h:515
#define MAX_LEN_NAME
Definition fc_types.h:68
@ VC_SPACERACE
Definition fc_types.h:966
@ O_LAST
Definition fc_types.h:103
signed short Continent_id
Definition fc_types.h:233
#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
void fc_mutex_allocate(fc_mutex *mutex)
Definition fcthread.c:144
void fc_mutex_init(fc_mutex *mutex)
Definition fcthread.c:128
void fc_mutex_release(fc_mutex *mutex)
Definition fcthread.c:152
fc_thread_id fc_thread_self(void)
Definition fcthread.c:112
bool register_at_thread_exit_callback(at_thread_exit_cb *cb)
Definition fcthread.c:32
bool fc_threads_equal(fc_thread_id thr1, fc_thread_id thr2)
Definition fcthread.c:120
void fc_mutex_destroy(fc_mutex *mutex)
Definition fcthread.c:136
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:1076
int map_signed_latitude(const struct tile *ptile)
Definition map.c:1701
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:1085
int get_island_surrounder(Continent_id id)
Definition map.c:851
int get_lake_surrounder(Continent_id id)
Definition map.c:884
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:507
#define MAP_MAX_LATITUDE
Definition map.h:611
#define adjc_iterate_end
Definition map.h:439
#define MAP_MAX_REAL_LATITUDE(_nmap)
Definition map.h:623
#define range_adjc_iterate_end
Definition map.h:510
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:397
#define cardinal_adjc_iterate_end
Definition map.h:465
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:434
#define is_whole_continent_known(cont)
Definition map.h:78
#define square_iterate_end
Definition map.h:400
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:461
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:407
#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:625
#define circle_iterate_end
Definition map.h:410
#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:1066
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:1016
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:484
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:472
const char * nation_group_rule_name(const struct nation_group *pgroup)
Definition nation.c:1071
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:443
bool nation_is_in_group(const struct nation_type *pnation, const struct nation_group *pgroup)
Definition nation.c:1088
const char * nation_group_name_translation(const struct nation_group *pgroup)
Definition nation.c:1080
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:999
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:945
#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:1316
bool player_has_state(const struct player *pplayer, enum plrstate_type state)
Definition player.c:1987
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Definition player.c:1812
int diplrel_by_rule_name(const char *value)
Definition player.c:1568
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1468
bool is_diplrel_to_other(const struct player *pplayer, int diplrel)
Definition player.c:1551
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1979
const char * diplrel_name_translation(int value)
Definition player.c:1614
bool is_diplrel_between(const struct player *player1, const struct player *player2, int diplrel)
Definition player.c:1504
int player_age(const struct player *pplayer)
Definition player.c:946
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1397
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:432
const char * diplrel_rule_name(int value)
Definition player.c:1602
#define players_iterate_end
Definition player.h:552
#define players_iterate(_pplayer)
Definition player.h:547
#define player_nation(_plr_)
Definition player.h:413
#define is_ai(plr)
Definition player.h:232
#define players_iterate_alive_end
Definition player.h:562
#define players_iterate_alive(_pplayer)
Definition player.h:557
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_tiledef_conn_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)
void requirements_free(void)
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 fc_tristate is_tiledef_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 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)
#define thr_req_data_list_iterate(trlist, ptrdata)
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)
void requirements_init(void)
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)
#define thr_req_data_list_iterate_end
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 fc_mutex trmutex
static struct thr_req_data_list * trdatas
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)
static void thr_exit_cb(void)
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
fc_thread_id thr_id
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:595
universals_u value
Definition fc_types.h:594
struct civ_map map
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:113
struct nation_style * style_by_number(int id)
Definition style.c:84
const char * style_name_translation(const struct nation_style *pstyle)
Definition style.c:95
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:104
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:110
bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag)
Definition tech.c:221
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:305
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:314
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:205
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:100
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:188
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:615
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:594
const char * terrain_class_name_translation(enum terrain_class tclass)
Definition terrain.c:664
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:240
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:157
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Definition terrain.c:676
bool is_terrain_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:330
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:249
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:585
bool is_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:461
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:148
bool is_terrain_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:441
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:351
#define T_UNKNOWN
Definition terrain.h:62
#define terrain_has_flag(terr, flag)
Definition terrain.h:177
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
const char * tiledef_rule_name(const struct tiledef *td)
Definition tiledef.c:104
int tiledef_number(const struct tiledef *td)
Definition tiledef.c:62
struct tiledef * tiledef_by_number(int id)
Definition tiledef.c:84
struct tiledef * tiledef_by_rule_name(const char *name)
Definition tiledef.c:113
bool tile_matches_tiledef(const struct tiledef *td, const struct tile *ptile)
Definition tiledef.c:150
bool is_tiledef_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct tiledef *ptd)
Definition tiledef.c:165
bool is_tiledef_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct tiledef *ptd)
Definition tiledef.c:181
const char * tiledef_name_translation(const struct tiledef *td)
Definition tiledef.c:95
#define tiledef_index(_td_)
Definition tiledef.h:41
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:536
struct tiledef * tiledef
Definition fc_types.h:538
int region_tiles
Definition fc_types.h:584
struct nation_style * style
Definition fc_types.h:541
enum ai_level ai_level
Definition fc_types.h:545
struct specialist * specialist
Definition fc_types.h:533
enum impr_genus_id impr_genus
Definition fc_types.h:569
enum citytile_type citytile
Definition fc_types.h:546
struct nation_group * nationgroup
Definition fc_types.h:540
struct extra_type * extra
Definition fc_types.h:537
enum wrap_flag wrap_property
Definition fc_types.h:587
enum plrstate_type plrstate
Definition fc_types.h:548
enum tilerel_type tilerel
Definition fc_types.h:549
struct nation_type * nation
Definition fc_types.h:530
int terrainclass
Definition fc_types.h:556
int unitclassflag
Definition fc_types.h:559
struct government * govern
Definition fc_types.h:528
struct nation_type * origowner
Definition fc_types.h:532
enum impr_flag_id impr_flag
Definition fc_types.h:570
int terrainalter
Definition fc_types.h:557
enum citystatus_type citystatus
Definition fc_types.h:547
int minforeignpct
Definition fc_types.h:552
const struct impr_type * building
Definition fc_types.h:529
int max_tile_total_units
Definition fc_types.h:573
int max_tile_top_units
Definition fc_types.h:574
struct achievement * achievement
Definition fc_types.h:539
ssetv ssetval
Definition fc_types.h:588
struct advance * advance
Definition fc_types.h:526
enum unit_activity activity
Definition fc_types.h:568
struct goods_type * good
Definition fc_types.h:543
struct terrain * terrain
Definition fc_types.h:534
int terrainflag
Definition fc_types.h:561
enum ustate_prop unit_state
Definition fc_types.h:567
Output_type_id outputtype
Definition fc_types.h:555
int distance_sq
Definition fc_types.h:583
enum topo_flag topo_property
Definition fc_types.h:586
struct counter * counter
Definition fc_types.h:527
int min_hit_points
Definition fc_types.h:576
struct unit_class * uclass
Definition fc_types.h:535
struct nation_type * nationality
Definition fc_types.h:531
struct action * action
Definition fc_types.h:542
int future_techs
Definition fc_types.h:580
enum plr_flag_id plr_flag
Definition fc_types.h:571
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