Freeciv-3.4
Loading...
Searching...
No Matches
requirements.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2004 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17#include <stdarg.h>
18
19/* utility */
20#include "astring.h"
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "achievements.h"
27#include "calendar.h"
28#include "citizens.h"
29#include "counters.h"
30#include "culture.h"
31#include "game.h"
32#include "government.h"
33#include "improvement.h"
34#include "movement.h"
35#include "nation.h"
36#include "player.h"
37#include "map.h"
38#include "research.h"
39#include "road.h"
40#include "server_settings.h"
41#include "specialist.h"
42#include "style.h"
43#include "tiledef.h"
44#include "victory.h" /* victory_enabled() */
45
46#include "requirements.h"
47
52
53/* get 'struct thr_req_data_list' and related functions: */
54#define SPECLIST_TAG thr_req_data
55#define SPECLIST_TYPE struct thr_req_data
56#include "speclist.h"
57
58#define thr_req_data_list_iterate(trlist, ptrdata) \
59 TYPED_LIST_ITERATE(struct thr_req_data, trlist, ptrdata)
60#define thr_req_data_list_iterate_end LIST_ITERATE_END
61
64
65/************************************************************************
66 Container for req_item_found functions
67************************************************************************/
68typedef enum req_item_found (*universal_found)(const struct requirement *,
69 const struct universal *);
71
72static
74 const struct req_context *context,
75 const struct req_context *other_context,
76 const struct requirement *req);
77
78/* Function pointer for requirement-type-specific is_req_active handlers */
79typedef enum fc_tristate
80(*is_req_active_cb)(const struct civ_map *nmap,
81 const struct req_context *context,
82 const struct req_context *other_context,
83 const struct requirement *req);
84
85static inline bool are_tiles_in_range(const struct tile *tile1,
86 const struct tile *tile2,
87 enum req_range range);
88
89/**********************************************************************/
94static enum req_unchanging_status
96 enum req_unchanging_status def,
97 const struct req_context *context,
98 const struct requirement *req)
99{
100 return req->range == REQ_RANGE_LOCAL ? REQUCH_YES : def;
101}
102#define REQUC_LOCAL unchanging_local
103
104/**********************************************************************/
107static enum req_unchanging_status
109 enum req_unchanging_status def,
110 const struct req_context *context,
111 const struct requirement *req)
112{
113 if (TRI_YES != tri_req_present(nmap, context, nullptr, req)) {
114 return REQUCH_NO;
115 }
116 return def;
117}
118#define REQUC_PRESENT unchanging_present
119
120/**********************************************************************/
123static enum req_unchanging_status
125 enum req_unchanging_status def,
126 const struct req_context *context,
127 const struct requirement *req)
128{
129 return
131 context, req);
132}
133#define REQUC_WORLD unchanging_world
134
135/**********************************************************************/
139static enum req_unchanging_status
141 enum req_unchanging_status def,
142 const struct req_context *context,
143 const struct requirement *req)
144{
145 if (REQ_RANGE_ALLIANCE == req->range
146 || REQ_RANGE_TEAM == req->range) {
147 struct requirement preq;
148
149 req_copy(&preq, req);
150 preq.range = REQ_RANGE_PLAYER;
151 if (TRI_YES != tri_req_present(nmap, context, nullptr, &preq)) {
152 return REQ_RANGE_TEAM == req->range ? REQUCH_ACT : REQUCH_NO;
153 }
154 }
155 return def;
156}
157#define REQUC_NALLY unchanging_noally
158
159/**********************************************************************/
162static enum req_unchanging_status
164 enum req_unchanging_status def,
165 const struct req_context *context,
166 const struct requirement *req)
167{
171 && context->city != nullptr && context->tile != nullptr
172 && city_tile(context->city) != nullptr
174 req->range))){
175 /* Cities don't move, and most reqs are present on city center */
176 return REQUCH_YES;
177 }
178 return def;
179}
180#define REQUC_CITYTILE unchanging_citytile
181
182/**********************************************************************/
185static enum req_unchanging_status
187 enum req_unchanging_status def,
188 const struct req_context *context,
189 const struct requirement *req)
190{
192
193 if (REQ_RANGE_CITY == req->range
196 return REQUCH_CTRL;
197 }
198
199 return def;
200}
201#define REQUC_CITYSTATUS unchanging_citystatus
202
203/**********************************************************************/
208static enum req_unchanging_status
210 enum req_unchanging_status def,
211 const struct req_context *context,
212 const struct requirement *req)
213{
214 const struct impr_type *b = req->source.value.building;
215
217 || VUT_SITE == req->source.kind, REQUCH_NO);
218 if (REQ_RANGE_LOCAL == req->range) {
219 /* Likely, won't be questioned for an obsolete building */
220 return REQUCH_YES;
221 }
222
223 if (req->source.kind == VUT_IMPROVEMENT
224 && improvement_obsolete(context->player, b, context->city)) {
225 /* FIXME: Sometimes can unobsolete, but considering it
226 * may sometimes put the function on endless recursion */
227 return REQUCH_ACT; /* Mostly about techs */
228 }
229 if (is_great_wonder(b)) {
232 && (req->range <= REQ_RANGE_CITY && TRI_YES
233 == tri_req_present(nmap, context, nullptr, req)))) {
234 /* If the wonder stays somewhere, it may either remain there
235 * or be destroyed. If it is destroyed, it is nowhere. */
236 return REQUCH_SCRIPTS;
237 }
238 }
239 return def;
240}
241#define REQUC_IMPR unchanging_building
242
248
249/**********************************************************************/
252static void thr_exit_cb(void)
253{
255
258 if (fc_threads_equal(self, data->thr_id)) {
260 free(data);
261 break;
262 }
265}
266
267/**********************************************************************/
276
277/**********************************************************************/
285
286/**********************************************************************/
294 const char *value)
295{
296 struct universal source;
297
299 if (!universals_n_is_valid(source.kind)) {
300 return source;
301 }
302
304
305 return source;
306}
307
308/**********************************************************************/
313{
314 return unit_activity_is_valid(act)
315 && act != ACTIVITY_SENTRY
316 && act != ACTIVITY_GOTO
317 && act != ACTIVITY_EXPLORE;
318}
319
320/**********************************************************************/
325{
326 if (univ->kind == VUT_ACTIVITY) {
328 }
329
330 return TRUE;
331}
332
333/**********************************************************************/
338{
339 /* Finally scan the value string based on the type of the source. */
340 switch (source->kind) {
341 case VUT_NONE:
342 return;
343 case VUT_ADVANCE:
344 source->value.advance = advance_by_rule_name(value);
345 if (source->value.advance != nullptr) {
346 return;
347 }
348 break;
349 case VUT_TECHFLAG:
350 source->value.techflag
352 if (tech_flag_id_is_valid(source->value.techflag)) {
353 return;
354 }
355 break;
356 case VUT_GOVERNMENT:
357 source->value.govern = government_by_rule_name(value);
358 if (source->value.govern != nullptr) {
359 return;
360 }
361 break;
362 case VUT_GOVFLAG:
364 if (gov_flag_id_is_valid(source->value.govflag)) {
365 return;
366 }
367 break;
368 case VUT_ACHIEVEMENT:
369 source->value.achievement = achievement_by_rule_name(value);
370 if (source->value.achievement != nullptr) {
371 return;
372 }
373 break;
374 case VUT_STYLE:
375 source->value.style = style_by_rule_name(value);
376 if (source->value.style != nullptr) {
377 return;
378 }
379 break;
380 case VUT_IMPROVEMENT:
381 case VUT_SITE:
382 source->value.building = improvement_by_rule_name(value);
383 if (source->value.building != nullptr) {
384 return;
385 }
386 break;
387 case VUT_IMPR_GENUS:
388 source->value.impr_genus = impr_genus_id_by_name(value, fc_strcasecmp);
389 if (impr_genus_id_is_valid(source->value.impr_genus)) {
390 return;
391 }
392 break;
393 case VUT_IMPR_FLAG:
394 source->value.impr_flag = impr_flag_id_by_name(value, fc_strcasecmp);
395 if (impr_flag_id_is_valid(source->value.impr_flag)) {
396 return;
397 }
398 break;
399 case VUT_PLAYER_FLAG:
400 source->value.plr_flag = plr_flag_id_by_name(value, fc_strcasecmp);
401 if (plr_flag_id_is_valid(source->value.plr_flag)) {
402 return;
403 }
404 break;
405 case VUT_EXTRA:
406 source->value.extra = extra_type_by_rule_name(value);
407 if (source->value.extra != nullptr) {
408 return;
409 }
410 break;
411 case VUT_TILEDEF:
413 source->value.tiledef = tiledef_by_rule_name(value);
414 if (source->value.tiledef != nullptr) {
415 return;
416 }
417 break;
418 case VUT_GOOD:
419 source->value.good = goods_by_rule_name(value);
420 if (source->value.good != nullptr) {
421 return;
422 }
423 break;
424 case VUT_TERRAIN:
425 source->value.terrain = terrain_by_rule_name(value);
426 if (source->value.terrain != T_UNKNOWN) {
427 return;
428 }
429 break;
430 case VUT_TERRFLAG:
431 source->value.terrainflag
433 if (terrain_flag_id_is_valid(source->value.terrainflag)) {
434 return;
435 }
436 break;
437 case VUT_NATION:
438 source->value.nation = nation_by_rule_name(value);
439 if (source->value.nation != NO_NATION_SELECTED) {
440 return;
441 }
442 break;
443 case VUT_NATIONGROUP:
444 source->value.nationgroup = nation_group_by_rule_name(value);
445 if (source->value.nationgroup != nullptr) {
446 return;
447 }
448 break;
449 case VUT_NATIONALITY:
450 source->value.nationality = nation_by_rule_name(value);
451 if (source->value.nationality != NO_NATION_SELECTED) {
452 return;
453 }
454 break;
456 source->value.origowner = nation_by_rule_name(value);
457 if (source->value.origowner != NO_NATION_SELECTED) {
458 return;
459 }
460 break;
461 case VUT_DIPLREL:
462 case VUT_DIPLREL_TILE:
466 source->value.diplrel = diplrel_by_rule_name(value);
467 if (source->value.diplrel != diplrel_other_invalid()) {
468 return;
469 }
470 break;
471 case VUT_UTYPE:
472 source->value.utype = unit_type_by_rule_name(value);
473 if (source->value.utype) {
474 return;
475 }
476 break;
477 case VUT_UTFLAG:
479 if (unit_type_flag_id_is_valid(source->value.unitflag)) {
480 return;
481 }
482 break;
483 case VUT_UCLASS:
484 source->value.uclass = unit_class_by_rule_name(value);
485 if (source->value.uclass) {
486 return;
487 }
488 break;
489 case VUT_UCFLAG:
490 source->value.unitclassflag
492 if (unit_class_flag_id_is_valid(source->value.unitclassflag)) {
493 return;
494 }
495 break;
496 case VUT_MINVETERAN:
497 source->value.minveteran = atoi(value);
498 if (source->value.minveteran > 0) {
499 return;
500 }
501 break;
502 case VUT_UNITSTATE:
503 source->value.unit_state = ustate_prop_by_name(value, fc_strcasecmp);
504 if (ustate_prop_is_valid(source->value.unit_state)) {
505 return;
506 }
507 break;
508 case VUT_ACTIVITY:
510 if (activity_is_valid_in_requirement(source->value.activity)) {
511 return;
512 }
513 break;
514 case VUT_MINMOVES:
515 source->value.minmoves = atoi(value);
516 if (source->value.minmoves > 0) {
517 return;
518 }
519 break;
520 case VUT_MINHP:
521 source->value.min_hit_points = atoi(value);
522 if (source->value.min_hit_points > 0) {
523 return;
524 }
525 break;
526 case VUT_AGE:
527 source->value.age = atoi(value);
528 if (source->value.age > 0) {
529 return;
530 }
531 break;
532 case VUT_FORM_AGE:
533 source->value.form_age = atoi(value);
534 if (source->value.form_age > 0) {
535 return;
536 }
537 break;
538 case VUT_MINTECHS:
539 source->value.min_techs = atoi(value);
540 if (source->value.min_techs > 0) {
541 return;
542 }
543 break;
544 case VUT_FUTURETECHS:
545 source->value.future_techs = atoi(value);
546 if (source->value.future_techs > 0) {
547 return;
548 }
549 break;
550 case VUT_MINCITIES:
551 source->value.min_cities = atoi(value);
552 if (source->value.min_cities > 0) {
553 return;
554 }
555 break;
556 case VUT_ACTION:
557 source->value.action = action_by_rule_name(value);
558 if (source->value.action != nullptr) {
559 return;
560 }
561 break;
562 case VUT_OTYPE:
563 source->value.outputtype = output_type_by_identifier(value);
564 if (source->value.outputtype != O_LAST) {
565 return;
566 }
567 break;
568 case VUT_SPECIALIST:
569 source->value.specialist = specialist_by_rule_name(value);
570 if (source->value.specialist) {
571 return;
572 }
573 break;
574 case VUT_MINSIZE:
575 source->value.minsize = atoi(value);
576 if (source->value.minsize > 0) {
577 return;
578 }
579 break;
580 case VUT_MINCULTURE:
581 source->value.minculture = atoi(value);
582 if (source->value.minculture > 0) {
583 return;
584 }
585 break;
587 source->value.minforeignpct = atoi(value);
588 if (source->value.minforeignpct > 0) {
589 return;
590 }
591 break;
592 case VUT_AI_LEVEL:
593 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
594 if (ai_level_is_valid(source->value.ai_level)) {
595 return;
596 }
597 break;
599 source->value.max_tile_total_units = atoi(value);
600 if (0 <= source->value.max_tile_total_units) {
601 return;
602 }
603 break;
605 source->value.max_tile_top_units = atoi(value);
606 if (0 <= source->value.max_tile_top_units) {
607 return;
608 }
609 break;
610 case VUT_TERRAINCLASS:
611 source->value.terrainclass
613 if (terrain_class_is_valid(source->value.terrainclass)) {
614 return;
615 }
616 break;
617 case VUT_ROADFLAG:
619 if (road_flag_id_is_valid(source->value.roadflag)) {
620 return;
621 }
622 break;
623 case VUT_EXTRAFLAG:
624 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
625 if (extra_flag_id_is_valid(source->value.extraflag)) {
626 return;
627 }
628 break;
629 case VUT_MINYEAR:
630 source->value.minyear = atoi(value);
631 return;
632 case VUT_MINCALFRAG:
633 /* Rule names are 0-based numbers, not pretty names from ruleset */
634 source->value.mincalfrag = atoi(value);
635 if (source->value.mincalfrag >= 0) {
636 /* More range checking done later, in sanity_check_req_individual() */
637 return;
638 }
639 break;
640 case VUT_TOPO:
641 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
642 if (topo_flag_is_valid(source->value.topo_property)) {
643 return;
644 }
645 break;
646 case VUT_WRAP:
647 source->value.wrap_property = wrap_flag_by_name(value, fc_strcasecmp);
648 if (wrap_flag_is_valid(source->value.wrap_property)) {
649 return;
650 }
651 break;
653 source->value.ssetval = ssetv_by_rule_name(value);
654 if (source->value.ssetval != SSETV_NONE) {
655 return;
656 }
657 break;
658 case VUT_TERRAINALTER:
659 source->value.terrainalter
661 if (terrain_alteration_is_valid(source->value.terrainalter)) {
662 return;
663 }
664 break;
665 case VUT_CITYTILE:
667 if (source->value.citytile != CITYT_LAST) {
668 return;
669 }
670 break;
671 case VUT_CITYSTATUS:
673 if (source->value.citystatus != CITYS_LAST) {
674 return;
675 }
676 break;
677 case VUT_PLAYER_STATE:
679 if (source->value.plrstate != PLRS_LAST) {
680 return;
681 }
682 break;
683 case VUT_MINLATITUDE:
684 case VUT_MAXLATITUDE:
685 source->value.latitude = atoi(value);
686 if (source->value.latitude >= -MAP_MAX_LATITUDE
687 && source->value.latitude <= MAP_MAX_LATITUDE) {
688 return;
689 }
690 break;
691 case VUT_COUNTER:
692 source->value.counter = counter_by_rule_name(value);
693 if (source->value.counter != nullptr) {
694 return;
695 }
696 break;
698 source->value.distance_sq = atoi(value);
699 if (0 <= source->value.distance_sq) {
700 return;
701 }
702 break;
704 source->value.region_tiles = atoi(value);
705 if (0 < source->value.region_tiles) {
706 return;
707 }
708 break;
709 case VUT_TILE_REL:
711 if (source->value.tilerel != TREL_COUNT) {
712 return;
713 }
714 break;
715 case VUT_COUNT:
716 break;
717 }
718
719 /* If we reach here there's been an error. */
721}
722
723/**********************************************************************/
730{
731 struct universal source;
732
733 source.kind = kind;
734
735 switch (source.kind) {
736 case VUT_NONE:
737 /* Avoid compiler warning about uninitialized source.value */
738 source.value.advance = nullptr;
739
740 return source;
741 case VUT_ADVANCE:
742 source.value.advance = advance_by_number(value);
743 if (source.value.advance != nullptr) {
744 return source;
745 }
746 break;
747 case VUT_TECHFLAG:
748 source.value.techflag = value;
749 return source;
750 case VUT_GOVERNMENT:
752 if (source.value.govern != nullptr) {
753 return source;
754 }
755 break;
756 case VUT_GOVFLAG:
757 source.value.govflag = value;
758 return source;
759 case VUT_ACHIEVEMENT:
761 if (source.value.achievement != nullptr) {
762 return source;
763 }
764 break;
765 case VUT_STYLE:
766 source.value.style = style_by_number(value);
767 if (source.value.style != nullptr) {
768 return source;
769 }
770 break;
771 case VUT_IMPROVEMENT:
772 case VUT_SITE:
773 source.value.building = improvement_by_number(value);
774 if (source.value.building != nullptr) {
775 return source;
776 }
777 break;
778 case VUT_IMPR_GENUS:
779 source.value.impr_genus = value;
780 return source;
781 case VUT_IMPR_FLAG:
782 source.value.impr_flag = value;
783 return source;
784 case VUT_PLAYER_FLAG:
785 source.value.plr_flag = value;
786 return source;
787 case VUT_EXTRA:
789 return source;
790 case VUT_TILEDEF:
792 source.value.tiledef = tiledef_by_number(value);
793 return source;
794 case VUT_GOOD:
795 source.value.good = goods_by_number(value);
796 return source;
797 case VUT_TERRAIN:
798 source.value.terrain = terrain_by_number(value);
799 if (source.value.terrain != nullptr) {
800 return source;
801 }
802 break;
803 case VUT_TERRFLAG:
804 source.value.terrainflag = value;
805 return source;
806 case VUT_NATION:
808 if (source.value.nation != nullptr) {
809 return source;
810 }
811 break;
812 case VUT_NATIONGROUP:
813 source.value.nationgroup = nation_group_by_number(value);
814 if (source.value.nationgroup != nullptr) {
815 return source;
816 }
817 break;
818 case VUT_DIPLREL:
819 case VUT_DIPLREL_TILE:
823 source.value.diplrel = value;
824 if (source.value.diplrel != diplrel_other_invalid()) {
825 return source;
826 }
827 break;
828 case VUT_NATIONALITY:
830 if (source.value.nationality != nullptr) {
831 return source;
832 }
833 break;
835 source.value.origowner = nation_by_number(value);
836 if (source.value.origowner != nullptr) {
837 return source;
838 }
839 break;
840 case VUT_UTYPE:
841 source.value.utype = utype_by_number(value);
842 if (source.value.utype != nullptr) {
843 return source;
844 }
845 break;
846 case VUT_UTFLAG:
847 source.value.unitflag = value;
848 return source;
849 case VUT_UCLASS:
851 if (source.value.uclass != nullptr) {
852 return source;
853 }
854 break;
855 case VUT_UCFLAG:
856 source.value.unitclassflag = value;
857 return source;
858 case VUT_MINVETERAN:
859 source.value.minveteran = value;
860 return source;
861 case VUT_UNITSTATE:
862 source.value.unit_state = value;
863 return source;
864 case VUT_ACTIVITY:
865 source.value.activity = value;
866 return source;
867 case VUT_MINMOVES:
868 source.value.minmoves = value;
869 return source;
870 case VUT_MINHP:
872 return source;
873 case VUT_AGE:
874 source.value.age = value;
875 return source;
876 case VUT_FORM_AGE:
877 source.value.form_age = value;
878 return source;
879 case VUT_MINTECHS:
880 source.value.min_techs = value;
881 return source;
882 case VUT_FUTURETECHS:
883 source.value.future_techs = value;
884 return source;
885 case VUT_MINCITIES:
886 source.value.min_cities = value;
887 return source;
888 case VUT_ACTION:
890 if (source.value.action != nullptr) {
891 return source;
892 }
893 break;
894 case VUT_OTYPE:
895 source.value.outputtype = value;
896 return source;
897 case VUT_SPECIALIST:
899 return source;
900 case VUT_MINSIZE:
901 source.value.minsize = value;
902 return source;
903 case VUT_MINCULTURE:
904 source.value.minculture = value;
905 return source;
907 source.value.minforeignpct = value;
908 return source;
909 case VUT_AI_LEVEL:
910 source.value.ai_level = value;
911 return source;
914 return source;
917 return source;
918 case VUT_TERRAINCLASS:
919 source.value.terrainclass = value;
920 return source;
921 case VUT_ROADFLAG:
922 source.value.roadflag = value;
923 return source;
924 case VUT_EXTRAFLAG:
925 source.value.extraflag = value;
926 return source;
927 case VUT_MINYEAR:
928 source.value.minyear = value;
929 return source;
930 case VUT_MINCALFRAG:
931 source.value.mincalfrag = value;
932 return source;
933 case VUT_TOPO:
934 source.value.topo_property = value;
935 return source;
936 case VUT_WRAP:
937 source.value.wrap_property = value;
938 return source;
940 source.value.ssetval = value;
941 return source;
942 case VUT_TERRAINALTER:
943 source.value.terrainalter = value;
944 return source;
945 case VUT_CITYTILE:
946 source.value.citytile = value;
947 return source;
948 case VUT_CITYSTATUS:
949 source.value.citystatus = value;
950 return source;
951 case VUT_PLAYER_STATE:
952 source.value.plrstate = value;
953 return source;
954 case VUT_COUNTER:
956 return source;
957 case VUT_MINLATITUDE:
958 case VUT_MAXLATITUDE:
959 source.value.latitude = value;
960 return source;
962 source.value.distance_sq = value;
963 return source;
965 source.value.region_tiles = value;
966 return source;
967 case VUT_TILE_REL:
968 source.value.tilerel = value;
969 return source;
970 case VUT_COUNT:
971 break;
972 }
973
974 /* If we reach here there's been an error. */
976 /* Avoid compiler warning about uninitialized source.value */
977 source.value.advance = nullptr;
978
979 return source;
980}
981
982/**********************************************************************/
985void universal_copy(struct universal *dst, const struct universal *src)
986{
987 dst->value = src->value;
988 dst->kind = src->kind;
989}
990
991/**********************************************************************/
996 int *kind, int *value)
997{
998 *kind = source->kind;
1000}
1001
1002/**********************************************************************/
1006{
1007 switch (source->kind) {
1008 case VUT_NONE:
1009 return 0;
1010 case VUT_ADVANCE:
1011 return advance_number(source->value.advance);
1012 case VUT_TECHFLAG:
1013 return source->value.techflag;
1014 case VUT_GOVERNMENT:
1015 return government_number(source->value.govern);
1016 case VUT_GOVFLAG:
1017 return source->value.govflag;
1018 case VUT_ACHIEVEMENT:
1019 return achievement_number(source->value.achievement);
1020 case VUT_STYLE:
1021 return style_number(source->value.style);
1022 case VUT_IMPROVEMENT:
1023 case VUT_SITE:
1024 return improvement_number(source->value.building);
1025 case VUT_IMPR_GENUS:
1026 return source->value.impr_genus;
1027 case VUT_IMPR_FLAG:
1028 return source->value.impr_flag;
1029 case VUT_PLAYER_FLAG:
1030 return source->value.plr_flag;
1031 case VUT_EXTRA:
1032 return extra_number(source->value.extra);
1033 case VUT_TILEDEF:
1035 return tiledef_number(source->value.tiledef);
1036 case VUT_GOOD:
1037 return goods_number(source->value.good);
1038 case VUT_TERRAIN:
1039 return terrain_number(source->value.terrain);
1040 case VUT_TERRFLAG:
1041 return source->value.terrainflag;
1042 case VUT_NATION:
1043 return nation_number(source->value.nation);
1044 case VUT_NATIONGROUP:
1045 return nation_group_number(source->value.nationgroup);
1046 case VUT_NATIONALITY:
1047 return nation_number(source->value.nationality);
1048 case VUT_ORIGINAL_OWNER:
1049 return nation_number(source->value.origowner);
1050 case VUT_DIPLREL:
1051 case VUT_DIPLREL_TILE:
1052 case VUT_DIPLREL_TILE_O:
1055 return source->value.diplrel;
1056 case VUT_UTYPE:
1057 return utype_number(source->value.utype);
1058 case VUT_UTFLAG:
1059 return source->value.unitflag;
1060 case VUT_UCLASS:
1061 return uclass_number(source->value.uclass);
1062 case VUT_UCFLAG:
1063 return source->value.unitclassflag;
1064 case VUT_MINVETERAN:
1065 return source->value.minveteran;
1066 case VUT_UNITSTATE:
1067 return source->value.unit_state;
1068 case VUT_ACTIVITY:
1069 return source->value.activity;
1070 case VUT_MINMOVES:
1071 return source->value.minmoves;
1072 case VUT_MINHP:
1073 return source->value.min_hit_points;
1074 case VUT_AGE:
1075 return source->value.age;
1076 case VUT_FORM_AGE:
1077 return source->value.form_age;
1078 case VUT_MINTECHS:
1079 return source->value.min_techs;
1080 case VUT_FUTURETECHS:
1081 return source->value.future_techs;
1082 case VUT_MINCITIES:
1083 return source->value.min_cities;
1084 case VUT_ACTION:
1085 return action_number(source->value.action);
1086 case VUT_OTYPE:
1087 return source->value.outputtype;
1088 case VUT_SPECIALIST:
1089 return specialist_number(source->value.specialist);
1090 case VUT_MINSIZE:
1091 return source->value.minsize;
1092 case VUT_MINCULTURE:
1093 return source->value.minculture;
1094 case VUT_MINFOREIGNPCT:
1095 return source->value.minforeignpct;
1096 case VUT_AI_LEVEL:
1097 return source->value.ai_level;
1099 return source->value.max_tile_total_units;
1101 return source->value.max_tile_top_units;
1102 case VUT_TERRAINCLASS:
1103 return source->value.terrainclass;
1104 case VUT_ROADFLAG:
1105 return source->value.roadflag;
1106 case VUT_EXTRAFLAG:
1107 return source->value.extraflag;
1108 case VUT_MINYEAR:
1109 return source->value.minyear;
1110 case VUT_MINCALFRAG:
1111 return source->value.mincalfrag;
1112 case VUT_TOPO:
1113 return source->value.topo_property;
1114 case VUT_WRAP:
1115 return source->value.wrap_property;
1116 case VUT_SERVERSETTING:
1117 return source->value.ssetval;
1118 case VUT_TERRAINALTER:
1119 return source->value.terrainalter;
1120 case VUT_CITYTILE:
1121 return source->value.citytile;
1122 case VUT_CITYSTATUS:
1123 return source->value.citystatus;
1124 case VUT_PLAYER_STATE:
1125 return source->value.plrstate;
1126 case VUT_COUNTER:
1127 return counter_id(source->value.counter);
1128 case VUT_MINLATITUDE:
1129 case VUT_MAXLATITUDE:
1130 return source->value.latitude;
1132 return source->value.distance_sq;
1134 return source->value.region_tiles;
1135 case VUT_TILE_REL:
1136 return source->value.tilerel;
1137 case VUT_COUNT:
1138 break;
1139 }
1140
1141 /* If we reach here there's been an error. */
1142 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
1143 source->kind);
1144 return 0;
1145}
1146
1147
1148/**********************************************************************/
1152{
1153 static const struct req_context empty = {};
1154 return &empty;
1155}
1156
1157
1158/**********************************************************************/
1166const char *req_to_fstring(const struct requirement *req,
1167 struct astring *astr)
1168{
1169 astr_init(astr);
1170
1171 astr_set(astr, "%s%s %s %s%s",
1172 req->survives ? "surviving " : "",
1173 req_range_name(req->range),
1175 req->present ? "" : "!",
1177
1178 return astr_str(astr);
1179}
1180
1181/**********************************************************************/
1189 bool survives, bool present, bool quiet,
1190 const char *value)
1191{
1192 struct requirement req;
1193 bool invalid;
1194 const char *error = nullptr;
1195
1196 req.source = universal_by_rule_name(type, value);
1197
1199 if (invalid) {
1200 error = "bad type or name";
1201 } else {
1202 /* Scan the range string to find the range. If no range is given a
1203 * default fallback is used rather than giving an error. */
1204 if (range != nullptr) {
1206 if (!req_range_is_valid(req.range)) {
1207 invalid = TRUE;
1208 }
1209 } else {
1210 switch (req.source.kind) {
1211 case VUT_NONE:
1212 case VUT_COUNT:
1213 break;
1214 case VUT_IMPROVEMENT:
1215 case VUT_SITE:
1216 case VUT_IMPR_GENUS:
1217 case VUT_IMPR_FLAG:
1218 case VUT_UTYPE:
1219 case VUT_UTFLAG:
1220 case VUT_UCLASS:
1221 case VUT_UCFLAG:
1222 case VUT_MINVETERAN:
1223 case VUT_UNITSTATE:
1224 case VUT_ACTIVITY:
1225 case VUT_MINMOVES:
1226 case VUT_MINHP:
1227 case VUT_AGE:
1228 case VUT_FORM_AGE:
1229 case VUT_ACTION:
1230 case VUT_OTYPE:
1231 case VUT_SPECIALIST:
1232 case VUT_DIPLREL_TILE_O:
1234 req.range = REQ_RANGE_LOCAL;
1235 break;
1236 case VUT_EXTRA:
1237 case VUT_TILEDEF:
1238 case VUT_ROADFLAG:
1239 case VUT_EXTRAFLAG:
1240 /* Keep old behavior */
1241 req.range = REQ_RANGE_TILE;
1242 break;
1243 case VUT_TERRAIN:
1244 case VUT_TERRFLAG:
1245 case VUT_TERRAINCLASS:
1246 case VUT_TERRAINALTER:
1247 case VUT_CITYTILE:
1250 case VUT_MINLATITUDE:
1251 case VUT_MAXLATITUDE:
1253 req.range = REQ_RANGE_TILE;
1254 break;
1255 case VUT_COUNTER:
1256 case VUT_MINSIZE:
1257 case VUT_MINCULTURE:
1258 case VUT_MINFOREIGNPCT:
1259 case VUT_NATIONALITY:
1260 case VUT_ORIGINAL_OWNER:
1261 case VUT_CITYSTATUS:
1262 case VUT_GOOD:
1264 req.range = REQ_RANGE_CITY;
1265 break;
1266 case VUT_GOVERNMENT:
1267 case VUT_GOVFLAG:
1268 case VUT_ACHIEVEMENT:
1269 case VUT_STYLE:
1270 case VUT_ADVANCE:
1271 case VUT_TECHFLAG:
1272 case VUT_NATION:
1273 case VUT_NATIONGROUP:
1274 case VUT_DIPLREL:
1275 case VUT_DIPLREL_TILE:
1277 case VUT_AI_LEVEL:
1278 case VUT_PLAYER_FLAG:
1279 case VUT_PLAYER_STATE:
1280 case VUT_MINCITIES:
1281 case VUT_FUTURETECHS:
1282 req.range = REQ_RANGE_PLAYER;
1283 break;
1284 case VUT_MINYEAR:
1285 case VUT_MINCALFRAG:
1286 case VUT_TOPO:
1287 case VUT_WRAP:
1288 case VUT_MINTECHS:
1289 case VUT_SERVERSETTING:
1290 req.range = REQ_RANGE_WORLD;
1291 break;
1294 break;
1295 case VUT_TILE_REL:
1296 req.range = REQ_RANGE_TILE;
1298 /* Not available at Tile range */
1300 }
1301 break;
1302 }
1303 }
1304
1305 req.survives = survives;
1306 req.present = present;
1307 req.quiet = quiet;
1308
1309 /* These checks match what combinations are supported inside
1310 * is_req_active(). However, it's only possible to do basic checks,
1311 * not anything that might depend on the rest of the ruleset which
1312 * might not have been loaded yet. */
1313 switch (req.source.kind) {
1314 case VUT_TERRAIN:
1315 case VUT_TERRAINCLASS:
1316 case VUT_TERRFLAG:
1317 invalid = (req.range != REQ_RANGE_TILE
1318 && req.range != REQ_RANGE_CADJACENT
1319 && req.range != REQ_RANGE_ADJACENT
1320 && req.range != REQ_RANGE_CITY
1321 && req.range != REQ_RANGE_TRADE_ROUTE);
1322 break;
1323 case VUT_EXTRA:
1324 case VUT_ROADFLAG:
1325 case VUT_EXTRAFLAG:
1327 break;
1328 case VUT_TILEDEF:
1330 || req.range == REQ_RANGE_LOCAL);
1331 break;
1332 case VUT_ACHIEVEMENT:
1333 case VUT_MINTECHS:
1334 case VUT_FUTURETECHS:
1335 invalid = (req.range < REQ_RANGE_PLAYER);
1336 break;
1337 case VUT_ADVANCE:
1338 case VUT_TECHFLAG:
1340 && req.range != REQ_RANGE_LOCAL);
1341 break;
1342 case VUT_GOVERNMENT:
1343 case VUT_GOVFLAG:
1344 case VUT_AI_LEVEL:
1345 case VUT_STYLE:
1346 case VUT_MINCITIES:
1347 invalid = (req.range != REQ_RANGE_PLAYER);
1348 break;
1349 case VUT_MINSIZE:
1350 case VUT_MINFOREIGNPCT:
1351 case VUT_NATIONALITY:
1352 case VUT_CITYSTATUS:
1353 invalid = (req.range != REQ_RANGE_CITY
1354 && req.range != REQ_RANGE_TRADE_ROUTE);
1355 break;
1356 case VUT_GOOD:
1357 case VUT_ORIGINAL_OWNER:
1359 invalid = (req.range != REQ_RANGE_CITY);
1360 break;
1361 case VUT_MINCULTURE:
1362 invalid = (req.range != REQ_RANGE_CITY
1364 && req.range != REQ_RANGE_PLAYER
1365 && req.range != REQ_RANGE_TEAM
1366 && req.range != REQ_RANGE_ALLIANCE
1367 && req.range != REQ_RANGE_WORLD);
1368 break;
1369 case VUT_DIPLREL:
1370 invalid = (req.range != REQ_RANGE_LOCAL
1371 && req.range != REQ_RANGE_PLAYER
1372 && req.range != REQ_RANGE_TEAM
1373 && req.range != REQ_RANGE_ALLIANCE
1374 && req.range != REQ_RANGE_WORLD)
1375 /* Non local foreign makes no sense. */
1376 || (req.source.value.diplrel == DRO_FOREIGN
1377 && req.range != REQ_RANGE_LOCAL);
1378 break;
1379 case VUT_DIPLREL_TILE:
1380 invalid = (req.range != REQ_RANGE_LOCAL
1381 && req.range != REQ_RANGE_PLAYER
1382 && req.range != REQ_RANGE_TEAM
1383 && req.range != REQ_RANGE_ALLIANCE)
1384 /* Non local foreign makes no sense. */
1385 || (req.source.value.diplrel == DRO_FOREIGN
1386 && req.range != REQ_RANGE_LOCAL);
1387 break;
1388 case VUT_DIPLREL_TILE_O:
1389 invalid = (req.range != REQ_RANGE_LOCAL);
1390 break;
1392 invalid = (req.range != REQ_RANGE_LOCAL
1393 && req.range != REQ_RANGE_PLAYER
1394 && req.range != REQ_RANGE_TEAM
1395 && req.range != REQ_RANGE_ALLIANCE)
1396 /* Non local foreign makes no sense. */
1397 || (req.source.value.diplrel == DRO_FOREIGN
1398 && req.range != REQ_RANGE_LOCAL);
1399 break;
1401 invalid = (req.range != REQ_RANGE_LOCAL);
1402 break;
1403 case VUT_NATION:
1404 case VUT_NATIONGROUP:
1406 && req.range != REQ_RANGE_TEAM
1407 && req.range != REQ_RANGE_ALLIANCE
1408 && req.range != REQ_RANGE_WORLD);
1409 break;
1410 case VUT_MINVETERAN:
1411 case VUT_UNITSTATE:
1412 case VUT_ACTIVITY:
1413 case VUT_MINMOVES:
1414 case VUT_MINHP:
1415 case VUT_ACTION:
1416 case VUT_OTYPE:
1417 case VUT_SPECIALIST:
1418 invalid = (req.range != REQ_RANGE_LOCAL);
1419 break;
1420 case VUT_UTYPE:
1421 case VUT_UTFLAG:
1422 case VUT_UCLASS:
1423 case VUT_UCFLAG:
1424 invalid = (req.range != REQ_RANGE_LOCAL
1425 && req.range != REQ_RANGE_TILE
1426 && req.range != REQ_RANGE_CADJACENT
1427 && req.range != REQ_RANGE_ADJACENT);
1428 break;
1429 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1431 invalid = (req.range != REQ_RANGE_TILE);
1432 break;
1433 case VUT_CITYTILE:
1436 invalid = (req.range != REQ_RANGE_TILE
1437 && req.range != REQ_RANGE_CADJACENT
1438 && req.range != REQ_RANGE_ADJACENT);
1439 break;
1440 case VUT_MINLATITUDE:
1441 case VUT_MAXLATITUDE:
1442 invalid = (req.range != REQ_RANGE_TILE
1443 && req.range != REQ_RANGE_CADJACENT
1444 && req.range != REQ_RANGE_ADJACENT
1445 && req.range != REQ_RANGE_WORLD)
1446 /* Avoid redundancy at tile range: no negated requirements
1447 * that could be emulated by a present requirement of the
1448 * other type */
1449 || (req.range == REQ_RANGE_TILE && !req.present);
1450 break;
1451 case VUT_MINYEAR:
1452 case VUT_MINCALFRAG:
1453 case VUT_TOPO:
1454 case VUT_WRAP:
1455 case VUT_SERVERSETTING:
1456 invalid = (req.range != REQ_RANGE_WORLD);
1457 break;
1458 case VUT_AGE:
1459 /* FIXME: Could support TRADE_ROUTE, TEAM, etc */
1460 invalid = (req.range != REQ_RANGE_LOCAL
1461 && req.range != REQ_RANGE_CITY
1462 && req.range != REQ_RANGE_PLAYER);
1463 break;
1464 case VUT_FORM_AGE:
1465 invalid = (req.range != REQ_RANGE_LOCAL);
1466 break;
1467 case VUT_IMPR_GENUS:
1468 /* TODO: Support other ranges too. */
1469 invalid = (req.range != REQ_RANGE_LOCAL);
1470 break;
1471 case VUT_IMPR_FLAG:
1472 invalid = (req.range != REQ_RANGE_LOCAL
1473 && req.range != REQ_RANGE_TILE
1474 && req.range != REQ_RANGE_CITY);
1475 break;
1476 case VUT_COUNTER:
1477 invalid = req.range != REQ_RANGE_CITY;
1478 break;
1479 case VUT_PLAYER_FLAG:
1480 case VUT_PLAYER_STATE:
1481 invalid = (req.range != REQ_RANGE_PLAYER);
1482 break;
1485 && req.range != REQ_RANGE_CADJACENT
1486 && req.range != REQ_RANGE_ADJACENT);
1487 break;
1488 case VUT_TILE_REL:
1490 && req.range != REQ_RANGE_CADJACENT
1491 && req.range != REQ_RANGE_TILE)
1492 /* TREL_ONLY_OTHER_REGION not supported at Tile range */
1494 && req.range == REQ_RANGE_TILE);
1495 break;
1496 case VUT_IMPROVEMENT:
1497 case VUT_SITE:
1498 /* Valid ranges depend on the building genus (wonder/improvement),
1499 * which might not have been loaded from the ruleset yet.
1500 * So we allow anything here, and do a proper check once ruleset
1501 * loading is complete, in sanity_check_req_individual(). */
1502 case VUT_NONE:
1503 invalid = FALSE;
1504 break;
1505 case VUT_COUNT:
1506 break;
1507 }
1508 if (invalid) {
1509 error = "bad range";
1510 }
1511 }
1512
1513 if (!invalid) {
1514 /* Check 'survives'. */
1515 switch (req.source.kind) {
1516 case VUT_IMPROVEMENT:
1517 case VUT_SITE:
1518 /* See buildings_in_range(). */
1520 break;
1521 case VUT_NATION:
1522 case VUT_ADVANCE:
1524 break;
1525 case VUT_COUNTER:
1526 case VUT_IMPR_GENUS:
1527 case VUT_IMPR_FLAG:
1528 case VUT_PLAYER_FLAG:
1529 case VUT_PLAYER_STATE:
1530 case VUT_GOVERNMENT:
1531 case VUT_GOVFLAG:
1532 case VUT_TERRAIN:
1533 case VUT_UTYPE:
1534 case VUT_UTFLAG:
1535 case VUT_UCLASS:
1536 case VUT_UCFLAG:
1537 case VUT_MINVETERAN:
1538 case VUT_UNITSTATE:
1539 case VUT_ACTIVITY:
1540 case VUT_MINMOVES:
1541 case VUT_MINHP:
1542 case VUT_AGE:
1543 case VUT_FORM_AGE:
1544 case VUT_ACTION:
1545 case VUT_OTYPE:
1546 case VUT_SPECIALIST:
1547 case VUT_MINSIZE:
1548 case VUT_MINCULTURE:
1549 case VUT_MINFOREIGNPCT:
1550 case VUT_AI_LEVEL:
1551 case VUT_TERRAINCLASS:
1552 case VUT_MINYEAR:
1553 case VUT_MINCALFRAG:
1554 case VUT_TOPO:
1555 case VUT_WRAP:
1556 case VUT_SERVERSETTING:
1557 case VUT_TERRAINALTER:
1558 case VUT_CITYTILE:
1559 case VUT_CITYSTATUS:
1560 case VUT_TERRFLAG:
1561 case VUT_NATIONALITY:
1562 case VUT_ORIGINAL_OWNER:
1563 case VUT_ROADFLAG:
1564 case VUT_EXTRAFLAG:
1565 case VUT_EXTRA:
1566 case VUT_TILEDEF:
1568 case VUT_GOOD:
1569 case VUT_TECHFLAG:
1570 case VUT_ACHIEVEMENT:
1571 case VUT_NATIONGROUP:
1572 case VUT_STYLE:
1573 case VUT_DIPLREL:
1574 case VUT_DIPLREL_TILE:
1575 case VUT_DIPLREL_TILE_O:
1580 case VUT_MINTECHS:
1581 case VUT_FUTURETECHS:
1582 case VUT_MINCITIES:
1583 case VUT_MINLATITUDE:
1584 case VUT_MAXLATITUDE:
1587 case VUT_TILE_REL:
1588 /* Most requirements don't support 'survives'. */
1589 invalid = survives;
1590 break;
1591 case VUT_NONE:
1592 case VUT_COUNT:
1593 break;
1594 }
1595 if (invalid) {
1596 error = "bad 'survives'";
1597 }
1598 }
1599
1600 if (invalid) {
1601 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1602 type, range, survives ? "survives" : "",
1603 present ? "present" : "", value, error);
1605 }
1606
1607 return req;
1608}
1609
1610/**********************************************************************/
1616 int value)
1617{
1618 struct requirement req;
1619
1620 req.source = universal_by_number(type, value);
1621 req.range = range;
1622 req.survives = survives;
1623 req.present = present;
1624 req.quiet = quiet;
1625
1626 return req;
1627}
1628
1629/**********************************************************************/
1633void req_get_values(const struct requirement *req,
1634 int *type, int *range,
1635 bool *survives, bool *present, bool *quiet,
1636 int *value)
1637{
1638 universal_extraction(&req->source, type, value);
1639 *range = req->range;
1640 *survives = req->survives;
1641 *present = req->present;
1642 *quiet = req->quiet;
1643}
1644
1645/**********************************************************************/
1648void req_copy(struct requirement *dst, const struct requirement *src)
1649{
1650 universal_copy(&(dst->source), &(src->source));
1651 dst->range = src->range;
1652 dst->survives = src->survives;
1653 dst->present = src->present;
1654 dst->quiet = src->quiet;
1655}
1656
1657/**********************************************************************/
1661bool are_requirements_equal(const struct requirement *req1,
1662 const struct requirement *req2)
1663{
1664 return (are_universals_equal(&req1->source, &req2->source)
1665 && req1->range == req2->range
1666 && req1->survives == req2->survives
1667 && req1->present == req2->present);
1668}
1669
1670/**********************************************************************/
1673static bool are_requirements_opposites(const struct requirement *req1,
1674 const struct requirement *req2)
1675{
1676 return (are_universals_equal(&req1->source, &req2->source)
1677 && req1->range == req2->range
1678 && req1->survives == req2->survives
1679 && req1->present != req2->present);
1680}
1681
1682/**********************************************************************/
1686static bool impr_contra_genus(const struct requirement *impr_req,
1687 const struct requirement *genus_req)
1688{
1689 /* The input is sane. */
1691 || impr_req->source.kind == VUT_SITE, FALSE);
1693
1694 if (impr_req->range == REQ_RANGE_LOCAL
1695 && genus_req->range == REQ_RANGE_LOCAL) {
1696 /* Applies to the same target building. */
1697
1698 if (impr_req->present && !genus_req->present) {
1699 /* The target building can't not have the genus it has. */
1700 return (impr_req->source.value.building->genus
1701 == genus_req->source.value.impr_genus);
1702 }
1703
1704 if (impr_req->present && genus_req->present) {
1705 /* The target building can't have another genus than it has. */
1706 return (impr_req->source.value.building->genus
1707 != genus_req->source.value.impr_genus);
1708 }
1709 }
1710
1711 /* No special knowledge. */
1712 return FALSE;
1713}
1714
1715/**********************************************************************/
1719static bool impr_contra_flag(const struct requirement *impr_req,
1720 const struct requirement *flag_req)
1721{
1722 /* The input is sane. */
1724 || impr_req->source.kind == VUT_SITE, FALSE);
1726
1727 if (impr_req->range == REQ_RANGE_LOCAL
1728 && flag_req->range == REQ_RANGE_LOCAL) {
1729 /* Applies to the same target building. */
1730
1731 if (impr_req->present && !flag_req->present) {
1732 /* The target building can't not have the flag it has. */
1733 return improvement_has_flag(impr_req->source.value.building,
1734 flag_req->source.value.impr_flag);
1735 }
1736
1737 if (impr_req->present && flag_req->present) {
1738 /* The target building can't have another flag than it has. */
1739 return !improvement_has_flag(impr_req->source.value.building,
1740 flag_req->source.value.impr_flag);
1741 }
1742 }
1743
1744 /* No special knowledge. */
1745 return FALSE;
1746}
1747
1748/**********************************************************************/
1753 const struct requirement *group_req)
1754{
1755 /* The input is sane. */
1756 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1758
1759 if (nation_req->range == REQ_RANGE_PLAYER
1760 && group_req->range == REQ_RANGE_PLAYER) {
1761 /* Applies to the same target building. */
1762
1763 if (nation_req->present && !group_req->present) {
1764 /* The target nation can't be in the group. */
1765 return nation_is_in_group(nation_req->source.value.nation,
1766 group_req->source.value.nationgroup);
1767 }
1768 }
1769
1770 /* No special knowledge. */
1771 return FALSE;
1772}
1773
1774/**********************************************************************/
1778static bool city_center_contra(const struct requirement *cc_req,
1779 const struct requirement *ct_req)
1780{
1781 /* The input is sane. */
1782 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1783 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1784
1785 if (cc_req->source.value.citytile == CITYT_CENTER
1786 && cc_req->present && cc_req->range <= ct_req->range) {
1787 switch (ct_req->source.value.citytile) {
1788 case CITYT_CENTER:
1789 case CITYT_CLAIMED:
1790 case CITYT_EXTRAS_OWNED:
1791 case CITYT_WORKED:
1793 /* Should be always on city center */
1794 return !ct_req->present;
1796 /* Handled later */
1797 break;
1798 case CITYT_LAST:
1799 /* Error */
1800 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1801 }
1802 }
1803 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1804 || cc_req->source.value.citytile == CITYT_CENTER)
1805 && ct_req->source.value.citytile
1807 && REQ_RANGE_TILE == cc_req->range
1808 && REQ_RANGE_TILE == ct_req->range) {
1809 /* Can't coexist */
1810 return cc_req->present ? ct_req->present : !ct_req->present;
1811 }
1812
1813 return FALSE;
1814}
1815
1816/**********************************************************************/
1821static bool present_implies_not_present(const struct requirement *req1,
1822 const struct requirement *req2)
1823{
1824 const struct requirement *absent, *present;
1825
1826 if (req1->present == req2->present) {
1827 /* Can't use the knowledge in universal_found_function when both are
1828 * required to be absent or when both are required to be present.
1829 * It is no contradiction to require !Spy unit and !Missile unit class.
1830 * It is no contradiction to require River and Irrigation at the same
1831 * tile. */
1832 return FALSE;
1833 }
1834
1835 if (req1->present) {
1836 absent = req2;
1837 present = req1;
1838 } else {
1839 absent = req1;
1840 present = req2;
1841 }
1842
1843 if (!universal_found_function[present->source.kind]) {
1844 /* No knowledge to exploit. */
1845 return FALSE;
1846 }
1847
1848 if (present->range != absent->range) {
1849 /* Larger ranges are not always strict supersets of smaller ranges.
1850 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1851 * but not in Trade Route. */
1852 return FALSE;
1853 }
1854
1856 &present->source);
1857}
1858
1859/**********************************************************************/
1862bool req_implies_req(const struct requirement *req1,
1863 const struct requirement *req2)
1864{
1865 struct requirement nreq2;
1866
1867 req_copy(&nreq2, req2);
1868 nreq2.present = !nreq2.present;
1870}
1871
1872/**********************************************************************/
1877static inline bool are_bounds_contradictions(int bound1, bool is_upper1,
1878 int bound2, bool is_upper2)
1879{
1880 /* If the bounds are on opposite sides, and one is inclusive, the other
1881 * exclusive, the number of values that satisfy both bounds is exactly
1882 * their difference, (upper bound) - (lower bound).
1883 * The bounds contradict each other iff this difference is 0 or less,
1884 * i.e. iff (upper bound) <= (lower bound) */
1885 if (is_upper1 && !is_upper2) {
1886 return bound1 <= bound2;
1887 } else if (!is_upper1 && is_upper2) {
1888 return bound1 >= bound2;
1889 }
1890 /* Both are upper or both are lower ~> no contradiction possible */
1891 return FALSE;
1892}
1893
1894/**********************************************************************/
1902 const struct requirement *req2)
1903{
1904 if (are_requirements_opposites(req1, req2)) {
1905 /* The exact opposite. */
1906 return TRUE;
1907 }
1908
1909 if (present_implies_not_present(req1, req2)) {
1910 return TRUE;
1911 }
1912
1913 switch (req1->source.kind) {
1914 case VUT_IMPROVEMENT:
1915 case VUT_SITE:
1916 if (req2->source.kind == VUT_IMPR_GENUS) {
1917 return impr_contra_genus(req1, req2);
1918 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1919 return impr_contra_flag(req1, req2);
1920 } else if (req2->source.kind == VUT_CITYTILE
1921 && req2->source.value.citytile == CITYT_CENTER
1922 && REQ_RANGE_TILE == req2->range
1923 && REQ_RANGE_TILE == req1->range
1924 && req1->present) {
1925 /* A building must be in a city */
1926 return !req2->present;
1927 }
1928
1929 /* No special knowledge. */
1930 return FALSE;
1931 case VUT_IMPR_GENUS:
1932 if (req2->source.kind == VUT_IMPROVEMENT
1933 || req2->source.kind == VUT_SITE) {
1934 return impr_contra_genus(req2, req1);
1935 }
1936
1937 /* No special knowledge. */
1938 return FALSE;
1939 case VUT_IMPR_FLAG:
1940 if (req2->source.kind == VUT_IMPROVEMENT
1941 || req2->source.kind == VUT_SITE) {
1942 return impr_contra_flag(req2, req1);
1943 }
1944
1945 /* No special knowledge. */
1946 return FALSE;
1947 case VUT_DIPLREL:
1948 case VUT_DIPLREL_TILE:
1949 case VUT_DIPLREL_TILE_O:
1952 if (req2->source.kind != req1->source.kind) {
1953 /* Finding contradictions across requirement kinds aren't supported
1954 * for DiplRel requirements. */
1955 return FALSE;
1956 } else {
1957 /* Use the special knowledge about DiplRel requirements to find
1958 * contradictions. */
1959
1961 int req2_pos;
1962
1965 req2->range,
1966 req2->present);
1967
1968 return BV_ISSET(req1_contra, req2_pos);
1969 }
1970 break;
1971 case VUT_MINMOVES:
1972 if (req2->source.kind != VUT_MINMOVES) {
1973 /* Finding contradictions across requirement kinds aren't supported
1974 * for MinMoveFrags requirements. */
1975 return FALSE;
1976 }
1978 req1->source.value.minmoves, !req1->present,
1979 req2->source.value.minmoves, !req2->present);
1980 case VUT_MINLATITUDE:
1981 case VUT_MAXLATITUDE:
1982 if (req2->source.kind != VUT_MINLATITUDE
1983 && req2->source.kind != VUT_MAXLATITUDE) {
1984 /* Finding contradictions across requirement kinds other than each
1985 * other is not supported for MinLatitude and MaxLatitude. */
1986 return FALSE;
1987 } else {
1988 /* For a contradiction, we need
1989 * - a minimum (present MinLatitude or negated MaxLatitude)
1990 * - a maximum (negated MinLatitude or present MaxLatitude)
1991 * - the maximum to be less than the minimum
1992 * - a requirement at the larger range that applies to the entire
1993 * range (i.e. a negated requirement, unless the range is Tile)
1994 * Otherwise, the two requirements could still be fulfilled
1995 * simultaneously by different tiles in the range */
1996
1997 /* Initial values beyond the boundaries to avoid edge cases */
1998 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
2000
2001#define EXTRACT_INFO(req) \
2002 if (req->present) { \
2003 if (req->source.kind == VUT_MINLATITUDE) { \
2004 /* present MinLatitude */ \
2005 minimum = MAX(minimum, req->source.value.latitude); \
2006 } else { \
2007 /* present MaxLatitude */ \
2008 maximum = MIN(maximum, req->source.value.latitude); \
2009 } \
2010 } else { \
2011 covered_range = MAX(covered_range, req->range); \
2012 if (req->source.kind == VUT_MINLATITUDE) { \
2013 /* negated MinLatitude */ \
2014 maximum = MIN(maximum, req->source.value.latitude - 1); \
2015 } else { \
2016 /* negated MaxLatitude */ \
2017 minimum = MAX(minimum, req->source.value.latitude + 1); \
2018 } \
2019 }
2020
2021 EXTRACT_INFO(req1);
2022 EXTRACT_INFO(req2);
2023
2024#undef EXTRACT_INFO
2025
2026 return (maximum < minimum
2027 && covered_range >= req1->range
2028 && covered_range >= req2->range);
2029 }
2030 break;
2031 case VUT_NATION:
2032 if (req2->source.kind == VUT_NATIONGROUP) {
2033 return nation_contra_group(req1, req2);
2034 }
2035
2036 /* No special knowledge. */
2037 return FALSE;
2038 break;
2039 case VUT_NATIONGROUP:
2040 if (req2->source.kind == VUT_NATION) {
2041 return nation_contra_group(req2, req1);
2042 }
2043
2044 /* No special knowledge. */
2045 return FALSE;
2046 break;
2047 case VUT_CITYTILE:
2048 if (req2->source.kind == VUT_CITYTILE) {
2049 return city_center_contra(req1, req2)
2050 || city_center_contra(req2, req1);
2051 } else if (req1->source.value.citytile == CITYT_CENTER
2052 && (req2->source.kind == VUT_IMPROVEMENT
2053 || req2->source.kind == VUT_SITE)
2054 && REQ_RANGE_TILE == req2->range
2055 && REQ_RANGE_TILE == req1->range
2056 && req2->present) {
2057 /* A building must be in a city */
2058 return !req1->present;
2059 }
2060
2061 return FALSE;
2063 if (req2->source.kind != VUT_MAX_DISTANCE_SQ) {
2064 /* Finding contradictions across requirement kinds isn't supported
2065 * for MaxDistanceSq requirements. */
2066 return FALSE;
2067 }
2069 req1->source.value.distance_sq, req1->present,
2070 req2->source.value.distance_sq, req2->present);
2072 if (req2->source.kind != VUT_MAX_REGION_TILES) {
2073 /* Finding contradictions across requirement kinds isn't supported
2074 * for MaxRegionTiles requirements. */
2075 return FALSE;
2076 } else if (req1->range != req2->range) {
2077 /* FIXME: Finding contradictions across ranges not yet supported.
2078 * In particular, a max at a small range and a min at a larger range
2079 * needs extra work to figure out. */
2080 return FALSE;
2081 }
2083 req1->source.value.region_tiles, req1->present,
2084 req2->source.value.region_tiles, req2->present);
2085 case VUT_TILE_REL:
2086 if (req2->source.kind != VUT_TILE_REL) {
2087 /* Finding contradictions across requirement kinds isn't supported
2088 * for TileRel requirements. */
2089 return FALSE;
2090 }
2091 if (req1->source.value.tilerel == req2->source.value.tilerel) {
2092 /* Same requirement at different ranges. Note that same range is
2093 * already covered by are_requirements_opposites() above. */
2094 switch (req1->source.value.tilerel) {
2095 case TREL_SAME_TCLASS:
2096 case TREL_SAME_REGION:
2098 /* Negated req at larger range contradicts present req at
2099 * smaller range. */
2100 if (req1->range > req2->range) {
2101 return !req1->present && req2->present;
2102 } else {
2103 return req1->present && !req2->present;
2104 }
2105 break;
2107 /* Present req at larger range contradicts negated req at
2108 * smaller range */
2109 if (req1->range > req2->range) {
2110 return req1->present && !req2->present;
2111 } else {
2112 return !req1->present && req2->present;
2113 }
2114 break;
2115 default:
2116 return FALSE;
2117 }
2118 }
2120 && req2->source.value.tilerel == TREL_SAME_REGION) {
2121 /* Same region at any range implies same terrain class at that range
2122 * and any larger range ~> contradicts negated */
2123 return (!req1->present && req2->present
2124 && (req1->range >= req2->range));
2125 } else if (req2->source.value.tilerel == TREL_SAME_TCLASS
2126 && req1->source.value.tilerel == TREL_SAME_REGION) {
2127 /* Same as above */
2128 return (req1->present && !req2->present
2129 && (req1->range <= req2->range));
2130 } else if (req1->source.value.tilerel == TREL_REGION_SURROUNDED
2132 const struct requirement *surr, *other;
2134 surr = req1;
2135 other = req2;
2136 } else {
2137 surr = req2;
2138 other = req1;
2139 }
2140 if (surr->present && surr->range == REQ_RANGE_TILE) {
2141 /* Target tile must be part of a surrounded region
2142 * ~> not the same terrain class
2143 * ~> not the same region
2144 * ~> not touched by a third region */
2145 switch (other->source.value.tilerel) {
2146 case TREL_SAME_TCLASS:
2147 case TREL_SAME_REGION:
2148 return (other->present && other->range == REQ_RANGE_TILE);
2150 return (!other->present);
2151 default:
2152 break;
2153 }
2154 }
2155 }
2156 /* No further contradictions we can detect */
2157 return FALSE;
2158 default:
2159 /* No special knowledge exists. The requirements aren't the exact
2160 * opposite of each other per the initial check. */
2161 return FALSE;
2162 }
2163}
2164
2165/**********************************************************************/
2173struct requirement *
2175 const struct requirement_vector *vec)
2176{
2177 /* If the requirement is contradicted by any requirement in the vector it
2178 * contradicts the entire requirement vector. */
2181 return preq;
2182 }
2184
2185 /* Not a single requirement in the requirement vector is contradicted to be
2186 * the specified requirement. */
2187 return nullptr;
2188}
2189
2190/**********************************************************************/
2195 const struct requirement_vector *vec)
2196{
2197 return req_vec_first_contradiction_in_vec(req, vec) != nullptr;
2198}
2199
2200/**********************************************************************/
2203static inline bool are_tiles_in_range(const struct tile *tile1,
2204 const struct tile *tile2,
2205 enum req_range range)
2206{
2207 switch (range) {
2208 case REQ_RANGE_ADJACENT:
2210 return TRUE;
2211 }
2213 case REQ_RANGE_TILE:
2214 return same_pos(tile1, tile2);
2216 return map_distance(tile1, tile2) <= 1;
2217 case REQ_RANGE_CITY:
2219 case REQ_RANGE_LOCAL:
2221 case REQ_RANGE_PLAYER:
2222 case REQ_RANGE_TEAM:
2223 case REQ_RANGE_ALLIANCE:
2224 case REQ_RANGE_WORLD:
2225 case REQ_RANGE_COUNT:
2226 /* Invalid */
2228 }
2229 return FALSE;
2230}
2231
2232/**********************************************************************/
2235static inline bool players_in_same_range(const struct player *pplayer1,
2236 const struct player *pplayer2,
2237 enum req_range range)
2238{
2239 switch (range) {
2240 case REQ_RANGE_WORLD:
2241 return TRUE;
2242 case REQ_RANGE_ALLIANCE:
2244 case REQ_RANGE_TEAM:
2246 case REQ_RANGE_PLAYER:
2247 return pplayer1 == pplayer2;
2250 case REQ_RANGE_CITY:
2251 case REQ_RANGE_ADJACENT:
2253 case REQ_RANGE_TILE:
2254 case REQ_RANGE_LOCAL:
2255 case REQ_RANGE_COUNT:
2256 break;
2257 }
2258
2259 fc_assert_msg(FALSE, "Invalid range %d.", range);
2260 return FALSE;
2261}
2262
2263#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
2264{ \
2265 fc_assert_ret_val(req != nullptr, TRI_MAYBE); \
2266 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
2267 fc_assert(context != nullptr); \
2268 fc_assert(other_context != nullptr); \
2269}
2270
2271/**********************************************************************/
2279static enum fc_tristate
2281 const struct req_context *context,
2282 const struct req_context *other_context,
2283 const struct requirement *req)
2284{
2286
2287 return TRI_YES;
2288}
2289
2290/**********************************************************************/
2294static int num_world_buildings_total(const struct impr_type *building)
2295{
2296 if (is_great_wonder(building)) {
2297 return (great_wonder_is_built(building)
2298 || great_wonder_is_destroyed(building) ? 1 : 0);
2299 } else {
2300 log_error("World-ranged requirements are only supported for wonders.");
2301 return 0;
2302 }
2303}
2304
2305/**********************************************************************/
2308static int num_world_buildings(const struct impr_type *building)
2309{
2310 if (is_great_wonder(building)) {
2311 return (great_wonder_is_built(building) ? 1 : 0);
2312 } else {
2313 log_error("World-ranged requirements are only supported for wonders.");
2314 return 0;
2315 }
2316}
2317
2318/**********************************************************************/
2329static bool player_has_ever_built(const struct player *pplayer,
2330 const struct impr_type *building)
2331{
2332 if (is_wonder(building)) {
2333 return (wonder_is_built(pplayer, building)
2334 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2335 } else {
2336 log_error("Player-ranged requirements are only supported for wonders.");
2337 return FALSE;
2338 }
2339}
2340
2341/**********************************************************************/
2344static int num_player_buildings(const struct player *pplayer,
2345 const struct impr_type *building)
2346{
2347 if (is_wonder(building)) {
2348 return (wonder_is_built(pplayer, building) ? 1 : 0);
2349 } else {
2350 log_error("Player-ranged requirements are only supported for wonders.");
2351 return 0;
2352 }
2353}
2354
2355/**********************************************************************/
2358static int num_continent_buildings(const struct player *pplayer,
2359 int continent,
2360 const struct impr_type *building)
2361{
2362 if (is_wonder(building)) {
2363 const struct city *pcity;
2364
2365 pcity = city_from_wonder(pplayer, building);
2366 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2367 return 1;
2368 }
2369 } else {
2370 log_error("Island-ranged requirements are only supported for wonders.");
2371 }
2372 return 0;
2373}
2374
2375/**********************************************************************/
2383static enum fc_tristate
2385 const struct req_context *context,
2386 const struct req_context *other_context,
2387 const struct requirement *req)
2388{
2389 const struct impr_type *building;
2390
2391 /* Can't use this assertion, as both VUT_IMPROVEMENT and VUT_SITE
2392 * are handled here. */
2393 /* IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT); */
2394
2395 building = req->source.value.building;
2396
2397 /* Check if it's certain that the building is obsolete given the
2398 * specification we have */
2399 if (req->source.kind == VUT_IMPROVEMENT
2400 && improvement_obsolete(context->player, building, context->city)) {
2401 return TRI_NO;
2402 }
2403
2404 if (req->survives) {
2405
2406 /* Check whether condition has ever held, using cached information. */
2407 switch (req->range) {
2408 case REQ_RANGE_WORLD:
2409 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2410 case REQ_RANGE_ALLIANCE:
2411 case REQ_RANGE_TEAM:
2412 if (context->player == nullptr) {
2413 return TRI_MAYBE;
2414 }
2415 players_iterate_alive(plr2) {
2416 if (players_in_same_range(context->player, plr2, req->range)
2417 && player_has_ever_built(plr2, building)) {
2418 return TRI_YES;
2419 }
2421 return TRI_NO;
2422 case REQ_RANGE_PLAYER:
2423 if (context->player == nullptr) {
2424 return TRI_MAYBE;
2425 }
2427 building));
2430 case REQ_RANGE_CITY:
2431 case REQ_RANGE_LOCAL:
2432 case REQ_RANGE_TILE:
2434 case REQ_RANGE_ADJACENT:
2435 /* There is no sources cache for this. */
2436 log_error("Surviving requirements are only supported at "
2437 "World/Alliance/Team/Player ranges.");
2438 return TRI_NO;
2439 case REQ_RANGE_COUNT:
2440 break;
2441 }
2442
2443 } else {
2444
2445 /* Non-surviving requirement. */
2446 switch (req->range) {
2447 case REQ_RANGE_WORLD:
2448 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2449 case REQ_RANGE_ALLIANCE:
2450 case REQ_RANGE_TEAM:
2451 if (context->player == nullptr) {
2452 return TRI_MAYBE;
2453 }
2454 players_iterate_alive(plr2) {
2455 if (players_in_same_range(context->player, plr2, req->range)
2456 && num_player_buildings(plr2, building) > 0) {
2457 return TRI_YES;
2458 }
2460 return TRI_NO;
2461 case REQ_RANGE_PLAYER:
2462 if (context->player == nullptr) {
2463 return TRI_MAYBE;
2464 }
2466 building)
2467 > 0);
2469 /* At present, "Continent" effects can affect only
2470 * cities and units in cities. */
2471 if (context->player && context->city) {
2472 int continent = tile_continent(context->city->tile);
2474 continent, building)
2475 > 0);
2476 } else {
2477 return TRI_MAYBE;
2478 }
2480 if (context->city) {
2481 if (city_has_building(context->city, building)) {
2482 return TRI_YES;
2483 } else {
2484 enum fc_tristate ret = TRI_NO;
2485
2487 if (trade_partner == nullptr) {
2488 ret = TRI_MAYBE;
2489 } else if (city_has_building(trade_partner, building)) {
2490 return TRI_YES;
2491 }
2493
2494 return ret;
2495 }
2496 } else {
2497 return TRI_MAYBE;
2498 }
2499 case REQ_RANGE_CITY:
2500 if (context->city) {
2501 return BOOL_TO_TRISTATE(city_has_building(context->city, building));
2502 } else {
2503 return TRI_MAYBE;
2504 }
2505 case REQ_RANGE_LOCAL:
2506 if (context->building) {
2507 if (context->building == building) {
2508 return TRI_YES;
2509 } else {
2510 return TRI_NO;
2511 }
2512 } else {
2513 /* TODO: Other local targets */
2514 return TRI_MAYBE;
2515 }
2516 case REQ_RANGE_TILE:
2517 if (context->tile) {
2518 const struct city *pcity = tile_city(context->tile);
2519
2520 if (pcity) {
2521 return BOOL_TO_TRISTATE(city_has_building(pcity, building));
2522 } else {
2523 return TRI_NO;
2524 }
2525 } else {
2526 return TRI_MAYBE;
2527 }
2529 case REQ_RANGE_ADJACENT:
2530 case REQ_RANGE_COUNT:
2531 break;
2532 }
2533
2534 }
2535
2536 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2537 return TRI_NO;
2538}
2539
2540/**********************************************************************/
2548static enum fc_tristate
2550 const struct req_context *context,
2551 const struct req_context *other_context,
2552 const struct requirement *req)
2553{
2555
2556 return (context->building ? BOOL_TO_TRISTATE(
2557 context->building->genus
2558 == req->source.value.impr_genus)
2559 : TRI_MAYBE);
2560}
2561
2562/**********************************************************************/
2566 enum impr_flag_id flag)
2567{
2568 struct player *owner;
2569
2570 if (pcity == nullptr) {
2571 return TRI_MAYBE;
2572 }
2573
2575 city_built_iterate(pcity, impr) {
2576 if (improvement_has_flag(impr, flag)
2577 && !improvement_obsolete(owner, impr, pcity)) {
2578 return TRI_YES;
2579 }
2581
2582 return TRI_NO;
2583}
2584
2585/**********************************************************************/
2593static enum fc_tristate
2595 const struct req_context *context,
2596 const struct req_context *other_context,
2597 const struct requirement *req)
2598{
2600
2601 switch (req->range) {
2602 case REQ_RANGE_LOCAL:
2603 return (context->building
2605 req->source.value.impr_flag))
2606 : TRI_MAYBE);
2607 case REQ_RANGE_CITY:
2609 case REQ_RANGE_TILE:
2610 if (context->tile == nullptr) {
2611 return TRI_MAYBE;
2612 }
2614 req->source.value.impr_flag);
2616 case REQ_RANGE_ADJACENT:
2619 case REQ_RANGE_PLAYER:
2620 case REQ_RANGE_ALLIANCE:
2621 case REQ_RANGE_TEAM:
2622 case REQ_RANGE_WORLD:
2623 case REQ_RANGE_COUNT:
2624 break;
2625 }
2626
2627 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2628
2629 return TRI_MAYBE;
2630}
2631
2632/**********************************************************************/
2640static enum fc_tristate
2642 const struct req_context *context,
2643 const struct req_context *other_context,
2644 const struct requirement *req)
2645{
2647
2648 switch (req->range) {
2649 case REQ_RANGE_PLAYER:
2650 return (context->player != nullptr
2652 req->source.value.plr_flag))
2653 : TRI_MAYBE);
2654 case REQ_RANGE_LOCAL:
2655 case REQ_RANGE_CITY:
2656 case REQ_RANGE_TILE:
2658 case REQ_RANGE_ADJACENT:
2661 case REQ_RANGE_ALLIANCE:
2662 case REQ_RANGE_TEAM:
2663 case REQ_RANGE_WORLD:
2664 case REQ_RANGE_COUNT:
2665 break;
2666 }
2667
2668 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2669
2670 return TRI_MAYBE;
2671}
2672
2673/**********************************************************************/
2681static enum fc_tristate
2683 const struct req_context *context,
2684 const struct req_context *other_context,
2685 const struct requirement *req)
2686{
2688
2689 switch (req->range) {
2690 case REQ_RANGE_PLAYER:
2691 return (context->player != nullptr
2693 req->source.value.plrstate))
2694 : TRI_MAYBE);
2695 case REQ_RANGE_LOCAL:
2696 case REQ_RANGE_CITY:
2697 case REQ_RANGE_TILE:
2699 case REQ_RANGE_ADJACENT:
2702 case REQ_RANGE_ALLIANCE:
2703 case REQ_RANGE_TEAM:
2704 case REQ_RANGE_WORLD:
2705 case REQ_RANGE_COUNT:
2706 break;
2707 }
2708
2709 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2710
2711 return TRI_MAYBE;
2712}
2713
2714/**********************************************************************/
2722static enum fc_tristate
2724 const struct req_context *context,
2725 const struct req_context *other_context,
2726 const struct requirement *req)
2727{
2728 Tech_type_id tech;
2729
2731
2732 tech = advance_number(req->source.value.advance);
2733
2734 if (req->survives) {
2737 }
2738
2739 /* Not a 'surviving' requirement. */
2740 switch (req->range) {
2741 case REQ_RANGE_PLAYER:
2742 if (context->player != nullptr) {
2744 (research_get(context->player), tech));
2745 } else {
2746 return TRI_MAYBE;
2747 }
2748 case REQ_RANGE_TEAM:
2749 case REQ_RANGE_ALLIANCE:
2750 case REQ_RANGE_WORLD:
2751 if (context->player == nullptr) {
2752 return TRI_MAYBE;
2753 }
2754 players_iterate_alive(plr2) {
2755 if (players_in_same_range(context->player, plr2, req->range)) {
2756 if (research_invention_state(research_get(plr2), tech)
2757 == TECH_KNOWN) {
2758 return TRI_YES;
2759 }
2760 }
2762
2763 return TRI_NO;
2764 case REQ_RANGE_LOCAL:
2765 if (context->player == nullptr) {
2766 return TRI_MAYBE;
2767 }
2768 if (research_get(context->player)->researching == tech) {
2769 return TRI_YES;
2770 }
2771 return TRI_NO;
2772 case REQ_RANGE_TILE:
2774 case REQ_RANGE_ADJACENT:
2775 case REQ_RANGE_CITY:
2778 case REQ_RANGE_COUNT:
2779 break;
2780 }
2781
2782 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2783
2784 return TRI_MAYBE;
2785}
2786
2787/**********************************************************************/
2795static enum fc_tristate
2797 const struct req_context *context,
2798 const struct req_context *other_context,
2799 const struct requirement *req)
2800{
2801 enum tech_flag_id techflag;
2802
2804
2805 techflag = req->source.value.techflag;
2806
2807 switch (req->range) {
2808 case REQ_RANGE_PLAYER:
2809 if (context->player != nullptr) {
2811 techflag));
2812 } else {
2813 return TRI_MAYBE;
2814 }
2815 break;
2816 case REQ_RANGE_TEAM:
2817 case REQ_RANGE_ALLIANCE:
2818 if (context->player == nullptr) {
2819 return TRI_MAYBE;
2820 }
2821 players_iterate_alive(plr2) {
2822 if (players_in_same_range(context->player, plr2, req->range)
2823 && player_knows_techs_with_flag(plr2, techflag)) {
2824 return TRI_YES;
2825 }
2827 return TRI_NO;
2828 case REQ_RANGE_WORLD:
2829 players_iterate(pplayer) {
2830 if (player_knows_techs_with_flag(pplayer, techflag)) {
2831 return TRI_YES;
2832 }
2834
2835 return TRI_NO;
2836 case REQ_RANGE_LOCAL:
2837 if (context->player == nullptr) {
2838 return TRI_MAYBE;
2839 }
2840 if (advance_has_flag(research_get(context->player)->researching, techflag)) {
2841 return TRI_YES;
2842 }
2843 return TRI_NO;
2844 case REQ_RANGE_TILE:
2846 case REQ_RANGE_ADJACENT:
2847 case REQ_RANGE_CITY:
2850 case REQ_RANGE_COUNT:
2851 break;
2852 }
2853
2854 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2855
2856 return TRI_MAYBE;
2857}
2858
2859/**********************************************************************/
2867static enum fc_tristate
2869 const struct req_context *context,
2870 const struct req_context *other_context,
2871 const struct requirement *req)
2872{
2873 int minculture;
2874
2876
2877 minculture = req->source.value.minculture;
2878
2879 switch (req->range) {
2880 case REQ_RANGE_CITY:
2881 if (!context->city) {
2882 return TRI_MAYBE;
2883 }
2884 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2886 if (!context->city) {
2887 return TRI_MAYBE;
2888 }
2889 if (city_culture(context->city) >= minculture) {
2890 return TRI_YES;
2891 } else {
2892 enum fc_tristate ret = TRI_NO;
2893
2895 if (trade_partner == nullptr) {
2896 ret = TRI_MAYBE;
2897 } else if (city_culture(trade_partner) >= minculture) {
2898 return TRI_YES;
2899 }
2901
2902 return ret;
2903 }
2904 case REQ_RANGE_PLAYER:
2905 case REQ_RANGE_TEAM:
2906 case REQ_RANGE_ALLIANCE:
2907 case REQ_RANGE_WORLD:
2908 if (context->player == nullptr) {
2909 return TRI_MAYBE;
2910 }
2911 players_iterate_alive(plr2) {
2912 if (players_in_same_range(context->player, plr2, req->range)) {
2913 if (player_culture(plr2) >= minculture) {
2914 return TRI_YES;
2915 }
2916 }
2918 return TRI_NO;
2919 case REQ_RANGE_LOCAL:
2920 case REQ_RANGE_TILE:
2922 case REQ_RANGE_ADJACENT:
2924 case REQ_RANGE_COUNT:
2925 break;
2926 }
2927
2928 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2929
2930 return TRI_MAYBE;
2931}
2932
2933/**********************************************************************/
2941static enum fc_tristate
2943 const struct req_context *context,
2944 const struct req_context *other_context,
2945 const struct requirement *req)
2946{
2948
2950
2952
2953 switch (req->range) {
2954 case REQ_RANGE_CITY:
2955 if (!context->city) {
2956 return TRI_MAYBE;
2957 }
2959 / city_size_get(context->city);
2962 if (!context->city) {
2963 return TRI_MAYBE;
2964 }
2966 / city_size_get(context->city);
2968 return TRI_YES;
2969 } else {
2970 enum fc_tristate ret = TRI_NO;
2971
2973 if (trade_partner == nullptr) {
2974 ret = TRI_MAYBE;
2975 } else {
2979 return TRI_YES;
2980 }
2981 }
2983
2984 return ret;
2985 }
2986 case REQ_RANGE_PLAYER:
2987 case REQ_RANGE_TEAM:
2988 case REQ_RANGE_ALLIANCE:
2989 case REQ_RANGE_WORLD:
2990 case REQ_RANGE_LOCAL:
2991 case REQ_RANGE_TILE:
2993 case REQ_RANGE_ADJACENT:
2995 case REQ_RANGE_COUNT:
2996 break;
2997 }
2998
2999 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3000
3001 return TRI_MAYBE;
3002}
3003
3004/**********************************************************************/
3012static enum fc_tristate
3014 const struct req_context *context,
3015 const struct req_context *other_context,
3016 const struct requirement *req)
3017{
3018 int max_units;
3019
3021
3023
3024 /* TODO: If can't see V_INVIS -> TRI_MAYBE */
3025 switch (req->range) {
3026 case REQ_RANGE_TILE:
3027 if (!context->tile) {
3028 return TRI_MAYBE;
3029 }
3030 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
3032 if (!context->tile) {
3033 return TRI_MAYBE;
3034 }
3035 if (unit_list_size(context->tile->units) <= max_units) {
3036 return TRI_YES;
3037 }
3039 if (unit_list_size(adjc_tile->units) <= max_units) {
3040 return TRI_YES;
3041 }
3043 return TRI_NO;
3044 case REQ_RANGE_ADJACENT:
3045 if (!context->tile) {
3046 return TRI_MAYBE;
3047 }
3048 if (unit_list_size(context->tile->units) <= max_units) {
3049 return TRI_YES;
3050 }
3052 if (unit_list_size(adjc_tile->units) <= max_units) {
3053 return TRI_YES;
3054 }
3056 return TRI_NO;
3057 case REQ_RANGE_CITY:
3060 case REQ_RANGE_PLAYER:
3061 case REQ_RANGE_TEAM:
3062 case REQ_RANGE_ALLIANCE:
3063 case REQ_RANGE_WORLD:
3064 case REQ_RANGE_LOCAL:
3065 case REQ_RANGE_COUNT:
3066 break;
3067 }
3068
3069 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3070
3071 return TRI_MAYBE;
3072}
3073
3074
3075/**********************************************************************/
3083static enum fc_tristate
3085 const struct req_context *context,
3086 const struct req_context *other_context,
3087 const struct requirement *req)
3088{
3089 int max_units;
3090 int count;
3091
3093
3095
3096 /* TODO: If can't see V_INVIS -> TRI_MAYBE */
3097 switch (req->range) {
3098 case REQ_RANGE_TILE:
3099 if (!context->tile) {
3100 return TRI_MAYBE;
3101 }
3102 count = 0;
3103 unit_list_iterate(context->tile->units, punit) {
3104 if (!unit_transported(punit)) {
3105 count++;
3106 }
3108 return BOOL_TO_TRISTATE(count <= max_units);
3110 if (!context->tile) {
3111 return TRI_MAYBE;
3112 }
3113 count = 0;
3114 unit_list_iterate(context->tile->units, punit) {
3115 if (!unit_transported(punit)) {
3116 count++;
3117 }
3119 if (count <= max_units) {
3120 return TRI_YES;
3121 }
3123 count = 0;
3125 if (!unit_transported(punit)) {
3126 count++;
3127 }
3129 if (count <= max_units) {
3130 return TRI_YES;
3131 }
3133
3134 return TRI_NO;
3135 case REQ_RANGE_ADJACENT:
3136 if (!context->tile) {
3137 return TRI_MAYBE;
3138 }
3139 count = 0;
3140 unit_list_iterate(context->tile->units, punit) {
3141 if (!unit_transported(punit)) {
3142 count++;
3143 }
3145 if (count <= max_units) {
3146 return TRI_YES;
3147 }
3149 count = 0;
3151 if (!unit_transported(punit)) {
3152 count++;
3153 }
3155 if (count <= max_units) {
3156 return TRI_YES;
3157 }
3159 return TRI_NO;
3160 case REQ_RANGE_CITY:
3163 case REQ_RANGE_PLAYER:
3164 case REQ_RANGE_TEAM:
3165 case REQ_RANGE_ALLIANCE:
3166 case REQ_RANGE_WORLD:
3167 case REQ_RANGE_LOCAL:
3168 case REQ_RANGE_COUNT:
3169 break;
3170 }
3171
3172 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3173
3174 return TRI_MAYBE;
3175}
3176
3177/**********************************************************************/
3185static enum fc_tristate
3187 const struct req_context *context,
3188 const struct req_context *other_context,
3189 const struct requirement *req)
3190{
3191 const struct extra_type *pextra;
3192 enum fc_tristate ret;
3193
3195
3196 pextra = req->source.value.extra;
3197
3198 switch (req->range) {
3199 case REQ_RANGE_LOCAL:
3200 if (!context->extra) {
3201 return TRI_MAYBE;
3202 }
3203 return BOOL_TO_TRISTATE(context->extra == pextra);
3204 case REQ_RANGE_TILE:
3205 /* The requirement is filled if the tile has extra of requested type. */
3206 if (!context->tile) {
3207 return TRI_MAYBE;
3208 }
3209 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
3211 if (!context->tile) {
3212 return TRI_MAYBE;
3213 }
3214 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
3215 || is_extra_card_near(nmap, context->tile, pextra));
3216 case REQ_RANGE_ADJACENT:
3217 if (!context->tile) {
3218 return TRI_MAYBE;
3219 }
3220 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
3221 || is_extra_near_tile(nmap, context->tile, pextra));
3222 case REQ_RANGE_CITY:
3223 if (!context->city) {
3224 return TRI_MAYBE;
3225 }
3227 city_tile(context->city), ptile) {
3228 if (tile_has_extra(ptile, pextra)) {
3229 return TRI_YES;
3230 }
3232
3233 return TRI_NO;
3234
3236 if (!context->city) {
3237 return TRI_MAYBE;
3238 }
3240 city_tile(context->city), ptile) {
3241 if (tile_has_extra(ptile, pextra)) {
3242 return TRI_YES;
3243 }
3245
3246 ret = TRI_NO;
3248 if (trade_partner == nullptr) {
3249 ret = TRI_MAYBE;
3250 } else {
3252 city_tile(trade_partner), ptile) {
3253 if (tile_has_extra(ptile, pextra)) {
3254 return TRI_YES;
3255 }
3257 }
3259
3260 return ret;
3261
3263 case REQ_RANGE_PLAYER:
3264 case REQ_RANGE_TEAM:
3265 case REQ_RANGE_ALLIANCE:
3266 case REQ_RANGE_WORLD:
3267 case REQ_RANGE_COUNT:
3268 break;
3269 }
3270
3271 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3272
3273 return TRI_MAYBE;
3274}
3275
3276/**********************************************************************/
3284static enum fc_tristate
3286 const struct req_context *context,
3287 const struct req_context *other_context,
3288 const struct requirement *req)
3289{
3290 const struct tiledef *ptdef;
3291 enum fc_tristate ret;
3292
3294
3295 ptdef = req->source.value.tiledef;
3296
3297 switch (req->range) {
3298 case REQ_RANGE_TILE:
3299 /* The requirement is filled if the tile has tiledef of requested type. */
3300 if (!context->tile) {
3301 return TRI_MAYBE;
3302 }
3305 if (!context->tile) {
3306 return TRI_MAYBE;
3307 }
3310 case REQ_RANGE_ADJACENT:
3311 if (!context->tile) {
3312 return TRI_MAYBE;
3313 }
3316 case REQ_RANGE_CITY:
3317 if (!context->city) {
3318 return TRI_MAYBE;
3319 }
3321 city_tile(context->city), ptile) {
3322 if (tile_matches_tiledef(ptdef, ptile)) {
3323 return TRI_YES;
3324 }
3326
3327 return TRI_NO;
3328
3330 if (!context->city) {
3331 return TRI_MAYBE;
3332 }
3334 city_tile(context->city), ptile) {
3335 if (tile_matches_tiledef(ptdef, ptile)) {
3336 return TRI_YES;
3337 }
3339
3340 ret = TRI_NO;
3342 if (trade_partner == nullptr) {
3343 ret = TRI_MAYBE;
3344 } else {
3346 city_tile(trade_partner), ptile) {
3347 if (tile_matches_tiledef(ptdef, ptile)) {
3348 return TRI_YES;
3349 }
3351 }
3353
3354 return ret;
3355
3356 case REQ_RANGE_LOCAL:
3358 case REQ_RANGE_PLAYER:
3359 case REQ_RANGE_TEAM:
3360 case REQ_RANGE_ALLIANCE:
3361 case REQ_RANGE_WORLD:
3362 case REQ_RANGE_COUNT:
3363 break;
3364 }
3365
3366 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3367
3368 return TRI_MAYBE;
3369}
3370
3371/**********************************************************************/
3379static enum fc_tristate
3381 const struct req_context *context,
3382 const struct req_context *other_context,
3383 const struct requirement *req)
3384{
3386
3387 if (req->range == REQ_RANGE_CITY) {
3388 if (context->city == nullptr
3389 || context->city->aarea == nullptr) {
3390 return TRI_MAYBE;
3391 }
3392
3393 if (BV_ISSET(context->city->aarea->tiledefs,
3395 return TRI_YES;
3396 }
3397
3398 return TRI_NO;
3399 }
3400
3401 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3402
3403 return TRI_MAYBE;
3404}
3405
3406/**********************************************************************/
3414static enum fc_tristate
3416 const struct req_context *context,
3417 const struct req_context *other_context,
3418 const struct requirement *req)
3419{
3420 const struct goods_type *pgood;
3421
3423
3424 pgood = req->source.value.good;
3425
3426 switch (req->range) {
3427 case REQ_RANGE_LOCAL:
3428 case REQ_RANGE_CITY:
3429 /* The requirement is filled if the city imports good of requested type. */
3430 if (!context->city) {
3431 return TRI_MAYBE;
3432 }
3436 nullptr)));
3437 case REQ_RANGE_TILE:
3439 case REQ_RANGE_ADJACENT:
3442 case REQ_RANGE_PLAYER:
3443 case REQ_RANGE_TEAM:
3444 case REQ_RANGE_ALLIANCE:
3445 case REQ_RANGE_WORLD:
3446 case REQ_RANGE_COUNT:
3447 break;
3448 }
3449
3450 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3451
3452 return TRI_MAYBE;
3453}
3454
3455/**********************************************************************/
3463static enum fc_tristate
3465 const struct req_context *context,
3466 const struct req_context *other_context,
3467 const struct requirement *req)
3468{
3470
3471 if (context->action) {
3472 return BOOL_TO_TRISTATE(action_number(context->action)
3473 == action_number(req->source.value.action));
3474 }
3475
3476 if (context->unit != nullptr && context->unit->action != ACTION_NONE) {
3477 log_normal("Unit action %s", action_id_rule_name(context->unit->action));
3478 return BOOL_TO_TRISTATE(context->unit->action
3479 == action_number(req->source.value.action));
3480 }
3481
3482 return TRI_NO;
3483}
3484
3485/**********************************************************************/
3493static enum fc_tristate
3495 const struct req_context *context,
3496 const struct req_context *other_context,
3497 const struct requirement *req)
3498{
3500
3501 return BOOL_TO_TRISTATE(context->output
3502 && context->output->index
3503 == req->source.value.outputtype);
3504}
3505
3506/**********************************************************************/
3514static enum fc_tristate
3516 const struct req_context *context,
3517 const struct req_context *other_context,
3518 const struct requirement *req)
3519{
3521
3522 return BOOL_TO_TRISTATE(context->specialist
3523 && context->specialist
3524 == req->source.value.specialist);
3525}
3526
3527/**********************************************************************/
3535static enum fc_tristate
3537 const struct req_context *context,
3538 const struct req_context *other_context,
3539 const struct requirement *req)
3540{
3541 const struct terrain *pterrain;
3542
3544
3545 pterrain = req->source.value.terrain;
3546
3547 switch (req->range) {
3548 case REQ_RANGE_TILE:
3549 /* The requirement is filled if the tile has the terrain. */
3550 if (!context->tile) {
3551 return TRI_MAYBE;
3552 }
3553 return pterrain && tile_terrain(context->tile) == pterrain;
3555 if (!context->tile) {
3556 return TRI_MAYBE;
3557 }
3558 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
3559 case REQ_RANGE_ADJACENT:
3560 if (!context->tile) {
3561 return TRI_MAYBE;
3562 }
3563 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
3564 case REQ_RANGE_CITY:
3565 if (!context->city) {
3566 return TRI_MAYBE;
3567 }
3568 if (pterrain != nullptr) {
3570 city_tile(context->city), ptile) {
3571 if (tile_terrain(ptile) == pterrain) {
3572 return TRI_YES;
3573 }
3575 }
3576 return TRI_NO;
3578 if (!context->city) {
3579 return TRI_MAYBE;
3580 }
3581 if (pterrain != nullptr) {
3582 enum fc_tristate ret;
3583
3585 city_tile(context->city), ptile) {
3586 if (tile_terrain(ptile) == pterrain) {
3587 return TRI_YES;
3588 }
3590
3591 ret = TRI_NO;
3593 if (trade_partner == nullptr) {
3594 ret = TRI_MAYBE;
3595 } else {
3597 city_tile(trade_partner), ptile) {
3598 if (tile_terrain(ptile) == pterrain) {
3599 return TRI_YES;
3600 }
3602 }
3604
3605 return ret;
3606 }
3607
3608 return TRI_MAYBE;
3610 case REQ_RANGE_PLAYER:
3611 case REQ_RANGE_TEAM:
3612 case REQ_RANGE_ALLIANCE:
3613 case REQ_RANGE_WORLD:
3614 case REQ_RANGE_LOCAL:
3615 case REQ_RANGE_COUNT:
3616 break;
3617 }
3618
3619 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3620
3621 return TRI_MAYBE;
3622}
3623
3624/**********************************************************************/
3632static enum fc_tristate
3634 const struct req_context *context,
3635 const struct req_context *other_context,
3636 const struct requirement *req)
3637{
3638 enum terrain_class pclass;
3639 enum fc_tristate ret;
3640
3642
3644
3645 switch (req->range) {
3646 case REQ_RANGE_TILE:
3647 /* The requirement is filled if the tile has the terrain of correct class. */
3648 if (!context->tile) {
3649 return TRI_MAYBE;
3650 }
3653 if (!context->tile) {
3654 return TRI_MAYBE;
3655 }
3658 case REQ_RANGE_ADJACENT:
3659 if (!context->tile) {
3660 return TRI_MAYBE;
3661 }
3664 case REQ_RANGE_CITY:
3665 if (!context->city) {
3666 return TRI_MAYBE;
3667 }
3669 city_tile(context->city), ptile) {
3670 const struct terrain *pterrain = tile_terrain(ptile);
3671
3672 if (pterrain != T_UNKNOWN
3673 && terrain_type_terrain_class(pterrain) == pclass) {
3674 return TRI_YES;
3675 }
3677
3678 return TRI_NO;
3680 if (!context->city) {
3681 return TRI_MAYBE;
3682 }
3684 city_tile(context->city), ptile) {
3685 const struct terrain *pterrain = tile_terrain(ptile);
3686
3687 if (pterrain != T_UNKNOWN
3688 && terrain_type_terrain_class(pterrain) == pclass) {
3689 return TRI_YES;
3690 }
3692
3693 ret = TRI_NO;
3695 if (trade_partner == nullptr) {
3696 ret = TRI_MAYBE;
3697 } else {
3699 city_tile(trade_partner), ptile) {
3700 const struct terrain *pterrain = tile_terrain(ptile);
3701
3702 if (pterrain != T_UNKNOWN
3703 && terrain_type_terrain_class(pterrain) == pclass) {
3704 return TRI_YES;
3705 }
3707 }
3709
3710 return ret;
3712 case REQ_RANGE_PLAYER:
3713 case REQ_RANGE_TEAM:
3714 case REQ_RANGE_ALLIANCE:
3715 case REQ_RANGE_WORLD:
3716 case REQ_RANGE_LOCAL:
3717 case REQ_RANGE_COUNT:
3718 break;
3719 }
3720
3721 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3722
3723 return TRI_MAYBE;
3724}
3725
3726/**********************************************************************/
3734static enum fc_tristate
3736 const struct req_context *context,
3737 const struct req_context *other_context,
3738 const struct requirement *req)
3739{
3741 enum fc_tristate ret;
3742
3744
3746
3747 switch (req->range) {
3748 case REQ_RANGE_TILE:
3749 /* The requirement is fulfilled if the tile has a terrain with
3750 * correct flag. */
3751 if (!context->tile) {
3752 return TRI_MAYBE;
3753 }
3755 terrflag));
3757 if (!context->tile) {
3758 return TRI_MAYBE;
3759 }
3761 terrflag)
3763 terrflag));
3764 case REQ_RANGE_ADJACENT:
3765 if (!context->tile) {
3766 return TRI_MAYBE;
3767 }
3769 terrflag)
3771 terrflag));
3772 case REQ_RANGE_CITY:
3773 if (!context->city) {
3774 return TRI_MAYBE;
3775 }
3777 city_tile(context->city), ptile) {
3778 const struct terrain *pterrain = tile_terrain(ptile);
3779
3780 if (pterrain != T_UNKNOWN
3781 && terrain_has_flag(pterrain, terrflag)) {
3782 return TRI_YES;
3783 }
3785
3786 return TRI_NO;
3788 if (!context->city) {
3789 return TRI_MAYBE;
3790 }
3792 city_tile(context->city), ptile) {
3793 const struct terrain *pterrain = tile_terrain(ptile);
3794
3795 if (pterrain != T_UNKNOWN
3796 && terrain_has_flag(pterrain, terrflag)) {
3797 return TRI_YES;
3798 }
3800
3801 ret = TRI_NO;
3803 if (trade_partner == nullptr) {
3804 ret = TRI_MAYBE;
3805 } else {
3807 city_tile(trade_partner), ptile) {
3808 const struct terrain *pterrain = tile_terrain(ptile);
3809
3810 if (pterrain != T_UNKNOWN
3811 && terrain_has_flag(pterrain, terrflag)) {
3812 return TRI_YES;
3813 }
3815 }
3817
3818 return ret;
3820 case REQ_RANGE_PLAYER:
3821 case REQ_RANGE_TEAM:
3822 case REQ_RANGE_ALLIANCE:
3823 case REQ_RANGE_WORLD:
3824 case REQ_RANGE_LOCAL:
3825 case REQ_RANGE_COUNT:
3826 break;
3827 }
3828
3829 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3830
3831 return TRI_MAYBE;
3832}
3833
3834/**********************************************************************/
3842static enum fc_tristate
3844 const struct req_context *context,
3845 const struct req_context *other_context,
3846 const struct requirement *req)
3847{
3848 enum road_flag_id roadflag;
3849 enum fc_tristate ret;
3850
3852
3853 roadflag = req->source.value.roadflag;
3854
3855 switch (req->range) {
3856 case REQ_RANGE_LOCAL:
3857 {
3858 if (!context->extra) {
3859 return TRI_MAYBE;
3860 }
3861 struct road_type *r = extra_road_get(context->extra);
3862
3863 return BOOL_TO_TRISTATE(
3864 r && road_has_flag(r, roadflag)
3865 );
3866 }
3867 case REQ_RANGE_TILE:
3868 /* The requirement is filled if the tile has a road with correct flag. */
3869 if (!context->tile) {
3870 return TRI_MAYBE;
3871 }
3872 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3874 if (!context->tile) {
3875 return TRI_MAYBE;
3876 }
3877 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3879 roadflag));
3880 case REQ_RANGE_ADJACENT:
3881 if (!context->tile) {
3882 return TRI_MAYBE;
3883 }
3884 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3886 roadflag));
3887 case REQ_RANGE_CITY:
3888 if (!context->city) {
3889 return TRI_MAYBE;
3890 }
3892 city_tile(context->city), ptile) {
3893 if (tile_has_road_flag(ptile, roadflag)) {
3894 return TRI_YES;
3895 }
3897
3898 return TRI_NO;
3900 if (!context->city) {
3901 return TRI_MAYBE;
3902 }
3904 city_tile(context->city), ptile) {
3905 if (tile_has_road_flag(ptile, roadflag)) {
3906 return TRI_YES;
3907 }
3909
3910 ret = TRI_NO;
3912 if (trade_partner == nullptr) {
3913 ret = TRI_MAYBE;
3914 } else {
3916 city_tile(trade_partner), ptile) {
3917 if (tile_has_road_flag(ptile, roadflag)) {
3918 return TRI_YES;
3919 }
3921 }
3923
3924 return ret;
3926 case REQ_RANGE_PLAYER:
3927 case REQ_RANGE_TEAM:
3928 case REQ_RANGE_ALLIANCE:
3929 case REQ_RANGE_WORLD:
3930 case REQ_RANGE_COUNT:
3931 break;
3932 }
3933
3934 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3935
3936 return TRI_MAYBE;
3937}
3938
3939/**********************************************************************/
3947static enum fc_tristate
3949 const struct req_context *context,
3950 const struct req_context *other_context,
3951 const struct requirement *req)
3952{
3953 enum extra_flag_id extraflag;
3954 enum fc_tristate ret;
3955
3957
3958 extraflag = req->source.value.extraflag;
3959
3960 switch (req->range) {
3961 case REQ_RANGE_LOCAL:
3962 if (!context->extra) {
3963 return TRI_MAYBE;
3964 }
3965 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3966 case REQ_RANGE_TILE:
3967 /* The requirement is filled if the tile has an extra with correct flag. */
3968 if (!context->tile) {
3969 return TRI_MAYBE;
3970 }
3971 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3973 if (!context->tile) {
3974 return TRI_MAYBE;
3975 }
3976 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3977 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3978 case REQ_RANGE_ADJACENT:
3979 if (!context->tile) {
3980 return TRI_MAYBE;
3981 }
3982 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3983 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3984 case REQ_RANGE_CITY:
3985 if (!context->city) {
3986 return TRI_MAYBE;
3987 }
3989 city_tile(context->city), ptile) {
3990 if (tile_has_extra_flag(ptile, extraflag)) {
3991 return TRI_YES;
3992 }
3994
3995 return TRI_NO;
3997 if (!context->city) {
3998 return TRI_MAYBE;
3999 }
4001 city_tile(context->city), ptile) {
4002 if (tile_has_extra_flag(ptile, extraflag)) {
4003 return TRI_YES;
4004 }
4006
4007 ret = TRI_NO;
4009 if (trade_partner == nullptr) {
4010 ret = TRI_MAYBE;
4011 } else {
4013 city_tile(trade_partner), ptile) {
4014 if (tile_has_extra_flag(ptile, extraflag)) {
4015 return TRI_YES;
4016 }
4018 }
4020
4021 return ret;
4023 case REQ_RANGE_PLAYER:
4024 case REQ_RANGE_TEAM:
4025 case REQ_RANGE_ALLIANCE:
4026 case REQ_RANGE_WORLD:
4027 case REQ_RANGE_COUNT:
4028 break;
4029 }
4030
4031 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4032
4033 return TRI_MAYBE;
4034}
4035
4036/**********************************************************************/
4044static enum fc_tristate
4046 const struct req_context *context,
4047 const struct req_context *other_context,
4048 const struct requirement *req)
4049{
4051
4053
4055
4056 if (!context->tile) {
4057 return TRI_MAYBE;
4058 }
4059
4060 switch (req->range) {
4061 case REQ_RANGE_TILE:
4065 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
4066 case REQ_RANGE_CITY:
4069 case REQ_RANGE_PLAYER:
4070 case REQ_RANGE_TEAM:
4071 case REQ_RANGE_ALLIANCE:
4072 case REQ_RANGE_WORLD:
4073 case REQ_RANGE_LOCAL:
4074 case REQ_RANGE_COUNT:
4075 break;
4076 }
4077
4078 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4079
4080 return TRI_MAYBE;
4081}
4082
4083/**********************************************************************/
4091static enum fc_tristate
4093 const struct req_context *context,
4094 const struct req_context *other_context,
4095 const struct requirement *req)
4096{
4098
4099 if (context->player == nullptr) {
4100 return TRI_MAYBE;
4101 } else {
4103 == req->source.value.govern);
4104 }
4105}
4106
4107/**********************************************************************/
4115static enum fc_tristate
4117 const struct req_context *context,
4118 const struct req_context *other_context,
4119 const struct requirement *req)
4120{
4122
4123 if (context->player == nullptr) {
4124 return TRI_MAYBE;
4125 } else {
4127 req->source.value.govflag));
4128 }
4129}
4130
4131/**********************************************************************/
4139static enum fc_tristate
4141 const struct req_context *context,
4142 const struct req_context *other_context,
4143 const struct requirement *req)
4144{
4146
4147 if (context->player == nullptr) {
4148 return TRI_MAYBE;
4149 } else {
4150 return BOOL_TO_TRISTATE(context->player->style
4151 == req->source.value.style);
4152 }
4153}
4154
4155/**********************************************************************/
4163static enum fc_tristate
4165 const struct req_context *context,
4166 const struct req_context *other_context,
4167 const struct requirement *req)
4168{
4170
4171 switch (req->range) {
4172 case REQ_RANGE_WORLD:
4173 /* "None" does not count */
4174 return ((game.info.global_advance_count - 1)
4175 >= req->source.value.min_techs);
4176 case REQ_RANGE_PLAYER:
4177 if (context->player == nullptr) {
4178 return TRI_MAYBE;
4179 } else {
4180 /* "None" does not count */
4181 return BOOL_TO_TRISTATE(
4182 (research_get(context->player)->techs_researched - 1)
4183 >= req->source.value.min_techs
4184 );
4185 }
4186 default:
4187 return TRI_MAYBE;
4188 }
4189}
4190
4191/**********************************************************************/
4199static enum fc_tristate
4201 const struct req_context *context,
4202 const struct req_context *other_context,
4203 const struct requirement *req)
4204{
4206
4207 switch (req->range) {
4208 case REQ_RANGE_WORLD:
4210 if (research_get(plr)->future_tech
4211 >= req->source.value.future_techs) {
4212 return TRI_YES;
4213 }
4215
4216 return TRI_NO;
4217 case REQ_RANGE_PLAYER:
4218 if (context->player == nullptr) {
4219 return TRI_MAYBE;
4220 } else {
4222 >= req->source.value.future_techs);
4223 }
4224 default:
4225 return TRI_MAYBE;
4226 }
4227}
4228
4229/**********************************************************************/
4237static enum fc_tristate
4239 const struct req_context *context,
4240 const struct req_context *other_context,
4241 const struct requirement *req)
4242{
4244
4245 switch (req->range) {
4246 case REQ_RANGE_PLAYER:
4247 if (context->player == nullptr) {
4248 return TRI_MAYBE;
4249 } else {
4250 /* "None" does not count */
4251 return BOOL_TO_TRISTATE(
4252 city_list_size(context->player->cities)
4253 >= req->source.value.min_cities
4254 );
4255 }
4256 default:
4257 return TRI_MAYBE;
4258 }
4259}
4260
4261/**********************************************************************/
4269static enum fc_tristate
4271 const struct req_context *context,
4272 const struct req_context *other_context,
4273 const struct requirement *req)
4274{
4276
4277 if (context->player == nullptr) {
4278 return TRI_MAYBE;
4279 } else {
4280 return BOOL_TO_TRISTATE(is_ai(context->player)
4281 && context->player->ai_common.skill_level
4282 == req->source.value.ai_level);
4283 }
4284}
4285
4286/**********************************************************************/
4294static enum fc_tristate
4296 const struct req_context *context,
4297 const struct req_context *other_context,
4298 const struct requirement *req)
4299{
4300 const struct nation_type *nation;
4301
4303
4304 nation = req->source.value.nation;
4305
4306 switch (req->range) {
4307 case REQ_RANGE_PLAYER:
4308 if (context->player == nullptr) {
4309 return TRI_MAYBE;
4310 }
4311 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
4312 case REQ_RANGE_TEAM:
4313 case REQ_RANGE_ALLIANCE:
4314 if (context->player == nullptr) {
4315 return TRI_MAYBE;
4316 }
4317 players_iterate_alive(plr2) {
4318 if (players_in_same_range(context->player, plr2, req->range)) {
4319 if (nation_of_player(plr2) == nation) {
4320 return TRI_YES;
4321 }
4322 }
4324 return TRI_NO;
4325 case REQ_RANGE_WORLD:
4326 /* NB: if a player is ever removed outright from the game
4327 * (e.g. via /remove), rather than just dying, this 'survives'
4328 * requirement will stop being true for their nation.
4329 * create_command_newcomer() can also cause this to happen. */
4330 return BOOL_TO_TRISTATE(nation->player != nullptr
4331 && (req->survives || nation->player->is_alive));
4332 case REQ_RANGE_LOCAL:
4333 case REQ_RANGE_TILE:
4335 case REQ_RANGE_ADJACENT:
4336 case REQ_RANGE_CITY:
4339 case REQ_RANGE_COUNT:
4340 break;
4341 }
4342
4343 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4344
4345 return TRI_MAYBE;
4346}
4347
4348/**********************************************************************/
4356static enum fc_tristate
4358 const struct req_context *context,
4359 const struct req_context *other_context,
4360 const struct requirement *req)
4361{
4362 const struct nation_group *ngroup;
4363
4365
4367
4368 switch (req->range) {
4369 case REQ_RANGE_PLAYER:
4370 if (context->player == nullptr) {
4371 return TRI_MAYBE;
4372 }
4374 nation_of_player(context->player), ngroup));
4375 case REQ_RANGE_TEAM:
4376 case REQ_RANGE_ALLIANCE:
4377 case REQ_RANGE_WORLD:
4378 if (context->player == nullptr) {
4379 return TRI_MAYBE;
4380 }
4381 players_iterate_alive(plr2) {
4382 if (players_in_same_range(context->player, plr2, req->range)) {
4384 return TRI_YES;
4385 }
4386 }
4388 return TRI_NO;
4389 case REQ_RANGE_LOCAL:
4390 case REQ_RANGE_TILE:
4392 case REQ_RANGE_ADJACENT:
4393 case REQ_RANGE_CITY:
4396 case REQ_RANGE_COUNT:
4397 break;
4398 }
4399
4400 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4401
4402 return TRI_MAYBE;
4403}
4404
4405/**********************************************************************/
4413static enum fc_tristate
4415 const struct req_context *context,
4416 const struct req_context *other_context,
4417 const struct requirement *req)
4418{
4419 const struct nation_type *nationality;
4420 enum fc_tristate ret;
4421
4423
4424 nationality = req->source.value.nationality;
4425
4426 switch (req->range) {
4427 case REQ_RANGE_CITY:
4428 if (context->city == nullptr) {
4429 return TRI_MAYBE;
4430 }
4431 citizens_iterate(context->city, slot, count) {
4432 if (player_slot_get_player(slot)->nation == nationality) {
4433 return TRI_YES;
4434 }
4436
4437 return TRI_NO;
4439 if (context->city == nullptr) {
4440 return TRI_MAYBE;
4441 }
4442 citizens_iterate(context->city, slot, count) {
4443 if (player_slot_get_player(slot)->nation == nationality) {
4444 return TRI_YES;
4445 }
4447
4448 ret = TRI_NO;
4450 if (trade_partner == nullptr) {
4451 ret = TRI_MAYBE;
4452 } else {
4453 citizens_iterate(trade_partner, slot, count) {
4454 if (player_slot_get_player(slot)->nation == nationality) {
4455 return TRI_YES;
4456 }
4458 }
4460
4461 return ret;
4462 case REQ_RANGE_PLAYER:
4463 case REQ_RANGE_TEAM:
4464 case REQ_RANGE_ALLIANCE:
4465 case REQ_RANGE_WORLD:
4466 case REQ_RANGE_LOCAL:
4467 case REQ_RANGE_TILE:
4469 case REQ_RANGE_ADJACENT:
4471 case REQ_RANGE_COUNT:
4472 break;
4473 }
4474
4475 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4476
4477 return TRI_MAYBE;
4478}
4479
4480/**********************************************************************/
4488static enum fc_tristate
4490 const struct req_context *context,
4491 const struct req_context *other_context,
4492 const struct requirement *req)
4493{
4494 const struct nation_type *nation;
4495
4497
4498 nation = req->source.value.origowner;
4499
4500 switch (req->range) {
4501 case REQ_RANGE_CITY:
4502 if (context->city == nullptr || context->city->original == nullptr) {
4503 return TRI_MAYBE;
4504 }
4505 if (player_nation(context->city->original) == nation) {
4506 return TRI_YES;
4507 }
4508
4509 return TRI_NO;
4511 case REQ_RANGE_PLAYER:
4512 case REQ_RANGE_TEAM:
4513 case REQ_RANGE_ALLIANCE:
4514 case REQ_RANGE_WORLD:
4515 case REQ_RANGE_LOCAL:
4516 case REQ_RANGE_TILE:
4518 case REQ_RANGE_ADJACENT:
4520 case REQ_RANGE_COUNT:
4521 break;
4522 }
4523
4524 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4525
4526 return TRI_MAYBE;
4527}
4528
4529/**********************************************************************/
4533 const struct player *other_player,
4534 enum req_range range,
4535 int diplrel)
4536{
4537 switch (range) {
4538 case REQ_RANGE_PLAYER:
4539 if (target_player == nullptr) {
4540 return TRI_MAYBE;
4541 }
4543 case REQ_RANGE_TEAM:
4544 case REQ_RANGE_ALLIANCE:
4545 case REQ_RANGE_WORLD:
4546 if (target_player == nullptr) {
4547 return TRI_MAYBE;
4548 }
4549 players_iterate_alive(plr2) {
4551 if (is_diplrel_to_other(plr2, diplrel)) {
4552 return TRI_YES;
4553 }
4554 }
4556 return TRI_NO;
4557 case REQ_RANGE_LOCAL:
4558 if (target_player == nullptr || other_player == nullptr) {
4559 return TRI_MAYBE;
4560 }
4561 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
4562 case REQ_RANGE_TILE:
4564 case REQ_RANGE_ADJACENT:
4565 case REQ_RANGE_CITY:
4568 case REQ_RANGE_COUNT:
4569 break;
4570 }
4571
4572 fc_assert_msg(FALSE, "Invalid range %d.", range);
4573
4574 return TRI_MAYBE;
4575}
4576
4577/**********************************************************************/
4585static enum fc_tristate
4587 const struct req_context *context,
4588 const struct req_context *other_context,
4589 const struct requirement *req)
4590{
4592
4593 return is_diplrel_in_range(context->player, other_context->player,
4594 req->range, req->source.value.diplrel);
4595}
4596
4597/**********************************************************************/
4605static enum fc_tristate
4607 const struct req_context *context,
4608 const struct req_context *other_context,
4609 const struct requirement *req)
4610{
4612
4613 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4614 : nullptr,
4615 context->player,
4616 req->range,
4617 req->source.value.diplrel);
4618}
4619
4620/**********************************************************************/
4629static enum fc_tristate
4631 const struct req_context *context,
4632 const struct req_context *other_context,
4633 const struct requirement *req)
4634{
4636
4637 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4638 : nullptr,
4639 other_context->player,
4640 req->range,
4641 req->source.value.diplrel);
4642}
4643
4644/**********************************************************************/
4647static enum fc_tristate
4649 const struct player *other_player,
4650 enum req_range range,
4651 int diplrel)
4652{
4653 enum fc_tristate out = TRI_NO;
4654
4655 if (target_tile == nullptr) {
4656 return TRI_MAYBE;
4657 }
4658
4661 unit_owner(target_unit), other_player, range, diplrel);
4662
4665
4666 return out;
4667}
4668
4669/**********************************************************************/
4678static enum fc_tristate
4680 const struct req_context *context,
4681 const struct req_context *other_context,
4682 const struct requirement *req)
4683{
4685
4686 return is_diplrel_unitany_in_range(context->tile, context->player,
4687 req->range,
4688 req->source.value.diplrel);
4689}
4690
4691/**********************************************************************/
4700static enum fc_tristate
4702 const struct req_context *context,
4703 const struct req_context *other_context,
4704 const struct requirement *req)
4705{
4707
4709 req->range,
4710 req->source.value.diplrel);
4711}
4712
4713/**********************************************************************/
4721static enum fc_tristate
4723 const struct req_context *context,
4724 const struct req_context *other_context,
4725 const struct requirement *req)
4726{
4727 const struct unit_type *punittype;
4728
4730
4731 punittype = req->source.value.utype;
4732
4733 switch (req->range) {
4734 case REQ_RANGE_LOCAL:
4735 if (!context->unittype) {
4736 return TRI_MAYBE;
4737 }
4738 return BOOL_TO_TRISTATE(context->unittype == punittype);
4739 case REQ_RANGE_TILE:
4741 case REQ_RANGE_ADJACENT:
4742 if (context->tile == nullptr) {
4743 return TRI_MAYBE;
4744 }
4745
4746 unit_list_iterate(context->tile->units, punit) {
4747 if (punit->utype == punittype) {
4748 return TRI_YES;
4749 }
4751
4752 if (req->range == REQ_RANGE_TILE) {
4753 return TRI_NO;
4754 }
4755
4756 if (req->range == REQ_RANGE_CADJACENT) {
4759 if (punit->utype == punittype) {
4760 return TRI_YES;
4761 }
4764 } else {
4766
4769 if (punit->utype == punittype) {
4770 return TRI_YES;
4771 }
4774 }
4775
4776 return TRI_NO;
4777
4778 case REQ_RANGE_CITY:
4781 case REQ_RANGE_PLAYER:
4782 case REQ_RANGE_TEAM:
4783 case REQ_RANGE_ALLIANCE:
4784 case REQ_RANGE_WORLD:
4785 case REQ_RANGE_COUNT:
4787 break;
4788 }
4789
4790 return TRI_NO;
4791}
4792
4793/**********************************************************************/
4801static enum fc_tristate
4803 const struct req_context *context,
4804 const struct req_context *other_context,
4805 const struct requirement *req)
4806{
4807 enum unit_type_flag_id unitflag;
4808
4810
4811 unitflag = req->source.value.unitflag;
4812
4813 switch (req->range) {
4814 case REQ_RANGE_LOCAL:
4815 if (!context->unittype) {
4816 return TRI_MAYBE;
4817 }
4818 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4819 case REQ_RANGE_TILE:
4821 case REQ_RANGE_ADJACENT:
4822 if (context->tile == nullptr) {
4823 return TRI_MAYBE;
4824 }
4825
4826 unit_list_iterate(context->tile->units, punit) {
4827 if (unit_has_type_flag(punit, unitflag)) {
4828 return TRI_YES;
4829 }
4831
4832 if (req->range == REQ_RANGE_TILE) {
4833 return TRI_NO;
4834 }
4835
4836 if (req->range == REQ_RANGE_CADJACENT) {
4839 if (unit_has_type_flag(punit, unitflag)) {
4840 return TRI_YES;
4841 }
4844 } else {
4846
4849 if (unit_has_type_flag(punit, unitflag)) {
4850 return TRI_YES;
4851 }
4854 }
4855
4856 return TRI_NO;
4857
4858 case REQ_RANGE_CITY:
4861 case REQ_RANGE_PLAYER:
4862 case REQ_RANGE_TEAM:
4863 case REQ_RANGE_ALLIANCE:
4864 case REQ_RANGE_WORLD:
4865 case REQ_RANGE_COUNT:
4867 break;
4868 }
4869
4870 return TRI_NO;
4871}
4872
4873/**********************************************************************/
4881static enum fc_tristate
4883 const struct req_context *context,
4884 const struct req_context *other_context,
4885 const struct requirement *req)
4886{
4887 const struct unit_class *pclass;
4888
4890
4891 pclass = req->source.value.uclass;
4892
4893 switch (req->range) {
4894 case REQ_RANGE_LOCAL:
4895 if (!context->unittype) {
4896 return TRI_MAYBE;
4897 }
4898 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4899 case REQ_RANGE_TILE:
4901 case REQ_RANGE_ADJACENT:
4902 if (context->tile == nullptr) {
4903 return TRI_MAYBE;
4904 }
4905
4906 unit_list_iterate(context->tile->units, punit) {
4907 if (unit_class_get(punit) == pclass) {
4908 return TRI_YES;
4909 }
4911
4912 if (req->range == REQ_RANGE_TILE) {
4913 return TRI_NO;
4914 }
4915
4916 if (req->range == REQ_RANGE_CADJACENT) {
4919 if (unit_class_get(punit) == pclass) {
4920 return TRI_YES;
4921 }
4924 } else {
4926
4929 if (unit_class_get(punit) == pclass) {
4930 return TRI_YES;
4931 }
4934 }
4935
4936 return TRI_NO;
4937
4938 case REQ_RANGE_CITY:
4941 case REQ_RANGE_PLAYER:
4942 case REQ_RANGE_TEAM:
4943 case REQ_RANGE_ALLIANCE:
4944 case REQ_RANGE_WORLD:
4945 case REQ_RANGE_COUNT:
4947 break;
4948 }
4949
4950 return TRI_NO;
4951}
4952
4953/**********************************************************************/
4961static enum fc_tristate
4963 const struct req_context *context,
4964 const struct req_context *other_context,
4965 const struct requirement *req)
4966{
4968
4970
4972
4973 switch (req->range) {
4974 case REQ_RANGE_LOCAL:
4975 if (!context->unittype) {
4976 return TRI_MAYBE;
4977 }
4979 case REQ_RANGE_TILE:
4981 case REQ_RANGE_ADJACENT:
4982 if (context->tile == nullptr) {
4983 return TRI_MAYBE;
4984 }
4985
4986 unit_list_iterate(context->tile->units, punit) {
4988 return TRI_YES;
4989 }
4991
4992 if (req->range == REQ_RANGE_TILE) {
4993 return TRI_NO;
4994 }
4995
4996 if (req->range == REQ_RANGE_CADJACENT) {
5000 return TRI_YES;
5001 }
5004 } else {
5006
5010 return TRI_YES;
5011 }
5014 }
5015
5016 return TRI_NO;
5017
5018 case REQ_RANGE_CITY:
5021 case REQ_RANGE_PLAYER:
5022 case REQ_RANGE_TEAM:
5023 case REQ_RANGE_ALLIANCE:
5024 case REQ_RANGE_WORLD:
5025 case REQ_RANGE_COUNT:
5027 break;
5028 }
5029
5030 return TRI_NO;
5031}
5032
5033/**********************************************************************/
5041static enum fc_tristate
5043 const struct req_context *context,
5044 const struct req_context *other_context,
5045 const struct requirement *req)
5046{
5047 enum ustate_prop uprop;
5048
5050
5052
5054 "Unsupported range \"%s\"",
5055 req_range_name(req->range));
5056
5057 /* Could be asked with incomplete data.
5058 * is_req_active() will handle it based on prob_type. */
5059 if (context->unit == nullptr) {
5060 return TRI_MAYBE;
5061 }
5062
5063 switch (uprop) {
5064 case USP_TRANSPORTED:
5065 return BOOL_TO_TRISTATE(context->unit->transporter != nullptr);
5066 case USP_LIVABLE_TILE:
5067 return BOOL_TO_TRISTATE(
5069 unit_tile(context->unit)));
5070 break;
5071 case USP_TRANSPORTING:
5073 case USP_HAS_HOME_CITY:
5074 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
5075 case USP_NATIVE_TILE:
5076 return BOOL_TO_TRISTATE(
5078 unit_tile(context->unit)));
5079 break;
5080 case USP_NATIVE_EXTRA:
5081 return BOOL_TO_TRISTATE(
5083 unit_type_get(context->unit)));
5084 break;
5086 return BOOL_TO_TRISTATE(context->unit->moved);
5087 case USP_COUNT:
5088 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
5089 /* Invalid property is unknowable. */
5090 return TRI_NO;
5091 }
5092
5093 /* Should never be reached */
5094 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
5095
5096 return TRI_NO;
5097}
5098
5099/**********************************************************************/
5107static enum fc_tristate
5109 const struct req_context *context,
5110 const struct req_context *other_context,
5111 const struct requirement *req)
5112{
5113 enum unit_activity activity;
5114
5116
5117 activity = req->source.value.activity;
5118
5120 "Unsupported range \"%s\"",
5121 req_range_name(req->range));
5122
5123 if (context->unit == nullptr) {
5124 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
5125 * it's the zero value that context has by default - so many callers
5126 * who meant not to set specific activity actually have ACTIVITY_IDLE
5127 * instead of ACTIVITY_LAST */
5128 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
5129 return BOOL_TO_TRISTATE(activity == context->activity);
5130 }
5131
5132 /* Could be asked with incomplete data.
5133 * is_req_active() will handle it based on prob_type. */
5134 return TRI_MAYBE;
5135 }
5136
5137 switch (context->unit->activity) {
5138 case ACTIVITY_IDLE:
5139 case ACTIVITY_SENTRY:
5140 case ACTIVITY_GOTO:
5141 case ACTIVITY_EXPLORE:
5142 /* Seen as idle. */
5143 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
5144 default:
5145 /* Handled below. */
5146 break;
5147 }
5148
5149 return BOOL_TO_TRISTATE(context->unit->activity == activity);
5150}
5151
5152/**********************************************************************/
5160static enum fc_tristate
5162 const struct req_context *context,
5163 const struct req_context *other_context,
5164 const struct requirement *req)
5165{
5167
5168 if (context->unit == nullptr) {
5169 return TRI_MAYBE;
5170 } else {
5171 return BOOL_TO_TRISTATE(context->unit->veteran
5172 >= req->source.value.minveteran);
5173 }
5174}
5175
5176/**********************************************************************/
5184static enum fc_tristate
5186 const struct req_context *context,
5187 const struct req_context *other_context,
5188 const struct requirement *req)
5189{
5191
5192 if (context->unit == nullptr) {
5193 return TRI_MAYBE;
5194 } else {
5196 <= context->unit->moves_left);
5197 }
5198}
5199
5200/**********************************************************************/
5208static enum fc_tristate
5210 const struct req_context *context,
5211 const struct req_context *other_context,
5212 const struct requirement *req)
5213{
5215
5216 if (context->unit == nullptr) {
5217 return TRI_MAYBE;
5218 } else {
5220 <= context->unit->hp);
5221 }
5222}
5223
5224/**********************************************************************/
5232static enum fc_tristate
5234 const struct req_context *context,
5235 const struct req_context *other_context,
5236 const struct requirement *req)
5237{
5239
5240 switch (req->range) {
5241 case REQ_RANGE_LOCAL:
5242 if (context->unit == nullptr || !is_server()) {
5243 return TRI_MAYBE;
5244 } else {
5245 return BOOL_TO_TRISTATE(
5246 req->source.value.age <=
5247 game.info.turn - context->unit->birth_turn);
5248 }
5249 break;
5250 case REQ_RANGE_CITY:
5251 if (context->city == nullptr) {
5252 return TRI_MAYBE;
5253 } else {
5254 return BOOL_TO_TRISTATE(
5255 req->source.value.age <=
5256 game.info.turn - context->city->turn_founded);
5257 }
5258 break;
5259 case REQ_RANGE_PLAYER:
5260 if (context->player == nullptr) {
5261 return TRI_MAYBE;
5262 } else {
5263 return BOOL_TO_TRISTATE(req->source.value.age
5264 <= player_age(context->player));
5265 }
5266 break;
5267 default:
5268 return TRI_MAYBE;
5269 break;
5270 }
5271}
5272
5273/**********************************************************************/
5281static enum fc_tristate
5283 const struct req_context *context,
5284 const struct req_context *other_context,
5285 const struct requirement *req)
5286{
5288
5289 switch (req->range) {
5290 case REQ_RANGE_LOCAL:
5291 if (context->unit == nullptr || !is_server()) {
5292 return TRI_MAYBE;
5293 } else {
5294 return BOOL_TO_TRISTATE(
5295 req->source.value.form_age <=
5296 game.info.turn - context->unit->current_form_turn);
5297 }
5298 break;
5299 default:
5300 return TRI_MAYBE;
5301 break;
5302 }
5303}
5304
5305/**********************************************************************/
5309static inline enum fc_tristate
5311{
5313 bool whole_known;
5314
5315 if (cont > 0) {
5318
5319 if (actual_surrounder > 0) {
5320 return TRI_NO;
5321 }
5322 } else if (cont < 0) {
5325
5326 if (actual_surrounder < 0) {
5327 return TRI_NO;
5328 }
5329 } else {
5330 return TRI_MAYBE;
5331 }
5332
5333 if (actual_surrounder == 0 || surrounder == 0) {
5334 return TRI_MAYBE;
5335 } else if (actual_surrounder != surrounder) {
5336 return TRI_NO;
5337 } else if (!whole_known) {
5338 return TRI_MAYBE;
5339 } else {
5340 return TRI_YES;
5341 }
5342}
5343
5344/**********************************************************************/
5352static enum fc_tristate
5354 const struct req_context *context,
5355 const struct req_context *other_context,
5356 const struct requirement *req)
5357{
5359
5360 if (context->tile == nullptr || other_context->tile == nullptr) {
5361 /* Note: For some values, we might be able to give a definitive
5362 * TRI_NO answer even if one of the tiles is missing, but that's
5363 * probably not worth the added effort. */
5364 return TRI_MAYBE;
5365 }
5366
5367 switch (req->source.value.tilerel) {
5368 case TREL_SAME_TCLASS:
5369 if (tile_terrain(other_context->tile) == T_UNKNOWN) {
5370 return TRI_MAYBE;
5371 }
5373 || req->range == REQ_RANGE_CADJACENT
5374 || req->range == REQ_RANGE_ADJACENT),
5375 TRI_MAYBE,
5376 "Invalid range %d for tile relation \"%s\" req",
5378 {
5381 bool seen_unknown = FALSE;
5382 const struct terrain *terr;
5383
5384 if ((terr = tile_terrain(context->tile)) == T_UNKNOWN) {
5386 } else if (terrain_type_terrain_class(terr) == cls) {
5387 return TRUE;
5388 }
5389
5391 if ((terr = tile_terrain(adj_tile)) == T_UNKNOWN) {
5393 } else if (terrain_type_terrain_class(terr) == cls) {
5394 return TRUE;
5395 }
5397
5398 if (seen_unknown) {
5399 return TRI_MAYBE;
5400 } else {
5401 return TRI_NO;
5402 }
5403 }
5404 break;
5405 case TREL_SAME_REGION:
5406 if (tile_continent(other_context->tile) == 0) {
5407 return TRI_MAYBE;
5408 }
5410 || req->range == REQ_RANGE_CADJACENT
5411 || req->range == REQ_RANGE_ADJACENT),
5412 TRI_MAYBE,
5413 "Invalid range %d for tile relation \"%s\" req",
5415
5416 if (tile_continent(context->tile)
5417 == tile_continent(other_context->tile)) {
5418 return TRI_YES;
5419 } else {
5420 bool seen_unknown = (tile_continent(context->tile) == 0);
5422
5425
5426 if (adj_cont == cont) {
5427 return TRI_YES;
5428 } else if (adj_cont == 0) {
5430 }
5432
5433 if (seen_unknown) {
5434 return TRI_MAYBE;
5435 } else {
5436 return TRI_NO;
5437 }
5438 }
5439 break;
5441 if (tile_continent(context->tile) == 0
5442 || tile_continent(other_context->tile) == 0) {
5443 /* Note: We could still give a definitive TRI_NO answer if there are
5444 * too many different adjacent continents, but that's probably not
5445 * worth the added effort. */
5446 return TRI_MAYBE;
5447 }
5449 || req->range == REQ_RANGE_ADJACENT),
5450 TRI_MAYBE,
5451 "Invalid range %d for tile relation \"%s\" req",
5452 req->range,
5454
5455 {
5456 bool seen_unknown = FALSE;
5457 Continent_id cont = tile_continent(context->tile);
5459
5462
5463 if (adj_cont == 0) {
5465 } else if (adj_cont != cont && adj_cont != other_cont) {
5466 return TRI_NO;
5467 }
5469
5470 if (seen_unknown) {
5471 return TRI_MAYBE;
5472 } else {
5473 return TRI_YES;
5474 }
5475 }
5476 break;
5479 || req->range == REQ_RANGE_CADJACENT
5480 || req->range == REQ_RANGE_ADJACENT),
5481 TRI_MAYBE,
5482 "Invalid range %d for tile relation \"%s\" req",
5483 req->range,
5485
5486 {
5487 bool seen_maybe = FALSE;
5489
5491 wanted)) {
5492 case TRI_YES:
5493 return TRI_YES;
5494 case TRI_MAYBE:
5495 seen_maybe = TRUE;
5496 break;
5497 default:
5498 break;
5499 }
5500
5503 wanted)) {
5504 case TRI_YES:
5505 return TRI_YES;
5506 case TRI_MAYBE:
5507 seen_maybe = TRUE;
5508 break;
5509 default:
5510 break;
5511 }
5513
5514 if (seen_maybe) {
5515 return TRI_MAYBE;
5516 } else {
5517 return TRI_NO;
5518 }
5519 }
5520 break;
5521 default:
5522 break;
5523 }
5524
5526 "Illegal value %d for tile relationship requirement.",
5527 req->source.value.tilerel);
5528 return TRI_MAYBE;
5529}
5530
5531/**********************************************************************/
5534static bool is_city_in_tile(const struct tile *ptile,
5535 const struct city *pcity)
5536{
5537 if (pcity == nullptr) {
5538 return tile_city(ptile) != nullptr;
5539 } else {
5540 return is_city_center(pcity, ptile);
5541 }
5542}
5543
5544/**********************************************************************/
5552static enum fc_tristate
5554 const struct req_context *context,
5555 const struct req_context *other_context,
5556 const struct requirement *req)
5557{
5558 enum citytile_type citytile;
5559
5561
5562 citytile = req->source.value.citytile;
5563
5565 if (context->tile == nullptr) {
5566 return TRI_MAYBE;
5567 }
5568
5569 switch (citytile) {
5570 case CITYT_CENTER:
5571 switch (req->range) {
5572 case REQ_RANGE_TILE:
5574 context->city));
5576 if (is_city_in_tile(context->tile, context->city)) {
5577 return TRI_YES;
5578 }
5580 if (is_city_in_tile(adjc_tile, context->city)) {
5581 return TRI_YES;
5582 }
5584
5585 return TRI_NO;
5586 case REQ_RANGE_ADJACENT:
5587 if (is_city_in_tile(context->tile, context->city)) {
5588 return TRI_YES;
5589 }
5591 if (is_city_in_tile(adjc_tile, context->city)) {
5592 return TRI_YES;
5593 }
5595
5596 return TRI_NO;
5597 case REQ_RANGE_CITY:
5600 case REQ_RANGE_PLAYER:
5601 case REQ_RANGE_TEAM:
5602 case REQ_RANGE_ALLIANCE:
5603 case REQ_RANGE_WORLD:
5604 case REQ_RANGE_LOCAL:
5605 case REQ_RANGE_COUNT:
5606 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5607 break;
5608 }
5609
5610 return TRI_MAYBE;
5611 case CITYT_CLAIMED:
5612 switch (req->range) {
5613 case REQ_RANGE_TILE:
5614 return BOOL_TO_TRISTATE(context->tile->owner != nullptr);
5616 if (context->tile->owner != nullptr) {
5617 return TRI_YES;
5618 }
5620 if (adjc_tile->owner != nullptr) {
5621 return TRI_YES;
5622 }
5624
5625 return TRI_NO;
5626 case REQ_RANGE_ADJACENT:
5627 if (context->tile->owner != nullptr) {
5628 return TRI_YES;
5629 }
5631 if (adjc_tile->owner != nullptr) {
5632 return TRI_YES;
5633 }
5635
5636 return TRI_NO;
5637 case REQ_RANGE_CITY:
5640 case REQ_RANGE_PLAYER:
5641 case REQ_RANGE_TEAM:
5642 case REQ_RANGE_ALLIANCE:
5643 case REQ_RANGE_WORLD:
5644 case REQ_RANGE_LOCAL:
5645 case REQ_RANGE_COUNT:
5646 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5647 break;
5648 }
5649
5650 return TRI_MAYBE;
5651 case CITYT_EXTRAS_OWNED:
5652 switch (req->range) {
5653 case REQ_RANGE_TILE:
5654 return BOOL_TO_TRISTATE(context->tile->extras_owner != nullptr);
5656 if (context->tile->extras_owner != nullptr) {
5657 return TRI_YES;
5658 }
5660 if (adjc_tile->extras_owner != nullptr) {
5661 return TRI_YES;
5662 }
5664
5665 return TRI_NO;
5666 case REQ_RANGE_ADJACENT:
5667 if (context->tile->extras_owner != nullptr) {
5668 return TRI_YES;
5669 }
5671 if (adjc_tile->extras_owner != nullptr) {
5672 return TRI_YES;
5673 }
5675
5676 return TRI_NO;
5677 case REQ_RANGE_CITY:
5680 case REQ_RANGE_PLAYER:
5681 case REQ_RANGE_TEAM:
5682 case REQ_RANGE_ALLIANCE:
5683 case REQ_RANGE_WORLD:
5684 case REQ_RANGE_LOCAL:
5685 case REQ_RANGE_COUNT:
5686 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5687 break;
5688 }
5689
5690 return TRI_MAYBE;
5691 case CITYT_WORKED:
5692 switch (req->range) {
5693 case REQ_RANGE_TILE:
5694 return BOOL_TO_TRISTATE(context->tile->worked != nullptr);
5696 if (context->tile->worked != nullptr) {
5697 return TRI_YES;
5698 }
5700 if (adjc_tile->worked != nullptr) {
5701 return TRI_YES;
5702 }
5704
5705 return TRI_NO;
5706 case REQ_RANGE_ADJACENT:
5707 if (context->tile->worked != nullptr) {
5708 return TRI_YES;
5709 }
5711 if (adjc_tile->worked != nullptr) {
5712 return TRI_YES;
5713 }
5715
5716 return TRI_NO;
5717 case REQ_RANGE_CITY:
5720 case REQ_RANGE_PLAYER:
5721 case REQ_RANGE_TEAM:
5722 case REQ_RANGE_ALLIANCE:
5723 case REQ_RANGE_WORLD:
5724 case REQ_RANGE_LOCAL:
5725 case REQ_RANGE_COUNT:
5726 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5727 break;
5728 }
5729
5730 return TRI_MAYBE;
5732 {
5734 const struct tile *target_tile = context->tile, *cc_tile;
5735
5736 if (!context->city) {
5737 return TRI_MAYBE;
5738 }
5739 cc_tile = city_tile(context->city);
5740 if (!cc_tile) {
5741 /* Unplaced virtual city */
5742 return TRI_MAYBE;
5743 }
5745 /* Note: No special treatment of 0 == cc here*/
5746 switch (req->range) {
5747 case REQ_RANGE_TILE:
5750 if (tile_continent(target_tile) == cc) {
5751 return TRI_YES;
5752 }
5754 if (tile_continent(adjc_tile) == cc) {
5755 return TRI_YES;
5756 }
5758
5759 return TRI_NO;
5760 case REQ_RANGE_ADJACENT:
5761 if (tile_continent(target_tile) == cc) {
5762 return TRI_YES;
5763 }
5765 if (tile_continent(adjc_tile) == cc) {
5766 return TRI_YES;
5767 }
5769
5770 return TRI_NO;
5771 case REQ_RANGE_CITY:
5774 case REQ_RANGE_PLAYER:
5775 case REQ_RANGE_TEAM:
5776 case REQ_RANGE_ALLIANCE:
5777 case REQ_RANGE_WORLD:
5778 case REQ_RANGE_LOCAL:
5779 case REQ_RANGE_COUNT:
5780 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5781 break;
5782 }
5783 }
5784
5785 return TRI_MAYBE;
5787 {
5788 int n = 0;
5790 bool ukt = FALSE;
5791 const struct tile *target_tile = context->tile, *cc_tile;
5792
5793 if (!context->city) {
5794 return TRI_MAYBE;
5795 }
5796 cc_tile = city_tile(context->city);
5797 if (!cc_tile) {
5798 /* Unplaced virtual city */
5799 return TRI_MAYBE;
5800 }
5802 if (!cc) {
5803 /* Don't know the city center terrain class.
5804 * Maybe, the city floats? Even if the rules prohibit it... */
5805 return TRI_MAYBE;
5806 }
5809
5810 if (0 != tc) {
5811 bool seen = FALSE;
5812 int i = n;
5813
5814 if (tc == cc) {
5815 continue;
5816 }
5817 while (--i >= 0) {
5818 if (adjc_cont[i] == tc) {
5819 seen = TRUE;
5820 break;
5821 }
5822 }
5823 if (seen) {
5824 continue;
5825 }
5827 } else {
5828 /* Likely, it's a black tile in client and we don't know
5829 * We possibly can calculate, but keep it simple. */
5830 ukt = TRUE;
5831 }
5833 if (0 == n) {
5834 return ukt ? TRI_MAYBE : TRI_NO;
5835 }
5836
5837 switch (req->range) {
5838 case REQ_RANGE_TILE:
5839 {
5841
5842 if (cc == tc) {
5843 return TRI_NO;
5844 }
5845 if (0 == tc || ukt) {
5846 return TRI_MAYBE;
5847 }
5848 for (int i = 0; i < n; i++) {
5849 if (tc == adjc_cont[i]) {
5850 return TRI_YES;
5851 }
5852 }
5853 }
5854
5855 return TRI_NO;
5856 case REQ_RANGE_ADJACENT:
5857 if (ukt) {
5858 /* If ALL the tiles in range are on cc, we can say it's false */
5860 if (tile_continent(adjc_tile) != cc) {
5861 return TRI_MAYBE;
5862 }
5864
5865 return TRI_NO;
5866 } else {
5869
5870 if (0 == tc) {
5871 return TRI_MAYBE;
5872 }
5873 for (int i = 0; i < n; i++) {
5874 if (tc == adjc_cont[i]) {
5875 return TRI_YES;
5876 }
5877 }
5879 }
5880
5881 return TRI_NO;
5883 if (ukt) {
5884 /* If ALL the tiles in range are on cc, we can say it's false */
5886 if (tile_continent(cadjc_tile) != cc) {
5887 return TRI_MAYBE;
5888 }
5890 } else {
5893
5894 if (0 == tc) {
5895 return TRI_MAYBE;
5896 }
5897 for (int i = 0; i < n; i++) {
5898 if (tc == adjc_cont[i]) {
5899 return TRI_YES;
5900 }
5901 }
5903 }
5904
5905 return TRI_NO;
5906 case REQ_RANGE_CITY:
5909 case REQ_RANGE_PLAYER:
5910 case REQ_RANGE_TEAM:
5911 case REQ_RANGE_ALLIANCE:
5912 case REQ_RANGE_WORLD:
5913 case REQ_RANGE_LOCAL:
5914 case REQ_RANGE_COUNT:
5915 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5916 break;
5917 }
5918 }
5919
5920 return TRI_MAYBE;
5921 case CITYT_LAST:
5922 /* Handled below */
5923 break;
5924 }
5925
5926 /* Not implemented */
5927 log_error("is_req_active(): citytile %d not supported.",
5928 citytile);
5929 return TRI_MAYBE;
5930}
5931
5932/**********************************************************************/
5940static enum fc_tristate
5942 const struct req_context *context,
5943 const struct req_context *other_context,
5944 const struct requirement *req)
5945{
5946 enum citystatus_type citystatus;
5947
5949
5950 citystatus = req->source.value.citystatus;
5951
5952 if (context->city == nullptr) {
5953 return TRI_MAYBE;
5954 }
5955
5956 switch (citystatus) {
5958 switch (req->range) {
5959 case REQ_RANGE_CITY:
5960 if (context->city->original == nullptr) {
5961 return TRI_MAYBE;
5962 }
5963 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
5965 {
5966 enum fc_tristate ret;
5967
5968 if (city_owner(context->city) == context->city->original) {
5969 return TRI_YES;
5970 }
5971
5972 ret = TRI_NO;
5974 if (trade_partner == nullptr || trade_partner->original == nullptr) {
5975 ret = TRI_MAYBE;
5976 } else if (city_owner(trade_partner) == trade_partner->original) {
5977 return TRI_YES;
5978 }
5980
5981 return ret;
5982 }
5983 case REQ_RANGE_LOCAL:
5984 case REQ_RANGE_TILE:
5986 case REQ_RANGE_ADJACENT:
5988 case REQ_RANGE_PLAYER:
5989 case REQ_RANGE_TEAM:
5990 case REQ_RANGE_ALLIANCE:
5991 case REQ_RANGE_WORLD:
5992 case REQ_RANGE_COUNT:
5993 break;
5994 }
5995
5996 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
5997 req->range);
5998
5999 return TRI_MAYBE;
6000
6001 case CITYS_STARVED:
6002 switch (req->range) {
6003 case REQ_RANGE_CITY:
6004 return BOOL_TO_TRISTATE(context->city->had_famine);
6006 {
6007 enum fc_tristate ret;
6008
6009 if (context->city->had_famine) {
6010 return TRI_YES;
6011 }
6012
6013 ret = TRI_NO;
6015 if (trade_partner == nullptr) {
6016 ret = TRI_MAYBE;
6017 } else if (trade_partner->had_famine) {
6018 return TRI_YES;
6019 }
6021
6022 return ret;
6023 }
6024 case REQ_RANGE_LOCAL:
6025 case REQ_RANGE_TILE:
6027 case REQ_RANGE_ADJACENT:
6029 case REQ_RANGE_PLAYER:
6030 case REQ_RANGE_TEAM:
6031 case REQ_RANGE_ALLIANCE:
6032 case REQ_RANGE_WORLD:
6033 case REQ_RANGE_COUNT:
6034 break;
6035 }
6036
6037 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
6038 req->range);
6039
6040 return TRI_MAYBE;
6041
6042 case CITYS_DISORDER:
6043 switch (req->range) {
6044 case REQ_RANGE_CITY:
6045 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
6047 {
6048 enum fc_tristate ret;
6049
6050 if (context->city->anarchy > 0) {
6051 return TRI_YES;
6052 }
6053
6054 ret = TRI_NO;
6056 if (trade_partner == nullptr) {
6057 ret = TRI_MAYBE;
6058 } else if (trade_partner->anarchy > 0) {
6059 return TRI_YES;
6060 }
6062
6063 return ret;
6064 }
6065 case REQ_RANGE_LOCAL:
6066 case REQ_RANGE_TILE:
6068 case REQ_RANGE_ADJACENT:
6070 case REQ_RANGE_PLAYER:
6071 case REQ_RANGE_TEAM:
6072 case REQ_RANGE_ALLIANCE:
6073 case REQ_RANGE_WORLD:
6074 case REQ_RANGE_COUNT:
6075 break;
6076 }
6077
6078 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
6079 req->range);
6080
6081 return TRI_MAYBE;
6082
6083 case CITYS_CELEBRATION:
6084 switch (req->range) {
6085 case REQ_RANGE_CITY:
6086 return BOOL_TO_TRISTATE(context->city->rapture > 0);
6088 {
6089 enum fc_tristate ret;
6090
6091 if (context->city->rapture > 0) {
6092 return TRI_YES;
6093 }
6094
6095 ret = TRI_NO;
6097 if (trade_partner == nullptr) {
6098 ret = TRI_MAYBE;
6099 } else if (trade_partner->rapture > 0) {
6100 return TRI_YES;
6101 }
6103
6104 return ret;
6105 }
6106 case REQ_RANGE_LOCAL:
6107 case REQ_RANGE_TILE:
6109 case REQ_RANGE_ADJACENT:
6111 case REQ_RANGE_PLAYER:
6112 case REQ_RANGE_TEAM:
6113 case REQ_RANGE_ALLIANCE:
6114 case REQ_RANGE_WORLD:
6115 case REQ_RANGE_COUNT:
6116 break;
6117 }
6118
6119 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
6120 req->range);
6121
6122 return TRI_MAYBE;
6123
6124 case CITYS_TRANSFERRED:
6125 switch (req->range) {
6126 case REQ_RANGE_CITY:
6127 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
6129 {
6130 enum fc_tristate ret;
6131
6132 if (context->city->acquire_t != CACQ_FOUNDED) {
6133 return TRI_YES;
6134 }
6135
6136 ret = TRI_NO;
6138 if (trade_partner == nullptr) {
6139 ret = TRI_MAYBE;
6140 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
6141 return TRI_YES;
6142 }
6144
6145 return ret;
6146 }
6147 case REQ_RANGE_LOCAL:
6148 case REQ_RANGE_TILE:
6150 case REQ_RANGE_ADJACENT:
6152 case REQ_RANGE_PLAYER:
6153 case REQ_RANGE_TEAM:
6154 case REQ_RANGE_ALLIANCE:
6155 case REQ_RANGE_WORLD:
6156 case REQ_RANGE_COUNT:
6157 break;
6158 }
6159
6160 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
6161 req->range);
6162
6163 return TRI_MAYBE;
6164
6166 switch (req->range) {
6167 case REQ_RANGE_CITY:
6168 if (context->city->aarea == nullptr) {
6169 return TRI_MAYBE;
6170 }
6171 return BOOL_TO_TRISTATE(context->city->aarea->capital);
6173 {
6174 enum fc_tristate ret;
6175
6176 if (context->city->aarea != nullptr
6177 && context->city->aarea->capital) {
6178 return TRI_YES;
6179 }
6180
6181 if (context->city->aarea == nullptr) {
6182 ret = TRI_MAYBE;
6183 } else {
6184 ret = TRI_NO;
6185 }
6187 if (trade_partner == nullptr
6188 || trade_partner->aarea == nullptr) {
6189 ret = TRI_MAYBE;
6190 } else if (trade_partner->aarea->capital) {
6191 return TRI_YES;
6192 }
6194
6195 return ret;
6196 }
6197 case REQ_RANGE_LOCAL:
6198 case REQ_RANGE_TILE:
6200 case REQ_RANGE_ADJACENT:
6202 case REQ_RANGE_PLAYER:
6203 case REQ_RANGE_TEAM:
6204 case REQ_RANGE_ALLIANCE:
6205 case REQ_RANGE_WORLD:
6206 case REQ_RANGE_COUNT:
6207 break;
6208 }
6209
6210 fc_assert_msg(FALSE, "Invalid range %d for citystatus CapitalConnected.",
6211 req->range);
6212
6213 return TRI_MAYBE;
6214
6215 case CITYS_LAST:
6216 break;
6217 }
6218
6219 /* Not implemented */
6220 log_error("is_req_active(): citystatus %d not supported.",
6221 citystatus);
6222
6223 return TRI_MAYBE;
6224}
6225
6226/**********************************************************************/
6234static enum fc_tristate
6236 const struct req_context *context,
6237 const struct req_context *other_context,
6238 const struct requirement *req)
6239{
6241
6242 if (context->city == nullptr) {
6243 return TRI_MAYBE;
6244 } else {
6245 if (req->range == REQ_RANGE_TRADE_ROUTE) {
6246 enum fc_tristate ret;
6247
6248 if (city_size_get(context->city) >= req->source.value.minsize) {
6249 return TRI_YES;
6250 }
6251
6252 ret = TRI_NO;
6254 if (trade_partner == nullptr) {
6255 ret = TRI_MAYBE;
6256 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
6257 return TRI_YES;
6258 }
6260
6261 return ret;
6262 } else {
6264 >= req->source.value.minsize);
6265 }
6266 }
6267}
6268
6269/**********************************************************************/
6277static enum fc_tristate
6279 const struct req_context *context,
6280 const struct req_context *other_context,
6281 const struct requirement *req)
6282{
6283 const struct counter *count;
6284
6286
6287 count = req->source.value.counter;
6288
6289 if (context->city == nullptr) {
6290 return TRI_MAYBE;
6291 }
6292 return BOOL_TO_TRISTATE(count->checkpoint <=
6293 context->city->counter_values[
6294 counter_index(count)]);
6295}
6296
6297/**********************************************************************/
6305static enum fc_tristate
6307 const struct req_context *context,
6308 const struct req_context *other_context,
6309 const struct requirement *req)
6310{
6311 const struct achievement *achievement;
6312
6314
6316
6317 if (req->range == REQ_RANGE_WORLD) {
6319 } else if (context->player == nullptr) {
6320 return TRI_MAYBE;
6321 } else if (req->range == REQ_RANGE_ALLIANCE
6322 || req->range == REQ_RANGE_TEAM) {
6323 players_iterate_alive(plr2) {
6324 if (players_in_same_range(context->player, plr2, req->range)
6326 return TRI_YES;
6327 }
6329 return TRI_NO;
6330 } else if (req->range == REQ_RANGE_PLAYER) {
6332 return TRI_YES;
6333 } else {
6334 return TRI_NO;
6335 }
6336 }
6337
6338 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
6339
6340 return TRI_MAYBE;
6341}
6342
6343/**********************************************************************/
6351static enum fc_tristate
6353 const struct req_context *context,
6354 const struct req_context *other_context,
6355 const struct requirement *req)
6356{
6357 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
6358
6359 fc_assert_ret_val(req != nullptr, TRI_MAYBE);
6360 fc_assert(context != nullptr);
6361
6362 switch (req->source.kind) {
6363 case VUT_MINLATITUDE:
6364 min = req->source.value.latitude;
6365 break;
6366 case VUT_MAXLATITUDE:
6367 max = req->source.value.latitude;
6368 break;
6369 default:
6371 || req->source.kind == VUT_MAXLATITUDE);
6372 break;
6373 }
6374
6375 switch (req->range) {
6376 case REQ_RANGE_WORLD:
6378 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
6379
6380 case REQ_RANGE_TILE:
6381 if (context->tile == nullptr) {
6382 return TRI_MAYBE;
6383 } else {
6385
6387 }
6388
6390 if (context->tile == nullptr) {
6391 return TRI_MAYBE;
6392 }
6393
6396
6398 return TRI_YES;
6399 }
6401 return TRI_NO;
6402
6403 case REQ_RANGE_ADJACENT:
6404 if (!context->tile) {
6405 return TRI_MAYBE;
6406 }
6407
6410
6412 return TRI_YES;
6413 }
6415 return TRI_NO;
6416
6417 case REQ_RANGE_CITY:
6420 case REQ_RANGE_PLAYER:
6421 case REQ_RANGE_TEAM:
6422 case REQ_RANGE_ALLIANCE:
6423 case REQ_RANGE_LOCAL:
6424 case REQ_RANGE_COUNT:
6425 break;
6426 }
6427
6429 "Illegal range %d for latitude requirement.", req->range);
6430
6431 return TRI_MAYBE;
6432}
6433
6434/**********************************************************************/
6442static enum fc_tristate
6444 const struct req_context *context,
6445 const struct req_context *other_context,
6446 const struct requirement *req)
6447{
6449
6450 switch (req->range) {
6451 case REQ_RANGE_TILE:
6452 if (context->tile == nullptr || other_context->tile == nullptr) {
6453 return TRI_MAYBE;
6454 }
6455 return BOOL_TO_TRISTATE(
6457 <= req->source.value.distance_sq
6458 );
6459 default:
6460 break;
6461 }
6462
6464 "Illegal range %d for max squared distance requirement.",
6465 req->range);
6466
6467 return TRI_MAYBE;
6468}
6469
6470/**********************************************************************/
6478static enum fc_tristate
6480 const struct req_context *context,
6481 const struct req_context *other_context,
6482 const struct requirement *req)
6483{
6484 int max_tiles, min_tiles = 1;
6485
6487
6488 switch (req->range) {
6490 case REQ_RANGE_ADJACENT:
6491 if (context->tile == nullptr) {
6492 /* The tile itself is included in the range */
6493 max_tiles = 1 + ((req->range == REQ_RANGE_CADJACENT)
6494 ? nmap->num_cardinal_dirs
6495 : nmap->num_valid_dirs);
6496
6497 break;
6498 } else {
6499 Continent_id cont = tile_continent(context->tile);
6500
6501 /* Count how many adjacent tiles there actually are as we go along */
6502 max_tiles = 1;
6503
6506
6507 if (adj_cont == 0 || cont == 0) {
6508 max_tiles++;
6509 } else if (adj_cont == cont) {
6510 min_tiles++;
6511 max_tiles++;
6512 }
6514 }
6515 break;
6517 {
6518 Continent_id cont = context->tile ? tile_continent(context->tile) : 0;
6519
6522
6523 /* Note: We could come up with a better upper bound by subtracting
6524 * all other continent/ocean sizes, or all except the largest if we
6525 * don't know the tile.
6526 * We could even do a flood-fill count of the unknown area bordered
6527 * by known tiles of the continent.
6528 * Probably not worth the effort though. */
6529 max_tiles = nmap->xsize * nmap->ysize;
6530
6531 if (cont > 0) {
6532 min_tiles = nmap->continent_sizes[cont];
6533 if (is_whole_continent_known(cont)) {
6535 }
6536 } else if (cont < 0) {
6537 min_tiles = nmap->ocean_sizes[-cont];
6538 if (is_whole_ocean_known(-cont)) {
6540 }
6541 }
6542 }
6543 break;
6544 default:
6546 "Illegal range %d for max region tiles requirement.",
6547 req->range);
6548 return TRI_MAYBE;
6549 }
6550
6551 if (min_tiles > req->source.value.region_tiles) {
6552 return TRI_NO;
6553 } else if (max_tiles <= req->source.value.region_tiles) {
6554 return TRI_YES;
6555 }
6556 return TRI_MAYBE;
6557}
6558
6559/**********************************************************************/
6567static enum fc_tristate
6569 const struct req_context *context,
6570 const struct req_context *other_context,
6571 const struct requirement *req)
6572{
6574
6576}
6577
6578/**********************************************************************/
6586static enum fc_tristate
6588 const struct req_context *context,
6589 const struct req_context *other_context,
6590 const struct requirement *req)
6591{
6593
6595 >= req->source.value.mincalfrag);
6596}
6597
6598/**********************************************************************/
6606static enum fc_tristate
6608 const struct req_context *context,
6609 const struct req_context *other_context,
6610 const struct requirement *req)
6611{
6613
6614 return BOOL_TO_TRISTATE(
6616}
6617
6618/**********************************************************************/
6626static enum fc_tristate
6628 const struct req_context *context,
6629 const struct req_context *other_context,
6630 const struct requirement *req)
6631{
6633
6634 return BOOL_TO_TRISTATE(
6636}
6637
6638/**********************************************************************/
6646static enum fc_tristate
6648 const struct req_context *context,
6649 const struct req_context *other_context,
6650 const struct requirement *req)
6651{
6653
6655 req->source.value.ssetval));
6656}
6657
6658/* Not const for potential ruleset-related adjustment */
6661
6662 /* Alphabetical order of enum constant */
6730};
6731
6732/**********************************************************************/
6746 const struct req_context *other_context,
6747 const struct requirement *req,
6748 const enum req_problem_type prob_type)
6749{
6750 const struct civ_map *nmap = &(wld.map);
6751 enum fc_tristate eval;
6753 struct thr_req_data *trdata = nullptr;
6754
6757 if (fc_threads_equal(self, data->thr_id)) {
6758 trdata = data;
6759 }
6761
6762 if (trdata == nullptr) {
6763 trdata = fc_malloc(sizeof(struct thr_req_data));
6764 trdata->thr_id = self;
6766 }
6768
6770
6771 if (eval == TRI_MAYBE) {
6772 if (prob_type == RPT_POSSIBLE) {
6773 return TRUE;
6774 } else {
6775 return FALSE;
6776 }
6777 }
6778
6779 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
6780}
6781
6782/**********************************************************************/
6791static
6793 const struct req_context *context,
6794 const struct req_context *other_context,
6795 const struct requirement *req)
6796{
6797 if (!context) {
6799 }
6800 if (!other_context) {
6802 }
6803
6804 if (req->source.kind >= VUT_COUNT) {
6805 log_error("tri_req_present(): invalid source kind %d.",
6806 req->source.kind);
6807 return TRI_NO;
6808 }
6809
6811
6812 return req_definitions[req->source.kind].cb(nmap, context,
6813 other_context, req);
6814}
6815
6816/**********************************************************************/
6826 const struct req_context *other_context,
6827 const struct requirement *req)
6828{
6829 const struct civ_map *nmap = &(wld.map);
6831
6832 if (!req->present) {
6833 if (TRI_NO == eval) {
6834 return TRI_YES;
6835 }
6836 if (TRI_YES == eval) {
6837 return TRI_NO;
6838 }
6839 }
6840
6841 return eval;
6842}
6843
6844/**********************************************************************/
6860 const struct req_context *other_context,
6861 const struct requirement_vector *reqs,
6862 const enum req_problem_type prob_type)
6863{
6866 return FALSE;
6867 }
6869
6870 return TRUE;
6871}
6872
6873/**********************************************************************/
6878 const enum req_range max_range,
6879 const struct req_context *context,
6880 const struct req_context *other_context,
6881 const struct requirement_vector *reqs,
6882 const enum req_problem_type prob_type)
6883{
6885 if (preq->range >= min_range && preq->range <= max_range) {
6887 return FALSE;
6888 }
6889 }
6891
6892 return TRUE;
6893}
6894
6895/**********************************************************************/
6901enum fc_tristate
6903 const struct req_context *context,
6904 const struct req_context *other_context,
6905 const struct requirement *req)
6906{
6907 /* FIXME: Doubles code from calendar.c */
6911 int fragment1 = fragment; /* If fragments don't advance */
6912 int year_inc, year_inc1;
6915 bool present, present1;
6916
6917 fc_assert(pass >= 0 && period >= 0);
6918 if (slowdown >= 3) {
6919 if (ypt > 1) {
6920 ypt = 1;
6921 }
6922 } else if (slowdown >= 2) {
6923 if (ypt > 2) {
6924 ypt = 2;
6925 }
6926 } else if (slowdown >= 1) {
6927 if (ypt > 5) {
6928 ypt = 5;
6929 }
6930 }
6931 year_inc = ypt * pass;
6934 int fragment_years;
6935
6936 fragment += fpt * pass;
6944 }
6946 if (year_inc + game.info.year >= 0) {
6947 year_inc++;
6948 year_inc1++;
6949 } else if (year_inc1 + game.info.year >= 0) {
6950 year_inc1++;
6951 }
6952 }
6953
6954 switch (req->source.kind) {
6955 case VUT_AGE:
6956 switch (req->range) {
6957 case REQ_RANGE_LOCAL:
6958 if (context->unit == nullptr || !is_server()) {
6959 return TRI_MAYBE;
6960 } else {
6961 int ua = game.info.turn + pass - context->unit->birth_turn;
6962
6963 present = req->source.value.age <= ua;
6964 present1 = req->source.value.age <= ua + period;
6965 }
6966 break;
6967 case REQ_RANGE_CITY:
6968 if (context->city == nullptr) {
6969 return TRI_MAYBE;
6970 } else {
6971 int ca = game.info.turn + pass - context->city->turn_founded;
6972
6973 present = req->source.value.age <= ca;
6974 present1 = req->source.value.age <= ca + period;
6975 }
6976 break;
6977 case REQ_RANGE_PLAYER:
6978 if (context->player == nullptr) {
6979 return TRI_MAYBE;
6980 } else {
6981 present = req->source.value.age
6982 <= player_age(context->player) + pass;
6983 present1 = req->source.value.age
6984 <= player_age(context->player) + pass + period;
6985 }
6986 break;
6987 default:
6988 return TRI_MAYBE;
6989 }
6990 break;
6991 case VUT_FORM_AGE:
6992 if (context->unit == nullptr || !is_server()) {
6993 return TRI_MAYBE;
6994 } else {
6995 int ua = game.info.turn + pass - context->unit->current_form_turn;
6996
6997 present = req->source.value.form_age <= ua;
6998 present1 = req->source.value.form_age <= ua + period;
6999 }
7000 break;
7001 case VUT_MINYEAR:
7002 present = game.info.year + year_inc >= req->source.value.minyear;
7004 break;
7005 case VUT_MINCALFRAG:
7007 /* Hope that the requirement is valid and fragments advance fine */
7008 return TRI_YES;
7009 }
7010 present = fragment >= req->source.value.mincalfrag;
7012 break;
7013 default:
7014 /* No special handling invented */
7015 return tri_req_active(context, other_context, req);
7016 }
7017 return BOOL_TO_TRISTATE(req->present
7018 ? present || present1 : !(present && present1));
7019}
7020
7021/**********************************************************************/
7027 (const struct req_context *context,
7028 const struct req_context *other_context,
7029 const struct requirement *req,
7030 void *data, int n_data)
7031{
7032 int i;
7033
7034 fc_assert_ret_val(data || n_data == 0, TRI_NO);
7035
7036 for (i = 0; i < n_data; i++) {
7037 if (are_requirements_contradictions(&((struct requirement *) data)[i],
7038 req)) {
7039 return TRI_NO;
7040 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
7041 return TRI_YES;
7042 }
7043 }
7044
7045 return tri_req_active(context, other_context, req);
7046}
7047
7048/**********************************************************************/
7054enum fc_tristate
7056 const struct req_context *other_context,
7057 const struct requirement_vector *reqs,
7060 void *data, int n_data)
7061{
7062 bool active = TRUE;
7063 bool certain = TRUE;
7064
7065 fc_assert_ret_val(tester != nullptr, TRI_NO);
7066
7069 data, n_data)) {
7070 case TRI_NO:
7071 active = FALSE;
7072 certain = TRUE;
7073 break;
7074 case TRI_YES:
7075 break;
7076 case TRI_MAYBE:
7077 certain = FALSE;
7078 if (maybe_reqs) {
7080 }
7081 break;
7082 default:
7084 active = FALSE;
7085 }
7086 if (!active) {
7087 break;
7088 }
7090
7091 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
7092}
7093
7094/**********************************************************************/
7104 const struct requirement *req)
7105{
7106 enum req_unchanging_status s;
7107 const struct civ_map *nmap = &(wld.map);
7108
7111 "Invalid source kind %d.", req->source.kind);
7113
7114 if (req->survives) {
7115 /* Special case for surviving requirements */
7116 /* Buildings may obsolete even here */
7117 if (VUT_IMPROVEMENT == req->source.kind) {
7118 const struct impr_type *b = req->source.value.building;
7119
7121 if (improvement_obsolete(context->player, b, context->city)) {
7122 /* FIXME: Sometimes can unobsolete, but considering it
7123 * may sometimes put the function on endless recursion */
7124 return REQUCH_ACT; /* Mostly about techs */
7125 } else {
7126 /* NOTE: May obsoletion reqs be unchanging? Hardly but why not. */
7127 return REQUCH_NO;
7128 }
7129 }
7130 }
7131 s = unchanging_present(nmap, s, context, req);
7132 if (s != REQUCH_NO) {
7133 return unchanging_noally(nmap, s, context, req);
7134 }
7135 } else {
7138
7139 if (cond) {
7140 return cond(nmap, s, context, req);
7141 }
7142 }
7143
7144 return s;
7145}
7146
7147/**********************************************************************/
7152 const struct req_context *other_context,
7153 const struct requirement *req,
7155{
7157
7158 if (REQUCH_NO != u) {
7159 /* Presence is precalculated */
7160 bool auto_present = (req->survives
7161 && !(VUT_IMPROVEMENT == req->source.kind
7165
7166 if (auto_present ? req->present
7168 /* Unchanging but does not block */
7169 return REQUCH_NO;
7170 }
7171 }
7172
7173 return u;
7174}
7175
7176/**********************************************************************/
7180bool is_req_in_vec(const struct requirement *req,
7181 const struct requirement_vector *vec)
7182{
7184 if (are_requirements_equal(req, preq)) {
7185 return TRUE;
7186 }
7188
7189 return FALSE;
7190}
7191
7192/**********************************************************************/
7200 enum universals_n kind)
7201{
7203 if (preq->present && preq->source.kind == kind) {
7204 return TRUE;
7205 }
7207 return FALSE;
7208}
7209
7210/**********************************************************************/
7219{
7220 switch (source->kind) {
7221 case VUT_ACTION:
7222 return !action_is_in_use(source->value.action);
7223 case VUT_UTFLAG:
7224 return !utype_flag_is_in_use(source->value.unitflag);
7225 case VUT_UCFLAG:
7226 return !uclass_flag_is_in_use(source->value.unitclassflag);
7227 case VUT_EXTRAFLAG:
7228 return !extra_flag_is_in_use(source->value.extraflag);
7229 case VUT_MINLATITUDE:
7230 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
7231 case VUT_MAXLATITUDE:
7232 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
7233 case VUT_COUNTER:
7234 case VUT_OTYPE:
7235 case VUT_SPECIALIST:
7236 case VUT_AI_LEVEL:
7237 case VUT_CITYTILE:
7238 case VUT_CITYSTATUS:
7239 case VUT_STYLE:
7240 case VUT_TOPO:
7241 case VUT_WRAP:
7242 case VUT_SERVERSETTING:
7243 case VUT_NATION:
7244 case VUT_NATIONGROUP:
7245 case VUT_ADVANCE:
7246 case VUT_TECHFLAG:
7247 case VUT_GOVERNMENT:
7248 case VUT_GOVFLAG:
7249 case VUT_ACHIEVEMENT:
7250 case VUT_IMPROVEMENT:
7251 case VUT_SITE:
7252 case VUT_IMPR_GENUS:
7253 case VUT_IMPR_FLAG:
7254 case VUT_PLAYER_FLAG:
7255 case VUT_PLAYER_STATE:
7256 case VUT_MINSIZE:
7257 case VUT_MINCULTURE:
7258 case VUT_MINFOREIGNPCT:
7259 case VUT_MINTECHS:
7260 case VUT_FUTURETECHS:
7261 case VUT_MINCITIES:
7262 case VUT_NATIONALITY:
7263 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
7264 case VUT_DIPLREL:
7265 case VUT_DIPLREL_TILE:
7266 case VUT_DIPLREL_TILE_O:
7271 case VUT_UTYPE:
7272 case VUT_UCLASS:
7273 case VUT_MINVETERAN:
7274 case VUT_UNITSTATE:
7275 case VUT_ACTIVITY:
7276 case VUT_MINMOVES:
7277 case VUT_MINHP:
7278 case VUT_AGE:
7279 case VUT_FORM_AGE:
7280 case VUT_ROADFLAG:
7281 case VUT_MINCALFRAG:
7282 case VUT_TERRAIN:
7283 case VUT_EXTRA:
7284 case VUT_TILEDEF:
7286 case VUT_GOOD:
7287 case VUT_TERRAINCLASS:
7288 case VUT_TERRFLAG:
7289 case VUT_TERRAINALTER:
7290 case VUT_MINYEAR:
7293 case VUT_TILE_REL:
7294 case VUT_NONE:
7295 case VUT_COUNT:
7296 /* Not implemented. */
7297 break;
7298 }
7299
7300 return FALSE;
7301}
7302
7303/**********************************************************************/
7312{
7313 /* Not known to be impossible to fulfill */
7314 return req->present && universal_never_there(&req->source);
7315}
7316
7317/**********************************************************************/
7326{
7329 return TRUE;
7330 }
7332
7333 /* Not known to be impossible to fulfill */
7334 return FALSE;
7335}
7336
7337/**********************************************************************/
7347 const struct requirement_vector *vec)
7348{
7349 if (vec) {
7350 return 0;
7351 } else {
7352 return -1;
7353 }
7354}
7355
7356/********************************************************************/
7365struct requirement_vector *
7367{
7368 fc_assert_ret_val(number == 0, nullptr);
7369
7370 return (struct requirement_vector *)parent_item;
7371}
7372
7373/**********************************************************************/
7384const char *req_vec_change_translation(const struct req_vec_change *change,
7386{
7387 const char *req_vec_description;
7388 static char buf[MAX_LEN_NAME * 3];
7389 struct astring astr;
7390
7391 fc_assert_ret_val(change, nullptr);
7393 nullptr);
7394
7395 /* Get rid of the previous. */
7396 buf[0] = '\0';
7397
7398 if (namer == nullptr) {
7399 /* TRANS: default description of a requirement vector
7400 * (used in ruledit) */
7401 req_vec_description = _("the requirement vector");
7402 } else {
7404 }
7405
7406 switch (change->operation) {
7407 case RVCO_REMOVE:
7408 fc_snprintf(buf, sizeof(buf),
7409 /* TRANS: remove a requirement from a requirement vector
7410 * (in ruledit).
7411 * The first %s is the operation.
7412 * The second %s is the requirement.
7413 * The third %s is a description of the requirement vector,
7414 * like "actor_reqs" */
7415 _("%s %s from %s"),
7417 req_to_fstring(&change->req, &astr),
7419 astr_free(&astr);
7420 break;
7421 case RVCO_APPEND:
7422 fc_snprintf(buf, sizeof(buf),
7423 /* TRANS: append a requirement to a requirement vector
7424 * (in ruledit).
7425 * The first %s is the operation.
7426 * The second %s is the requirement.
7427 * The third %s is a description of the requirement vector,
7428 * like "actor_reqs" */
7429 _("%s %s to %s"),
7431 req_to_fstring(&change->req, &astr),
7433 astr_free(&astr);
7434 break;
7435 case RVCO_NOOP:
7436 fc_snprintf(buf, sizeof(buf),
7437 /* TRANS: do nothing to a requirement vector (in ruledit).
7438 * The first %s is a description of the requirement vector,
7439 * like "actor_reqs" */
7440 _("Do nothing to %s"), req_vec_description);
7441 break;
7442 }
7443
7444 return buf;
7445}
7446
7447/**********************************************************************/
7460 const void *parent_item)
7461{
7462 struct requirement_vector *target
7463 = getter(parent_item, modification->vector_number);
7464 int i = 0;
7465
7466 switch (modification->operation) {
7467 case RVCO_APPEND:
7469 return TRUE;
7470 case RVCO_REMOVE:
7474 return TRUE;
7475 }
7476 i++;
7478 return FALSE;
7479 case RVCO_NOOP:
7480 return FALSE;
7481 }
7482
7483 return FALSE;
7484}
7485
7486/**********************************************************************/
7496struct req_vec_problem *
7498 const char *description,
7499 const char *description_translated)
7500{
7501 struct req_vec_problem *out;
7502 int i;
7503
7504 out = fc_malloc(sizeof(*out));
7505
7506 fc_strlcpy(out->description, description, sizeof(out->description));
7507 fc_strlcpy(out->description_translated, _(description_translated),
7508 sizeof(out->description_translated));
7509
7510 out->num_suggested_solutions = num_suggested_solutions;
7511 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
7512 * sizeof(struct req_vec_change));
7513 for (i = 0; i < out->num_suggested_solutions; i++) {
7514 /* No suggestions are ready yet. */
7515 out->suggested_solutions[i].operation = RVCO_NOOP;
7516 out->suggested_solutions[i].vector_number = -1;
7517 out->suggested_solutions[i].req.source.kind = VUT_NONE;
7518 }
7519
7520 return out;
7521}
7522
7523/**********************************************************************/
7533 const char *descr, ...)
7534{
7535 char description[500];
7536 char description_translated[500];
7537 va_list ap;
7538
7539 va_start(ap, descr);
7540 fc_vsnprintf(description, sizeof(description), descr, ap);
7541 va_end(ap);
7542
7543 va_start(ap, descr);
7545 _(descr), ap);
7546 va_end(ap);
7547
7550}
7551
7552/**********************************************************************/
7559{
7560 FC_FREE(issue->suggested_solutions);
7561 issue->num_suggested_solutions = 0;
7562
7563 FC_FREE(issue);
7564}
7565
7566/**********************************************************************/
7578struct req_vec_problem *
7581 const void *parent_item)
7582{
7583 int i, j;
7585
7586 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7587 /* No vector. */
7588 return nullptr;
7589 }
7590
7591 if (get_num == nullptr || parent_item == nullptr) {
7592 vec_num = 0;
7593 } else {
7594 vec_num = get_num(parent_item, vec);
7595 }
7596
7597 /* Look for contradictions */
7598 for (i = 0; i < requirement_vector_size(vec); i++) {
7599 struct requirement *preq = requirement_vector_get(vec, i);
7600 for (j = 0; j < requirement_vector_size(vec); j++) {
7601 struct requirement *nreq = requirement_vector_get(vec, j);
7602
7604 struct req_vec_problem *problem;
7605 struct astring astr;
7606 struct astring nastr;
7607
7609 N_("Requirements {%s} and {%s} contradict each other."),
7611
7612 astr_free(&astr);
7613 astr_free(&nastr);
7614
7615 /* The solution is to remove one of the contradictions. */
7616 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7617 problem->suggested_solutions[0].vector_number = vec_num;
7618 problem->suggested_solutions[0].req = *preq;
7619
7620 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7621 problem->suggested_solutions[1].vector_number = vec_num;
7622 problem->suggested_solutions[1].req = *nreq;
7623
7624 /* Only the first contradiction is reported. */
7625 return problem;
7626 }
7627 }
7628 }
7629
7630 return nullptr;
7631}
7632
7633/**********************************************************************/
7644struct req_vec_problem *
7647 const void *parent_item)
7648{
7649 /* Check for self contradictins. */
7651}
7652
7653/**********************************************************************/
7666struct req_vec_problem *
7669 const void *parent_item)
7670{
7671 int i;
7673 struct req_vec_problem *problem = nullptr;
7674
7675 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7676 /* No vector. */
7677 return nullptr;
7678 }
7679
7680 if (get_num == nullptr || parent_item == nullptr) {
7681 vec_num = 0;
7682 } else {
7683 vec_num = get_num(parent_item, vec);
7684 }
7685
7686 /* Look for contradictions */
7687 for (i = 0; i < requirement_vector_size(vec); i++) {
7688 struct requirement *preq = requirement_vector_get(vec, i);
7689
7690 if (universal_never_there(&preq->source)) {
7691 struct astring astr;
7692
7693 if (preq->present) {
7694 /* The requirement vector can never be fulfilled. Removing the
7695 * requirement makes it possible to fulfill it. This is a rule
7696 * change and shouldn't be "fixed" without thinking. Don't offer any
7697 * automatic solution to prevent mindless "fixes". */
7698 /* TRANS: Ruledit warns a user about an unused requirement vector
7699 * that never can be fulfilled because it asks for something that
7700 * never will be there. */
7701 if (problem == nullptr) {
7703 N_("Requirement {%s} requires %s but it will never be"
7704 " there."),
7706 astr_free(&astr);
7707 }
7708
7709 /* Continue to check if other problems have a solution proposal,
7710 * and prefer to return those. */
7711 continue;
7712 }
7713
7714 if (problem != nullptr) {
7715 /* Free previous one (one with no solution proposals) */
7717 }
7718
7720 N_("Requirement {%s} mentions %s but it will never be there."),
7722
7723 astr_free(&astr);
7724
7725 /* The solution is to remove the reference to the missing
7726 * universal. */
7727 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7728 problem->suggested_solutions[0].vector_number = vec_num;
7729 problem->suggested_solutions[0].req = *preq;
7730
7731 /* Only the first missing universal is reported. */
7732 return problem;
7733 }
7734 }
7735
7736 return problem;
7737}
7738
7739/**********************************************************************/
7752struct req_vec_problem *
7755 const void *parent_item)
7756{
7757 int i, j;
7759
7760 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7761 /* No vector. */
7762 return nullptr;
7763 }
7764
7765 if (get_num == nullptr || parent_item == nullptr) {
7766 vec_num = 0;
7767 } else {
7768 vec_num = get_num(parent_item, vec);
7769 }
7770
7771 /* Look for repeated requirements */
7772 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
7773 struct requirement *preq = requirement_vector_get(vec, i);
7774 for (j = i + 1; j < requirement_vector_size(vec); j++) {
7775 struct requirement *nreq = requirement_vector_get(vec, j);
7776
7778 struct req_vec_problem *problem;
7779 struct astring astr;
7780 struct astring nastr;
7781
7783 N_("Requirements {%s} and {%s} are the same."),
7785
7786 astr_free(&astr);
7787 astr_free(&nastr);
7788
7789 /* The solution is to remove one of the redundant requirements. */
7790 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7791 problem->suggested_solutions[0].vector_number = vec_num;
7792 problem->suggested_solutions[0].req = *preq;
7793
7794 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7795 problem->suggested_solutions[1].vector_number = vec_num;
7796 problem->suggested_solutions[1].req = *nreq;
7797
7798 /* Only the first redundancy is reported. */
7799 return problem;
7800 }
7801 }
7802 }
7803
7804 return nullptr;
7805}
7806
7807/**********************************************************************/
7819struct req_vec_problem *
7822 const void *parent_item)
7823{
7824 struct req_vec_problem *out;
7825
7827 if (out != nullptr) {
7828 /* A bug, not just a potential improvement */
7829 return out;
7830 }
7831
7832 /* Check if a universal that never will appear in the game is checked. */
7834 if (out != nullptr) {
7835 return out;
7836 }
7837
7838 /* Check if a requirement is redundant. */
7840 return out;
7841}
7842
7843/**********************************************************************/
7848 const struct universal *psource2)
7849{
7850 if (psource1->kind != psource2->kind) {
7851 return FALSE;
7852 }
7853 switch (psource1->kind) {
7854 case VUT_NONE:
7855 return TRUE;
7856 case VUT_COUNTER:
7857 return psource1->value.counter == psource2->value.counter;
7858 case VUT_ADVANCE:
7859 return psource1->value.advance == psource2->value.advance;
7860 case VUT_TECHFLAG:
7861 return psource1->value.techflag == psource2->value.techflag;
7862 case VUT_GOVERNMENT:
7863 return psource1->value.govern == psource2->value.govern;
7864 case VUT_GOVFLAG:
7865 return psource1->value.govflag == psource2->value.govflag;
7866 case VUT_ACHIEVEMENT:
7867 return psource1->value.achievement == psource2->value.achievement;
7868 case VUT_STYLE:
7869 return psource1->value.style == psource2->value.style;
7870 case VUT_IMPROVEMENT:
7871 case VUT_SITE:
7872 return psource1->value.building == psource2->value.building;
7873 case VUT_IMPR_GENUS:
7874 return psource1->value.impr_genus == psource2->value.impr_genus;
7875 case VUT_IMPR_FLAG:
7876 return psource1->value.impr_flag == psource2->value.impr_flag;
7877 case VUT_PLAYER_FLAG:
7878 return psource1->value.plr_flag == psource2->value.plr_flag;
7879 case VUT_PLAYER_STATE:
7880 return psource1->value.plrstate == psource2->value.plrstate;
7881 case VUT_EXTRA:
7882 return psource1->value.extra == psource2->value.extra;
7883 case VUT_TILEDEF:
7885 return psource1->value.tiledef == psource2->value.tiledef;
7886 case VUT_GOOD:
7887 return psource1->value.good == psource2->value.good;
7888 case VUT_TERRAIN:
7889 return psource1->value.terrain == psource2->value.terrain;
7890 case VUT_TERRFLAG:
7891 return psource1->value.terrainflag == psource2->value.terrainflag;
7892 case VUT_NATION:
7893 return psource1->value.nation == psource2->value.nation;
7894 case VUT_NATIONGROUP:
7895 return psource1->value.nationgroup == psource2->value.nationgroup;
7896 case VUT_NATIONALITY:
7897 return psource1->value.nationality == psource2->value.nationality;
7898 case VUT_ORIGINAL_OWNER:
7899 return psource1->value.origowner == psource2->value.origowner;
7900 case VUT_DIPLREL:
7901 case VUT_DIPLREL_TILE:
7902 case VUT_DIPLREL_TILE_O:
7905 return psource1->value.diplrel == psource2->value.diplrel;
7906 case VUT_UTYPE:
7907 return psource1->value.utype == psource2->value.utype;
7908 case VUT_UTFLAG:
7909 return psource1->value.unitflag == psource2->value.unitflag;
7910 case VUT_UCLASS:
7911 return psource1->value.uclass == psource2->value.uclass;
7912 case VUT_UCFLAG:
7913 return psource1->value.unitclassflag == psource2->value.unitclassflag;
7914 case VUT_MINVETERAN:
7915 return psource1->value.minveteran == psource2->value.minveteran;
7916 case VUT_UNITSTATE:
7917 return psource1->value.unit_state == psource2->value.unit_state;
7918 case VUT_ACTIVITY:
7919 return psource1->value.activity == psource2->value.activity;
7920 case VUT_MINMOVES:
7921 return psource1->value.minmoves == psource2->value.minmoves;
7922 case VUT_MINHP:
7923 return psource1->value.min_hit_points == psource2->value.min_hit_points;
7924 case VUT_AGE:
7925 return psource1->value.age == psource2->value.age;
7926 case VUT_FORM_AGE:
7927 return psource1->value.form_age == psource2->value.form_age;
7928 case VUT_MINTECHS:
7929 return psource1->value.min_techs == psource2->value.min_techs;
7930 case VUT_FUTURETECHS:
7931 return psource1->value.future_techs == psource2->value.future_techs;
7932 case VUT_MINCITIES:
7933 return psource1->value.min_cities == psource2->value.min_cities;
7934 case VUT_ACTION:
7935 return (action_number(psource1->value.action)
7936 == action_number(psource2->value.action));
7937 case VUT_OTYPE:
7938 return psource1->value.outputtype == psource2->value.outputtype;
7939 case VUT_SPECIALIST:
7940 return psource1->value.specialist == psource2->value.specialist;
7941 case VUT_MINSIZE:
7942 return psource1->value.minsize == psource2->value.minsize;
7943 case VUT_MINCULTURE:
7944 return psource1->value.minculture == psource2->value.minculture;
7945 case VUT_MINFOREIGNPCT:
7946 return psource1->value.minforeignpct == psource2->value.minforeignpct;
7947 case VUT_AI_LEVEL:
7948 return psource1->value.ai_level == psource2->value.ai_level;
7950 return psource1->value.max_tile_total_units == psource2->value.max_tile_total_units;
7952 return psource1->value.max_tile_top_units == psource2->value.max_tile_top_units;
7953 case VUT_TERRAINCLASS:
7954 return psource1->value.terrainclass == psource2->value.terrainclass;
7955 case VUT_ROADFLAG:
7956 return psource1->value.roadflag == psource2->value.roadflag;
7957 case VUT_EXTRAFLAG:
7958 return psource1->value.extraflag == psource2->value.extraflag;
7959 case VUT_MINYEAR:
7960 return psource1->value.minyear == psource2->value.minyear;
7961 case VUT_MINCALFRAG:
7962 return psource1->value.mincalfrag == psource2->value.mincalfrag;
7963 case VUT_TOPO:
7964 return psource1->value.topo_property == psource2->value.topo_property;
7965 case VUT_WRAP:
7966 return psource1->value.wrap_property == psource2->value.wrap_property;
7967 case VUT_SERVERSETTING:
7968 return psource1->value.ssetval == psource2->value.ssetval;
7969 case VUT_TERRAINALTER:
7970 return psource1->value.terrainalter == psource2->value.terrainalter;
7971 case VUT_CITYTILE:
7972 return psource1->value.citytile == psource2->value.citytile;
7973 case VUT_CITYSTATUS:
7974 return psource1->value.citystatus == psource2->value.citystatus;
7975 case VUT_TILE_REL:
7976 return psource1->value.tilerel == psource2->value.tilerel;
7977 case VUT_MINLATITUDE:
7978 case VUT_MAXLATITUDE:
7979 return psource1->value.latitude == psource2->value.latitude;
7981 return psource1->value.distance_sq == psource2->value.distance_sq;
7983 return psource1->value.region_tiles == psource2->value.region_tiles;
7984 case VUT_COUNT:
7985 break;
7986 }
7987
7988 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
7989 return FALSE;
7990}
7991
7992/**********************************************************************/
7996const char *universal_rule_name(const struct universal *psource)
7997{
7998 static char buffer[10];
7999
8000 switch (psource->kind) {
8001 case VUT_NONE:
8002 return "(none)";
8003 case VUT_COUNTER:
8004 return counter_rule_name(psource->value.counter);
8005 case VUT_CITYTILE:
8006 return citytile_type_name(psource->value.citytile);
8007 case VUT_CITYSTATUS:
8008 return citystatus_type_name(psource->value.citystatus);
8009 case VUT_TILE_REL:
8010 return tilerel_type_name(psource->value.tilerel);
8011 case VUT_MINYEAR:
8012 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
8013
8014 return buffer;
8015 case VUT_MINCALFRAG:
8016 /* Rule name is 0-based number, not pretty name from ruleset */
8017 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
8018
8019 return buffer;
8020 case VUT_TOPO:
8021 return topo_flag_name(psource->value.topo_property);
8022 case VUT_WRAP:
8023 return wrap_flag_name(psource->value.wrap_property);
8024 case VUT_SERVERSETTING:
8025 return ssetv_rule_name(psource->value.ssetval);
8026 case VUT_ADVANCE:
8027 return advance_rule_name(psource->value.advance);
8028 case VUT_TECHFLAG:
8029 return tech_flag_id_name(psource->value.techflag);
8030 case VUT_GOVERNMENT:
8031 return government_rule_name(psource->value.govern);
8032 case VUT_GOVFLAG:
8033 return gov_flag_id_name(psource->value.govflag);
8034 case VUT_ACHIEVEMENT:
8035 return achievement_rule_name(psource->value.achievement);
8036 case VUT_STYLE:
8037 return style_rule_name(psource->value.style);
8038 case VUT_IMPROVEMENT:
8039 case VUT_SITE:
8040 return improvement_rule_name(psource->value.building);
8041 case VUT_IMPR_GENUS:
8042 return impr_genus_id_name(psource->value.impr_genus);
8043 case VUT_IMPR_FLAG:
8044 return impr_flag_id_name(psource->value.impr_flag);
8045 case VUT_PLAYER_FLAG:
8046 return plr_flag_id_name(psource->value.plr_flag);
8047 case VUT_PLAYER_STATE:
8048 return plrstate_type_name(psource->value.plrstate);
8049 case VUT_EXTRA:
8050 return extra_rule_name(psource->value.extra);
8051 case VUT_TILEDEF:
8053 return tiledef_rule_name(psource->value.tiledef);
8054 case VUT_GOOD:
8055 return goods_rule_name(psource->value.good);
8056 case VUT_TERRAIN:
8057 return terrain_rule_name(psource->value.terrain);
8058 case VUT_TERRFLAG:
8059 return terrain_flag_id_name(psource->value.terrainflag);
8060 case VUT_NATION:
8061 return nation_rule_name(psource->value.nation);
8062 case VUT_NATIONGROUP:
8063 return nation_group_rule_name(psource->value.nationgroup);
8064 case VUT_DIPLREL:
8065 case VUT_DIPLREL_TILE:
8066 case VUT_DIPLREL_TILE_O:
8069 return diplrel_rule_name(psource->value.diplrel);
8070 case VUT_NATIONALITY:
8071 return nation_rule_name(psource->value.nationality);
8072 case VUT_ORIGINAL_OWNER:
8073 return nation_rule_name(psource->value.origowner);
8074 case VUT_UTYPE:
8075 return utype_rule_name(psource->value.utype);
8076 case VUT_UTFLAG:
8077 return unit_type_flag_id_name(psource->value.unitflag);
8078 case VUT_UCLASS:
8079 return uclass_rule_name(psource->value.uclass);
8080 case VUT_UCFLAG:
8081 return unit_class_flag_id_name(psource->value.unitclassflag);
8082 case VUT_MINVETERAN:
8083 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
8084
8085 return buffer;
8086 case VUT_UNITSTATE:
8087 return ustate_prop_name(psource->value.unit_state);
8088 case VUT_ACTIVITY:
8089 return unit_activity_name(psource->value.activity);
8090 case VUT_MINMOVES:
8091 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
8092
8093 return buffer;
8094 case VUT_MINHP:
8095 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
8096
8097 return buffer;
8098 case VUT_AGE:
8099 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
8100
8101 return buffer;
8102 case VUT_FORM_AGE:
8103 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
8104
8105 return buffer;
8106 case VUT_MINTECHS:
8107 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
8108
8109 return buffer;
8110 case VUT_FUTURETECHS:
8111 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.future_techs);
8112
8113 return buffer;
8114 case VUT_MINCITIES:
8115 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_cities);
8116
8117 return buffer;
8118 case VUT_ACTION:
8119 return action_rule_name(psource->value.action);
8120 case VUT_OTYPE:
8121 return get_output_identifier(psource->value.outputtype);
8122 case VUT_SPECIALIST:
8123 return specialist_rule_name(psource->value.specialist);
8124 case VUT_MINSIZE:
8125 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
8126
8127 return buffer;
8128 case VUT_MINCULTURE:
8129 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
8130
8131 return buffer;
8132 case VUT_MINFOREIGNPCT:
8133 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
8134
8135 return buffer;
8136 case VUT_AI_LEVEL:
8137 return ai_level_name(psource->value.ai_level);
8139 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_total_units);
8140 return buffer;
8142 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_top_units);
8143 return buffer;
8144 case VUT_TERRAINCLASS:
8145 return terrain_class_name(psource->value.terrainclass);
8146 case VUT_ROADFLAG:
8147 return road_flag_id_name(psource->value.roadflag);
8148 case VUT_EXTRAFLAG:
8149 return extra_flag_id_name(psource->value.extraflag);
8150 case VUT_TERRAINALTER:
8151 return terrain_alteration_name(psource->value.terrainalter);
8152 case VUT_MINLATITUDE:
8153 case VUT_MAXLATITUDE:
8154 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
8155
8156 return buffer;
8158 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.distance_sq);
8159
8160 return buffer;
8162 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.region_tiles);
8163
8164 return buffer;
8165 case VUT_COUNT:
8166 break;
8167 }
8168
8169 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8170
8171 return nullptr;
8172}
8173
8174/**********************************************************************/
8183 char *buf, size_t bufsz)
8184{
8185 buf[0] = '\0'; /* to be safe. */
8186 switch (psource->kind) {
8187 case VUT_NONE:
8188 /* TRANS: missing value */
8189 fc_strlcat(buf, _("(none)"), bufsz);
8190 return buf;
8191 case VUT_ADVANCE:
8193 return buf;
8194 case VUT_COUNTER:
8196 return buf;
8197 case VUT_TECHFLAG:
8198 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
8199 tech_flag_id_translated_name(psource->value.techflag));
8200 return buf;
8201 case VUT_GOVERNMENT:
8203 bufsz);
8204 return buf;
8205 case VUT_GOVFLAG:
8206 cat_snprintf(buf, bufsz, _("\"%s\" gov"),
8207 gov_flag_id_translated_name(psource->value.govflag));
8208 return buf;
8209 case VUT_ACHIEVEMENT:
8211 bufsz);
8212 return buf;
8213 case VUT_STYLE:
8215 bufsz);
8216 return buf;
8217 case VUT_IMPROVEMENT:
8219 bufsz);
8220 return buf;
8221 case VUT_SITE:
8222 {
8223 char local_buf[1024];
8224
8225 fc_snprintf(local_buf, sizeof(local_buf), _("%s site"),
8226 improvement_name_translation(psource->value.building));
8228 }
8229
8230 return buf;
8231 case VUT_IMPR_GENUS:
8233 impr_genus_id_translated_name(psource->value.impr_genus),
8234 bufsz);
8235 return buf;
8236 case VUT_IMPR_FLAG:
8238 impr_flag_id_translated_name(psource->value.impr_flag),
8239 bufsz);
8240 return buf;
8241 case VUT_PLAYER_FLAG:
8243 plr_flag_id_translated_name(psource->value.plr_flag),
8244 bufsz);
8245 return buf;
8246 case VUT_PLAYER_STATE:
8248 plrstate_type_translated_name(psource->value.plrstate),
8249 bufsz);
8250 return buf;
8251 case VUT_EXTRA:
8253 return buf;
8254 case VUT_TILEDEF:
8257 return buf;
8258 case VUT_GOOD:
8260 return buf;
8261 case VUT_TERRAIN:
8263 return buf;
8264 case VUT_NATION:
8266 bufsz);
8267 return buf;
8268 case VUT_NATIONGROUP:
8270 bufsz);
8271 return buf;
8272 case VUT_NATIONALITY:
8273 cat_snprintf(buf, bufsz, _("%s citizens"),
8274 nation_adjective_translation(psource->value.nationality));
8275 return buf;
8276 case VUT_ORIGINAL_OWNER:
8277 /* TRANS: Keep short. City founding nation. */
8278 cat_snprintf(buf, bufsz, _("%s original owner"),
8279 nation_adjective_translation(psource->value.origowner));
8280 return buf;
8281 case VUT_DIPLREL:
8282 case VUT_DIPLREL_TILE:
8283 case VUT_DIPLREL_TILE_O:
8287 bufsz);
8288 return buf;
8289 case VUT_UTYPE:
8291 return buf;
8292 case VUT_UTFLAG:
8294 /* TRANS: Unit type flag */
8295 Q_("?utflag:\"%s\" units"),
8297 psource->value.unitflag));
8298 return buf;
8299 case VUT_UCLASS:
8301 /* TRANS: Unit class */
8302 _("%s units"),
8303 uclass_name_translation(psource->value.uclass));
8304 return buf;
8305 case VUT_UCFLAG:
8307 /* TRANS: Unit class flag */
8308 Q_("?ucflag:\"%s\" units"),
8310 psource->value.unitclassflag));
8311 return buf;
8312 case VUT_MINVETERAN:
8313 /* FIXME */
8314 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
8315 psource->value.minveteran);
8316 return buf;
8317 case VUT_UNITSTATE:
8318 switch (psource->value.unit_state) {
8319 case USP_TRANSPORTED:
8320 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
8321 cat_snprintf(buf, bufsz, _("Transported"));
8322 break;
8323 case USP_LIVABLE_TILE:
8325 /* TRANS: unit state. (appears in strings like
8326 * "Missile+On livable tile") */
8327 _("On livable tile"));
8328 break;
8329 case USP_TRANSPORTING:
8330 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
8331 cat_snprintf(buf, bufsz, _("Transporting"));
8332 break;
8333 case USP_HAS_HOME_CITY:
8334 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
8335 cat_snprintf(buf, bufsz, _("Has a home city"));
8336 break;
8337 case USP_NATIVE_TILE:
8339 /* TRANS: unit state. (appears in strings like
8340 * "Missile+On native tile") */
8341 _("On native tile"));
8342 break;
8343 case USP_NATIVE_EXTRA:
8345 /* TRANS: unit state. (appears in strings like
8346 * "Missile+In native extra") */
8347 _("In native extra"));
8348 break;
8350 /* TRANS: unit state. (appears in strings like
8351 * "Missile+Has moved this turn") */
8352 cat_snprintf(buf, bufsz, _("Has moved this turn"));
8353 break;
8354 case USP_COUNT:
8355 fc_assert_msg(psource->value.unit_state != USP_COUNT,
8356 "Invalid unit state property.");
8357 break;
8358 }
8359 return buf;
8360 case VUT_ACTIVITY:
8361 cat_snprintf(buf, bufsz, _("%s activity"),
8362 Q_(unit_activity_name(psource->value.activity)));
8363 return buf;
8364 case VUT_MINMOVES:
8365 /* TRANS: Minimum unit movement points left for requirement to be met
8366 * (%s is a string like "1" or "2 1/3") */
8367 cat_snprintf(buf, bufsz, _("%s MP"),
8368 move_points_text(psource->value.minmoves, TRUE));
8369 return buf;
8370 case VUT_MINHP:
8371 /* TRANS: HP = hit points */
8372 cat_snprintf(buf, bufsz, _("%d HP"),
8373 psource->value.min_hit_points);
8374 return buf;
8375 case VUT_AGE:
8376 cat_snprintf(buf, bufsz, _("Age %d"),
8377 psource->value.age);
8378 return buf;
8379 case VUT_FORM_AGE:
8380 cat_snprintf(buf, bufsz, _("Form age %d"),
8381 psource->value.form_age);
8382 return buf;
8383 case VUT_MINTECHS:
8384 cat_snprintf(buf, bufsz, _("%d Techs"),
8385 psource->value.min_techs);
8386 return buf;
8387 case VUT_FUTURETECHS:
8388 cat_snprintf(buf, bufsz, _("%d Future techs"),
8389 psource->value.future_techs);
8390 return buf;
8391 case VUT_MINCITIES:
8392 cat_snprintf(buf, bufsz, _("%d Cities"),
8393 psource->value.min_cities);
8394 return buf;
8395 case VUT_ACTION:
8397 bufsz);
8398 return buf;
8399 case VUT_OTYPE:
8400 /* FIXME */
8401 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
8402 return buf;
8403 case VUT_SPECIALIST:
8405 bufsz);
8406 return buf;
8407 case VUT_MINSIZE:
8408 cat_snprintf(buf, bufsz, _("Size %d"),
8409 psource->value.minsize);
8410 return buf;
8411 case VUT_MINCULTURE:
8412 cat_snprintf(buf, bufsz, _("Culture %d"),
8413 psource->value.minculture);
8414 return buf;
8415 case VUT_MINFOREIGNPCT:
8416 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
8417 psource->value.minforeignpct);
8418 return buf;
8419 case VUT_AI_LEVEL:
8420 /* TRANS: "Hard AI" */
8421 cat_snprintf(buf, bufsz, _("%s AI"),
8422 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
8423 return buf;
8425 /* TRANS: here <= means 'less than or equal' */
8426 cat_snprintf(buf, bufsz, PL_("<=%d total unit",
8427 "<=%d total units",
8428 psource->value.max_tile_total_units),
8429 psource->value.max_tile_total_units);
8430 return buf;
8432 /* TRANS: here <= means 'less than or equal' */
8433 cat_snprintf(buf, bufsz, PL_("<=%d unit",
8434 "<=%d units", psource->value.max_tile_top_units),
8435 psource->value.max_tile_top_units);
8436 return buf;
8437 case VUT_TERRAINCLASS:
8438 /* TRANS: Terrain class: "Land terrain" */
8439 cat_snprintf(buf, bufsz, _("%s terrain"),
8440 terrain_class_name_translation(psource->value.terrainclass));
8441 return buf;
8442 case VUT_TERRFLAG:
8444 /* TRANS: Terrain flag */
8445 Q_("?terrflag:\"%s\" terrain"),
8447 psource->value.terrainflag));
8448 return buf;
8449 case VUT_ROADFLAG:
8451 /* TRANS: Road flag */
8452 Q_("?roadflag:\"%s\" road"),
8453 road_flag_id_translated_name(psource->value.roadflag));
8454 return buf;
8455 case VUT_EXTRAFLAG:
8457 /* TRANS: Extra flag */
8458 Q_("?extraflag:\"%s\" extra"),
8459 extra_flag_id_translated_name(psource->value.extraflag));
8460 return buf;
8461 case VUT_MINYEAR:
8462 cat_snprintf(buf, bufsz, _("After %s"),
8463 textyear(psource->value.minyear));
8464 return buf;
8465 case VUT_MINCALFRAG:
8466 /* TRANS: here >= means 'greater than or equal'.
8467 * %s identifies a calendar fragment (may be bare number). */
8468 cat_snprintf(buf, bufsz, _(">=%s"),
8469 textcalfrag(psource->value.mincalfrag));
8470 return buf;
8471 case VUT_TOPO:
8472 /* TRANS: topology flag name ("Hex", "ISO") */
8473 cat_snprintf(buf, bufsz, _("%s map"),
8474 _(topo_flag_name(psource->value.topo_property)));
8475 return buf;
8476 case VUT_WRAP:
8477 /* TRANS: wrap flag name ("WrapX", "WrapY") */
8478 cat_snprintf(buf, bufsz, _("%s map"),
8479 _(wrap_flag_name(psource->value.wrap_property)));
8480 return buf;
8481 case VUT_SERVERSETTING:
8483 bufsz);
8484 return buf;
8485 case VUT_TERRAINALTER:
8486 /* TRANS: "Irrigation possible" */
8487 cat_snprintf(buf, bufsz, _("%s possible"),
8488 Q_(terrain_alteration_name(psource->value.terrainalter)));
8489 return buf;
8490 case VUT_CITYTILE:
8491 switch (psource->value.citytile) {
8492 case CITYT_CENTER:
8493 fc_strlcat(buf, _("City center"), bufsz);
8494 break;
8495 case CITYT_CLAIMED:
8496 fc_strlcat(buf, _("Tile claimed"), bufsz);
8497 break;
8498 case CITYT_EXTRAS_OWNED:
8499 fc_strlcat(buf, _("Extras owned"), bufsz);
8500 break;
8501 case CITYT_WORKED:
8502 fc_strlcat(buf, _("Worked tile"), bufsz);
8503 break;
8505 fc_strlcat(buf, _("Same continent tile"), bufsz);
8506 break;
8508 /* TRANS: Short for "a tile of other terrain class mass near city" */
8509 fc_strlcat(buf, _("Port reachable tile"), bufsz);
8510 break;
8511 case CITYT_LAST:
8512 fc_assert(psource->value.citytile != CITYT_LAST);
8513 fc_strlcat(buf, "error", bufsz);
8514 break;
8515 }
8516 return buf;
8517 case VUT_CITYSTATUS:
8518 switch (psource->value.citystatus) {
8520 fc_strlcat(buf, _("Owned by original"), bufsz);
8521 break;
8522 case CITYS_STARVED:
8523 fc_strlcat(buf, _("Starved"), bufsz);
8524 break;
8525 case CITYS_DISORDER:
8526 fc_strlcat(buf, _("Disorder"), bufsz);
8527 break;
8528 case CITYS_CELEBRATION:
8529 fc_strlcat(buf, _("Celebration"), bufsz);
8530 break;
8531 case CITYS_TRANSFERRED:
8532 /* TRANS: CityStatus value - city has changed hands */
8533 fc_strlcat(buf, _("Transferred"), bufsz);
8534 break;
8536 fc_strlcat(buf, _("CapitalConnected"), bufsz);
8537 break;
8538 case CITYS_LAST:
8539 fc_assert(psource->value.citystatus != CITYS_LAST);
8540 fc_strlcat(buf, "error", bufsz);
8541 break;
8542 }
8543 return buf;
8544 case VUT_TILE_REL:
8545 switch (psource->value.tilerel) {
8546 case TREL_SAME_TCLASS:
8547 fc_strlcat(buf, _("Same terrain class"), bufsz);
8548 break;
8549 case TREL_SAME_REGION:
8550 fc_strlcat(buf, _("Same continent/ocean"), bufsz);
8551 break;
8553 fc_strlcat(buf, _("Only other continent/ocean"), bufsz);
8554 break;
8556 fc_strlcat(buf, _("Lake/island surrounded"), bufsz);
8557 break;
8558 case TREL_COUNT:
8559 fc_assert(psource->value.tilerel != TREL_COUNT);
8560 fc_strlcat(buf, "error", bufsz);
8561 break;
8562 }
8563 return buf;
8564 case VUT_MINLATITUDE:
8565 /* TRANS: here >= means 'greater than or equal'. */
8566 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
8567 psource->value.latitude);
8568 return buf;
8569 case VUT_MAXLATITUDE:
8570 /* TRANS: here <= means 'less than or equal'. */
8571 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
8572 psource->value.latitude);
8573 return buf;
8575 /* TRANS: here <= means 'less than or equal'. */
8576 cat_snprintf(buf, bufsz, _("Squared distance <= %d"),
8577 psource->value.distance_sq);
8578 return buf;
8580 cat_snprintf(buf, bufsz, _("%d or fewer region tiles"),
8581 psource->value.region_tiles);
8582 return buf;
8583 case VUT_COUNT:
8584 break;
8585 }
8586
8587 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8588 return buf;
8589}
8590
8591/**********************************************************************/
8595{
8596 return universals_n_name(psource->kind);
8597}
8598
8599/**********************************************************************/
8603 const struct universal *target)
8604{
8605 switch (target->kind) {
8606 case VUT_IMPROVEMENT:
8607 case VUT_SITE:
8608 return impr_build_shield_cost(pcity, target->value.building);
8609 case VUT_UTYPE:
8610 return utype_build_shield_cost(pcity, nullptr, target->value.utype);
8611 default:
8612 break;
8613 }
8614 return FC_INFINITY;
8615}
8616
8617/**********************************************************************/
8623 const struct universal *to_replace,
8624 const struct universal *replacement)
8625{
8626 bool changed = FALSE;
8627
8630 preq->source = *replacement;
8631 changed = TRUE;
8632 }
8634
8635 return changed;
8636}
8637
8638/**********************************************************************/
8643 const struct requirement_vector *reqs,
8644 const struct universal *psource)
8645{
8648 return TRUE;
8649 }
8651
8652 return FALSE;
8653}
8654
8655/**********************************************************************/
8666 struct universal *unis,
8667 size_t n_unis)
8668{
8669 int i;
8670
8671 for (i = 0; i < n_unis; i++) {
8673 /* This universal makes it impossible to fulfill the specified
8674 * requirement vector */
8675 return TRUE;
8676 }
8677 }
8678
8679 /* No specified universal is known to guarantee that the requirement
8680 * vector never will be fulfilled. */
8681 return FALSE;
8682}
8683
8684/**********************************************************************/
8700 struct universal *unis,
8701 size_t n_unis)
8702{
8704 int i;
8706
8707 for (i = 0; i < n_unis; i++) {
8708 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
8709 case ITF_NO:
8710 case ITF_YES:
8711 /* this req matched this source */
8713 break;
8714 case ITF_NOT_APPLICABLE:
8715 /* Not a mention. */
8716 break;
8717 }
8718 }
8719
8721 /* A requirement not relevant to any of the specified universals was
8722 * found in the requirement vector. */
8723 return FALSE;
8724 }
8726
8727 /* No requirement not relevant to any of the specified universals was
8728 * found in the requirement vector. */
8729 return TRUE;
8730}
8731
8732/**********************************************************************/
8735enum req_item_found
8737 const struct universal *source)
8738{
8741 "No req item found function for %s",
8743
8744 return (*universal_found_function[source->kind])(preq, source);
8745}
8746
8747/**********************************************************************/
8758 const struct requirement_vector *reqs,
8759 const struct universal *source)
8760{
8761 bool necessary = FALSE;
8762
8765 "No req item found function for %s",
8767
8769 switch ((*universal_found_function[source->kind])(preq, source)) {
8770 case ITF_NOT_APPLICABLE:
8771 continue;
8772 case ITF_NO:
8773 if (preq->present) {
8774 return FALSE;
8775 }
8776 break;
8777 case ITF_YES:
8778 if (preq->present) {
8779 necessary = TRUE;
8780 } else {
8781 return FALSE;
8782 }
8783 break;
8784 }
8786
8787 return (!check_necessary || necessary);
8788}
8789
8790/**********************************************************************/
8795 const struct universal *source)
8796{
8797 switch (universal_fulfills_requirement(req, source)) {
8798 case ITF_NOT_APPLICABLE:
8799 return FALSE;
8800 case ITF_NO:
8801 case ITF_YES:
8802 return TRUE;
8803 }
8804
8805 log_error("Unhandled item_found value");
8806 return FALSE;
8807}
8808
8809/**********************************************************************/
8813 const struct universal *source)
8814{
8815 fc_assert(source->value.nation);
8816
8817 switch (preq->source.kind) {
8818 case VUT_NATION:
8819 return preq->source.value.nation == source->value.nation ? ITF_YES
8820 : ITF_NO;
8821 case VUT_NATIONGROUP:
8822 return nation_is_in_group(source->value.nation,
8823 preq->source.value.nationgroup) ? ITF_YES
8824 : ITF_NO;
8825 default:
8826 break;
8827 }
8828
8829 return ITF_NOT_APPLICABLE;
8830}
8831
8832/**********************************************************************/
8836 const struct universal *source)
8837{
8838 fc_assert(source->value.govern);
8839
8840 if (preq->source.kind == VUT_GOVERNMENT) {
8841 return preq->source.value.govern == source->value.govern ? ITF_YES
8842 : ITF_NO;
8843 } else if (preq->source.kind == VUT_GOVFLAG) {
8844 return BV_ISSET(source->value.govern->flags, preq->source.value.govflag)
8845 ? ITF_YES : ITF_NO;
8846 }
8847
8848 return ITF_NOT_APPLICABLE;
8849}
8850
8851/**********************************************************************/
8855 const struct universal *source)
8856{
8857 fc_assert(source->value.min_cities);
8858
8859 if (preq->source.kind == VUT_MINCITIES) {
8860 return preq->source.value.min_cities <= source->value.min_cities ? ITF_YES
8861 : ITF_NO;
8862 }
8863
8864 return ITF_NOT_APPLICABLE;
8865}
8866
8867/**********************************************************************/
8871 const struct universal *source)
8872{
8873 fc_assert(source->value.building);
8874
8875 /* We only ever return ITF_YES, because requiring a different
8876 * improvement does not mean that the improvement under consideration
8877 * cannot fulfill the requirements. This is necessary to allow
8878 * requirement vectors to specify multiple required improvements. */
8879
8880 switch (preq->source.kind) {
8881 case VUT_IMPROVEMENT:
8882 case VUT_SITE:
8883 if (source->value.building == preq->source.value.building) {
8884 return ITF_YES;
8885 }
8886 break;
8887 case VUT_IMPR_GENUS:
8888 if (source->value.building->genus == preq->source.value.impr_genus) {
8889 return ITF_YES;
8890 }
8891 break;
8892 case VUT_IMPR_FLAG:
8893 if (improvement_has_flag(source->value.building,
8894 preq->source.value.impr_flag)) {
8895 return ITF_YES;
8896 }
8897 break;
8898 default:
8899 break;
8900 }
8901
8902 return ITF_NOT_APPLICABLE;
8903}
8904
8905/**********************************************************************/
8909 const struct universal *source)
8910{
8911 fc_assert(source->value.uclass);
8912
8913 switch (preq->source.kind) {
8914 case VUT_UCLASS:
8915 return source->value.uclass == preq->source.value.uclass ? ITF_YES
8916 : ITF_NO;
8917 case VUT_UCFLAG:
8918 return uclass_has_flag(source->value.uclass,
8919 preq->source.value.unitclassflag) ? ITF_YES
8920 : ITF_NO;
8921
8922 default:
8923 /* Not found and not relevant. */
8924 return ITF_NOT_APPLICABLE;
8925 };
8926}
8927
8928/**********************************************************************/
8932 const struct universal *source)
8933{
8934 fc_assert(source->value.utype);
8935
8936 switch (preq->source.kind) {
8937 case VUT_UTYPE:
8938 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
8939 case VUT_UCLASS:
8940 return utype_class(source->value.utype) == preq->source.value.uclass
8941 ? ITF_YES : ITF_NO;
8942 case VUT_UTFLAG:
8943 return utype_has_flag(source->value.utype,
8944 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
8945 case VUT_UCFLAG:
8946 return uclass_has_flag(utype_class(source->value.utype),
8947 preq->source.value.unitclassflag) ? ITF_YES
8948 : ITF_NO;
8949 default:
8950 /* Not found and not relevant. */
8951 return ITF_NOT_APPLICABLE;
8952 };
8953}
8954
8955/**********************************************************************/
8958static enum req_item_found
8960 const struct universal *source)
8961{
8964
8965 switch (preq->source.kind) {
8966 case VUT_ACTIVITY:
8967 return source->value.activity == preq->source.value.activity ? ITF_YES
8968 : ITF_NO;
8969 default:
8970 /* Not found and not relevant. */
8971 return ITF_NOT_APPLICABLE;
8972 };
8973}
8974
8975/**********************************************************************/
8979 const struct universal *source)
8980{
8981 fc_assert(source->value.terrain);
8982
8983 switch (preq->source.kind) {
8984 case VUT_TERRAIN:
8985 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
8986 case VUT_TERRAINCLASS:
8987 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
8988 ? ITF_YES : ITF_NO;
8989 case VUT_TERRFLAG:
8990 return terrain_has_flag(source->value.terrain,
8991 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
8992 case VUT_TERRAINALTER:
8993 return (terrain_can_support_alteration(source->value.terrain,
8994 preq->source.value.terrainalter)
8995 ? ITF_YES : ITF_NO);
8996 default:
8997 /* Not found and not relevant. */
8998 return ITF_NOT_APPLICABLE;
8999 };
9000}
9001
9002/**********************************************************************/
9006 const struct universal *source)
9007{
9010
9011 switch (preq->source.kind) {
9012 case VUT_CITYTILE:
9013 return (source->value.citytile == preq->source.value.citytile
9014 ? ITF_YES
9015 /* The presence of one tile state doesn't block another */
9017 default:
9018 /* Not found and not relevant. */
9019 return ITF_NOT_APPLICABLE;
9020 };
9021}
9022
9023/**********************************************************************/
9029 const struct universal *source)
9030{
9031 fc_assert(source->value.extra);
9032
9033 switch (preq->source.kind) {
9034 case VUT_EXTRA:
9035 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
9036 case VUT_EXTRAFLAG:
9037 return extra_has_flag(source->value.extra,
9038 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
9039 case VUT_ROADFLAG:
9040 {
9041 struct road_type *r = extra_road_get(source->value.extra);
9042 return r && road_has_flag(r, preq->source.value.roadflag)
9043 ? ITF_YES : ITF_NO;
9044 }
9045 default:
9046 /* Not found and not relevant. */
9047 return ITF_NOT_APPLICABLE;
9048 }
9049}
9050
9051/**********************************************************************/
9055 const struct universal *source)
9056{
9057 fc_assert(source->value.action);
9058
9059 if (preq->source.kind == VUT_ACTION) {
9060 return preq->source.value.action == source->value.action ? ITF_YES
9061 : ITF_NO;
9062 }
9063
9064 return ITF_NOT_APPLICABLE;
9065}
9066
9067/**********************************************************************/
9071 const struct universal *source)
9072{
9074 || source->kind == VUT_DIPLREL_TILE
9075 || source->kind == VUT_DIPLREL_TILE_O
9076 || source->kind == VUT_DIPLREL_UNITANY
9077 || source->kind == VUT_DIPLREL_UNITANY_O),
9079
9080 if (preq->source.kind == source->kind) {
9081 if (preq->source.value.diplrel == source->value.diplrel) {
9082 /* The diplrel itself. */
9083 return ITF_YES;
9084 }
9085 if (preq->source.value.diplrel == DRO_FOREIGN
9086 && source->value.diplrel < DS_LAST) {
9087 /* All diplstate_type values are to foreigners. */
9088 return ITF_YES;
9089 }
9090 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
9091 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
9092 /* A real embassy is an embassy. */
9093 return ITF_YES;
9094 }
9095 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
9096 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
9097 /* A real embassy is an embassy. */
9098 return ITF_YES;
9099 }
9100 if (preq->source.value.diplrel < DS_LAST
9101 && source->value.diplrel < DS_LAST
9102 && preq->range == REQ_RANGE_LOCAL) {
9103 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
9104 ITF_YES);
9105 /* Can only have one diplstate_type to a specific player. */
9106 return ITF_NO;
9107 }
9108 /* Can't say this diplrel blocks the other diplrel. */
9109 return ITF_NOT_APPLICABLE;
9110 }
9111
9112 /* Not relevant. */
9113 return ITF_NOT_APPLICABLE;
9114}
9115
9116/**********************************************************************/
9120 const struct universal *source)
9121{
9122 switch (preq->source.kind) {
9123 case VUT_OTYPE:
9124 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
9125 : ITF_NO;
9126 default:
9127 /* Not found and not relevant. */
9128 return ITF_NOT_APPLICABLE;
9129 }
9130}
9131
9132/**********************************************************************/
9136 const struct universal *source)
9137{
9138 if (preq->range != REQ_RANGE_LOCAL) {
9139 return ITF_NOT_APPLICABLE;
9140 }
9141
9142 if (preq->source.kind == VUT_UNITSTATE) {
9143 switch (source->value.unit_state) {
9144 case USP_TRANSPORTED:
9145 case USP_TRANSPORTING:
9146 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
9147 case USP_LIVABLE_TILE:
9148 case USP_NATIVE_TILE:
9149 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
9150 * UTYF_COAST_STRICT. */
9151 case USP_HAS_HOME_CITY:
9152 case USP_NATIVE_EXTRA:
9154 if (source->value.unit_state == preq->source.value.unit_state) {
9155 /* The other unit states doesn't contradict */
9156 return ITF_YES;
9157 }
9158 break;
9159 case USP_COUNT:
9160 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
9162 }
9163 }
9164
9165 /* Not found and not relevant. */
9166 return ITF_NOT_APPLICABLE;
9167}
9168
9169/**********************************************************************/
9194
9195/**********************************************************************/
9203int requirement_kind_ereq(const int value,
9204 const enum req_range range,
9205 const bool present,
9206 const int max_value)
9207{
9208 /* The enumerators in each range starts with present for every possible
9209 * value followed by !present for every possible value. */
9210 const int pres_start = (present ? 0 : max_value);
9211
9212 /* The enumerators for every range follows all the positions of the
9213 * previous range(s). */
9214 const int range_start = ((max_value - 1) * 2) * range;
9215
9216 return range_start + pres_start + value;
9217}
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
struct achievement * achievement_by_number(int id)
int achievement_number(const struct achievement *pach)
const char * achievement_rule_name(struct achievement *pach)
struct achievement * achievement_by_rule_name(const char *name)
const char * achievement_name_translation(struct achievement *pach)
bool achievement_claimed(const struct achievement *pach)
const char * action_name_translation(const struct action *paction)
Definition actions.c:1251
bool action_is_in_use(struct action *paction)
Definition actions.c:5910
struct action * action_by_rule_name(const char *name)
Definition actions.c:1100
const char * action_rule_name(const struct action *action)
Definition actions.c:1237
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1260
int action_number(const struct action *action)
Definition actions.c:1229
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define ACTION_NONE
Definition actions.h:59
void astr_free(struct astring *astr)
Definition astring.c:148
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:251
void astr_init(struct astring *astr)
Definition astring.c:139
#define n
Definition astring.c:77
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
const char * textcalfrag(int frag)
Definition calendar.c:101
const char * textyear(int year)
Definition calendar.c:121
citizens citizens_nation_foreign(const struct city *pcity)
Definition citizens.c:91
#define citizens_iterate_end
Definition citizens.h:54
#define citizens_iterate(_pcity, _pslot, _nationality)
Definition citizens.h:48
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:1296
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:56
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:57
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
struct @22::@23 reqs
int get_world_bonus(enum effect_type effect_type)
Definition effects.c:812
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
bool extra_flag_is_in_use(enum extra_flag_id id)
Definition extras.c:1001
bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:904
bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:884
bool is_extra_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:379
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:875
bool is_extra_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:363
struct extra_type * extra_by_number(int id)
Definition extras.c:183
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:194
#define extra_road_get(_e_)
Definition extras.h:191
static bool is_server(void)
int Tech_type_id
Definition fc_types.h:238
req_problem_type
Definition fc_types.h:514
@ RPT_POSSIBLE
Definition fc_types.h:515
#define MAX_LEN_NAME
Definition fc_types.h:68
@ VC_SPACERACE
Definition fc_types.h:966
@ O_LAST
Definition fc_types.h:103
signed short Continent_id
Definition fc_types.h:233
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
void fc_mutex_allocate(fc_mutex *mutex)
Definition fcthread.c:144
void fc_mutex_init(fc_mutex *mutex)
Definition fcthread.c:128
void fc_mutex_release(fc_mutex *mutex)
Definition fcthread.c:152
fc_thread_id fc_thread_self(void)
Definition fcthread.c:112
bool register_at_thread_exit_callback(at_thread_exit_cb *cb)
Definition fcthread.c:32
bool fc_threads_equal(fc_thread_id thr1, fc_thread_id thr2)
Definition fcthread.c:120
void fc_mutex_destroy(fc_mutex *mutex)
Definition fcthread.c:136
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
const char * government_name_translation(const struct government *pgovern)
Definition government.c: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:142
const struct unit_type * utype
Definition unit.h:141
enum universals_n kind
Definition fc_types.h:595
universals_u value
Definition fc_types.h:594
struct civ_map map
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:113
struct nation_style * style_by_number(int id)
Definition style.c:84
const char * style_name_translation(const struct nation_style *pstyle)
Definition style.c:95
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:104
int style_number(const struct nation_style *pstyle)
Definition style.c:68
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:822
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define bool
Definition support.h:71
#define fc__fallthrough
Definition support.h:119
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:110
bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag)
Definition tech.c:221
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:305
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:314
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:205
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:100
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:188
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:615
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:594
const char * terrain_class_name_translation(enum terrain_class tclass)
Definition terrain.c:664
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:240
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:157
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Definition terrain.c:676
bool is_terrain_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:330
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:249
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:585
bool is_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:461
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:148
bool is_terrain_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:441
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:351
#define T_UNKNOWN
Definition terrain.h:62
#define terrain_has_flag(terr, flag)
Definition terrain.h:177
bool tile_has_extra_flag(const struct tile *ptile, enum extra_flag_id flag)
Definition tile.c:887
bool tile_has_native_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:325
bool tile_has_road_flag(const struct tile *ptile, enum road_flag_id flag)
Definition tile.c:869
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_terrain(_tile)
Definition tile.h:115
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#define tile_owner(_tile)
Definition tile.h:97
const char * tiledef_rule_name(const struct tiledef *td)
Definition tiledef.c:104
int tiledef_number(const struct tiledef *td)
Definition tiledef.c:62
struct tiledef * tiledef_by_number(int id)
Definition tiledef.c:84
struct tiledef * tiledef_by_rule_name(const char *name)
Definition tiledef.c:113
bool tile_matches_tiledef(const struct tiledef *td, const struct tile *ptile)
Definition tiledef.c:150
bool is_tiledef_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct tiledef *ptd)
Definition tiledef.c:171
bool is_tiledef_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct tiledef *ptd)
Definition tiledef.c:187
const char * tiledef_name_translation(const struct tiledef *td)
Definition tiledef.c:95
#define tiledef_index(_td_)
Definition tiledef.h:43
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:1840
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2511
#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