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 if (ptdef->known && context->player == nullptr) {
3298 return TRI_MAYBE;
3299 }
3300
3301 switch (req->range) {
3302 case REQ_RANGE_TILE:
3303 /* The requirement is filled if the tile has tiledef of requested type. */
3304 if (!context->tile) {
3305 return TRI_MAYBE;
3306 }
3308 context->player));
3310 if (!context->tile) {
3311 return TRI_MAYBE;
3312 }
3314 context->player)
3316 context->player));
3317 case REQ_RANGE_ADJACENT:
3318 if (!context->tile) {
3319 return TRI_MAYBE;
3320 }
3322 context->player)
3324 context->player));
3325 case REQ_RANGE_CITY:
3326 if (!context->city) {
3327 return TRI_MAYBE;
3328 }
3330 city_tile(context->city), ptile) {
3331 if (tile_matches_tiledef(ptdef, ptile, context->player)) {
3332 return TRI_YES;
3333 }
3335
3336 return TRI_NO;
3337
3339 if (!context->city) {
3340 return TRI_MAYBE;
3341 }
3343 city_tile(context->city), ptile) {
3344 if (tile_matches_tiledef(ptdef, ptile, context->player)) {
3345 return TRI_YES;
3346 }
3348
3349 ret = TRI_NO;
3351 if (trade_partner == nullptr) {
3352 ret = TRI_MAYBE;
3353 } else {
3355 city_tile(trade_partner), ptile) {
3356 if (tile_matches_tiledef(ptdef, ptile, context->player)) {
3357 return TRI_YES;
3358 }
3360 }
3362
3363 return ret;
3364
3365 case REQ_RANGE_LOCAL:
3367 case REQ_RANGE_PLAYER:
3368 case REQ_RANGE_TEAM:
3369 case REQ_RANGE_ALLIANCE:
3370 case REQ_RANGE_WORLD:
3371 case REQ_RANGE_COUNT:
3372 break;
3373 }
3374
3375 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3376
3377 return TRI_MAYBE;
3378}
3379
3380/**********************************************************************/
3388static enum fc_tristate
3390 const struct req_context *context,
3391 const struct req_context *other_context,
3392 const struct requirement *req)
3393{
3395
3396 if (req->range == REQ_RANGE_CITY) {
3397 if (context->city == nullptr
3398 || context->city->aarea == nullptr) {
3399 return TRI_MAYBE;
3400 }
3401
3402 if (BV_ISSET(context->city->aarea->tiledefs,
3404 return TRI_YES;
3405 }
3406
3407 return TRI_NO;
3408 }
3409
3410 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3411
3412 return TRI_MAYBE;
3413}
3414
3415/**********************************************************************/
3423static enum fc_tristate
3425 const struct req_context *context,
3426 const struct req_context *other_context,
3427 const struct requirement *req)
3428{
3429 const struct goods_type *pgood;
3430
3432
3433 pgood = req->source.value.good;
3434
3435 switch (req->range) {
3436 case REQ_RANGE_LOCAL:
3437 case REQ_RANGE_CITY:
3438 /* The requirement is filled if the city imports good of requested type. */
3439 if (!context->city) {
3440 return TRI_MAYBE;
3441 }
3445 nullptr)));
3446 case REQ_RANGE_TILE:
3448 case REQ_RANGE_ADJACENT:
3451 case REQ_RANGE_PLAYER:
3452 case REQ_RANGE_TEAM:
3453 case REQ_RANGE_ALLIANCE:
3454 case REQ_RANGE_WORLD:
3455 case REQ_RANGE_COUNT:
3456 break;
3457 }
3458
3459 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3460
3461 return TRI_MAYBE;
3462}
3463
3464/**********************************************************************/
3472static enum fc_tristate
3474 const struct req_context *context,
3475 const struct req_context *other_context,
3476 const struct requirement *req)
3477{
3479
3480 if (context->action) {
3481 return BOOL_TO_TRISTATE(action_number(context->action)
3482 == action_number(req->source.value.action));
3483 }
3484
3485 if (context->unit != nullptr && context->unit->action != ACTION_NONE) {
3486 log_normal("Unit action %s", action_id_rule_name(context->unit->action));
3487 return BOOL_TO_TRISTATE(context->unit->action
3488 == action_number(req->source.value.action));
3489 }
3490
3491 return TRI_NO;
3492}
3493
3494/**********************************************************************/
3502static enum fc_tristate
3504 const struct req_context *context,
3505 const struct req_context *other_context,
3506 const struct requirement *req)
3507{
3509
3510 return BOOL_TO_TRISTATE(context->output
3511 && context->output->index
3512 == req->source.value.outputtype);
3513}
3514
3515/**********************************************************************/
3523static enum fc_tristate
3525 const struct req_context *context,
3526 const struct req_context *other_context,
3527 const struct requirement *req)
3528{
3530
3531 return BOOL_TO_TRISTATE(context->specialist
3532 && context->specialist
3533 == req->source.value.specialist);
3534}
3535
3536/**********************************************************************/
3544static enum fc_tristate
3546 const struct req_context *context,
3547 const struct req_context *other_context,
3548 const struct requirement *req)
3549{
3550 const struct terrain *pterrain;
3551
3553
3554 pterrain = req->source.value.terrain;
3555
3556 switch (req->range) {
3557 case REQ_RANGE_TILE:
3558 /* The requirement is filled if the tile has the terrain. */
3559 if (!context->tile) {
3560 return TRI_MAYBE;
3561 }
3562 return pterrain && tile_terrain(context->tile) == pterrain;
3564 if (!context->tile) {
3565 return TRI_MAYBE;
3566 }
3567 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
3568 case REQ_RANGE_ADJACENT:
3569 if (!context->tile) {
3570 return TRI_MAYBE;
3571 }
3572 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
3573 case REQ_RANGE_CITY:
3574 if (!context->city) {
3575 return TRI_MAYBE;
3576 }
3577 if (pterrain != nullptr) {
3579 city_tile(context->city), ptile) {
3580 if (tile_terrain(ptile) == pterrain) {
3581 return TRI_YES;
3582 }
3584 }
3585 return TRI_NO;
3587 if (!context->city) {
3588 return TRI_MAYBE;
3589 }
3590 if (pterrain != nullptr) {
3591 enum fc_tristate ret;
3592
3594 city_tile(context->city), ptile) {
3595 if (tile_terrain(ptile) == pterrain) {
3596 return TRI_YES;
3597 }
3599
3600 ret = TRI_NO;
3602 if (trade_partner == nullptr) {
3603 ret = TRI_MAYBE;
3604 } else {
3606 city_tile(trade_partner), ptile) {
3607 if (tile_terrain(ptile) == pterrain) {
3608 return TRI_YES;
3609 }
3611 }
3613
3614 return ret;
3615 }
3616
3617 return TRI_MAYBE;
3619 case REQ_RANGE_PLAYER:
3620 case REQ_RANGE_TEAM:
3621 case REQ_RANGE_ALLIANCE:
3622 case REQ_RANGE_WORLD:
3623 case REQ_RANGE_LOCAL:
3624 case REQ_RANGE_COUNT:
3625 break;
3626 }
3627
3628 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3629
3630 return TRI_MAYBE;
3631}
3632
3633/**********************************************************************/
3641static enum fc_tristate
3643 const struct req_context *context,
3644 const struct req_context *other_context,
3645 const struct requirement *req)
3646{
3647 enum terrain_class pclass;
3648 enum fc_tristate ret;
3649
3651
3653
3654 switch (req->range) {
3655 case REQ_RANGE_TILE:
3656 /* The requirement is filled if the tile has the terrain of correct class. */
3657 if (!context->tile) {
3658 return TRI_MAYBE;
3659 }
3662 if (!context->tile) {
3663 return TRI_MAYBE;
3664 }
3667 case REQ_RANGE_ADJACENT:
3668 if (!context->tile) {
3669 return TRI_MAYBE;
3670 }
3673 case REQ_RANGE_CITY:
3674 if (!context->city) {
3675 return TRI_MAYBE;
3676 }
3678 city_tile(context->city), ptile) {
3679 const struct terrain *pterrain = tile_terrain(ptile);
3680
3681 if (pterrain != T_UNKNOWN
3682 && terrain_type_terrain_class(pterrain) == pclass) {
3683 return TRI_YES;
3684 }
3686
3687 return TRI_NO;
3689 if (!context->city) {
3690 return TRI_MAYBE;
3691 }
3693 city_tile(context->city), ptile) {
3694 const struct terrain *pterrain = tile_terrain(ptile);
3695
3696 if (pterrain != T_UNKNOWN
3697 && terrain_type_terrain_class(pterrain) == pclass) {
3698 return TRI_YES;
3699 }
3701
3702 ret = TRI_NO;
3704 if (trade_partner == nullptr) {
3705 ret = TRI_MAYBE;
3706 } else {
3708 city_tile(trade_partner), ptile) {
3709 const struct terrain *pterrain = tile_terrain(ptile);
3710
3711 if (pterrain != T_UNKNOWN
3712 && terrain_type_terrain_class(pterrain) == pclass) {
3713 return TRI_YES;
3714 }
3716 }
3718
3719 return ret;
3721 case REQ_RANGE_PLAYER:
3722 case REQ_RANGE_TEAM:
3723 case REQ_RANGE_ALLIANCE:
3724 case REQ_RANGE_WORLD:
3725 case REQ_RANGE_LOCAL:
3726 case REQ_RANGE_COUNT:
3727 break;
3728 }
3729
3730 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3731
3732 return TRI_MAYBE;
3733}
3734
3735/**********************************************************************/
3743static enum fc_tristate
3745 const struct req_context *context,
3746 const struct req_context *other_context,
3747 const struct requirement *req)
3748{
3750 enum fc_tristate ret;
3751
3753
3755
3756 switch (req->range) {
3757 case REQ_RANGE_TILE:
3758 /* The requirement is fulfilled if the tile has a terrain with
3759 * correct flag. */
3760 if (!context->tile) {
3761 return TRI_MAYBE;
3762 }
3764 terrflag));
3766 if (!context->tile) {
3767 return TRI_MAYBE;
3768 }
3770 terrflag)
3772 terrflag));
3773 case REQ_RANGE_ADJACENT:
3774 if (!context->tile) {
3775 return TRI_MAYBE;
3776 }
3778 terrflag)
3780 terrflag));
3781 case REQ_RANGE_CITY:
3782 if (!context->city) {
3783 return TRI_MAYBE;
3784 }
3786 city_tile(context->city), ptile) {
3787 const struct terrain *pterrain = tile_terrain(ptile);
3788
3789 if (pterrain != T_UNKNOWN
3790 && terrain_has_flag(pterrain, terrflag)) {
3791 return TRI_YES;
3792 }
3794
3795 return TRI_NO;
3797 if (!context->city) {
3798 return TRI_MAYBE;
3799 }
3801 city_tile(context->city), ptile) {
3802 const struct terrain *pterrain = tile_terrain(ptile);
3803
3804 if (pterrain != T_UNKNOWN
3805 && terrain_has_flag(pterrain, terrflag)) {
3806 return TRI_YES;
3807 }
3809
3810 ret = TRI_NO;
3812 if (trade_partner == nullptr) {
3813 ret = TRI_MAYBE;
3814 } else {
3816 city_tile(trade_partner), ptile) {
3817 const struct terrain *pterrain = tile_terrain(ptile);
3818
3819 if (pterrain != T_UNKNOWN
3820 && terrain_has_flag(pterrain, terrflag)) {
3821 return TRI_YES;
3822 }
3824 }
3826
3827 return ret;
3829 case REQ_RANGE_PLAYER:
3830 case REQ_RANGE_TEAM:
3831 case REQ_RANGE_ALLIANCE:
3832 case REQ_RANGE_WORLD:
3833 case REQ_RANGE_LOCAL:
3834 case REQ_RANGE_COUNT:
3835 break;
3836 }
3837
3838 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3839
3840 return TRI_MAYBE;
3841}
3842
3843/**********************************************************************/
3851static enum fc_tristate
3853 const struct req_context *context,
3854 const struct req_context *other_context,
3855 const struct requirement *req)
3856{
3857 enum road_flag_id roadflag;
3858 enum fc_tristate ret;
3859
3861
3862 roadflag = req->source.value.roadflag;
3863
3864 switch (req->range) {
3865 case REQ_RANGE_LOCAL:
3866 {
3867 if (!context->extra) {
3868 return TRI_MAYBE;
3869 }
3870 struct road_type *r = extra_road_get(context->extra);
3871
3872 return BOOL_TO_TRISTATE(
3873 r && road_has_flag(r, roadflag)
3874 );
3875 }
3876 case REQ_RANGE_TILE:
3877 /* The requirement is filled if the tile has a road with correct flag. */
3878 if (!context->tile) {
3879 return TRI_MAYBE;
3880 }
3881 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3883 if (!context->tile) {
3884 return TRI_MAYBE;
3885 }
3886 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3888 roadflag));
3889 case REQ_RANGE_ADJACENT:
3890 if (!context->tile) {
3891 return TRI_MAYBE;
3892 }
3893 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3895 roadflag));
3896 case REQ_RANGE_CITY:
3897 if (!context->city) {
3898 return TRI_MAYBE;
3899 }
3901 city_tile(context->city), ptile) {
3902 if (tile_has_road_flag(ptile, roadflag)) {
3903 return TRI_YES;
3904 }
3906
3907 return TRI_NO;
3909 if (!context->city) {
3910 return TRI_MAYBE;
3911 }
3913 city_tile(context->city), ptile) {
3914 if (tile_has_road_flag(ptile, roadflag)) {
3915 return TRI_YES;
3916 }
3918
3919 ret = TRI_NO;
3921 if (trade_partner == nullptr) {
3922 ret = TRI_MAYBE;
3923 } else {
3925 city_tile(trade_partner), ptile) {
3926 if (tile_has_road_flag(ptile, roadflag)) {
3927 return TRI_YES;
3928 }
3930 }
3932
3933 return ret;
3935 case REQ_RANGE_PLAYER:
3936 case REQ_RANGE_TEAM:
3937 case REQ_RANGE_ALLIANCE:
3938 case REQ_RANGE_WORLD:
3939 case REQ_RANGE_COUNT:
3940 break;
3941 }
3942
3943 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3944
3945 return TRI_MAYBE;
3946}
3947
3948/**********************************************************************/
3956static enum fc_tristate
3958 const struct req_context *context,
3959 const struct req_context *other_context,
3960 const struct requirement *req)
3961{
3962 enum extra_flag_id extraflag;
3963 enum fc_tristate ret;
3964
3966
3967 extraflag = req->source.value.extraflag;
3968
3969 switch (req->range) {
3970 case REQ_RANGE_LOCAL:
3971 if (!context->extra) {
3972 return TRI_MAYBE;
3973 }
3974 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3975 case REQ_RANGE_TILE:
3976 /* The requirement is filled if the tile has an extra with correct flag. */
3977 if (!context->tile) {
3978 return TRI_MAYBE;
3979 }
3980 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3982 if (!context->tile) {
3983 return TRI_MAYBE;
3984 }
3985 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3986 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3987 case REQ_RANGE_ADJACENT:
3988 if (!context->tile) {
3989 return TRI_MAYBE;
3990 }
3991 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3992 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3993 case REQ_RANGE_CITY:
3994 if (!context->city) {
3995 return TRI_MAYBE;
3996 }
3998 city_tile(context->city), ptile) {
3999 if (tile_has_extra_flag(ptile, extraflag)) {
4000 return TRI_YES;
4001 }
4003
4004 return TRI_NO;
4006 if (!context->city) {
4007 return TRI_MAYBE;
4008 }
4010 city_tile(context->city), ptile) {
4011 if (tile_has_extra_flag(ptile, extraflag)) {
4012 return TRI_YES;
4013 }
4015
4016 ret = TRI_NO;
4018 if (trade_partner == nullptr) {
4019 ret = TRI_MAYBE;
4020 } else {
4022 city_tile(trade_partner), ptile) {
4023 if (tile_has_extra_flag(ptile, extraflag)) {
4024 return TRI_YES;
4025 }
4027 }
4029
4030 return ret;
4032 case REQ_RANGE_PLAYER:
4033 case REQ_RANGE_TEAM:
4034 case REQ_RANGE_ALLIANCE:
4035 case REQ_RANGE_WORLD:
4036 case REQ_RANGE_COUNT:
4037 break;
4038 }
4039
4040 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4041
4042 return TRI_MAYBE;
4043}
4044
4045/**********************************************************************/
4053static enum fc_tristate
4055 const struct req_context *context,
4056 const struct req_context *other_context,
4057 const struct requirement *req)
4058{
4060
4062
4064
4065 if (!context->tile) {
4066 return TRI_MAYBE;
4067 }
4068
4069 switch (req->range) {
4070 case REQ_RANGE_TILE:
4074 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
4075 case REQ_RANGE_CITY:
4078 case REQ_RANGE_PLAYER:
4079 case REQ_RANGE_TEAM:
4080 case REQ_RANGE_ALLIANCE:
4081 case REQ_RANGE_WORLD:
4082 case REQ_RANGE_LOCAL:
4083 case REQ_RANGE_COUNT:
4084 break;
4085 }
4086
4087 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4088
4089 return TRI_MAYBE;
4090}
4091
4092/**********************************************************************/
4100static enum fc_tristate
4102 const struct req_context *context,
4103 const struct req_context *other_context,
4104 const struct requirement *req)
4105{
4107
4108 if (context->player == nullptr) {
4109 return TRI_MAYBE;
4110 } else {
4112 == req->source.value.govern);
4113 }
4114}
4115
4116/**********************************************************************/
4124static enum fc_tristate
4126 const struct req_context *context,
4127 const struct req_context *other_context,
4128 const struct requirement *req)
4129{
4131
4132 if (context->player == nullptr) {
4133 return TRI_MAYBE;
4134 } else {
4136 req->source.value.govflag));
4137 }
4138}
4139
4140/**********************************************************************/
4148static enum fc_tristate
4150 const struct req_context *context,
4151 const struct req_context *other_context,
4152 const struct requirement *req)
4153{
4155
4156 if (context->player == nullptr) {
4157 return TRI_MAYBE;
4158 } else {
4159 return BOOL_TO_TRISTATE(context->player->style
4160 == req->source.value.style);
4161 }
4162}
4163
4164/**********************************************************************/
4172static enum fc_tristate
4174 const struct req_context *context,
4175 const struct req_context *other_context,
4176 const struct requirement *req)
4177{
4179
4180 switch (req->range) {
4181 case REQ_RANGE_WORLD:
4182 /* "None" does not count */
4183 return ((game.info.global_advance_count - 1)
4184 >= req->source.value.min_techs);
4185 case REQ_RANGE_PLAYER:
4186 if (context->player == nullptr) {
4187 return TRI_MAYBE;
4188 } else {
4189 /* "None" does not count */
4190 return BOOL_TO_TRISTATE(
4191 (research_get(context->player)->techs_researched - 1)
4192 >= req->source.value.min_techs
4193 );
4194 }
4195 default:
4196 return TRI_MAYBE;
4197 }
4198}
4199
4200/**********************************************************************/
4208static enum fc_tristate
4210 const struct req_context *context,
4211 const struct req_context *other_context,
4212 const struct requirement *req)
4213{
4215
4216 switch (req->range) {
4217 case REQ_RANGE_WORLD:
4219 if (research_get(plr)->future_tech
4220 >= req->source.value.future_techs) {
4221 return TRI_YES;
4222 }
4224
4225 return TRI_NO;
4226 case REQ_RANGE_PLAYER:
4227 if (context->player == nullptr) {
4228 return TRI_MAYBE;
4229 } else {
4231 >= req->source.value.future_techs);
4232 }
4233 default:
4234 return TRI_MAYBE;
4235 }
4236}
4237
4238/**********************************************************************/
4246static enum fc_tristate
4248 const struct req_context *context,
4249 const struct req_context *other_context,
4250 const struct requirement *req)
4251{
4253
4254 switch (req->range) {
4255 case REQ_RANGE_PLAYER:
4256 if (context->player == nullptr) {
4257 return TRI_MAYBE;
4258 } else {
4259 /* "None" does not count */
4260 return BOOL_TO_TRISTATE(
4261 city_list_size(context->player->cities)
4262 >= req->source.value.min_cities
4263 );
4264 }
4265 default:
4266 return TRI_MAYBE;
4267 }
4268}
4269
4270/**********************************************************************/
4278static enum fc_tristate
4280 const struct req_context *context,
4281 const struct req_context *other_context,
4282 const struct requirement *req)
4283{
4285
4286 if (context->player == nullptr) {
4287 return TRI_MAYBE;
4288 } else {
4289 return BOOL_TO_TRISTATE(is_ai(context->player)
4290 && context->player->ai_common.skill_level
4291 == req->source.value.ai_level);
4292 }
4293}
4294
4295/**********************************************************************/
4303static enum fc_tristate
4305 const struct req_context *context,
4306 const struct req_context *other_context,
4307 const struct requirement *req)
4308{
4309 const struct nation_type *nation;
4310
4312
4313 nation = req->source.value.nation;
4314
4315 switch (req->range) {
4316 case REQ_RANGE_PLAYER:
4317 if (context->player == nullptr) {
4318 return TRI_MAYBE;
4319 }
4320 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
4321 case REQ_RANGE_TEAM:
4322 case REQ_RANGE_ALLIANCE:
4323 if (context->player == nullptr) {
4324 return TRI_MAYBE;
4325 }
4326 players_iterate_alive(plr2) {
4327 if (players_in_same_range(context->player, plr2, req->range)) {
4328 if (nation_of_player(plr2) == nation) {
4329 return TRI_YES;
4330 }
4331 }
4333 return TRI_NO;
4334 case REQ_RANGE_WORLD:
4335 /* NB: if a player is ever removed outright from the game
4336 * (e.g. via /remove), rather than just dying, this 'survives'
4337 * requirement will stop being true for their nation.
4338 * create_command_newcomer() can also cause this to happen. */
4339 return BOOL_TO_TRISTATE(nation->player != nullptr
4340 && (req->survives || nation->player->is_alive));
4341 case REQ_RANGE_LOCAL:
4342 case REQ_RANGE_TILE:
4344 case REQ_RANGE_ADJACENT:
4345 case REQ_RANGE_CITY:
4348 case REQ_RANGE_COUNT:
4349 break;
4350 }
4351
4352 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4353
4354 return TRI_MAYBE;
4355}
4356
4357/**********************************************************************/
4365static enum fc_tristate
4367 const struct req_context *context,
4368 const struct req_context *other_context,
4369 const struct requirement *req)
4370{
4371 const struct nation_group *ngroup;
4372
4374
4376
4377 switch (req->range) {
4378 case REQ_RANGE_PLAYER:
4379 if (context->player == nullptr) {
4380 return TRI_MAYBE;
4381 }
4383 nation_of_player(context->player), ngroup));
4384 case REQ_RANGE_TEAM:
4385 case REQ_RANGE_ALLIANCE:
4386 case REQ_RANGE_WORLD:
4387 if (context->player == nullptr) {
4388 return TRI_MAYBE;
4389 }
4390 players_iterate_alive(plr2) {
4391 if (players_in_same_range(context->player, plr2, req->range)) {
4393 return TRI_YES;
4394 }
4395 }
4397 return TRI_NO;
4398 case REQ_RANGE_LOCAL:
4399 case REQ_RANGE_TILE:
4401 case REQ_RANGE_ADJACENT:
4402 case REQ_RANGE_CITY:
4405 case REQ_RANGE_COUNT:
4406 break;
4407 }
4408
4409 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4410
4411 return TRI_MAYBE;
4412}
4413
4414/**********************************************************************/
4422static enum fc_tristate
4424 const struct req_context *context,
4425 const struct req_context *other_context,
4426 const struct requirement *req)
4427{
4428 const struct nation_type *nationality;
4429 enum fc_tristate ret;
4430
4432
4433 nationality = req->source.value.nationality;
4434
4435 switch (req->range) {
4436 case REQ_RANGE_CITY:
4437 if (context->city == nullptr) {
4438 return TRI_MAYBE;
4439 }
4440 citizens_iterate(context->city, slot, count) {
4441 if (player_slot_get_player(slot)->nation == nationality) {
4442 return TRI_YES;
4443 }
4445
4446 return TRI_NO;
4448 if (context->city == nullptr) {
4449 return TRI_MAYBE;
4450 }
4451 citizens_iterate(context->city, slot, count) {
4452 if (player_slot_get_player(slot)->nation == nationality) {
4453 return TRI_YES;
4454 }
4456
4457 ret = TRI_NO;
4459 if (trade_partner == nullptr) {
4460 ret = TRI_MAYBE;
4461 } else {
4462 citizens_iterate(trade_partner, slot, count) {
4463 if (player_slot_get_player(slot)->nation == nationality) {
4464 return TRI_YES;
4465 }
4467 }
4469
4470 return ret;
4471 case REQ_RANGE_PLAYER:
4472 case REQ_RANGE_TEAM:
4473 case REQ_RANGE_ALLIANCE:
4474 case REQ_RANGE_WORLD:
4475 case REQ_RANGE_LOCAL:
4476 case REQ_RANGE_TILE:
4478 case REQ_RANGE_ADJACENT:
4480 case REQ_RANGE_COUNT:
4481 break;
4482 }
4483
4484 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4485
4486 return TRI_MAYBE;
4487}
4488
4489/**********************************************************************/
4497static enum fc_tristate
4499 const struct req_context *context,
4500 const struct req_context *other_context,
4501 const struct requirement *req)
4502{
4503 const struct nation_type *nation;
4504
4506
4507 nation = req->source.value.origowner;
4508
4509 switch (req->range) {
4510 case REQ_RANGE_CITY:
4511 if (context->city == nullptr || context->city->original == nullptr) {
4512 return TRI_MAYBE;
4513 }
4514 if (player_nation(context->city->original) == nation) {
4515 return TRI_YES;
4516 }
4517
4518 return TRI_NO;
4520 case REQ_RANGE_PLAYER:
4521 case REQ_RANGE_TEAM:
4522 case REQ_RANGE_ALLIANCE:
4523 case REQ_RANGE_WORLD:
4524 case REQ_RANGE_LOCAL:
4525 case REQ_RANGE_TILE:
4527 case REQ_RANGE_ADJACENT:
4529 case REQ_RANGE_COUNT:
4530 break;
4531 }
4532
4533 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4534
4535 return TRI_MAYBE;
4536}
4537
4538/**********************************************************************/
4542 const struct player *other_player,
4543 enum req_range range,
4544 int diplrel)
4545{
4546 switch (range) {
4547 case REQ_RANGE_PLAYER:
4548 if (target_player == nullptr) {
4549 return TRI_MAYBE;
4550 }
4552 case REQ_RANGE_TEAM:
4553 case REQ_RANGE_ALLIANCE:
4554 case REQ_RANGE_WORLD:
4555 if (target_player == nullptr) {
4556 return TRI_MAYBE;
4557 }
4558 players_iterate_alive(plr2) {
4560 if (is_diplrel_to_other(plr2, diplrel)) {
4561 return TRI_YES;
4562 }
4563 }
4565 return TRI_NO;
4566 case REQ_RANGE_LOCAL:
4567 if (target_player == nullptr || other_player == nullptr) {
4568 return TRI_MAYBE;
4569 }
4570 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
4571 case REQ_RANGE_TILE:
4573 case REQ_RANGE_ADJACENT:
4574 case REQ_RANGE_CITY:
4577 case REQ_RANGE_COUNT:
4578 break;
4579 }
4580
4581 fc_assert_msg(FALSE, "Invalid range %d.", range);
4582
4583 return TRI_MAYBE;
4584}
4585
4586/**********************************************************************/
4594static enum fc_tristate
4596 const struct req_context *context,
4597 const struct req_context *other_context,
4598 const struct requirement *req)
4599{
4601
4602 return is_diplrel_in_range(context->player, other_context->player,
4603 req->range, req->source.value.diplrel);
4604}
4605
4606/**********************************************************************/
4614static enum fc_tristate
4616 const struct req_context *context,
4617 const struct req_context *other_context,
4618 const struct requirement *req)
4619{
4621
4622 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4623 : nullptr,
4624 context->player,
4625 req->range,
4626 req->source.value.diplrel);
4627}
4628
4629/**********************************************************************/
4638static enum fc_tristate
4640 const struct req_context *context,
4641 const struct req_context *other_context,
4642 const struct requirement *req)
4643{
4645
4646 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4647 : nullptr,
4648 other_context->player,
4649 req->range,
4650 req->source.value.diplrel);
4651}
4652
4653/**********************************************************************/
4656static enum fc_tristate
4658 const struct player *other_player,
4659 enum req_range range,
4660 int diplrel)
4661{
4662 enum fc_tristate out = TRI_NO;
4663
4664 if (target_tile == nullptr) {
4665 return TRI_MAYBE;
4666 }
4667
4670 unit_owner(target_unit), other_player, range, diplrel);
4671
4674
4675 return out;
4676}
4677
4678/**********************************************************************/
4687static enum fc_tristate
4689 const struct req_context *context,
4690 const struct req_context *other_context,
4691 const struct requirement *req)
4692{
4694
4695 return is_diplrel_unitany_in_range(context->tile, context->player,
4696 req->range,
4697 req->source.value.diplrel);
4698}
4699
4700/**********************************************************************/
4709static enum fc_tristate
4711 const struct req_context *context,
4712 const struct req_context *other_context,
4713 const struct requirement *req)
4714{
4716
4718 req->range,
4719 req->source.value.diplrel);
4720}
4721
4722/**********************************************************************/
4730static enum fc_tristate
4732 const struct req_context *context,
4733 const struct req_context *other_context,
4734 const struct requirement *req)
4735{
4736 const struct unit_type *punittype;
4737
4739
4740 punittype = req->source.value.utype;
4741
4742 switch (req->range) {
4743 case REQ_RANGE_LOCAL:
4744 if (!context->unittype) {
4745 return TRI_MAYBE;
4746 }
4747 return BOOL_TO_TRISTATE(context->unittype == punittype);
4748 case REQ_RANGE_TILE:
4750 case REQ_RANGE_ADJACENT:
4751 if (context->tile == nullptr) {
4752 return TRI_MAYBE;
4753 }
4754
4755 unit_list_iterate(context->tile->units, punit) {
4756 if (punit->utype == punittype) {
4757 return TRI_YES;
4758 }
4760
4761 if (req->range == REQ_RANGE_TILE) {
4762 return TRI_NO;
4763 }
4764
4765 if (req->range == REQ_RANGE_CADJACENT) {
4768 if (punit->utype == punittype) {
4769 return TRI_YES;
4770 }
4773 } else {
4775
4778 if (punit->utype == punittype) {
4779 return TRI_YES;
4780 }
4783 }
4784
4785 return TRI_NO;
4786
4787 case REQ_RANGE_CITY:
4790 case REQ_RANGE_PLAYER:
4791 case REQ_RANGE_TEAM:
4792 case REQ_RANGE_ALLIANCE:
4793 case REQ_RANGE_WORLD:
4794 case REQ_RANGE_COUNT:
4796 break;
4797 }
4798
4799 return TRI_NO;
4800}
4801
4802/**********************************************************************/
4810static enum fc_tristate
4812 const struct req_context *context,
4813 const struct req_context *other_context,
4814 const struct requirement *req)
4815{
4816 enum unit_type_flag_id unitflag;
4817
4819
4820 unitflag = req->source.value.unitflag;
4821
4822 switch (req->range) {
4823 case REQ_RANGE_LOCAL:
4824 if (!context->unittype) {
4825 return TRI_MAYBE;
4826 }
4827 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4828 case REQ_RANGE_TILE:
4830 case REQ_RANGE_ADJACENT:
4831 if (context->tile == nullptr) {
4832 return TRI_MAYBE;
4833 }
4834
4835 unit_list_iterate(context->tile->units, punit) {
4836 if (unit_has_type_flag(punit, unitflag)) {
4837 return TRI_YES;
4838 }
4840
4841 if (req->range == REQ_RANGE_TILE) {
4842 return TRI_NO;
4843 }
4844
4845 if (req->range == REQ_RANGE_CADJACENT) {
4848 if (unit_has_type_flag(punit, unitflag)) {
4849 return TRI_YES;
4850 }
4853 } else {
4855
4858 if (unit_has_type_flag(punit, unitflag)) {
4859 return TRI_YES;
4860 }
4863 }
4864
4865 return TRI_NO;
4866
4867 case REQ_RANGE_CITY:
4870 case REQ_RANGE_PLAYER:
4871 case REQ_RANGE_TEAM:
4872 case REQ_RANGE_ALLIANCE:
4873 case REQ_RANGE_WORLD:
4874 case REQ_RANGE_COUNT:
4876 break;
4877 }
4878
4879 return TRI_NO;
4880}
4881
4882/**********************************************************************/
4890static enum fc_tristate
4892 const struct req_context *context,
4893 const struct req_context *other_context,
4894 const struct requirement *req)
4895{
4896 const struct unit_class *pclass;
4897
4899
4900 pclass = req->source.value.uclass;
4901
4902 switch (req->range) {
4903 case REQ_RANGE_LOCAL:
4904 if (!context->unittype) {
4905 return TRI_MAYBE;
4906 }
4907 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4908 case REQ_RANGE_TILE:
4910 case REQ_RANGE_ADJACENT:
4911 if (context->tile == nullptr) {
4912 return TRI_MAYBE;
4913 }
4914
4915 unit_list_iterate(context->tile->units, punit) {
4916 if (unit_class_get(punit) == pclass) {
4917 return TRI_YES;
4918 }
4920
4921 if (req->range == REQ_RANGE_TILE) {
4922 return TRI_NO;
4923 }
4924
4925 if (req->range == REQ_RANGE_CADJACENT) {
4928 if (unit_class_get(punit) == pclass) {
4929 return TRI_YES;
4930 }
4933 } else {
4935
4938 if (unit_class_get(punit) == pclass) {
4939 return TRI_YES;
4940 }
4943 }
4944
4945 return TRI_NO;
4946
4947 case REQ_RANGE_CITY:
4950 case REQ_RANGE_PLAYER:
4951 case REQ_RANGE_TEAM:
4952 case REQ_RANGE_ALLIANCE:
4953 case REQ_RANGE_WORLD:
4954 case REQ_RANGE_COUNT:
4956 break;
4957 }
4958
4959 return TRI_NO;
4960}
4961
4962/**********************************************************************/
4970static enum fc_tristate
4972 const struct req_context *context,
4973 const struct req_context *other_context,
4974 const struct requirement *req)
4975{
4977
4979
4981
4982 switch (req->range) {
4983 case REQ_RANGE_LOCAL:
4984 if (!context->unittype) {
4985 return TRI_MAYBE;
4986 }
4988 case REQ_RANGE_TILE:
4990 case REQ_RANGE_ADJACENT:
4991 if (context->tile == nullptr) {
4992 return TRI_MAYBE;
4993 }
4994
4995 unit_list_iterate(context->tile->units, punit) {
4997 return TRI_YES;
4998 }
5000
5001 if (req->range == REQ_RANGE_TILE) {
5002 return TRI_NO;
5003 }
5004
5005 if (req->range == REQ_RANGE_CADJACENT) {
5009 return TRI_YES;
5010 }
5013 } else {
5015
5019 return TRI_YES;
5020 }
5023 }
5024
5025 return TRI_NO;
5026
5027 case REQ_RANGE_CITY:
5030 case REQ_RANGE_PLAYER:
5031 case REQ_RANGE_TEAM:
5032 case REQ_RANGE_ALLIANCE:
5033 case REQ_RANGE_WORLD:
5034 case REQ_RANGE_COUNT:
5036 break;
5037 }
5038
5039 return TRI_NO;
5040}
5041
5042/**********************************************************************/
5050static enum fc_tristate
5052 const struct req_context *context,
5053 const struct req_context *other_context,
5054 const struct requirement *req)
5055{
5056 enum ustate_prop uprop;
5057
5059
5061
5063 "Unsupported range \"%s\"",
5064 req_range_name(req->range));
5065
5066 /* Could be asked with incomplete data.
5067 * is_req_active() will handle it based on prob_type. */
5068 if (context->unit == nullptr) {
5069 return TRI_MAYBE;
5070 }
5071
5072 switch (uprop) {
5073 case USP_TRANSPORTED:
5074 return BOOL_TO_TRISTATE(context->unit->transporter != nullptr);
5075 case USP_LIVABLE_TILE:
5076 return BOOL_TO_TRISTATE(
5078 unit_tile(context->unit)));
5079 break;
5080 case USP_TRANSPORTING:
5082 case USP_HAS_HOME_CITY:
5083 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
5084 case USP_NATIVE_TILE:
5085 return BOOL_TO_TRISTATE(
5087 unit_tile(context->unit)));
5088 break;
5089 case USP_NATIVE_EXTRA:
5090 return BOOL_TO_TRISTATE(
5092 unit_type_get(context->unit)));
5093 break;
5095 return BOOL_TO_TRISTATE(context->unit->moved);
5096 case USP_COUNT:
5097 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
5098 /* Invalid property is unknowable. */
5099 return TRI_NO;
5100 }
5101
5102 /* Should never be reached */
5103 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
5104
5105 return TRI_NO;
5106}
5107
5108/**********************************************************************/
5116static enum fc_tristate
5118 const struct req_context *context,
5119 const struct req_context *other_context,
5120 const struct requirement *req)
5121{
5122 enum unit_activity activity;
5123
5125
5126 activity = req->source.value.activity;
5127
5129 "Unsupported range \"%s\"",
5130 req_range_name(req->range));
5131
5132 if (context->unit == nullptr) {
5133 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
5134 * it's the zero value that context has by default - so many callers
5135 * who meant not to set specific activity actually have ACTIVITY_IDLE
5136 * instead of ACTIVITY_LAST */
5137 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
5138 return BOOL_TO_TRISTATE(activity == context->activity);
5139 }
5140
5141 /* Could be asked with incomplete data.
5142 * is_req_active() will handle it based on prob_type. */
5143 return TRI_MAYBE;
5144 }
5145
5146 switch (context->unit->activity) {
5147 case ACTIVITY_IDLE:
5148 case ACTIVITY_SENTRY:
5149 case ACTIVITY_GOTO:
5150 case ACTIVITY_EXPLORE:
5151 /* Seen as idle. */
5152 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
5153 default:
5154 /* Handled below. */
5155 break;
5156 }
5157
5158 return BOOL_TO_TRISTATE(context->unit->activity == activity);
5159}
5160
5161/**********************************************************************/
5169static enum fc_tristate
5171 const struct req_context *context,
5172 const struct req_context *other_context,
5173 const struct requirement *req)
5174{
5176
5177 if (context->unit == nullptr) {
5178 return TRI_MAYBE;
5179 } else {
5180 return BOOL_TO_TRISTATE(context->unit->veteran
5181 >= req->source.value.minveteran);
5182 }
5183}
5184
5185/**********************************************************************/
5193static enum fc_tristate
5195 const struct req_context *context,
5196 const struct req_context *other_context,
5197 const struct requirement *req)
5198{
5200
5201 if (context->unit == nullptr) {
5202 return TRI_MAYBE;
5203 } else {
5205 <= context->unit->moves_left);
5206 }
5207}
5208
5209/**********************************************************************/
5217static enum fc_tristate
5219 const struct req_context *context,
5220 const struct req_context *other_context,
5221 const struct requirement *req)
5222{
5224
5225 if (context->unit == nullptr) {
5226 return TRI_MAYBE;
5227 } else {
5229 <= context->unit->hp);
5230 }
5231}
5232
5233/**********************************************************************/
5241static enum fc_tristate
5243 const struct req_context *context,
5244 const struct req_context *other_context,
5245 const struct requirement *req)
5246{
5248
5249 switch (req->range) {
5250 case REQ_RANGE_LOCAL:
5251 if (context->unit == nullptr || !is_server()) {
5252 return TRI_MAYBE;
5253 } else {
5254 return BOOL_TO_TRISTATE(
5255 req->source.value.age <=
5256 game.info.turn - context->unit->birth_turn);
5257 }
5258 break;
5259 case REQ_RANGE_CITY:
5260 if (context->city == nullptr) {
5261 return TRI_MAYBE;
5262 } else {
5263 return BOOL_TO_TRISTATE(
5264 req->source.value.age <=
5265 game.info.turn - context->city->turn_founded);
5266 }
5267 break;
5268 case REQ_RANGE_PLAYER:
5269 if (context->player == nullptr) {
5270 return TRI_MAYBE;
5271 } else {
5272 return BOOL_TO_TRISTATE(req->source.value.age
5273 <= player_age(context->player));
5274 }
5275 break;
5276 default:
5277 return TRI_MAYBE;
5278 break;
5279 }
5280}
5281
5282/**********************************************************************/
5290static enum fc_tristate
5292 const struct req_context *context,
5293 const struct req_context *other_context,
5294 const struct requirement *req)
5295{
5297
5298 switch (req->range) {
5299 case REQ_RANGE_LOCAL:
5300 if (context->unit == nullptr || !is_server()) {
5301 return TRI_MAYBE;
5302 } else {
5303 return BOOL_TO_TRISTATE(
5304 req->source.value.form_age <=
5305 game.info.turn - context->unit->current_form_turn);
5306 }
5307 break;
5308 default:
5309 return TRI_MAYBE;
5310 break;
5311 }
5312}
5313
5314/**********************************************************************/
5318static inline enum fc_tristate
5320{
5322 bool whole_known;
5323
5324 if (cont > 0) {
5327
5328 if (actual_surrounder > 0) {
5329 return TRI_NO;
5330 }
5331 } else if (cont < 0) {
5334
5335 if (actual_surrounder < 0) {
5336 return TRI_NO;
5337 }
5338 } else {
5339 return TRI_MAYBE;
5340 }
5341
5342 if (actual_surrounder == 0 || surrounder == 0) {
5343 return TRI_MAYBE;
5344 } else if (actual_surrounder != surrounder) {
5345 return TRI_NO;
5346 } else if (!whole_known) {
5347 return TRI_MAYBE;
5348 } else {
5349 return TRI_YES;
5350 }
5351}
5352
5353/**********************************************************************/
5361static enum fc_tristate
5363 const struct req_context *context,
5364 const struct req_context *other_context,
5365 const struct requirement *req)
5366{
5368
5369 if (context->tile == nullptr || other_context->tile == nullptr) {
5370 /* Note: For some values, we might be able to give a definitive
5371 * TRI_NO answer even if one of the tiles is missing, but that's
5372 * probably not worth the added effort. */
5373 return TRI_MAYBE;
5374 }
5375
5376 switch (req->source.value.tilerel) {
5377 case TREL_SAME_TCLASS:
5378 if (tile_terrain(other_context->tile) == T_UNKNOWN) {
5379 return TRI_MAYBE;
5380 }
5382 || req->range == REQ_RANGE_CADJACENT
5383 || req->range == REQ_RANGE_ADJACENT),
5384 TRI_MAYBE,
5385 "Invalid range %d for tile relation \"%s\" req",
5387 {
5390 bool seen_unknown = FALSE;
5391 const struct terrain *terr;
5392
5393 if ((terr = tile_terrain(context->tile)) == T_UNKNOWN) {
5395 } else if (terrain_type_terrain_class(terr) == cls) {
5396 return TRUE;
5397 }
5398
5400 if ((terr = tile_terrain(adj_tile)) == T_UNKNOWN) {
5402 } else if (terrain_type_terrain_class(terr) == cls) {
5403 return TRUE;
5404 }
5406
5407 if (seen_unknown) {
5408 return TRI_MAYBE;
5409 } else {
5410 return TRI_NO;
5411 }
5412 }
5413 break;
5414 case TREL_SAME_REGION:
5415 if (tile_continent(other_context->tile) == 0) {
5416 return TRI_MAYBE;
5417 }
5419 || req->range == REQ_RANGE_CADJACENT
5420 || req->range == REQ_RANGE_ADJACENT),
5421 TRI_MAYBE,
5422 "Invalid range %d for tile relation \"%s\" req",
5424
5425 if (tile_continent(context->tile)
5426 == tile_continent(other_context->tile)) {
5427 return TRI_YES;
5428 } else {
5429 bool seen_unknown = (tile_continent(context->tile) == 0);
5431
5434
5435 if (adj_cont == cont) {
5436 return TRI_YES;
5437 } else if (adj_cont == 0) {
5439 }
5441
5442 if (seen_unknown) {
5443 return TRI_MAYBE;
5444 } else {
5445 return TRI_NO;
5446 }
5447 }
5448 break;
5450 if (tile_continent(context->tile) == 0
5451 || tile_continent(other_context->tile) == 0) {
5452 /* Note: We could still give a definitive TRI_NO answer if there are
5453 * too many different adjacent continents, but that's probably not
5454 * worth the added effort. */
5455 return TRI_MAYBE;
5456 }
5458 || req->range == REQ_RANGE_ADJACENT),
5459 TRI_MAYBE,
5460 "Invalid range %d for tile relation \"%s\" req",
5461 req->range,
5463
5464 {
5465 bool seen_unknown = FALSE;
5466 Continent_id cont = tile_continent(context->tile);
5468
5471
5472 if (adj_cont == 0) {
5474 } else if (adj_cont != cont && adj_cont != other_cont) {
5475 return TRI_NO;
5476 }
5478
5479 if (seen_unknown) {
5480 return TRI_MAYBE;
5481 } else {
5482 return TRI_YES;
5483 }
5484 }
5485 break;
5488 || req->range == REQ_RANGE_CADJACENT
5489 || req->range == REQ_RANGE_ADJACENT),
5490 TRI_MAYBE,
5491 "Invalid range %d for tile relation \"%s\" req",
5492 req->range,
5494
5495 {
5496 bool seen_maybe = FALSE;
5498
5500 wanted)) {
5501 case TRI_YES:
5502 return TRI_YES;
5503 case TRI_MAYBE:
5504 seen_maybe = TRUE;
5505 break;
5506 default:
5507 break;
5508 }
5509
5512 wanted)) {
5513 case TRI_YES:
5514 return TRI_YES;
5515 case TRI_MAYBE:
5516 seen_maybe = TRUE;
5517 break;
5518 default:
5519 break;
5520 }
5522
5523 if (seen_maybe) {
5524 return TRI_MAYBE;
5525 } else {
5526 return TRI_NO;
5527 }
5528 }
5529 break;
5530 default:
5531 break;
5532 }
5533
5535 "Illegal value %d for tile relationship requirement.",
5536 req->source.value.tilerel);
5537 return TRI_MAYBE;
5538}
5539
5540/**********************************************************************/
5543static bool is_city_in_tile(const struct tile *ptile,
5544 const struct city *pcity)
5545{
5546 if (pcity == nullptr) {
5547 return tile_city(ptile) != nullptr;
5548 } else {
5549 return is_city_center(pcity, ptile);
5550 }
5551}
5552
5553/**********************************************************************/
5561static enum fc_tristate
5563 const struct req_context *context,
5564 const struct req_context *other_context,
5565 const struct requirement *req)
5566{
5567 enum citytile_type citytile;
5568
5570
5571 citytile = req->source.value.citytile;
5572
5574 if (context->tile == nullptr) {
5575 return TRI_MAYBE;
5576 }
5577
5578 switch (citytile) {
5579 case CITYT_CENTER:
5580 switch (req->range) {
5581 case REQ_RANGE_TILE:
5583 context->city));
5585 if (is_city_in_tile(context->tile, context->city)) {
5586 return TRI_YES;
5587 }
5589 if (is_city_in_tile(adjc_tile, context->city)) {
5590 return TRI_YES;
5591 }
5593
5594 return TRI_NO;
5595 case REQ_RANGE_ADJACENT:
5596 if (is_city_in_tile(context->tile, context->city)) {
5597 return TRI_YES;
5598 }
5600 if (is_city_in_tile(adjc_tile, context->city)) {
5601 return TRI_YES;
5602 }
5604
5605 return TRI_NO;
5606 case REQ_RANGE_CITY:
5609 case REQ_RANGE_PLAYER:
5610 case REQ_RANGE_TEAM:
5611 case REQ_RANGE_ALLIANCE:
5612 case REQ_RANGE_WORLD:
5613 case REQ_RANGE_LOCAL:
5614 case REQ_RANGE_COUNT:
5615 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5616 break;
5617 }
5618
5619 return TRI_MAYBE;
5620 case CITYT_CLAIMED:
5621 switch (req->range) {
5622 case REQ_RANGE_TILE:
5623 return BOOL_TO_TRISTATE(context->tile->owner != nullptr);
5625 if (context->tile->owner != nullptr) {
5626 return TRI_YES;
5627 }
5629 if (adjc_tile->owner != nullptr) {
5630 return TRI_YES;
5631 }
5633
5634 return TRI_NO;
5635 case REQ_RANGE_ADJACENT:
5636 if (context->tile->owner != nullptr) {
5637 return TRI_YES;
5638 }
5640 if (adjc_tile->owner != nullptr) {
5641 return TRI_YES;
5642 }
5644
5645 return TRI_NO;
5646 case REQ_RANGE_CITY:
5649 case REQ_RANGE_PLAYER:
5650 case REQ_RANGE_TEAM:
5651 case REQ_RANGE_ALLIANCE:
5652 case REQ_RANGE_WORLD:
5653 case REQ_RANGE_LOCAL:
5654 case REQ_RANGE_COUNT:
5655 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5656 break;
5657 }
5658
5659 return TRI_MAYBE;
5660 case CITYT_EXTRAS_OWNED:
5661 switch (req->range) {
5662 case REQ_RANGE_TILE:
5663 return BOOL_TO_TRISTATE(context->tile->extras_owner != nullptr);
5665 if (context->tile->extras_owner != nullptr) {
5666 return TRI_YES;
5667 }
5669 if (adjc_tile->extras_owner != nullptr) {
5670 return TRI_YES;
5671 }
5673
5674 return TRI_NO;
5675 case REQ_RANGE_ADJACENT:
5676 if (context->tile->extras_owner != nullptr) {
5677 return TRI_YES;
5678 }
5680 if (adjc_tile->extras_owner != nullptr) {
5681 return TRI_YES;
5682 }
5684
5685 return TRI_NO;
5686 case REQ_RANGE_CITY:
5689 case REQ_RANGE_PLAYER:
5690 case REQ_RANGE_TEAM:
5691 case REQ_RANGE_ALLIANCE:
5692 case REQ_RANGE_WORLD:
5693 case REQ_RANGE_LOCAL:
5694 case REQ_RANGE_COUNT:
5695 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5696 break;
5697 }
5698
5699 return TRI_MAYBE;
5700 case CITYT_WORKED:
5701 switch (req->range) {
5702 case REQ_RANGE_TILE:
5703 return BOOL_TO_TRISTATE(context->tile->worked != nullptr);
5705 if (context->tile->worked != nullptr) {
5706 return TRI_YES;
5707 }
5709 if (adjc_tile->worked != nullptr) {
5710 return TRI_YES;
5711 }
5713
5714 return TRI_NO;
5715 case REQ_RANGE_ADJACENT:
5716 if (context->tile->worked != nullptr) {
5717 return TRI_YES;
5718 }
5720 if (adjc_tile->worked != nullptr) {
5721 return TRI_YES;
5722 }
5724
5725 return TRI_NO;
5726 case REQ_RANGE_CITY:
5729 case REQ_RANGE_PLAYER:
5730 case REQ_RANGE_TEAM:
5731 case REQ_RANGE_ALLIANCE:
5732 case REQ_RANGE_WORLD:
5733 case REQ_RANGE_LOCAL:
5734 case REQ_RANGE_COUNT:
5735 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5736 break;
5737 }
5738
5739 return TRI_MAYBE;
5741 {
5743 const struct tile *target_tile = context->tile, *cc_tile;
5744
5745 if (!context->city) {
5746 return TRI_MAYBE;
5747 }
5748 cc_tile = city_tile(context->city);
5749 if (!cc_tile) {
5750 /* Unplaced virtual city */
5751 return TRI_MAYBE;
5752 }
5754 /* Note: No special treatment of 0 == cc here*/
5755 switch (req->range) {
5756 case REQ_RANGE_TILE:
5759 if (tile_continent(target_tile) == cc) {
5760 return TRI_YES;
5761 }
5763 if (tile_continent(adjc_tile) == cc) {
5764 return TRI_YES;
5765 }
5767
5768 return TRI_NO;
5769 case REQ_RANGE_ADJACENT:
5770 if (tile_continent(target_tile) == cc) {
5771 return TRI_YES;
5772 }
5774 if (tile_continent(adjc_tile) == cc) {
5775 return TRI_YES;
5776 }
5778
5779 return TRI_NO;
5780 case REQ_RANGE_CITY:
5783 case REQ_RANGE_PLAYER:
5784 case REQ_RANGE_TEAM:
5785 case REQ_RANGE_ALLIANCE:
5786 case REQ_RANGE_WORLD:
5787 case REQ_RANGE_LOCAL:
5788 case REQ_RANGE_COUNT:
5789 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5790 break;
5791 }
5792 }
5793
5794 return TRI_MAYBE;
5796 {
5797 int n = 0;
5799 bool ukt = FALSE;
5800 const struct tile *target_tile = context->tile, *cc_tile;
5801
5802 if (!context->city) {
5803 return TRI_MAYBE;
5804 }
5805 cc_tile = city_tile(context->city);
5806 if (!cc_tile) {
5807 /* Unplaced virtual city */
5808 return TRI_MAYBE;
5809 }
5811 if (!cc) {
5812 /* Don't know the city center terrain class.
5813 * Maybe, the city floats? Even if the rules prohibit it... */
5814 return TRI_MAYBE;
5815 }
5818
5819 if (0 != tc) {
5820 bool seen = FALSE;
5821 int i = n;
5822
5823 if (tc == cc) {
5824 continue;
5825 }
5826 while (--i >= 0) {
5827 if (adjc_cont[i] == tc) {
5828 seen = TRUE;
5829 break;
5830 }
5831 }
5832 if (seen) {
5833 continue;
5834 }
5836 } else {
5837 /* Likely, it's a black tile in client and we don't know
5838 * We possibly can calculate, but keep it simple. */
5839 ukt = TRUE;
5840 }
5842 if (0 == n) {
5843 return ukt ? TRI_MAYBE : TRI_NO;
5844 }
5845
5846 switch (req->range) {
5847 case REQ_RANGE_TILE:
5848 {
5850
5851 if (cc == tc) {
5852 return TRI_NO;
5853 }
5854 if (0 == tc || ukt) {
5855 return TRI_MAYBE;
5856 }
5857 for (int i = 0; i < n; i++) {
5858 if (tc == adjc_cont[i]) {
5859 return TRI_YES;
5860 }
5861 }
5862 }
5863
5864 return TRI_NO;
5865 case REQ_RANGE_ADJACENT:
5866 if (ukt) {
5867 /* If ALL the tiles in range are on cc, we can say it's false */
5869 if (tile_continent(adjc_tile) != cc) {
5870 return TRI_MAYBE;
5871 }
5873
5874 return TRI_NO;
5875 } else {
5878
5879 if (0 == tc) {
5880 return TRI_MAYBE;
5881 }
5882 for (int i = 0; i < n; i++) {
5883 if (tc == adjc_cont[i]) {
5884 return TRI_YES;
5885 }
5886 }
5888 }
5889
5890 return TRI_NO;
5892 if (ukt) {
5893 /* If ALL the tiles in range are on cc, we can say it's false */
5895 if (tile_continent(cadjc_tile) != cc) {
5896 return TRI_MAYBE;
5897 }
5899 } else {
5902
5903 if (0 == tc) {
5904 return TRI_MAYBE;
5905 }
5906 for (int i = 0; i < n; i++) {
5907 if (tc == adjc_cont[i]) {
5908 return TRI_YES;
5909 }
5910 }
5912 }
5913
5914 return TRI_NO;
5915 case REQ_RANGE_CITY:
5918 case REQ_RANGE_PLAYER:
5919 case REQ_RANGE_TEAM:
5920 case REQ_RANGE_ALLIANCE:
5921 case REQ_RANGE_WORLD:
5922 case REQ_RANGE_LOCAL:
5923 case REQ_RANGE_COUNT:
5924 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5925 break;
5926 }
5927 }
5928
5929 return TRI_MAYBE;
5930 case CITYT_LAST:
5931 /* Handled below */
5932 break;
5933 }
5934
5935 /* Not implemented */
5936 log_error("is_req_active(): citytile %d not supported.",
5937 citytile);
5938 return TRI_MAYBE;
5939}
5940
5941/**********************************************************************/
5949static enum fc_tristate
5951 const struct req_context *context,
5952 const struct req_context *other_context,
5953 const struct requirement *req)
5954{
5955 enum citystatus_type citystatus;
5956
5958
5959 citystatus = req->source.value.citystatus;
5960
5961 if (context->city == nullptr) {
5962 return TRI_MAYBE;
5963 }
5964
5965 switch (citystatus) {
5967 switch (req->range) {
5968 case REQ_RANGE_CITY:
5969 if (context->city->original == nullptr) {
5970 return TRI_MAYBE;
5971 }
5972 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
5974 {
5975 enum fc_tristate ret;
5976
5977 if (city_owner(context->city) == context->city->original) {
5978 return TRI_YES;
5979 }
5980
5981 ret = TRI_NO;
5983 if (trade_partner == nullptr || trade_partner->original == nullptr) {
5984 ret = TRI_MAYBE;
5985 } else if (city_owner(trade_partner) == trade_partner->original) {
5986 return TRI_YES;
5987 }
5989
5990 return ret;
5991 }
5992 case REQ_RANGE_LOCAL:
5993 case REQ_RANGE_TILE:
5995 case REQ_RANGE_ADJACENT:
5997 case REQ_RANGE_PLAYER:
5998 case REQ_RANGE_TEAM:
5999 case REQ_RANGE_ALLIANCE:
6000 case REQ_RANGE_WORLD:
6001 case REQ_RANGE_COUNT:
6002 break;
6003 }
6004
6005 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
6006 req->range);
6007
6008 return TRI_MAYBE;
6009
6010 case CITYS_STARVED:
6011 switch (req->range) {
6012 case REQ_RANGE_CITY:
6013 return BOOL_TO_TRISTATE(context->city->had_famine);
6015 {
6016 enum fc_tristate ret;
6017
6018 if (context->city->had_famine) {
6019 return TRI_YES;
6020 }
6021
6022 ret = TRI_NO;
6024 if (trade_partner == nullptr) {
6025 ret = TRI_MAYBE;
6026 } else if (trade_partner->had_famine) {
6027 return TRI_YES;
6028 }
6030
6031 return ret;
6032 }
6033 case REQ_RANGE_LOCAL:
6034 case REQ_RANGE_TILE:
6036 case REQ_RANGE_ADJACENT:
6038 case REQ_RANGE_PLAYER:
6039 case REQ_RANGE_TEAM:
6040 case REQ_RANGE_ALLIANCE:
6041 case REQ_RANGE_WORLD:
6042 case REQ_RANGE_COUNT:
6043 break;
6044 }
6045
6046 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
6047 req->range);
6048
6049 return TRI_MAYBE;
6050
6051 case CITYS_DISORDER:
6052 switch (req->range) {
6053 case REQ_RANGE_CITY:
6054 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
6056 {
6057 enum fc_tristate ret;
6058
6059 if (context->city->anarchy > 0) {
6060 return TRI_YES;
6061 }
6062
6063 ret = TRI_NO;
6065 if (trade_partner == nullptr) {
6066 ret = TRI_MAYBE;
6067 } else if (trade_partner->anarchy > 0) {
6068 return TRI_YES;
6069 }
6071
6072 return ret;
6073 }
6074 case REQ_RANGE_LOCAL:
6075 case REQ_RANGE_TILE:
6077 case REQ_RANGE_ADJACENT:
6079 case REQ_RANGE_PLAYER:
6080 case REQ_RANGE_TEAM:
6081 case REQ_RANGE_ALLIANCE:
6082 case REQ_RANGE_WORLD:
6083 case REQ_RANGE_COUNT:
6084 break;
6085 }
6086
6087 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
6088 req->range);
6089
6090 return TRI_MAYBE;
6091
6092 case CITYS_CELEBRATION:
6093 switch (req->range) {
6094 case REQ_RANGE_CITY:
6095 return BOOL_TO_TRISTATE(context->city->rapture > 0);
6097 {
6098 enum fc_tristate ret;
6099
6100 if (context->city->rapture > 0) {
6101 return TRI_YES;
6102 }
6103
6104 ret = TRI_NO;
6106 if (trade_partner == nullptr) {
6107 ret = TRI_MAYBE;
6108 } else if (trade_partner->rapture > 0) {
6109 return TRI_YES;
6110 }
6112
6113 return ret;
6114 }
6115 case REQ_RANGE_LOCAL:
6116 case REQ_RANGE_TILE:
6118 case REQ_RANGE_ADJACENT:
6120 case REQ_RANGE_PLAYER:
6121 case REQ_RANGE_TEAM:
6122 case REQ_RANGE_ALLIANCE:
6123 case REQ_RANGE_WORLD:
6124 case REQ_RANGE_COUNT:
6125 break;
6126 }
6127
6128 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
6129 req->range);
6130
6131 return TRI_MAYBE;
6132
6133 case CITYS_TRANSFERRED:
6134 switch (req->range) {
6135 case REQ_RANGE_CITY:
6136 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
6138 {
6139 enum fc_tristate ret;
6140
6141 if (context->city->acquire_t != CACQ_FOUNDED) {
6142 return TRI_YES;
6143 }
6144
6145 ret = TRI_NO;
6147 if (trade_partner == nullptr) {
6148 ret = TRI_MAYBE;
6149 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
6150 return TRI_YES;
6151 }
6153
6154 return ret;
6155 }
6156 case REQ_RANGE_LOCAL:
6157 case REQ_RANGE_TILE:
6159 case REQ_RANGE_ADJACENT:
6161 case REQ_RANGE_PLAYER:
6162 case REQ_RANGE_TEAM:
6163 case REQ_RANGE_ALLIANCE:
6164 case REQ_RANGE_WORLD:
6165 case REQ_RANGE_COUNT:
6166 break;
6167 }
6168
6169 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
6170 req->range);
6171
6172 return TRI_MAYBE;
6173
6175 switch (req->range) {
6176 case REQ_RANGE_CITY:
6177 if (context->city->aarea == nullptr) {
6178 return TRI_MAYBE;
6179 }
6180 return BOOL_TO_TRISTATE(context->city->aarea->capital);
6182 {
6183 enum fc_tristate ret;
6184
6185 if (context->city->aarea != nullptr
6186 && context->city->aarea->capital) {
6187 return TRI_YES;
6188 }
6189
6190 if (context->city->aarea == nullptr) {
6191 ret = TRI_MAYBE;
6192 } else {
6193 ret = TRI_NO;
6194 }
6196 if (trade_partner == nullptr
6197 || trade_partner->aarea == nullptr) {
6198 ret = TRI_MAYBE;
6199 } else if (trade_partner->aarea->capital) {
6200 return TRI_YES;
6201 }
6203
6204 return ret;
6205 }
6206 case REQ_RANGE_LOCAL:
6207 case REQ_RANGE_TILE:
6209 case REQ_RANGE_ADJACENT:
6211 case REQ_RANGE_PLAYER:
6212 case REQ_RANGE_TEAM:
6213 case REQ_RANGE_ALLIANCE:
6214 case REQ_RANGE_WORLD:
6215 case REQ_RANGE_COUNT:
6216 break;
6217 }
6218
6219 fc_assert_msg(FALSE, "Invalid range %d for citystatus CapitalConnected.",
6220 req->range);
6221
6222 return TRI_MAYBE;
6223
6224 case CITYS_LAST:
6225 break;
6226 }
6227
6228 /* Not implemented */
6229 log_error("is_req_active(): citystatus %d not supported.",
6230 citystatus);
6231
6232 return TRI_MAYBE;
6233}
6234
6235/**********************************************************************/
6243static enum fc_tristate
6245 const struct req_context *context,
6246 const struct req_context *other_context,
6247 const struct requirement *req)
6248{
6250
6251 if (context->city == nullptr) {
6252 return TRI_MAYBE;
6253 } else {
6254 if (req->range == REQ_RANGE_TRADE_ROUTE) {
6255 enum fc_tristate ret;
6256
6257 if (city_size_get(context->city) >= req->source.value.minsize) {
6258 return TRI_YES;
6259 }
6260
6261 ret = TRI_NO;
6263 if (trade_partner == nullptr) {
6264 ret = TRI_MAYBE;
6265 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
6266 return TRI_YES;
6267 }
6269
6270 return ret;
6271 } else {
6273 >= req->source.value.minsize);
6274 }
6275 }
6276}
6277
6278/**********************************************************************/
6286static enum fc_tristate
6288 const struct req_context *context,
6289 const struct req_context *other_context,
6290 const struct requirement *req)
6291{
6292 const struct counter *count;
6293
6295
6296 count = req->source.value.counter;
6297
6298 if (context->city == nullptr) {
6299 return TRI_MAYBE;
6300 }
6301 return BOOL_TO_TRISTATE(count->checkpoint <=
6302 context->city->counter_values[
6303 counter_index(count)]);
6304}
6305
6306/**********************************************************************/
6314static enum fc_tristate
6316 const struct req_context *context,
6317 const struct req_context *other_context,
6318 const struct requirement *req)
6319{
6320 const struct achievement *achievement;
6321
6323
6325
6326 if (req->range == REQ_RANGE_WORLD) {
6328 } else if (context->player == nullptr) {
6329 return TRI_MAYBE;
6330 } else if (req->range == REQ_RANGE_ALLIANCE
6331 || req->range == REQ_RANGE_TEAM) {
6332 players_iterate_alive(plr2) {
6333 if (players_in_same_range(context->player, plr2, req->range)
6335 return TRI_YES;
6336 }
6338 return TRI_NO;
6339 } else if (req->range == REQ_RANGE_PLAYER) {
6341 return TRI_YES;
6342 } else {
6343 return TRI_NO;
6344 }
6345 }
6346
6347 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
6348
6349 return TRI_MAYBE;
6350}
6351
6352/**********************************************************************/
6360static enum fc_tristate
6362 const struct req_context *context,
6363 const struct req_context *other_context,
6364 const struct requirement *req)
6365{
6366 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
6367
6368 fc_assert_ret_val(req != nullptr, TRI_MAYBE);
6369 fc_assert(context != nullptr);
6370
6371 switch (req->source.kind) {
6372 case VUT_MINLATITUDE:
6373 min = req->source.value.latitude;
6374 break;
6375 case VUT_MAXLATITUDE:
6376 max = req->source.value.latitude;
6377 break;
6378 default:
6380 || req->source.kind == VUT_MAXLATITUDE);
6381 break;
6382 }
6383
6384 switch (req->range) {
6385 case REQ_RANGE_WORLD:
6387 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
6388
6389 case REQ_RANGE_TILE:
6390 if (context->tile == nullptr) {
6391 return TRI_MAYBE;
6392 } else {
6394
6396 }
6397
6399 if (context->tile == nullptr) {
6400 return TRI_MAYBE;
6401 }
6402
6405
6407 return TRI_YES;
6408 }
6410 return TRI_NO;
6411
6412 case REQ_RANGE_ADJACENT:
6413 if (!context->tile) {
6414 return TRI_MAYBE;
6415 }
6416
6419
6421 return TRI_YES;
6422 }
6424 return TRI_NO;
6425
6426 case REQ_RANGE_CITY:
6429 case REQ_RANGE_PLAYER:
6430 case REQ_RANGE_TEAM:
6431 case REQ_RANGE_ALLIANCE:
6432 case REQ_RANGE_LOCAL:
6433 case REQ_RANGE_COUNT:
6434 break;
6435 }
6436
6438 "Illegal range %d for latitude requirement.", req->range);
6439
6440 return TRI_MAYBE;
6441}
6442
6443/**********************************************************************/
6451static enum fc_tristate
6453 const struct req_context *context,
6454 const struct req_context *other_context,
6455 const struct requirement *req)
6456{
6458
6459 switch (req->range) {
6460 case REQ_RANGE_TILE:
6461 if (context->tile == nullptr || other_context->tile == nullptr) {
6462 return TRI_MAYBE;
6463 }
6464 return BOOL_TO_TRISTATE(
6466 <= req->source.value.distance_sq
6467 );
6468 default:
6469 break;
6470 }
6471
6473 "Illegal range %d for max squared distance requirement.",
6474 req->range);
6475
6476 return TRI_MAYBE;
6477}
6478
6479/**********************************************************************/
6487static enum fc_tristate
6489 const struct req_context *context,
6490 const struct req_context *other_context,
6491 const struct requirement *req)
6492{
6493 int max_tiles, min_tiles = 1;
6494
6496
6497 switch (req->range) {
6499 case REQ_RANGE_ADJACENT:
6500 if (context->tile == nullptr) {
6501 /* The tile itself is included in the range */
6502 max_tiles = 1 + ((req->range == REQ_RANGE_CADJACENT)
6503 ? nmap->num_cardinal_dirs
6504 : nmap->num_valid_dirs);
6505
6506 break;
6507 } else {
6508 Continent_id cont = tile_continent(context->tile);
6509
6510 /* Count how many adjacent tiles there actually are as we go along */
6511 max_tiles = 1;
6512
6515
6516 if (adj_cont == 0 || cont == 0) {
6517 max_tiles++;
6518 } else if (adj_cont == cont) {
6519 min_tiles++;
6520 max_tiles++;
6521 }
6523 }
6524 break;
6526 {
6527 Continent_id cont = context->tile ? tile_continent(context->tile) : 0;
6528
6531
6532 /* Note: We could come up with a better upper bound by subtracting
6533 * all other continent/ocean sizes, or all except the largest if we
6534 * don't know the tile.
6535 * We could even do a flood-fill count of the unknown area bordered
6536 * by known tiles of the continent.
6537 * Probably not worth the effort though. */
6538 max_tiles = nmap->xsize * nmap->ysize;
6539
6540 if (cont > 0) {
6541 min_tiles = nmap->continent_sizes[cont];
6542 if (is_whole_continent_known(cont)) {
6544 }
6545 } else if (cont < 0) {
6546 min_tiles = nmap->ocean_sizes[-cont];
6547 if (is_whole_ocean_known(-cont)) {
6549 }
6550 }
6551 }
6552 break;
6553 default:
6555 "Illegal range %d for max region tiles requirement.",
6556 req->range);
6557 return TRI_MAYBE;
6558 }
6559
6560 if (min_tiles > req->source.value.region_tiles) {
6561 return TRI_NO;
6562 } else if (max_tiles <= req->source.value.region_tiles) {
6563 return TRI_YES;
6564 }
6565 return TRI_MAYBE;
6566}
6567
6568/**********************************************************************/
6576static enum fc_tristate
6578 const struct req_context *context,
6579 const struct req_context *other_context,
6580 const struct requirement *req)
6581{
6583
6585}
6586
6587/**********************************************************************/
6595static enum fc_tristate
6597 const struct req_context *context,
6598 const struct req_context *other_context,
6599 const struct requirement *req)
6600{
6602
6604 >= req->source.value.mincalfrag);
6605}
6606
6607/**********************************************************************/
6615static enum fc_tristate
6617 const struct req_context *context,
6618 const struct req_context *other_context,
6619 const struct requirement *req)
6620{
6622
6623 return BOOL_TO_TRISTATE(
6625}
6626
6627/**********************************************************************/
6635static enum fc_tristate
6637 const struct req_context *context,
6638 const struct req_context *other_context,
6639 const struct requirement *req)
6640{
6642
6643 return BOOL_TO_TRISTATE(
6645}
6646
6647/**********************************************************************/
6655static enum fc_tristate
6657 const struct req_context *context,
6658 const struct req_context *other_context,
6659 const struct requirement *req)
6660{
6662
6664 req->source.value.ssetval));
6665}
6666
6667/* Not const for potential ruleset-related adjustment */
6670
6671 /* Alphabetical order of enum constant */
6739};
6740
6741/**********************************************************************/
6755 const struct req_context *other_context,
6756 const struct requirement *req,
6757 const enum req_problem_type prob_type)
6758{
6759 const struct civ_map *nmap = &(wld.map);
6760 enum fc_tristate eval;
6762 struct thr_req_data *trdata = nullptr;
6763
6766 if (fc_threads_equal(self, data->thr_id)) {
6767 trdata = data;
6768 }
6770
6771 if (trdata == nullptr) {
6772 trdata = fc_malloc(sizeof(struct thr_req_data));
6773 trdata->thr_id = self;
6775 }
6777
6779
6780 if (eval == TRI_MAYBE) {
6781 if (prob_type == RPT_POSSIBLE) {
6782 return TRUE;
6783 } else {
6784 return FALSE;
6785 }
6786 }
6787
6788 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
6789}
6790
6791/**********************************************************************/
6800static
6802 const struct req_context *context,
6803 const struct req_context *other_context,
6804 const struct requirement *req)
6805{
6806 if (!context) {
6808 }
6809 if (!other_context) {
6811 }
6812
6813 if (req->source.kind >= VUT_COUNT) {
6814 log_error("tri_req_present(): invalid source kind %d.",
6815 req->source.kind);
6816 return TRI_NO;
6817 }
6818
6820
6821 return req_definitions[req->source.kind].cb(nmap, context,
6822 other_context, req);
6823}
6824
6825/**********************************************************************/
6835 const struct req_context *other_context,
6836 const struct requirement *req)
6837{
6838 const struct civ_map *nmap = &(wld.map);
6840
6841 if (!req->present) {
6842 if (TRI_NO == eval) {
6843 return TRI_YES;
6844 }
6845 if (TRI_YES == eval) {
6846 return TRI_NO;
6847 }
6848 }
6849
6850 return eval;
6851}
6852
6853/**********************************************************************/
6869 const struct req_context *other_context,
6870 const struct requirement_vector *reqs,
6871 const enum req_problem_type prob_type)
6872{
6875 return FALSE;
6876 }
6878
6879 return TRUE;
6880}
6881
6882/**********************************************************************/
6887 const enum req_range max_range,
6888 const struct req_context *context,
6889 const struct req_context *other_context,
6890 const struct requirement_vector *reqs,
6891 const enum req_problem_type prob_type)
6892{
6894 if (preq->range >= min_range && preq->range <= max_range) {
6896 return FALSE;
6897 }
6898 }
6900
6901 return TRUE;
6902}
6903
6904/**********************************************************************/
6910enum fc_tristate
6912 const struct req_context *context,
6913 const struct req_context *other_context,
6914 const struct requirement *req)
6915{
6916 /* FIXME: Doubles code from calendar.c */
6920 int fragment1 = fragment; /* If fragments don't advance */
6921 int year_inc, year_inc1;
6924 bool present, present1;
6925
6926 fc_assert(pass >= 0 && period >= 0);
6927 if (slowdown >= 3) {
6928 if (ypt > 1) {
6929 ypt = 1;
6930 }
6931 } else if (slowdown >= 2) {
6932 if (ypt > 2) {
6933 ypt = 2;
6934 }
6935 } else if (slowdown >= 1) {
6936 if (ypt > 5) {
6937 ypt = 5;
6938 }
6939 }
6940 year_inc = ypt * pass;
6943 int fragment_years;
6944
6945 fragment += fpt * pass;
6953 }
6955 if (year_inc + game.info.year >= 0) {
6956 year_inc++;
6957 year_inc1++;
6958 } else if (year_inc1 + game.info.year >= 0) {
6959 year_inc1++;
6960 }
6961 }
6962
6963 switch (req->source.kind) {
6964 case VUT_AGE:
6965 switch (req->range) {
6966 case REQ_RANGE_LOCAL:
6967 if (context->unit == nullptr || !is_server()) {
6968 return TRI_MAYBE;
6969 } else {
6970 int ua = game.info.turn + pass - context->unit->birth_turn;
6971
6972 present = req->source.value.age <= ua;
6973 present1 = req->source.value.age <= ua + period;
6974 }
6975 break;
6976 case REQ_RANGE_CITY:
6977 if (context->city == nullptr) {
6978 return TRI_MAYBE;
6979 } else {
6980 int ca = game.info.turn + pass - context->city->turn_founded;
6981
6982 present = req->source.value.age <= ca;
6983 present1 = req->source.value.age <= ca + period;
6984 }
6985 break;
6986 case REQ_RANGE_PLAYER:
6987 if (context->player == nullptr) {
6988 return TRI_MAYBE;
6989 } else {
6990 present = req->source.value.age
6991 <= player_age(context->player) + pass;
6992 present1 = req->source.value.age
6993 <= player_age(context->player) + pass + period;
6994 }
6995 break;
6996 default:
6997 return TRI_MAYBE;
6998 }
6999 break;
7000 case VUT_FORM_AGE:
7001 if (context->unit == nullptr || !is_server()) {
7002 return TRI_MAYBE;
7003 } else {
7004 int ua = game.info.turn + pass - context->unit->current_form_turn;
7005
7006 present = req->source.value.form_age <= ua;
7007 present1 = req->source.value.form_age <= ua + period;
7008 }
7009 break;
7010 case VUT_MINYEAR:
7011 present = game.info.year + year_inc >= req->source.value.minyear;
7013 break;
7014 case VUT_MINCALFRAG:
7016 /* Hope that the requirement is valid and fragments advance fine */
7017 return TRI_YES;
7018 }
7019 present = fragment >= req->source.value.mincalfrag;
7021 break;
7022 default:
7023 /* No special handling invented */
7024 return tri_req_active(context, other_context, req);
7025 }
7026 return BOOL_TO_TRISTATE(req->present
7027 ? present || present1 : !(present && present1));
7028}
7029
7030/**********************************************************************/
7036 (const struct req_context *context,
7037 const struct req_context *other_context,
7038 const struct requirement *req,
7039 void *data, int n_data)
7040{
7041 int i;
7042
7043 fc_assert_ret_val(data || n_data == 0, TRI_NO);
7044
7045 for (i = 0; i < n_data; i++) {
7046 if (are_requirements_contradictions(&((struct requirement *) data)[i],
7047 req)) {
7048 return TRI_NO;
7049 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
7050 return TRI_YES;
7051 }
7052 }
7053
7054 return tri_req_active(context, other_context, req);
7055}
7056
7057/**********************************************************************/
7063enum fc_tristate
7065 const struct req_context *other_context,
7066 const struct requirement_vector *reqs,
7069 void *data, int n_data)
7070{
7071 bool active = TRUE;
7072 bool certain = TRUE;
7073
7074 fc_assert_ret_val(tester != nullptr, TRI_NO);
7075
7078 data, n_data)) {
7079 case TRI_NO:
7080 active = FALSE;
7081 certain = TRUE;
7082 break;
7083 case TRI_YES:
7084 break;
7085 case TRI_MAYBE:
7086 certain = FALSE;
7087 if (maybe_reqs) {
7089 }
7090 break;
7091 default:
7093 active = FALSE;
7094 }
7095 if (!active) {
7096 break;
7097 }
7099
7100 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
7101}
7102
7103/**********************************************************************/
7113 const struct requirement *req)
7114{
7115 enum req_unchanging_status s;
7116 const struct civ_map *nmap = &(wld.map);
7117
7120 "Invalid source kind %d.", req->source.kind);
7122
7123 if (req->survives) {
7124 /* Special case for surviving requirements */
7125 /* Buildings may obsolete even here */
7126 if (VUT_IMPROVEMENT == req->source.kind) {
7127 const struct impr_type *b = req->source.value.building;
7128
7130 if (improvement_obsolete(context->player, b, context->city)) {
7131 /* FIXME: Sometimes can unobsolete, but considering it
7132 * may sometimes put the function on endless recursion */
7133 return REQUCH_ACT; /* Mostly about techs */
7134 } else {
7135 /* NOTE: May obsoletion reqs be unchanging? Hardly but why not. */
7136 return REQUCH_NO;
7137 }
7138 }
7139 }
7140 s = unchanging_present(nmap, s, context, req);
7141 if (s != REQUCH_NO) {
7142 return unchanging_noally(nmap, s, context, req);
7143 }
7144 } else {
7147
7148 if (cond) {
7149 return cond(nmap, s, context, req);
7150 }
7151 }
7152
7153 return s;
7154}
7155
7156/**********************************************************************/
7161 const struct req_context *other_context,
7162 const struct requirement *req,
7164{
7166
7167 if (REQUCH_NO != u) {
7168 /* Presence is precalculated */
7169 bool auto_present = (req->survives
7170 && !(VUT_IMPROVEMENT == req->source.kind
7174
7175 if (auto_present ? req->present
7177 /* Unchanging but does not block */
7178 return REQUCH_NO;
7179 }
7180 }
7181
7182 return u;
7183}
7184
7185/**********************************************************************/
7189bool is_req_in_vec(const struct requirement *req,
7190 const struct requirement_vector *vec)
7191{
7193 if (are_requirements_equal(req, preq)) {
7194 return TRUE;
7195 }
7197
7198 return FALSE;
7199}
7200
7201/**********************************************************************/
7209 enum universals_n kind)
7210{
7212 if (preq->present && preq->source.kind == kind) {
7213 return TRUE;
7214 }
7216 return FALSE;
7217}
7218
7219/**********************************************************************/
7228{
7229 switch (source->kind) {
7230 case VUT_ACTION:
7231 return !action_is_in_use(source->value.action);
7232 case VUT_UTFLAG:
7233 return !utype_flag_is_in_use(source->value.unitflag);
7234 case VUT_UCFLAG:
7235 return !uclass_flag_is_in_use(source->value.unitclassflag);
7236 case VUT_EXTRAFLAG:
7237 return !extra_flag_is_in_use(source->value.extraflag);
7238 case VUT_MINLATITUDE:
7239 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
7240 case VUT_MAXLATITUDE:
7241 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
7242 case VUT_COUNTER:
7243 case VUT_OTYPE:
7244 case VUT_SPECIALIST:
7245 case VUT_AI_LEVEL:
7246 case VUT_CITYTILE:
7247 case VUT_CITYSTATUS:
7248 case VUT_STYLE:
7249 case VUT_TOPO:
7250 case VUT_WRAP:
7251 case VUT_SERVERSETTING:
7252 case VUT_NATION:
7253 case VUT_NATIONGROUP:
7254 case VUT_ADVANCE:
7255 case VUT_TECHFLAG:
7256 case VUT_GOVERNMENT:
7257 case VUT_GOVFLAG:
7258 case VUT_ACHIEVEMENT:
7259 case VUT_IMPROVEMENT:
7260 case VUT_SITE:
7261 case VUT_IMPR_GENUS:
7262 case VUT_IMPR_FLAG:
7263 case VUT_PLAYER_FLAG:
7264 case VUT_PLAYER_STATE:
7265 case VUT_MINSIZE:
7266 case VUT_MINCULTURE:
7267 case VUT_MINFOREIGNPCT:
7268 case VUT_MINTECHS:
7269 case VUT_FUTURETECHS:
7270 case VUT_MINCITIES:
7271 case VUT_NATIONALITY:
7272 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
7273 case VUT_DIPLREL:
7274 case VUT_DIPLREL_TILE:
7275 case VUT_DIPLREL_TILE_O:
7280 case VUT_UTYPE:
7281 case VUT_UCLASS:
7282 case VUT_MINVETERAN:
7283 case VUT_UNITSTATE:
7284 case VUT_ACTIVITY:
7285 case VUT_MINMOVES:
7286 case VUT_MINHP:
7287 case VUT_AGE:
7288 case VUT_FORM_AGE:
7289 case VUT_ROADFLAG:
7290 case VUT_MINCALFRAG:
7291 case VUT_TERRAIN:
7292 case VUT_EXTRA:
7293 case VUT_TILEDEF:
7295 case VUT_GOOD:
7296 case VUT_TERRAINCLASS:
7297 case VUT_TERRFLAG:
7298 case VUT_TERRAINALTER:
7299 case VUT_MINYEAR:
7302 case VUT_TILE_REL:
7303 case VUT_NONE:
7304 case VUT_COUNT:
7305 /* Not implemented. */
7306 break;
7307 }
7308
7309 return FALSE;
7310}
7311
7312/**********************************************************************/
7321{
7322 /* Not known to be impossible to fulfill */
7323 return req->present && universal_never_there(&req->source);
7324}
7325
7326/**********************************************************************/
7335{
7338 return TRUE;
7339 }
7341
7342 /* Not known to be impossible to fulfill */
7343 return FALSE;
7344}
7345
7346/**********************************************************************/
7356 const struct requirement_vector *vec)
7357{
7358 if (vec) {
7359 return 0;
7360 } else {
7361 return -1;
7362 }
7363}
7364
7365/********************************************************************/
7374struct requirement_vector *
7376{
7377 fc_assert_ret_val(number == 0, nullptr);
7378
7379 return (struct requirement_vector *)parent_item;
7380}
7381
7382/**********************************************************************/
7393const char *req_vec_change_translation(const struct req_vec_change *change,
7395{
7396 const char *req_vec_description;
7397 static char buf[MAX_LEN_NAME * 3];
7398 struct astring astr;
7399
7400 fc_assert_ret_val(change, nullptr);
7402 nullptr);
7403
7404 /* Get rid of the previous. */
7405 buf[0] = '\0';
7406
7407 if (namer == nullptr) {
7408 /* TRANS: default description of a requirement vector
7409 * (used in ruledit) */
7410 req_vec_description = _("the requirement vector");
7411 } else {
7413 }
7414
7415 switch (change->operation) {
7416 case RVCO_REMOVE:
7417 fc_snprintf(buf, sizeof(buf),
7418 /* TRANS: remove a requirement from a requirement vector
7419 * (in ruledit).
7420 * The first %s is the operation.
7421 * The second %s is the requirement.
7422 * The third %s is a description of the requirement vector,
7423 * like "actor_reqs" */
7424 _("%s %s from %s"),
7426 req_to_fstring(&change->req, &astr),
7428 astr_free(&astr);
7429 break;
7430 case RVCO_APPEND:
7431 fc_snprintf(buf, sizeof(buf),
7432 /* TRANS: append a requirement to a requirement vector
7433 * (in ruledit).
7434 * The first %s is the operation.
7435 * The second %s is the requirement.
7436 * The third %s is a description of the requirement vector,
7437 * like "actor_reqs" */
7438 _("%s %s to %s"),
7440 req_to_fstring(&change->req, &astr),
7442 astr_free(&astr);
7443 break;
7444 case RVCO_NOOP:
7445 fc_snprintf(buf, sizeof(buf),
7446 /* TRANS: do nothing to a requirement vector (in ruledit).
7447 * The first %s is a description of the requirement vector,
7448 * like "actor_reqs" */
7449 _("Do nothing to %s"), req_vec_description);
7450 break;
7451 }
7452
7453 return buf;
7454}
7455
7456/**********************************************************************/
7469 const void *parent_item)
7470{
7471 struct requirement_vector *target
7472 = getter(parent_item, modification->vector_number);
7473 int i = 0;
7474
7475 switch (modification->operation) {
7476 case RVCO_APPEND:
7478 return TRUE;
7479 case RVCO_REMOVE:
7483 return TRUE;
7484 }
7485 i++;
7487 return FALSE;
7488 case RVCO_NOOP:
7489 return FALSE;
7490 }
7491
7492 return FALSE;
7493}
7494
7495/**********************************************************************/
7505struct req_vec_problem *
7507 const char *description,
7508 const char *description_translated)
7509{
7510 struct req_vec_problem *out;
7511 int i;
7512
7513 out = fc_malloc(sizeof(*out));
7514
7515 fc_strlcpy(out->description, description, sizeof(out->description));
7516 fc_strlcpy(out->description_translated, _(description_translated),
7517 sizeof(out->description_translated));
7518
7519 out->num_suggested_solutions = num_suggested_solutions;
7520 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
7521 * sizeof(struct req_vec_change));
7522 for (i = 0; i < out->num_suggested_solutions; i++) {
7523 /* No suggestions are ready yet. */
7524 out->suggested_solutions[i].operation = RVCO_NOOP;
7525 out->suggested_solutions[i].vector_number = -1;
7526 out->suggested_solutions[i].req.source.kind = VUT_NONE;
7527 }
7528
7529 return out;
7530}
7531
7532/**********************************************************************/
7542 const char *descr, ...)
7543{
7544 char description[500];
7545 char description_translated[500];
7546 va_list ap;
7547
7548 va_start(ap, descr);
7549 fc_vsnprintf(description, sizeof(description), descr, ap);
7550 va_end(ap);
7551
7552 va_start(ap, descr);
7554 _(descr), ap);
7555 va_end(ap);
7556
7559}
7560
7561/**********************************************************************/
7568{
7569 FC_FREE(issue->suggested_solutions);
7570 issue->num_suggested_solutions = 0;
7571
7572 FC_FREE(issue);
7573}
7574
7575/**********************************************************************/
7587struct req_vec_problem *
7590 const void *parent_item)
7591{
7592 int i, j;
7594
7595 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7596 /* No vector. */
7597 return nullptr;
7598 }
7599
7600 if (get_num == nullptr || parent_item == nullptr) {
7601 vec_num = 0;
7602 } else {
7603 vec_num = get_num(parent_item, vec);
7604 }
7605
7606 /* Look for contradictions */
7607 for (i = 0; i < requirement_vector_size(vec); i++) {
7608 struct requirement *preq = requirement_vector_get(vec, i);
7609 for (j = 0; j < requirement_vector_size(vec); j++) {
7610 struct requirement *nreq = requirement_vector_get(vec, j);
7611
7613 struct req_vec_problem *problem;
7614 struct astring astr;
7615 struct astring nastr;
7616
7618 N_("Requirements {%s} and {%s} contradict each other."),
7620
7621 astr_free(&astr);
7622 astr_free(&nastr);
7623
7624 /* The solution is to remove one of the contradictions. */
7625 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7626 problem->suggested_solutions[0].vector_number = vec_num;
7627 problem->suggested_solutions[0].req = *preq;
7628
7629 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7630 problem->suggested_solutions[1].vector_number = vec_num;
7631 problem->suggested_solutions[1].req = *nreq;
7632
7633 /* Only the first contradiction is reported. */
7634 return problem;
7635 }
7636 }
7637 }
7638
7639 return nullptr;
7640}
7641
7642/**********************************************************************/
7653struct req_vec_problem *
7656 const void *parent_item)
7657{
7658 /* Check for self contradictins. */
7660}
7661
7662/**********************************************************************/
7675struct req_vec_problem *
7678 const void *parent_item)
7679{
7680 int i;
7682 struct req_vec_problem *problem = nullptr;
7683
7684 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7685 /* No vector. */
7686 return nullptr;
7687 }
7688
7689 if (get_num == nullptr || parent_item == nullptr) {
7690 vec_num = 0;
7691 } else {
7692 vec_num = get_num(parent_item, vec);
7693 }
7694
7695 /* Look for contradictions */
7696 for (i = 0; i < requirement_vector_size(vec); i++) {
7697 struct requirement *preq = requirement_vector_get(vec, i);
7698
7699 if (universal_never_there(&preq->source)) {
7700 struct astring astr;
7701
7702 if (preq->present) {
7703 /* The requirement vector can never be fulfilled. Removing the
7704 * requirement makes it possible to fulfill it. This is a rule
7705 * change and shouldn't be "fixed" without thinking. Don't offer any
7706 * automatic solution to prevent mindless "fixes". */
7707 /* TRANS: Ruledit warns a user about an unused requirement vector
7708 * that never can be fulfilled because it asks for something that
7709 * never will be there. */
7710 if (problem == nullptr) {
7712 N_("Requirement {%s} requires %s but it will never be"
7713 " there."),
7715 astr_free(&astr);
7716 }
7717
7718 /* Continue to check if other problems have a solution proposal,
7719 * and prefer to return those. */
7720 continue;
7721 }
7722
7723 if (problem != nullptr) {
7724 /* Free previous one (one with no solution proposals) */
7726 }
7727
7729 N_("Requirement {%s} mentions %s but it will never be there."),
7731
7732 astr_free(&astr);
7733
7734 /* The solution is to remove the reference to the missing
7735 * universal. */
7736 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7737 problem->suggested_solutions[0].vector_number = vec_num;
7738 problem->suggested_solutions[0].req = *preq;
7739
7740 /* Only the first missing universal is reported. */
7741 return problem;
7742 }
7743 }
7744
7745 return problem;
7746}
7747
7748/**********************************************************************/
7761struct req_vec_problem *
7764 const void *parent_item)
7765{
7766 int i, j;
7768
7769 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7770 /* No vector. */
7771 return nullptr;
7772 }
7773
7774 if (get_num == nullptr || parent_item == nullptr) {
7775 vec_num = 0;
7776 } else {
7777 vec_num = get_num(parent_item, vec);
7778 }
7779
7780 /* Look for repeated requirements */
7781 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
7782 struct requirement *preq = requirement_vector_get(vec, i);
7783 for (j = i + 1; j < requirement_vector_size(vec); j++) {
7784 struct requirement *nreq = requirement_vector_get(vec, j);
7785
7787 struct req_vec_problem *problem;
7788 struct astring astr;
7789 struct astring nastr;
7790
7792 N_("Requirements {%s} and {%s} are the same."),
7794
7795 astr_free(&astr);
7796 astr_free(&nastr);
7797
7798 /* The solution is to remove one of the redundant requirements. */
7799 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7800 problem->suggested_solutions[0].vector_number = vec_num;
7801 problem->suggested_solutions[0].req = *preq;
7802
7803 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7804 problem->suggested_solutions[1].vector_number = vec_num;
7805 problem->suggested_solutions[1].req = *nreq;
7806
7807 /* Only the first redundancy is reported. */
7808 return problem;
7809 }
7810 }
7811 }
7812
7813 return nullptr;
7814}
7815
7816/**********************************************************************/
7828struct req_vec_problem *
7831 const void *parent_item)
7832{
7833 struct req_vec_problem *out;
7834
7836 if (out != nullptr) {
7837 /* A bug, not just a potential improvement */
7838 return out;
7839 }
7840
7841 /* Check if a universal that never will appear in the game is checked. */
7843 if (out != nullptr) {
7844 return out;
7845 }
7846
7847 /* Check if a requirement is redundant. */
7849 return out;
7850}
7851
7852/**********************************************************************/
7857 const struct universal *psource2)
7858{
7859 if (psource1->kind != psource2->kind) {
7860 return FALSE;
7861 }
7862 switch (psource1->kind) {
7863 case VUT_NONE:
7864 return TRUE;
7865 case VUT_COUNTER:
7866 return psource1->value.counter == psource2->value.counter;
7867 case VUT_ADVANCE:
7868 return psource1->value.advance == psource2->value.advance;
7869 case VUT_TECHFLAG:
7870 return psource1->value.techflag == psource2->value.techflag;
7871 case VUT_GOVERNMENT:
7872 return psource1->value.govern == psource2->value.govern;
7873 case VUT_GOVFLAG:
7874 return psource1->value.govflag == psource2->value.govflag;
7875 case VUT_ACHIEVEMENT:
7876 return psource1->value.achievement == psource2->value.achievement;
7877 case VUT_STYLE:
7878 return psource1->value.style == psource2->value.style;
7879 case VUT_IMPROVEMENT:
7880 case VUT_SITE:
7881 return psource1->value.building == psource2->value.building;
7882 case VUT_IMPR_GENUS:
7883 return psource1->value.impr_genus == psource2->value.impr_genus;
7884 case VUT_IMPR_FLAG:
7885 return psource1->value.impr_flag == psource2->value.impr_flag;
7886 case VUT_PLAYER_FLAG:
7887 return psource1->value.plr_flag == psource2->value.plr_flag;
7888 case VUT_PLAYER_STATE:
7889 return psource1->value.plrstate == psource2->value.plrstate;
7890 case VUT_EXTRA:
7891 return psource1->value.extra == psource2->value.extra;
7892 case VUT_TILEDEF:
7894 return psource1->value.tiledef == psource2->value.tiledef;
7895 case VUT_GOOD:
7896 return psource1->value.good == psource2->value.good;
7897 case VUT_TERRAIN:
7898 return psource1->value.terrain == psource2->value.terrain;
7899 case VUT_TERRFLAG:
7900 return psource1->value.terrainflag == psource2->value.terrainflag;
7901 case VUT_NATION:
7902 return psource1->value.nation == psource2->value.nation;
7903 case VUT_NATIONGROUP:
7904 return psource1->value.nationgroup == psource2->value.nationgroup;
7905 case VUT_NATIONALITY:
7906 return psource1->value.nationality == psource2->value.nationality;
7907 case VUT_ORIGINAL_OWNER:
7908 return psource1->value.origowner == psource2->value.origowner;
7909 case VUT_DIPLREL:
7910 case VUT_DIPLREL_TILE:
7911 case VUT_DIPLREL_TILE_O:
7914 return psource1->value.diplrel == psource2->value.diplrel;
7915 case VUT_UTYPE:
7916 return psource1->value.utype == psource2->value.utype;
7917 case VUT_UTFLAG:
7918 return psource1->value.unitflag == psource2->value.unitflag;
7919 case VUT_UCLASS:
7920 return psource1->value.uclass == psource2->value.uclass;
7921 case VUT_UCFLAG:
7922 return psource1->value.unitclassflag == psource2->value.unitclassflag;
7923 case VUT_MINVETERAN:
7924 return psource1->value.minveteran == psource2->value.minveteran;
7925 case VUT_UNITSTATE:
7926 return psource1->value.unit_state == psource2->value.unit_state;
7927 case VUT_ACTIVITY:
7928 return psource1->value.activity == psource2->value.activity;
7929 case VUT_MINMOVES:
7930 return psource1->value.minmoves == psource2->value.minmoves;
7931 case VUT_MINHP:
7932 return psource1->value.min_hit_points == psource2->value.min_hit_points;
7933 case VUT_AGE:
7934 return psource1->value.age == psource2->value.age;
7935 case VUT_FORM_AGE:
7936 return psource1->value.form_age == psource2->value.form_age;
7937 case VUT_MINTECHS:
7938 return psource1->value.min_techs == psource2->value.min_techs;
7939 case VUT_FUTURETECHS:
7940 return psource1->value.future_techs == psource2->value.future_techs;
7941 case VUT_MINCITIES:
7942 return psource1->value.min_cities == psource2->value.min_cities;
7943 case VUT_ACTION:
7944 return (action_number(psource1->value.action)
7945 == action_number(psource2->value.action));
7946 case VUT_OTYPE:
7947 return psource1->value.outputtype == psource2->value.outputtype;
7948 case VUT_SPECIALIST:
7949 return psource1->value.specialist == psource2->value.specialist;
7950 case VUT_MINSIZE:
7951 return psource1->value.minsize == psource2->value.minsize;
7952 case VUT_MINCULTURE:
7953 return psource1->value.minculture == psource2->value.minculture;
7954 case VUT_MINFOREIGNPCT:
7955 return psource1->value.minforeignpct == psource2->value.minforeignpct;
7956 case VUT_AI_LEVEL:
7957 return psource1->value.ai_level == psource2->value.ai_level;
7959 return psource1->value.max_tile_total_units == psource2->value.max_tile_total_units;
7961 return psource1->value.max_tile_top_units == psource2->value.max_tile_top_units;
7962 case VUT_TERRAINCLASS:
7963 return psource1->value.terrainclass == psource2->value.terrainclass;
7964 case VUT_ROADFLAG:
7965 return psource1->value.roadflag == psource2->value.roadflag;
7966 case VUT_EXTRAFLAG:
7967 return psource1->value.extraflag == psource2->value.extraflag;
7968 case VUT_MINYEAR:
7969 return psource1->value.minyear == psource2->value.minyear;
7970 case VUT_MINCALFRAG:
7971 return psource1->value.mincalfrag == psource2->value.mincalfrag;
7972 case VUT_TOPO:
7973 return psource1->value.topo_property == psource2->value.topo_property;
7974 case VUT_WRAP:
7975 return psource1->value.wrap_property == psource2->value.wrap_property;
7976 case VUT_SERVERSETTING:
7977 return psource1->value.ssetval == psource2->value.ssetval;
7978 case VUT_TERRAINALTER:
7979 return psource1->value.terrainalter == psource2->value.terrainalter;
7980 case VUT_CITYTILE:
7981 return psource1->value.citytile == psource2->value.citytile;
7982 case VUT_CITYSTATUS:
7983 return psource1->value.citystatus == psource2->value.citystatus;
7984 case VUT_TILE_REL:
7985 return psource1->value.tilerel == psource2->value.tilerel;
7986 case VUT_MINLATITUDE:
7987 case VUT_MAXLATITUDE:
7988 return psource1->value.latitude == psource2->value.latitude;
7990 return psource1->value.distance_sq == psource2->value.distance_sq;
7992 return psource1->value.region_tiles == psource2->value.region_tiles;
7993 case VUT_COUNT:
7994 break;
7995 }
7996
7997 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
7998 return FALSE;
7999}
8000
8001/**********************************************************************/
8005const char *universal_rule_name(const struct universal *psource)
8006{
8007 static char buffer[10];
8008
8009 switch (psource->kind) {
8010 case VUT_NONE:
8011 return "(none)";
8012 case VUT_COUNTER:
8013 return counter_rule_name(psource->value.counter);
8014 case VUT_CITYTILE:
8015 return citytile_type_name(psource->value.citytile);
8016 case VUT_CITYSTATUS:
8017 return citystatus_type_name(psource->value.citystatus);
8018 case VUT_TILE_REL:
8019 return tilerel_type_name(psource->value.tilerel);
8020 case VUT_MINYEAR:
8021 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
8022
8023 return buffer;
8024 case VUT_MINCALFRAG:
8025 /* Rule name is 0-based number, not pretty name from ruleset */
8026 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
8027
8028 return buffer;
8029 case VUT_TOPO:
8030 return topo_flag_name(psource->value.topo_property);
8031 case VUT_WRAP:
8032 return wrap_flag_name(psource->value.wrap_property);
8033 case VUT_SERVERSETTING:
8034 return ssetv_rule_name(psource->value.ssetval);
8035 case VUT_ADVANCE:
8036 return advance_rule_name(psource->value.advance);
8037 case VUT_TECHFLAG:
8038 return tech_flag_id_name(psource->value.techflag);
8039 case VUT_GOVERNMENT:
8040 return government_rule_name(psource->value.govern);
8041 case VUT_GOVFLAG:
8042 return gov_flag_id_name(psource->value.govflag);
8043 case VUT_ACHIEVEMENT:
8044 return achievement_rule_name(psource->value.achievement);
8045 case VUT_STYLE:
8046 return style_rule_name(psource->value.style);
8047 case VUT_IMPROVEMENT:
8048 case VUT_SITE:
8049 return improvement_rule_name(psource->value.building);
8050 case VUT_IMPR_GENUS:
8051 return impr_genus_id_name(psource->value.impr_genus);
8052 case VUT_IMPR_FLAG:
8053 return impr_flag_id_name(psource->value.impr_flag);
8054 case VUT_PLAYER_FLAG:
8055 return plr_flag_id_name(psource->value.plr_flag);
8056 case VUT_PLAYER_STATE:
8057 return plrstate_type_name(psource->value.plrstate);
8058 case VUT_EXTRA:
8059 return extra_rule_name(psource->value.extra);
8060 case VUT_TILEDEF:
8062 return tiledef_rule_name(psource->value.tiledef);
8063 case VUT_GOOD:
8064 return goods_rule_name(psource->value.good);
8065 case VUT_TERRAIN:
8066 return terrain_rule_name(psource->value.terrain);
8067 case VUT_TERRFLAG:
8068 return terrain_flag_id_name(psource->value.terrainflag);
8069 case VUT_NATION:
8070 return nation_rule_name(psource->value.nation);
8071 case VUT_NATIONGROUP:
8072 return nation_group_rule_name(psource->value.nationgroup);
8073 case VUT_DIPLREL:
8074 case VUT_DIPLREL_TILE:
8075 case VUT_DIPLREL_TILE_O:
8078 return diplrel_rule_name(psource->value.diplrel);
8079 case VUT_NATIONALITY:
8080 return nation_rule_name(psource->value.nationality);
8081 case VUT_ORIGINAL_OWNER:
8082 return nation_rule_name(psource->value.origowner);
8083 case VUT_UTYPE:
8084 return utype_rule_name(psource->value.utype);
8085 case VUT_UTFLAG:
8086 return unit_type_flag_id_name(psource->value.unitflag);
8087 case VUT_UCLASS:
8088 return uclass_rule_name(psource->value.uclass);
8089 case VUT_UCFLAG:
8090 return unit_class_flag_id_name(psource->value.unitclassflag);
8091 case VUT_MINVETERAN:
8092 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
8093
8094 return buffer;
8095 case VUT_UNITSTATE:
8096 return ustate_prop_name(psource->value.unit_state);
8097 case VUT_ACTIVITY:
8098 return unit_activity_name(psource->value.activity);
8099 case VUT_MINMOVES:
8100 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
8101
8102 return buffer;
8103 case VUT_MINHP:
8104 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
8105
8106 return buffer;
8107 case VUT_AGE:
8108 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
8109
8110 return buffer;
8111 case VUT_FORM_AGE:
8112 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
8113
8114 return buffer;
8115 case VUT_MINTECHS:
8116 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
8117
8118 return buffer;
8119 case VUT_FUTURETECHS:
8120 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.future_techs);
8121
8122 return buffer;
8123 case VUT_MINCITIES:
8124 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_cities);
8125
8126 return buffer;
8127 case VUT_ACTION:
8128 return action_rule_name(psource->value.action);
8129 case VUT_OTYPE:
8130 return get_output_identifier(psource->value.outputtype);
8131 case VUT_SPECIALIST:
8132 return specialist_rule_name(psource->value.specialist);
8133 case VUT_MINSIZE:
8134 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
8135
8136 return buffer;
8137 case VUT_MINCULTURE:
8138 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
8139
8140 return buffer;
8141 case VUT_MINFOREIGNPCT:
8142 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
8143
8144 return buffer;
8145 case VUT_AI_LEVEL:
8146 return ai_level_name(psource->value.ai_level);
8148 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_total_units);
8149 return buffer;
8151 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_top_units);
8152 return buffer;
8153 case VUT_TERRAINCLASS:
8154 return terrain_class_name(psource->value.terrainclass);
8155 case VUT_ROADFLAG:
8156 return road_flag_id_name(psource->value.roadflag);
8157 case VUT_EXTRAFLAG:
8158 return extra_flag_id_name(psource->value.extraflag);
8159 case VUT_TERRAINALTER:
8160 return terrain_alteration_name(psource->value.terrainalter);
8161 case VUT_MINLATITUDE:
8162 case VUT_MAXLATITUDE:
8163 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
8164
8165 return buffer;
8167 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.distance_sq);
8168
8169 return buffer;
8171 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.region_tiles);
8172
8173 return buffer;
8174 case VUT_COUNT:
8175 break;
8176 }
8177
8178 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8179
8180 return nullptr;
8181}
8182
8183/**********************************************************************/
8192 char *buf, size_t bufsz)
8193{
8194 buf[0] = '\0'; /* to be safe. */
8195 switch (psource->kind) {
8196 case VUT_NONE:
8197 /* TRANS: missing value */
8198 fc_strlcat(buf, _("(none)"), bufsz);
8199 return buf;
8200 case VUT_ADVANCE:
8202 return buf;
8203 case VUT_COUNTER:
8205 return buf;
8206 case VUT_TECHFLAG:
8207 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
8208 tech_flag_id_translated_name(psource->value.techflag));
8209 return buf;
8210 case VUT_GOVERNMENT:
8212 bufsz);
8213 return buf;
8214 case VUT_GOVFLAG:
8215 cat_snprintf(buf, bufsz, _("\"%s\" gov"),
8216 gov_flag_id_translated_name(psource->value.govflag));
8217 return buf;
8218 case VUT_ACHIEVEMENT:
8220 bufsz);
8221 return buf;
8222 case VUT_STYLE:
8224 bufsz);
8225 return buf;
8226 case VUT_IMPROVEMENT:
8228 bufsz);
8229 return buf;
8230 case VUT_SITE:
8231 {
8232 char local_buf[1024];
8233
8234 fc_snprintf(local_buf, sizeof(local_buf), _("%s site"),
8235 improvement_name_translation(psource->value.building));
8237 }
8238
8239 return buf;
8240 case VUT_IMPR_GENUS:
8242 impr_genus_id_translated_name(psource->value.impr_genus),
8243 bufsz);
8244 return buf;
8245 case VUT_IMPR_FLAG:
8247 impr_flag_id_translated_name(psource->value.impr_flag),
8248 bufsz);
8249 return buf;
8250 case VUT_PLAYER_FLAG:
8252 plr_flag_id_translated_name(psource->value.plr_flag),
8253 bufsz);
8254 return buf;
8255 case VUT_PLAYER_STATE:
8257 plrstate_type_translated_name(psource->value.plrstate),
8258 bufsz);
8259 return buf;
8260 case VUT_EXTRA:
8262 return buf;
8263 case VUT_TILEDEF:
8266 return buf;
8267 case VUT_GOOD:
8269 return buf;
8270 case VUT_TERRAIN:
8272 return buf;
8273 case VUT_NATION:
8275 bufsz);
8276 return buf;
8277 case VUT_NATIONGROUP:
8279 bufsz);
8280 return buf;
8281 case VUT_NATIONALITY:
8282 cat_snprintf(buf, bufsz, _("%s citizens"),
8283 nation_adjective_translation(psource->value.nationality));
8284 return buf;
8285 case VUT_ORIGINAL_OWNER:
8286 /* TRANS: Keep short. City founding nation. */
8287 cat_snprintf(buf, bufsz, _("%s original owner"),
8288 nation_adjective_translation(psource->value.origowner));
8289 return buf;
8290 case VUT_DIPLREL:
8291 case VUT_DIPLREL_TILE:
8292 case VUT_DIPLREL_TILE_O:
8296 bufsz);
8297 return buf;
8298 case VUT_UTYPE:
8300 return buf;
8301 case VUT_UTFLAG:
8303 /* TRANS: Unit type flag */
8304 Q_("?utflag:\"%s\" units"),
8306 psource->value.unitflag));
8307 return buf;
8308 case VUT_UCLASS:
8310 /* TRANS: Unit class */
8311 _("%s units"),
8312 uclass_name_translation(psource->value.uclass));
8313 return buf;
8314 case VUT_UCFLAG:
8316 /* TRANS: Unit class flag */
8317 Q_("?ucflag:\"%s\" units"),
8319 psource->value.unitclassflag));
8320 return buf;
8321 case VUT_MINVETERAN:
8322 /* FIXME */
8323 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
8324 psource->value.minveteran);
8325 return buf;
8326 case VUT_UNITSTATE:
8327 switch (psource->value.unit_state) {
8328 case USP_TRANSPORTED:
8329 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
8330 cat_snprintf(buf, bufsz, _("Transported"));
8331 break;
8332 case USP_LIVABLE_TILE:
8334 /* TRANS: unit state. (appears in strings like
8335 * "Missile+On livable tile") */
8336 _("On livable tile"));
8337 break;
8338 case USP_TRANSPORTING:
8339 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
8340 cat_snprintf(buf, bufsz, _("Transporting"));
8341 break;
8342 case USP_HAS_HOME_CITY:
8343 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
8344 cat_snprintf(buf, bufsz, _("Has a home city"));
8345 break;
8346 case USP_NATIVE_TILE:
8348 /* TRANS: unit state. (appears in strings like
8349 * "Missile+On native tile") */
8350 _("On native tile"));
8351 break;
8352 case USP_NATIVE_EXTRA:
8354 /* TRANS: unit state. (appears in strings like
8355 * "Missile+In native extra") */
8356 _("In native extra"));
8357 break;
8359 /* TRANS: unit state. (appears in strings like
8360 * "Missile+Has moved this turn") */
8361 cat_snprintf(buf, bufsz, _("Has moved this turn"));
8362 break;
8363 case USP_COUNT:
8364 fc_assert_msg(psource->value.unit_state != USP_COUNT,
8365 "Invalid unit state property.");
8366 break;
8367 }
8368 return buf;
8369 case VUT_ACTIVITY:
8370 cat_snprintf(buf, bufsz, _("%s activity"),
8371 Q_(unit_activity_name(psource->value.activity)));
8372 return buf;
8373 case VUT_MINMOVES:
8374 /* TRANS: Minimum unit movement points left for requirement to be met
8375 * (%s is a string like "1" or "2 1/3") */
8376 cat_snprintf(buf, bufsz, _("%s MP"),
8377 move_points_text(psource->value.minmoves, TRUE));
8378 return buf;
8379 case VUT_MINHP:
8380 /* TRANS: HP = hit points */
8381 cat_snprintf(buf, bufsz, _("%d HP"),
8382 psource->value.min_hit_points);
8383 return buf;
8384 case VUT_AGE:
8385 cat_snprintf(buf, bufsz, _("Age %d"),
8386 psource->value.age);
8387 return buf;
8388 case VUT_FORM_AGE:
8389 cat_snprintf(buf, bufsz, _("Form age %d"),
8390 psource->value.form_age);
8391 return buf;
8392 case VUT_MINTECHS:
8393 cat_snprintf(buf, bufsz, _("%d Techs"),
8394 psource->value.min_techs);
8395 return buf;
8396 case VUT_FUTURETECHS:
8397 cat_snprintf(buf, bufsz, _("%d Future techs"),
8398 psource->value.future_techs);
8399 return buf;
8400 case VUT_MINCITIES:
8401 cat_snprintf(buf, bufsz, _("%d Cities"),
8402 psource->value.min_cities);
8403 return buf;
8404 case VUT_ACTION:
8406 bufsz);
8407 return buf;
8408 case VUT_OTYPE:
8409 /* FIXME */
8410 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
8411 return buf;
8412 case VUT_SPECIALIST:
8414 bufsz);
8415 return buf;
8416 case VUT_MINSIZE:
8417 cat_snprintf(buf, bufsz, _("Size %d"),
8418 psource->value.minsize);
8419 return buf;
8420 case VUT_MINCULTURE:
8421 cat_snprintf(buf, bufsz, _("Culture %d"),
8422 psource->value.minculture);
8423 return buf;
8424 case VUT_MINFOREIGNPCT:
8425 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
8426 psource->value.minforeignpct);
8427 return buf;
8428 case VUT_AI_LEVEL:
8429 /* TRANS: "Hard AI" */
8430 cat_snprintf(buf, bufsz, _("%s AI"),
8431 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
8432 return buf;
8434 /* TRANS: here <= means 'less than or equal' */
8435 cat_snprintf(buf, bufsz, PL_("<=%d total unit",
8436 "<=%d total units",
8437 psource->value.max_tile_total_units),
8438 psource->value.max_tile_total_units);
8439 return buf;
8441 /* TRANS: here <= means 'less than or equal' */
8442 cat_snprintf(buf, bufsz, PL_("<=%d unit",
8443 "<=%d units", psource->value.max_tile_top_units),
8444 psource->value.max_tile_top_units);
8445 return buf;
8446 case VUT_TERRAINCLASS:
8447 /* TRANS: Terrain class: "Land terrain" */
8448 cat_snprintf(buf, bufsz, _("%s terrain"),
8449 terrain_class_name_translation(psource->value.terrainclass));
8450 return buf;
8451 case VUT_TERRFLAG:
8453 /* TRANS: Terrain flag */
8454 Q_("?terrflag:\"%s\" terrain"),
8456 psource->value.terrainflag));
8457 return buf;
8458 case VUT_ROADFLAG:
8460 /* TRANS: Road flag */
8461 Q_("?roadflag:\"%s\" road"),
8462 road_flag_id_translated_name(psource->value.roadflag));
8463 return buf;
8464 case VUT_EXTRAFLAG:
8466 /* TRANS: Extra flag */
8467 Q_("?extraflag:\"%s\" extra"),
8468 extra_flag_id_translated_name(psource->value.extraflag));
8469 return buf;
8470 case VUT_MINYEAR:
8471 cat_snprintf(buf, bufsz, _("After %s"),
8472 textyear(psource->value.minyear));
8473 return buf;
8474 case VUT_MINCALFRAG:
8475 /* TRANS: here >= means 'greater than or equal'.
8476 * %s identifies a calendar fragment (may be bare number). */
8477 cat_snprintf(buf, bufsz, _(">=%s"),
8478 textcalfrag(psource->value.mincalfrag));
8479 return buf;
8480 case VUT_TOPO:
8481 /* TRANS: topology flag name ("Hex", "ISO") */
8482 cat_snprintf(buf, bufsz, _("%s map"),
8483 _(topo_flag_name(psource->value.topo_property)));
8484 return buf;
8485 case VUT_WRAP:
8486 /* TRANS: wrap flag name ("WrapX", "WrapY") */
8487 cat_snprintf(buf, bufsz, _("%s map"),
8488 _(wrap_flag_name(psource->value.wrap_property)));
8489 return buf;
8490 case VUT_SERVERSETTING:
8492 bufsz);
8493 return buf;
8494 case VUT_TERRAINALTER:
8495 /* TRANS: "Irrigation possible" */
8496 cat_snprintf(buf, bufsz, _("%s possible"),
8497 Q_(terrain_alteration_name(psource->value.terrainalter)));
8498 return buf;
8499 case VUT_CITYTILE:
8500 switch (psource->value.citytile) {
8501 case CITYT_CENTER:
8502 fc_strlcat(buf, _("City center"), bufsz);
8503 break;
8504 case CITYT_CLAIMED:
8505 fc_strlcat(buf, _("Tile claimed"), bufsz);
8506 break;
8507 case CITYT_EXTRAS_OWNED:
8508 fc_strlcat(buf, _("Extras owned"), bufsz);
8509 break;
8510 case CITYT_WORKED:
8511 fc_strlcat(buf, _("Worked tile"), bufsz);
8512 break;
8514 fc_strlcat(buf, _("Same continent tile"), bufsz);
8515 break;
8517 /* TRANS: Short for "a tile of other terrain class mass near city" */
8518 fc_strlcat(buf, _("Port reachable tile"), bufsz);
8519 break;
8520 case CITYT_LAST:
8521 fc_assert(psource->value.citytile != CITYT_LAST);
8522 fc_strlcat(buf, "error", bufsz);
8523 break;
8524 }
8525 return buf;
8526 case VUT_CITYSTATUS:
8527 switch (psource->value.citystatus) {
8529 fc_strlcat(buf, _("Owned by original"), bufsz);
8530 break;
8531 case CITYS_STARVED:
8532 fc_strlcat(buf, _("Starved"), bufsz);
8533 break;
8534 case CITYS_DISORDER:
8535 fc_strlcat(buf, _("Disorder"), bufsz);
8536 break;
8537 case CITYS_CELEBRATION:
8538 fc_strlcat(buf, _("Celebration"), bufsz);
8539 break;
8540 case CITYS_TRANSFERRED:
8541 /* TRANS: CityStatus value - city has changed hands */
8542 fc_strlcat(buf, _("Transferred"), bufsz);
8543 break;
8545 fc_strlcat(buf, _("CapitalConnected"), bufsz);
8546 break;
8547 case CITYS_LAST:
8548 fc_assert(psource->value.citystatus != CITYS_LAST);
8549 fc_strlcat(buf, "error", bufsz);
8550 break;
8551 }
8552 return buf;
8553 case VUT_TILE_REL:
8554 switch (psource->value.tilerel) {
8555 case TREL_SAME_TCLASS:
8556 fc_strlcat(buf, _("Same terrain class"), bufsz);
8557 break;
8558 case TREL_SAME_REGION:
8559 fc_strlcat(buf, _("Same continent/ocean"), bufsz);
8560 break;
8562 fc_strlcat(buf, _("Only other continent/ocean"), bufsz);
8563 break;
8565 fc_strlcat(buf, _("Lake/island surrounded"), bufsz);
8566 break;
8567 case TREL_COUNT:
8568 fc_assert(psource->value.tilerel != TREL_COUNT);
8569 fc_strlcat(buf, "error", bufsz);
8570 break;
8571 }
8572 return buf;
8573 case VUT_MINLATITUDE:
8574 /* TRANS: here >= means 'greater than or equal'. */
8575 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
8576 psource->value.latitude);
8577 return buf;
8578 case VUT_MAXLATITUDE:
8579 /* TRANS: here <= means 'less than or equal'. */
8580 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
8581 psource->value.latitude);
8582 return buf;
8584 /* TRANS: here <= means 'less than or equal'. */
8585 cat_snprintf(buf, bufsz, _("Squared distance <= %d"),
8586 psource->value.distance_sq);
8587 return buf;
8589 cat_snprintf(buf, bufsz, _("%d or fewer region tiles"),
8590 psource->value.region_tiles);
8591 return buf;
8592 case VUT_COUNT:
8593 break;
8594 }
8595
8596 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8597 return buf;
8598}
8599
8600/**********************************************************************/
8604{
8605 return universals_n_name(psource->kind);
8606}
8607
8608/**********************************************************************/
8612 const struct universal *target)
8613{
8614 switch (target->kind) {
8615 case VUT_IMPROVEMENT:
8616 case VUT_SITE:
8617 return impr_build_shield_cost(pcity, target->value.building);
8618 case VUT_UTYPE:
8619 return utype_build_shield_cost(pcity, nullptr, target->value.utype);
8620 default:
8621 break;
8622 }
8623 return FC_INFINITY;
8624}
8625
8626/**********************************************************************/
8632 const struct universal *to_replace,
8633 const struct universal *replacement)
8634{
8635 bool changed = FALSE;
8636
8639 preq->source = *replacement;
8640 changed = TRUE;
8641 }
8643
8644 return changed;
8645}
8646
8647/**********************************************************************/
8652 const struct requirement_vector *reqs,
8653 const struct universal *psource)
8654{
8657 return TRUE;
8658 }
8660
8661 return FALSE;
8662}
8663
8664/**********************************************************************/
8675 struct universal *unis,
8676 size_t n_unis)
8677{
8678 int i;
8679
8680 for (i = 0; i < n_unis; i++) {
8682 /* This universal makes it impossible to fulfill the specified
8683 * requirement vector */
8684 return TRUE;
8685 }
8686 }
8687
8688 /* No specified universal is known to guarantee that the requirement
8689 * vector never will be fulfilled. */
8690 return FALSE;
8691}
8692
8693/**********************************************************************/
8709 struct universal *unis,
8710 size_t n_unis)
8711{
8713 int i;
8715
8716 for (i = 0; i < n_unis; i++) {
8717 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
8718 case ITF_NO:
8719 case ITF_YES:
8720 /* this req matched this source */
8722 break;
8723 case ITF_NOT_APPLICABLE:
8724 /* Not a mention. */
8725 break;
8726 }
8727 }
8728
8730 /* A requirement not relevant to any of the specified universals was
8731 * found in the requirement vector. */
8732 return FALSE;
8733 }
8735
8736 /* No requirement not relevant to any of the specified universals was
8737 * found in the requirement vector. */
8738 return TRUE;
8739}
8740
8741/**********************************************************************/
8744enum req_item_found
8746 const struct universal *source)
8747{
8750 "No req item found function for %s",
8752
8753 return (*universal_found_function[source->kind])(preq, source);
8754}
8755
8756/**********************************************************************/
8767 const struct requirement_vector *reqs,
8768 const struct universal *source)
8769{
8770 bool necessary = FALSE;
8771
8774 "No req item found function for %s",
8776
8778 switch ((*universal_found_function[source->kind])(preq, source)) {
8779 case ITF_NOT_APPLICABLE:
8780 continue;
8781 case ITF_NO:
8782 if (preq->present) {
8783 return FALSE;
8784 }
8785 break;
8786 case ITF_YES:
8787 if (preq->present) {
8788 necessary = TRUE;
8789 } else {
8790 return FALSE;
8791 }
8792 break;
8793 }
8795
8796 return (!check_necessary || necessary);
8797}
8798
8799/**********************************************************************/
8804 const struct universal *source)
8805{
8806 switch (universal_fulfills_requirement(req, source)) {
8807 case ITF_NOT_APPLICABLE:
8808 return FALSE;
8809 case ITF_NO:
8810 case ITF_YES:
8811 return TRUE;
8812 }
8813
8814 log_error("Unhandled item_found value");
8815 return FALSE;
8816}
8817
8818/**********************************************************************/
8822 const struct universal *source)
8823{
8824 fc_assert(source->value.nation);
8825
8826 switch (preq->source.kind) {
8827 case VUT_NATION:
8828 return preq->source.value.nation == source->value.nation ? ITF_YES
8829 : ITF_NO;
8830 case VUT_NATIONGROUP:
8831 return nation_is_in_group(source->value.nation,
8832 preq->source.value.nationgroup) ? ITF_YES
8833 : ITF_NO;
8834 default:
8835 break;
8836 }
8837
8838 return ITF_NOT_APPLICABLE;
8839}
8840
8841/**********************************************************************/
8845 const struct universal *source)
8846{
8847 fc_assert(source->value.govern);
8848
8849 if (preq->source.kind == VUT_GOVERNMENT) {
8850 return preq->source.value.govern == source->value.govern ? ITF_YES
8851 : ITF_NO;
8852 } else if (preq->source.kind == VUT_GOVFLAG) {
8853 return BV_ISSET(source->value.govern->flags, preq->source.value.govflag)
8854 ? ITF_YES : ITF_NO;
8855 }
8856
8857 return ITF_NOT_APPLICABLE;
8858}
8859
8860/**********************************************************************/
8864 const struct universal *source)
8865{
8866 fc_assert(source->value.min_cities);
8867
8868 if (preq->source.kind == VUT_MINCITIES) {
8869 return preq->source.value.min_cities <= source->value.min_cities ? ITF_YES
8870 : ITF_NO;
8871 }
8872
8873 return ITF_NOT_APPLICABLE;
8874}
8875
8876/**********************************************************************/
8880 const struct universal *source)
8881{
8882 fc_assert(source->value.building);
8883
8884 /* We only ever return ITF_YES, because requiring a different
8885 * improvement does not mean that the improvement under consideration
8886 * cannot fulfill the requirements. This is necessary to allow
8887 * requirement vectors to specify multiple required improvements. */
8888
8889 switch (preq->source.kind) {
8890 case VUT_IMPROVEMENT:
8891 case VUT_SITE:
8892 if (source->value.building == preq->source.value.building) {
8893 return ITF_YES;
8894 }
8895 break;
8896 case VUT_IMPR_GENUS:
8897 if (source->value.building->genus == preq->source.value.impr_genus) {
8898 return ITF_YES;
8899 }
8900 break;
8901 case VUT_IMPR_FLAG:
8902 if (improvement_has_flag(source->value.building,
8903 preq->source.value.impr_flag)) {
8904 return ITF_YES;
8905 }
8906 break;
8907 default:
8908 break;
8909 }
8910
8911 return ITF_NOT_APPLICABLE;
8912}
8913
8914/**********************************************************************/
8918 const struct universal *source)
8919{
8920 fc_assert(source->value.uclass);
8921
8922 switch (preq->source.kind) {
8923 case VUT_UCLASS:
8924 return source->value.uclass == preq->source.value.uclass ? ITF_YES
8925 : ITF_NO;
8926 case VUT_UCFLAG:
8927 return uclass_has_flag(source->value.uclass,
8928 preq->source.value.unitclassflag) ? ITF_YES
8929 : ITF_NO;
8930
8931 default:
8932 /* Not found and not relevant. */
8933 return ITF_NOT_APPLICABLE;
8934 };
8935}
8936
8937/**********************************************************************/
8941 const struct universal *source)
8942{
8943 fc_assert(source->value.utype);
8944
8945 switch (preq->source.kind) {
8946 case VUT_UTYPE:
8947 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
8948 case VUT_UCLASS:
8949 return utype_class(source->value.utype) == preq->source.value.uclass
8950 ? ITF_YES : ITF_NO;
8951 case VUT_UTFLAG:
8952 return utype_has_flag(source->value.utype,
8953 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
8954 case VUT_UCFLAG:
8955 return uclass_has_flag(utype_class(source->value.utype),
8956 preq->source.value.unitclassflag) ? ITF_YES
8957 : ITF_NO;
8958 default:
8959 /* Not found and not relevant. */
8960 return ITF_NOT_APPLICABLE;
8961 };
8962}
8963
8964/**********************************************************************/
8967static enum req_item_found
8969 const struct universal *source)
8970{
8973
8974 switch (preq->source.kind) {
8975 case VUT_ACTIVITY:
8976 return source->value.activity == preq->source.value.activity ? ITF_YES
8977 : ITF_NO;
8978 default:
8979 /* Not found and not relevant. */
8980 return ITF_NOT_APPLICABLE;
8981 };
8982}
8983
8984/**********************************************************************/
8988 const struct universal *source)
8989{
8990 fc_assert(source->value.terrain);
8991
8992 switch (preq->source.kind) {
8993 case VUT_TERRAIN:
8994 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
8995 case VUT_TERRAINCLASS:
8996 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
8997 ? ITF_YES : ITF_NO;
8998 case VUT_TERRFLAG:
8999 return terrain_has_flag(source->value.terrain,
9000 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
9001 case VUT_TERRAINALTER:
9002 return (terrain_can_support_alteration(source->value.terrain,
9003 preq->source.value.terrainalter)
9004 ? ITF_YES : ITF_NO);
9005 default:
9006 /* Not found and not relevant. */
9007 return ITF_NOT_APPLICABLE;
9008 };
9009}
9010
9011/**********************************************************************/
9015 const struct universal *source)
9016{
9019
9020 switch (preq->source.kind) {
9021 case VUT_CITYTILE:
9022 return (source->value.citytile == preq->source.value.citytile
9023 ? ITF_YES
9024 /* The presence of one tile state doesn't block another */
9026 default:
9027 /* Not found and not relevant. */
9028 return ITF_NOT_APPLICABLE;
9029 };
9030}
9031
9032/**********************************************************************/
9038 const struct universal *source)
9039{
9040 fc_assert(source->value.extra);
9041
9042 switch (preq->source.kind) {
9043 case VUT_EXTRA:
9044 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
9045 case VUT_EXTRAFLAG:
9046 return extra_has_flag(source->value.extra,
9047 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
9048 case VUT_ROADFLAG:
9049 {
9050 struct road_type *r = extra_road_get(source->value.extra);
9051 return r && road_has_flag(r, preq->source.value.roadflag)
9052 ? ITF_YES : ITF_NO;
9053 }
9054 default:
9055 /* Not found and not relevant. */
9056 return ITF_NOT_APPLICABLE;
9057 }
9058}
9059
9060/**********************************************************************/
9064 const struct universal *source)
9065{
9066 fc_assert(source->value.action);
9067
9068 if (preq->source.kind == VUT_ACTION) {
9069 return preq->source.value.action == source->value.action ? ITF_YES
9070 : ITF_NO;
9071 }
9072
9073 return ITF_NOT_APPLICABLE;
9074}
9075
9076/**********************************************************************/
9080 const struct universal *source)
9081{
9083 || source->kind == VUT_DIPLREL_TILE
9084 || source->kind == VUT_DIPLREL_TILE_O
9085 || source->kind == VUT_DIPLREL_UNITANY
9086 || source->kind == VUT_DIPLREL_UNITANY_O),
9088
9089 if (preq->source.kind == source->kind) {
9090 if (preq->source.value.diplrel == source->value.diplrel) {
9091 /* The diplrel itself. */
9092 return ITF_YES;
9093 }
9094 if (preq->source.value.diplrel == DRO_FOREIGN
9095 && source->value.diplrel < DS_LAST) {
9096 /* All diplstate_type values are to foreigners. */
9097 return ITF_YES;
9098 }
9099 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
9100 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
9101 /* A real embassy is an embassy. */
9102 return ITF_YES;
9103 }
9104 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
9105 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
9106 /* A real embassy is an embassy. */
9107 return ITF_YES;
9108 }
9109 if (preq->source.value.diplrel < DS_LAST
9110 && source->value.diplrel < DS_LAST
9111 && preq->range == REQ_RANGE_LOCAL) {
9112 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
9113 ITF_YES);
9114 /* Can only have one diplstate_type to a specific player. */
9115 return ITF_NO;
9116 }
9117 /* Can't say this diplrel blocks the other diplrel. */
9118 return ITF_NOT_APPLICABLE;
9119 }
9120
9121 /* Not relevant. */
9122 return ITF_NOT_APPLICABLE;
9123}
9124
9125/**********************************************************************/
9129 const struct universal *source)
9130{
9131 switch (preq->source.kind) {
9132 case VUT_OTYPE:
9133 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
9134 : ITF_NO;
9135 default:
9136 /* Not found and not relevant. */
9137 return ITF_NOT_APPLICABLE;
9138 }
9139}
9140
9141/**********************************************************************/
9145 const struct universal *source)
9146{
9147 if (preq->range != REQ_RANGE_LOCAL) {
9148 return ITF_NOT_APPLICABLE;
9149 }
9150
9151 if (preq->source.kind == VUT_UNITSTATE) {
9152 switch (source->value.unit_state) {
9153 case USP_TRANSPORTED:
9154 case USP_TRANSPORTING:
9155 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
9156 case USP_LIVABLE_TILE:
9157 case USP_NATIVE_TILE:
9158 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
9159 * UTYF_COAST_STRICT. */
9160 case USP_HAS_HOME_CITY:
9161 case USP_NATIVE_EXTRA:
9163 if (source->value.unit_state == preq->source.value.unit_state) {
9164 /* The other unit states doesn't contradict */
9165 return ITF_YES;
9166 }
9167 break;
9168 case USP_COUNT:
9169 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
9171 }
9172 }
9173
9174 /* Not found and not relevant. */
9175 return ITF_NOT_APPLICABLE;
9176}
9177
9178/**********************************************************************/
9203
9204/**********************************************************************/
9212int requirement_kind_ereq(const int value,
9213 const enum req_range range,
9214 const bool present,
9215 const int max_value)
9216{
9217 /* The enumerators in each range starts with present for every possible
9218 * value followed by !present for every possible value. */
9219 const int pres_start = (present ? 0 : max_value);
9220
9221 /* The enumerators for every range follows all the positions of the
9222 * previous range(s). */
9223 const int range_start = ((max_value - 1) * 2) * range;
9224
9225 return range_start + pres_start + value;
9226}
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:5915
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:1292
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:876
#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:842
#define city_built_iterate_end
Definition city.h:848
static struct ai_type * self
Definition classicai.c:47
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:55
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:56
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:73
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:77
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:141
struct government * government_by_number(const Government_type_id gov)
Definition government.c:103
struct government * government_of_player(const struct player *pplayer)
Definition government.c:115
Government_type_id government_number(const struct government *pgovern)
Definition government.c:92
const char * government_rule_name(const struct government *pgovern)
Definition government.c:132
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:417
bool is_road_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:447
bool is_road_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:426
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:141
const struct unit_type * utype
Definition unit.h:140
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:925
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:742
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:787
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:951
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:851
#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
bool is_tiledef_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct tiledef *ptd, const struct player *pplayer)
Definition tiledef.c:177
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 is_tiledef_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct tiledef *ptd, const struct player *pplayer)
Definition tiledef.c:193
bool tile_matches_tiledef(const struct tiledef *td, const struct tile *ptile, const struct player *pplayer)
Definition tiledef.c:150
const char * tiledef_name_translation(const struct tiledef *td)
Definition tiledef.c:95
#define tiledef_index(_td_)
Definition tiledef.h:44
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:1841
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2512
#define unit_tile(_pu)
Definition unit.h:408
#define unit_owner(_pu)
Definition unit.h:407
#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:1794
bool uclass_flag_is_in_use(enum unit_class_flag_id ucflag)
Definition unittype.c:3018
struct unit_class * uclass_by_number(const Unit_Class_id id)
Definition unittype.c:2511
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:2535
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:1811
bool utype_flag_is_in_use(enum unit_type_flag_id uflag)
Definition unittype.c:3037
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:2502
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