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:
412 source->value.tiledef = tiledef_by_rule_name(value);
413 if (source->value.tiledef != nullptr) {
414 return;
415 }
416 break;
417 case VUT_GOOD:
418 source->value.good = goods_by_rule_name(value);
419 if (source->value.good != nullptr) {
420 return;
421 }
422 break;
423 case VUT_TERRAIN:
424 source->value.terrain = terrain_by_rule_name(value);
425 if (source->value.terrain != T_UNKNOWN) {
426 return;
427 }
428 break;
429 case VUT_TERRFLAG:
430 source->value.terrainflag
432 if (terrain_flag_id_is_valid(source->value.terrainflag)) {
433 return;
434 }
435 break;
436 case VUT_NATION:
437 source->value.nation = nation_by_rule_name(value);
438 if (source->value.nation != NO_NATION_SELECTED) {
439 return;
440 }
441 break;
442 case VUT_NATIONGROUP:
443 source->value.nationgroup = nation_group_by_rule_name(value);
444 if (source->value.nationgroup != nullptr) {
445 return;
446 }
447 break;
448 case VUT_NATIONALITY:
449 source->value.nationality = nation_by_rule_name(value);
450 if (source->value.nationality != NO_NATION_SELECTED) {
451 return;
452 }
453 break;
455 source->value.origowner = nation_by_rule_name(value);
456 if (source->value.origowner != NO_NATION_SELECTED) {
457 return;
458 }
459 break;
460 case VUT_DIPLREL:
461 case VUT_DIPLREL_TILE:
465 source->value.diplrel = diplrel_by_rule_name(value);
466 if (source->value.diplrel != diplrel_other_invalid()) {
467 return;
468 }
469 break;
470 case VUT_UTYPE:
471 source->value.utype = unit_type_by_rule_name(value);
472 if (source->value.utype) {
473 return;
474 }
475 break;
476 case VUT_UTFLAG:
478 if (unit_type_flag_id_is_valid(source->value.unitflag)) {
479 return;
480 }
481 break;
482 case VUT_UCLASS:
483 source->value.uclass = unit_class_by_rule_name(value);
484 if (source->value.uclass) {
485 return;
486 }
487 break;
488 case VUT_UCFLAG:
489 source->value.unitclassflag
491 if (unit_class_flag_id_is_valid(source->value.unitclassflag)) {
492 return;
493 }
494 break;
495 case VUT_MINVETERAN:
496 source->value.minveteran = atoi(value);
497 if (source->value.minveteran > 0) {
498 return;
499 }
500 break;
501 case VUT_UNITSTATE:
502 source->value.unit_state = ustate_prop_by_name(value, fc_strcasecmp);
503 if (ustate_prop_is_valid(source->value.unit_state)) {
504 return;
505 }
506 break;
507 case VUT_ACTIVITY:
509 if (activity_is_valid_in_requirement(source->value.activity)) {
510 return;
511 }
512 break;
513 case VUT_MINMOVES:
514 source->value.minmoves = atoi(value);
515 if (source->value.minmoves > 0) {
516 return;
517 }
518 break;
519 case VUT_MINHP:
520 source->value.min_hit_points = atoi(value);
521 if (source->value.min_hit_points > 0) {
522 return;
523 }
524 break;
525 case VUT_AGE:
526 source->value.age = atoi(value);
527 if (source->value.age > 0) {
528 return;
529 }
530 break;
531 case VUT_FORM_AGE:
532 source->value.form_age = atoi(value);
533 if (source->value.form_age > 0) {
534 return;
535 }
536 break;
537 case VUT_MINTECHS:
538 source->value.min_techs = atoi(value);
539 if (source->value.min_techs > 0) {
540 return;
541 }
542 break;
543 case VUT_FUTURETECHS:
544 source->value.future_techs = atoi(value);
545 if (source->value.future_techs > 0) {
546 return;
547 }
548 break;
549 case VUT_MINCITIES:
550 source->value.min_cities = atoi(value);
551 if (source->value.min_cities > 0) {
552 return;
553 }
554 break;
555 case VUT_ACTION:
556 source->value.action = action_by_rule_name(value);
557 if (source->value.action != nullptr) {
558 return;
559 }
560 break;
561 case VUT_OTYPE:
562 source->value.outputtype = output_type_by_identifier(value);
563 if (source->value.outputtype != O_LAST) {
564 return;
565 }
566 break;
567 case VUT_SPECIALIST:
568 source->value.specialist = specialist_by_rule_name(value);
569 if (source->value.specialist) {
570 return;
571 }
572 break;
573 case VUT_MINSIZE:
574 source->value.minsize = atoi(value);
575 if (source->value.minsize > 0) {
576 return;
577 }
578 break;
579 case VUT_MINCULTURE:
580 source->value.minculture = atoi(value);
581 if (source->value.minculture > 0) {
582 return;
583 }
584 break;
586 source->value.minforeignpct = atoi(value);
587 if (source->value.minforeignpct > 0) {
588 return;
589 }
590 break;
591 case VUT_AI_LEVEL:
592 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
593 if (ai_level_is_valid(source->value.ai_level)) {
594 return;
595 }
596 break;
598 source->value.max_tile_total_units = atoi(value);
599 if (0 <= source->value.max_tile_total_units) {
600 return;
601 }
602 break;
604 source->value.max_tile_top_units = atoi(value);
605 if (0 <= source->value.max_tile_top_units) {
606 return;
607 }
608 break;
609 case VUT_TERRAINCLASS:
610 source->value.terrainclass
612 if (terrain_class_is_valid(source->value.terrainclass)) {
613 return;
614 }
615 break;
616 case VUT_ROADFLAG:
618 if (road_flag_id_is_valid(source->value.roadflag)) {
619 return;
620 }
621 break;
622 case VUT_EXTRAFLAG:
623 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
624 if (extra_flag_id_is_valid(source->value.extraflag)) {
625 return;
626 }
627 break;
628 case VUT_MINYEAR:
629 source->value.minyear = atoi(value);
630 return;
631 case VUT_MINCALFRAG:
632 /* Rule names are 0-based numbers, not pretty names from ruleset */
633 source->value.mincalfrag = atoi(value);
634 if (source->value.mincalfrag >= 0) {
635 /* More range checking done later, in sanity_check_req_individual() */
636 return;
637 }
638 break;
639 case VUT_TOPO:
640 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
641 if (topo_flag_is_valid(source->value.topo_property)) {
642 return;
643 }
644 break;
645 case VUT_WRAP:
646 source->value.wrap_property = wrap_flag_by_name(value, fc_strcasecmp);
647 if (wrap_flag_is_valid(source->value.wrap_property)) {
648 return;
649 }
650 break;
652 source->value.ssetval = ssetv_by_rule_name(value);
653 if (source->value.ssetval != SSETV_NONE) {
654 return;
655 }
656 break;
657 case VUT_TERRAINALTER:
658 source->value.terrainalter
660 if (terrain_alteration_is_valid(source->value.terrainalter)) {
661 return;
662 }
663 break;
664 case VUT_CITYTILE:
666 if (source->value.citytile != CITYT_LAST) {
667 return;
668 }
669 break;
670 case VUT_CITYSTATUS:
672 if (source->value.citystatus != CITYS_LAST) {
673 return;
674 }
675 break;
676 case VUT_PLAYER_STATE:
678 if (source->value.plrstate != PLRS_LAST) {
679 return;
680 }
681 break;
682 case VUT_MINLATITUDE:
683 case VUT_MAXLATITUDE:
684 source->value.latitude = atoi(value);
685 if (source->value.latitude >= -MAP_MAX_LATITUDE
686 && source->value.latitude <= MAP_MAX_LATITUDE) {
687 return;
688 }
689 break;
690 case VUT_COUNTER:
691 source->value.counter = counter_by_rule_name(value);
692 if (source->value.counter != nullptr) {
693 return;
694 }
695 break;
697 source->value.distance_sq = atoi(value);
698 if (0 <= source->value.distance_sq) {
699 return;
700 }
701 break;
703 source->value.region_tiles = atoi(value);
704 if (0 < source->value.region_tiles) {
705 return;
706 }
707 break;
708 case VUT_TILE_REL:
710 if (source->value.tilerel != TREL_COUNT) {
711 return;
712 }
713 break;
714 case VUT_COUNT:
715 break;
716 }
717
718 /* If we reach here there's been an error. */
720}
721
722/**********************************************************************/
729{
730 struct universal source;
731
732 source.kind = kind;
733
734 switch (source.kind) {
735 case VUT_NONE:
736 /* Avoid compiler warning about uninitialized source.value */
737 source.value.advance = nullptr;
738
739 return source;
740 case VUT_ADVANCE:
741 source.value.advance = advance_by_number(value);
742 if (source.value.advance != nullptr) {
743 return source;
744 }
745 break;
746 case VUT_TECHFLAG:
747 source.value.techflag = value;
748 return source;
749 case VUT_GOVERNMENT:
751 if (source.value.govern != nullptr) {
752 return source;
753 }
754 break;
755 case VUT_GOVFLAG:
756 source.value.govflag = value;
757 return source;
758 case VUT_ACHIEVEMENT:
760 if (source.value.achievement != nullptr) {
761 return source;
762 }
763 break;
764 case VUT_STYLE:
765 source.value.style = style_by_number(value);
766 if (source.value.style != nullptr) {
767 return source;
768 }
769 break;
770 case VUT_IMPROVEMENT:
771 case VUT_SITE:
772 source.value.building = improvement_by_number(value);
773 if (source.value.building != nullptr) {
774 return source;
775 }
776 break;
777 case VUT_IMPR_GENUS:
778 source.value.impr_genus = value;
779 return source;
780 case VUT_IMPR_FLAG:
781 source.value.impr_flag = value;
782 return source;
783 case VUT_PLAYER_FLAG:
784 source.value.plr_flag = value;
785 return source;
786 case VUT_EXTRA:
788 return source;
789 case VUT_TILEDEF:
790 source.value.tiledef = tiledef_by_number(value);
791 return source;
792 case VUT_GOOD:
793 source.value.good = goods_by_number(value);
794 return source;
795 case VUT_TERRAIN:
796 source.value.terrain = terrain_by_number(value);
797 if (source.value.terrain != nullptr) {
798 return source;
799 }
800 break;
801 case VUT_TERRFLAG:
802 source.value.terrainflag = value;
803 return source;
804 case VUT_NATION:
806 if (source.value.nation != nullptr) {
807 return source;
808 }
809 break;
810 case VUT_NATIONGROUP:
811 source.value.nationgroup = nation_group_by_number(value);
812 if (source.value.nationgroup != nullptr) {
813 return source;
814 }
815 break;
816 case VUT_DIPLREL:
817 case VUT_DIPLREL_TILE:
821 source.value.diplrel = value;
822 if (source.value.diplrel != diplrel_other_invalid()) {
823 return source;
824 }
825 break;
826 case VUT_NATIONALITY:
828 if (source.value.nationality != nullptr) {
829 return source;
830 }
831 break;
833 source.value.origowner = nation_by_number(value);
834 if (source.value.origowner != nullptr) {
835 return source;
836 }
837 break;
838 case VUT_UTYPE:
839 source.value.utype = utype_by_number(value);
840 if (source.value.utype != nullptr) {
841 return source;
842 }
843 break;
844 case VUT_UTFLAG:
845 source.value.unitflag = value;
846 return source;
847 case VUT_UCLASS:
849 if (source.value.uclass != nullptr) {
850 return source;
851 }
852 break;
853 case VUT_UCFLAG:
854 source.value.unitclassflag = value;
855 return source;
856 case VUT_MINVETERAN:
857 source.value.minveteran = value;
858 return source;
859 case VUT_UNITSTATE:
860 source.value.unit_state = value;
861 return source;
862 case VUT_ACTIVITY:
863 source.value.activity = value;
864 return source;
865 case VUT_MINMOVES:
866 source.value.minmoves = value;
867 return source;
868 case VUT_MINHP:
870 return source;
871 case VUT_AGE:
872 source.value.age = value;
873 return source;
874 case VUT_FORM_AGE:
875 source.value.form_age = value;
876 return source;
877 case VUT_MINTECHS:
878 source.value.min_techs = value;
879 return source;
880 case VUT_FUTURETECHS:
881 source.value.future_techs = value;
882 return source;
883 case VUT_MINCITIES:
884 source.value.min_cities = value;
885 return source;
886 case VUT_ACTION:
888 if (source.value.action != nullptr) {
889 return source;
890 }
891 break;
892 case VUT_OTYPE:
893 source.value.outputtype = value;
894 return source;
895 case VUT_SPECIALIST:
897 return source;
898 case VUT_MINSIZE:
899 source.value.minsize = value;
900 return source;
901 case VUT_MINCULTURE:
902 source.value.minculture = value;
903 return source;
905 source.value.minforeignpct = value;
906 return source;
907 case VUT_AI_LEVEL:
908 source.value.ai_level = value;
909 return source;
912 return source;
915 return source;
916 case VUT_TERRAINCLASS:
917 source.value.terrainclass = value;
918 return source;
919 case VUT_ROADFLAG:
920 source.value.roadflag = value;
921 return source;
922 case VUT_EXTRAFLAG:
923 source.value.extraflag = value;
924 return source;
925 case VUT_MINYEAR:
926 source.value.minyear = value;
927 return source;
928 case VUT_MINCALFRAG:
929 source.value.mincalfrag = value;
930 return source;
931 case VUT_TOPO:
932 source.value.topo_property = value;
933 return source;
934 case VUT_WRAP:
935 source.value.wrap_property = value;
936 return source;
938 source.value.ssetval = value;
939 return source;
940 case VUT_TERRAINALTER:
941 source.value.terrainalter = value;
942 return source;
943 case VUT_CITYTILE:
944 source.value.citytile = value;
945 return source;
946 case VUT_CITYSTATUS:
947 source.value.citystatus = value;
948 return source;
949 case VUT_PLAYER_STATE:
950 source.value.plrstate = value;
951 return source;
952 case VUT_COUNTER:
954 return source;
955 case VUT_MINLATITUDE:
956 case VUT_MAXLATITUDE:
957 source.value.latitude = value;
958 return source;
960 source.value.distance_sq = value;
961 return source;
963 source.value.region_tiles = value;
964 return source;
965 case VUT_TILE_REL:
966 source.value.tilerel = value;
967 return source;
968 case VUT_COUNT:
969 break;
970 }
971
972 /* If we reach here there's been an error. */
974 /* Avoid compiler warning about uninitialized source.value */
975 source.value.advance = nullptr;
976
977 return source;
978}
979
980/**********************************************************************/
983void universal_copy(struct universal *dst, const struct universal *src)
984{
985 dst->value = src->value;
986 dst->kind = src->kind;
987}
988
989/**********************************************************************/
994 int *kind, int *value)
995{
996 *kind = source->kind;
998}
999
1000/**********************************************************************/
1004{
1005 switch (source->kind) {
1006 case VUT_NONE:
1007 return 0;
1008 case VUT_ADVANCE:
1009 return advance_number(source->value.advance);
1010 case VUT_TECHFLAG:
1011 return source->value.techflag;
1012 case VUT_GOVERNMENT:
1013 return government_number(source->value.govern);
1014 case VUT_GOVFLAG:
1015 return source->value.govflag;
1016 case VUT_ACHIEVEMENT:
1017 return achievement_number(source->value.achievement);
1018 case VUT_STYLE:
1019 return style_number(source->value.style);
1020 case VUT_IMPROVEMENT:
1021 case VUT_SITE:
1022 return improvement_number(source->value.building);
1023 case VUT_IMPR_GENUS:
1024 return source->value.impr_genus;
1025 case VUT_IMPR_FLAG:
1026 return source->value.impr_flag;
1027 case VUT_PLAYER_FLAG:
1028 return source->value.plr_flag;
1029 case VUT_EXTRA:
1030 return extra_number(source->value.extra);
1031 case VUT_TILEDEF:
1032 return tiledef_number(source->value.tiledef);
1033 case VUT_GOOD:
1034 return goods_number(source->value.good);
1035 case VUT_TERRAIN:
1036 return terrain_number(source->value.terrain);
1037 case VUT_TERRFLAG:
1038 return source->value.terrainflag;
1039 case VUT_NATION:
1040 return nation_number(source->value.nation);
1041 case VUT_NATIONGROUP:
1042 return nation_group_number(source->value.nationgroup);
1043 case VUT_NATIONALITY:
1044 return nation_number(source->value.nationality);
1045 case VUT_ORIGINAL_OWNER:
1046 return nation_number(source->value.origowner);
1047 case VUT_DIPLREL:
1048 case VUT_DIPLREL_TILE:
1049 case VUT_DIPLREL_TILE_O:
1052 return source->value.diplrel;
1053 case VUT_UTYPE:
1054 return utype_number(source->value.utype);
1055 case VUT_UTFLAG:
1056 return source->value.unitflag;
1057 case VUT_UCLASS:
1058 return uclass_number(source->value.uclass);
1059 case VUT_UCFLAG:
1060 return source->value.unitclassflag;
1061 case VUT_MINVETERAN:
1062 return source->value.minveteran;
1063 case VUT_UNITSTATE:
1064 return source->value.unit_state;
1065 case VUT_ACTIVITY:
1066 return source->value.activity;
1067 case VUT_MINMOVES:
1068 return source->value.minmoves;
1069 case VUT_MINHP:
1070 return source->value.min_hit_points;
1071 case VUT_AGE:
1072 return source->value.age;
1073 case VUT_FORM_AGE:
1074 return source->value.form_age;
1075 case VUT_MINTECHS:
1076 return source->value.min_techs;
1077 case VUT_FUTURETECHS:
1078 return source->value.future_techs;
1079 case VUT_MINCITIES:
1080 return source->value.min_cities;
1081 case VUT_ACTION:
1082 return action_number(source->value.action);
1083 case VUT_OTYPE:
1084 return source->value.outputtype;
1085 case VUT_SPECIALIST:
1086 return specialist_number(source->value.specialist);
1087 case VUT_MINSIZE:
1088 return source->value.minsize;
1089 case VUT_MINCULTURE:
1090 return source->value.minculture;
1091 case VUT_MINFOREIGNPCT:
1092 return source->value.minforeignpct;
1093 case VUT_AI_LEVEL:
1094 return source->value.ai_level;
1096 return source->value.max_tile_total_units;
1098 return source->value.max_tile_top_units;
1099 case VUT_TERRAINCLASS:
1100 return source->value.terrainclass;
1101 case VUT_ROADFLAG:
1102 return source->value.roadflag;
1103 case VUT_EXTRAFLAG:
1104 return source->value.extraflag;
1105 case VUT_MINYEAR:
1106 return source->value.minyear;
1107 case VUT_MINCALFRAG:
1108 return source->value.mincalfrag;
1109 case VUT_TOPO:
1110 return source->value.topo_property;
1111 case VUT_WRAP:
1112 return source->value.wrap_property;
1113 case VUT_SERVERSETTING:
1114 return source->value.ssetval;
1115 case VUT_TERRAINALTER:
1116 return source->value.terrainalter;
1117 case VUT_CITYTILE:
1118 return source->value.citytile;
1119 case VUT_CITYSTATUS:
1120 return source->value.citystatus;
1121 case VUT_PLAYER_STATE:
1122 return source->value.plrstate;
1123 case VUT_COUNTER:
1124 return counter_id(source->value.counter);
1125 case VUT_MINLATITUDE:
1126 case VUT_MAXLATITUDE:
1127 return source->value.latitude;
1129 return source->value.distance_sq;
1131 return source->value.region_tiles;
1132 case VUT_TILE_REL:
1133 return source->value.tilerel;
1134 case VUT_COUNT:
1135 break;
1136 }
1137
1138 /* If we reach here there's been an error. */
1139 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
1140 source->kind);
1141 return 0;
1142}
1143
1144
1145/**********************************************************************/
1149{
1150 static const struct req_context empty = {};
1151 return &empty;
1152}
1153
1154
1155/**********************************************************************/
1163const char *req_to_fstring(const struct requirement *req,
1164 struct astring *astr)
1165{
1166 astr_init(astr);
1167
1168 astr_set(astr, "%s%s %s %s%s",
1169 req->survives ? "surviving " : "",
1170 req_range_name(req->range),
1172 req->present ? "" : "!",
1174
1175 return astr_str(astr);
1176}
1177
1178/**********************************************************************/
1186 bool survives, bool present, bool quiet,
1187 const char *value)
1188{
1189 struct requirement req;
1190 bool invalid;
1191 const char *error = nullptr;
1192
1193 req.source = universal_by_rule_name(type, value);
1194
1196 if (invalid) {
1197 error = "bad type or name";
1198 } else {
1199 /* Scan the range string to find the range. If no range is given a
1200 * default fallback is used rather than giving an error. */
1201 if (range != nullptr) {
1203 if (!req_range_is_valid(req.range)) {
1204 invalid = TRUE;
1205 }
1206 } else {
1207 switch (req.source.kind) {
1208 case VUT_NONE:
1209 case VUT_COUNT:
1210 break;
1211 case VUT_IMPROVEMENT:
1212 case VUT_SITE:
1213 case VUT_IMPR_GENUS:
1214 case VUT_IMPR_FLAG:
1215 case VUT_UTYPE:
1216 case VUT_UTFLAG:
1217 case VUT_UCLASS:
1218 case VUT_UCFLAG:
1219 case VUT_MINVETERAN:
1220 case VUT_UNITSTATE:
1221 case VUT_ACTIVITY:
1222 case VUT_MINMOVES:
1223 case VUT_MINHP:
1224 case VUT_AGE:
1225 case VUT_FORM_AGE:
1226 case VUT_ACTION:
1227 case VUT_OTYPE:
1228 case VUT_SPECIALIST:
1229 case VUT_DIPLREL_TILE_O:
1231 req.range = REQ_RANGE_LOCAL;
1232 break;
1233 case VUT_EXTRA:
1234 case VUT_TILEDEF:
1235 case VUT_ROADFLAG:
1236 case VUT_EXTRAFLAG:
1237 /* Keep old behavior */
1238 req.range = REQ_RANGE_TILE;
1239 break;
1240 case VUT_TERRAIN:
1241 case VUT_TERRFLAG:
1242 case VUT_TERRAINCLASS:
1243 case VUT_TERRAINALTER:
1244 case VUT_CITYTILE:
1247 case VUT_MINLATITUDE:
1248 case VUT_MAXLATITUDE:
1250 req.range = REQ_RANGE_TILE;
1251 break;
1252 case VUT_COUNTER:
1253 case VUT_MINSIZE:
1254 case VUT_MINCULTURE:
1255 case VUT_MINFOREIGNPCT:
1256 case VUT_NATIONALITY:
1257 case VUT_ORIGINAL_OWNER:
1258 case VUT_CITYSTATUS:
1259 case VUT_GOOD:
1260 req.range = REQ_RANGE_CITY;
1261 break;
1262 case VUT_GOVERNMENT:
1263 case VUT_GOVFLAG:
1264 case VUT_ACHIEVEMENT:
1265 case VUT_STYLE:
1266 case VUT_ADVANCE:
1267 case VUT_TECHFLAG:
1268 case VUT_NATION:
1269 case VUT_NATIONGROUP:
1270 case VUT_DIPLREL:
1271 case VUT_DIPLREL_TILE:
1273 case VUT_AI_LEVEL:
1274 case VUT_PLAYER_FLAG:
1275 case VUT_PLAYER_STATE:
1276 case VUT_MINCITIES:
1277 case VUT_FUTURETECHS:
1278 req.range = REQ_RANGE_PLAYER;
1279 break;
1280 case VUT_MINYEAR:
1281 case VUT_MINCALFRAG:
1282 case VUT_TOPO:
1283 case VUT_WRAP:
1284 case VUT_MINTECHS:
1285 case VUT_SERVERSETTING:
1286 req.range = REQ_RANGE_WORLD;
1287 break;
1290 break;
1291 case VUT_TILE_REL:
1292 req.range = REQ_RANGE_TILE;
1294 /* Not available at Tile range */
1296 }
1297 break;
1298 }
1299 }
1300
1301 req.survives = survives;
1302 req.present = present;
1303 req.quiet = quiet;
1304
1305 /* These checks match what combinations are supported inside
1306 * is_req_active(). However, it's only possible to do basic checks,
1307 * not anything that might depend on the rest of the ruleset which
1308 * might not have been loaded yet. */
1309 switch (req.source.kind) {
1310 case VUT_TERRAIN:
1311 case VUT_TERRAINCLASS:
1312 case VUT_TERRFLAG:
1313 invalid = (req.range != REQ_RANGE_TILE
1314 && req.range != REQ_RANGE_CADJACENT
1315 && req.range != REQ_RANGE_ADJACENT
1316 && req.range != REQ_RANGE_CITY
1317 && req.range != REQ_RANGE_TRADE_ROUTE);
1318 break;
1319 case VUT_EXTRA:
1320 case VUT_ROADFLAG:
1321 case VUT_EXTRAFLAG:
1323 break;
1324 case VUT_TILEDEF:
1326 || req.range == REQ_RANGE_LOCAL);
1327 break;
1328 case VUT_ACHIEVEMENT:
1329 case VUT_MINTECHS:
1330 case VUT_FUTURETECHS:
1331 invalid = (req.range < REQ_RANGE_PLAYER);
1332 break;
1333 case VUT_ADVANCE:
1334 case VUT_TECHFLAG:
1336 && req.range != REQ_RANGE_LOCAL);
1337 break;
1338 case VUT_GOVERNMENT:
1339 case VUT_GOVFLAG:
1340 case VUT_AI_LEVEL:
1341 case VUT_STYLE:
1342 case VUT_MINCITIES:
1343 invalid = (req.range != REQ_RANGE_PLAYER);
1344 break;
1345 case VUT_MINSIZE:
1346 case VUT_MINFOREIGNPCT:
1347 case VUT_NATIONALITY:
1348 case VUT_CITYSTATUS:
1349 invalid = (req.range != REQ_RANGE_CITY
1350 && req.range != REQ_RANGE_TRADE_ROUTE);
1351 break;
1352 case VUT_GOOD:
1353 case VUT_ORIGINAL_OWNER:
1354 invalid = (req.range != REQ_RANGE_CITY);
1355 break;
1356 case VUT_MINCULTURE:
1357 invalid = (req.range != REQ_RANGE_CITY
1359 && req.range != REQ_RANGE_PLAYER
1360 && req.range != REQ_RANGE_TEAM
1361 && req.range != REQ_RANGE_ALLIANCE
1362 && req.range != REQ_RANGE_WORLD);
1363 break;
1364 case VUT_DIPLREL:
1365 invalid = (req.range != REQ_RANGE_LOCAL
1366 && req.range != REQ_RANGE_PLAYER
1367 && req.range != REQ_RANGE_TEAM
1368 && req.range != REQ_RANGE_ALLIANCE
1369 && req.range != REQ_RANGE_WORLD)
1370 /* Non local foreign makes no sense. */
1371 || (req.source.value.diplrel == DRO_FOREIGN
1372 && req.range != REQ_RANGE_LOCAL);
1373 break;
1374 case VUT_DIPLREL_TILE:
1375 invalid = (req.range != REQ_RANGE_LOCAL
1376 && req.range != REQ_RANGE_PLAYER
1377 && req.range != REQ_RANGE_TEAM
1378 && req.range != REQ_RANGE_ALLIANCE)
1379 /* Non local foreign makes no sense. */
1380 || (req.source.value.diplrel == DRO_FOREIGN
1381 && req.range != REQ_RANGE_LOCAL);
1382 break;
1383 case VUT_DIPLREL_TILE_O:
1384 invalid = (req.range != REQ_RANGE_LOCAL);
1385 break;
1387 invalid = (req.range != REQ_RANGE_LOCAL
1388 && req.range != REQ_RANGE_PLAYER
1389 && req.range != REQ_RANGE_TEAM
1390 && req.range != REQ_RANGE_ALLIANCE)
1391 /* Non local foreign makes no sense. */
1392 || (req.source.value.diplrel == DRO_FOREIGN
1393 && req.range != REQ_RANGE_LOCAL);
1394 break;
1396 invalid = (req.range != REQ_RANGE_LOCAL);
1397 break;
1398 case VUT_NATION:
1399 case VUT_NATIONGROUP:
1401 && req.range != REQ_RANGE_TEAM
1402 && req.range != REQ_RANGE_ALLIANCE
1403 && req.range != REQ_RANGE_WORLD);
1404 break;
1405 case VUT_MINVETERAN:
1406 case VUT_UNITSTATE:
1407 case VUT_ACTIVITY:
1408 case VUT_MINMOVES:
1409 case VUT_MINHP:
1410 case VUT_ACTION:
1411 case VUT_OTYPE:
1412 case VUT_SPECIALIST:
1413 invalid = (req.range != REQ_RANGE_LOCAL);
1414 break;
1415 case VUT_UTYPE:
1416 case VUT_UTFLAG:
1417 case VUT_UCLASS:
1418 case VUT_UCFLAG:
1419 invalid = (req.range != REQ_RANGE_LOCAL
1420 && req.range != REQ_RANGE_TILE
1421 && req.range != REQ_RANGE_CADJACENT
1422 && req.range != REQ_RANGE_ADJACENT);
1423 break;
1424 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1426 invalid = (req.range != REQ_RANGE_TILE);
1427 break;
1428 case VUT_CITYTILE:
1431 invalid = (req.range != REQ_RANGE_TILE
1432 && req.range != REQ_RANGE_CADJACENT
1433 && req.range != REQ_RANGE_ADJACENT);
1434 break;
1435 case VUT_MINLATITUDE:
1436 case VUT_MAXLATITUDE:
1437 invalid = (req.range != REQ_RANGE_TILE
1438 && req.range != REQ_RANGE_CADJACENT
1439 && req.range != REQ_RANGE_ADJACENT
1440 && req.range != REQ_RANGE_WORLD)
1441 /* Avoid redundancy at tile range: no negated requirements
1442 * that could be emulated by a present requirement of the
1443 * other type */
1444 || (req.range == REQ_RANGE_TILE && !req.present);
1445 break;
1446 case VUT_MINYEAR:
1447 case VUT_MINCALFRAG:
1448 case VUT_TOPO:
1449 case VUT_WRAP:
1450 case VUT_SERVERSETTING:
1451 invalid = (req.range != REQ_RANGE_WORLD);
1452 break;
1453 case VUT_AGE:
1454 /* FIXME: Could support TRADE_ROUTE, TEAM, etc */
1455 invalid = (req.range != REQ_RANGE_LOCAL
1456 && req.range != REQ_RANGE_CITY
1457 && req.range != REQ_RANGE_PLAYER);
1458 break;
1459 case VUT_FORM_AGE:
1460 invalid = (req.range != REQ_RANGE_LOCAL);
1461 break;
1462 case VUT_IMPR_GENUS:
1463 /* TODO: Support other ranges too. */
1464 invalid = (req.range != REQ_RANGE_LOCAL);
1465 break;
1466 case VUT_IMPR_FLAG:
1467 invalid = (req.range != REQ_RANGE_LOCAL
1468 && req.range != REQ_RANGE_TILE
1469 && req.range != REQ_RANGE_CITY);
1470 break;
1471 case VUT_COUNTER:
1472 invalid = req.range != REQ_RANGE_CITY;
1473 break;
1474 case VUT_PLAYER_FLAG:
1475 case VUT_PLAYER_STATE:
1476 invalid = (req.range != REQ_RANGE_PLAYER);
1477 break;
1480 && req.range != REQ_RANGE_CADJACENT
1481 && req.range != REQ_RANGE_ADJACENT);
1482 break;
1483 case VUT_TILE_REL:
1485 && req.range != REQ_RANGE_CADJACENT
1486 && req.range != REQ_RANGE_TILE)
1487 /* TREL_ONLY_OTHER_REGION not supported at Tile range */
1489 && req.range == REQ_RANGE_TILE);
1490 break;
1491 case VUT_IMPROVEMENT:
1492 case VUT_SITE:
1493 /* Valid ranges depend on the building genus (wonder/improvement),
1494 * which might not have been loaded from the ruleset yet.
1495 * So we allow anything here, and do a proper check once ruleset
1496 * loading is complete, in sanity_check_req_individual(). */
1497 case VUT_NONE:
1498 invalid = FALSE;
1499 break;
1500 case VUT_COUNT:
1501 break;
1502 }
1503 if (invalid) {
1504 error = "bad range";
1505 }
1506 }
1507
1508 if (!invalid) {
1509 /* Check 'survives'. */
1510 switch (req.source.kind) {
1511 case VUT_IMPROVEMENT:
1512 case VUT_SITE:
1513 /* See buildings_in_range(). */
1515 break;
1516 case VUT_NATION:
1517 case VUT_ADVANCE:
1519 break;
1520 case VUT_COUNTER:
1521 case VUT_IMPR_GENUS:
1522 case VUT_IMPR_FLAG:
1523 case VUT_PLAYER_FLAG:
1524 case VUT_PLAYER_STATE:
1525 case VUT_GOVERNMENT:
1526 case VUT_GOVFLAG:
1527 case VUT_TERRAIN:
1528 case VUT_UTYPE:
1529 case VUT_UTFLAG:
1530 case VUT_UCLASS:
1531 case VUT_UCFLAG:
1532 case VUT_MINVETERAN:
1533 case VUT_UNITSTATE:
1534 case VUT_ACTIVITY:
1535 case VUT_MINMOVES:
1536 case VUT_MINHP:
1537 case VUT_AGE:
1538 case VUT_FORM_AGE:
1539 case VUT_ACTION:
1540 case VUT_OTYPE:
1541 case VUT_SPECIALIST:
1542 case VUT_MINSIZE:
1543 case VUT_MINCULTURE:
1544 case VUT_MINFOREIGNPCT:
1545 case VUT_AI_LEVEL:
1546 case VUT_TERRAINCLASS:
1547 case VUT_MINYEAR:
1548 case VUT_MINCALFRAG:
1549 case VUT_TOPO:
1550 case VUT_WRAP:
1551 case VUT_SERVERSETTING:
1552 case VUT_TERRAINALTER:
1553 case VUT_CITYTILE:
1554 case VUT_CITYSTATUS:
1555 case VUT_TERRFLAG:
1556 case VUT_NATIONALITY:
1557 case VUT_ORIGINAL_OWNER:
1558 case VUT_ROADFLAG:
1559 case VUT_EXTRAFLAG:
1560 case VUT_EXTRA:
1561 case VUT_TILEDEF:
1562 case VUT_GOOD:
1563 case VUT_TECHFLAG:
1564 case VUT_ACHIEVEMENT:
1565 case VUT_NATIONGROUP:
1566 case VUT_STYLE:
1567 case VUT_DIPLREL:
1568 case VUT_DIPLREL_TILE:
1569 case VUT_DIPLREL_TILE_O:
1574 case VUT_MINTECHS:
1575 case VUT_FUTURETECHS:
1576 case VUT_MINCITIES:
1577 case VUT_MINLATITUDE:
1578 case VUT_MAXLATITUDE:
1581 case VUT_TILE_REL:
1582 /* Most requirements don't support 'survives'. */
1583 invalid = survives;
1584 break;
1585 case VUT_NONE:
1586 case VUT_COUNT:
1587 break;
1588 }
1589 if (invalid) {
1590 error = "bad 'survives'";
1591 }
1592 }
1593
1594 if (invalid) {
1595 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1596 type, range, survives ? "survives" : "",
1597 present ? "present" : "", value, error);
1599 }
1600
1601 return req;
1602}
1603
1604/**********************************************************************/
1610 int value)
1611{
1612 struct requirement req;
1613
1614 req.source = universal_by_number(type, value);
1615 req.range = range;
1616 req.survives = survives;
1617 req.present = present;
1618 req.quiet = quiet;
1619
1620 return req;
1621}
1622
1623/**********************************************************************/
1627void req_get_values(const struct requirement *req,
1628 int *type, int *range,
1629 bool *survives, bool *present, bool *quiet,
1630 int *value)
1631{
1632 universal_extraction(&req->source, type, value);
1633 *range = req->range;
1634 *survives = req->survives;
1635 *present = req->present;
1636 *quiet = req->quiet;
1637}
1638
1639/**********************************************************************/
1642void req_copy(struct requirement *dst, const struct requirement *src)
1643{
1644 universal_copy(&(dst->source), &(src->source));
1645 dst->range = src->range;
1646 dst->survives = src->survives;
1647 dst->present = src->present;
1648 dst->quiet = src->quiet;
1649}
1650
1651/**********************************************************************/
1655bool are_requirements_equal(const struct requirement *req1,
1656 const struct requirement *req2)
1657{
1658 return (are_universals_equal(&req1->source, &req2->source)
1659 && req1->range == req2->range
1660 && req1->survives == req2->survives
1661 && req1->present == req2->present);
1662}
1663
1664/**********************************************************************/
1667static bool are_requirements_opposites(const struct requirement *req1,
1668 const struct requirement *req2)
1669{
1670 return (are_universals_equal(&req1->source, &req2->source)
1671 && req1->range == req2->range
1672 && req1->survives == req2->survives
1673 && req1->present != req2->present);
1674}
1675
1676/**********************************************************************/
1680static bool impr_contra_genus(const struct requirement *impr_req,
1681 const struct requirement *genus_req)
1682{
1683 /* The input is sane. */
1685 || impr_req->source.kind == VUT_SITE, FALSE);
1687
1688 if (impr_req->range == REQ_RANGE_LOCAL
1689 && genus_req->range == REQ_RANGE_LOCAL) {
1690 /* Applies to the same target building. */
1691
1692 if (impr_req->present && !genus_req->present) {
1693 /* The target building can't not have the genus it has. */
1694 return (impr_req->source.value.building->genus
1695 == genus_req->source.value.impr_genus);
1696 }
1697
1698 if (impr_req->present && genus_req->present) {
1699 /* The target building can't have another genus than it has. */
1700 return (impr_req->source.value.building->genus
1701 != genus_req->source.value.impr_genus);
1702 }
1703 }
1704
1705 /* No special knowledge. */
1706 return FALSE;
1707}
1708
1709/**********************************************************************/
1713static bool impr_contra_flag(const struct requirement *impr_req,
1714 const struct requirement *flag_req)
1715{
1716 /* The input is sane. */
1718 || impr_req->source.kind == VUT_SITE, FALSE);
1720
1721 if (impr_req->range == REQ_RANGE_LOCAL
1722 && flag_req->range == REQ_RANGE_LOCAL) {
1723 /* Applies to the same target building. */
1724
1725 if (impr_req->present && !flag_req->present) {
1726 /* The target building can't not have the flag it has. */
1727 return improvement_has_flag(impr_req->source.value.building,
1728 flag_req->source.value.impr_flag);
1729 }
1730
1731 if (impr_req->present && flag_req->present) {
1732 /* The target building can't have another flag than it has. */
1733 return !improvement_has_flag(impr_req->source.value.building,
1734 flag_req->source.value.impr_flag);
1735 }
1736 }
1737
1738 /* No special knowledge. */
1739 return FALSE;
1740}
1741
1742/**********************************************************************/
1747 const struct requirement *group_req)
1748{
1749 /* The input is sane. */
1750 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1752
1753 if (nation_req->range == REQ_RANGE_PLAYER
1754 && group_req->range == REQ_RANGE_PLAYER) {
1755 /* Applies to the same target building. */
1756
1757 if (nation_req->present && !group_req->present) {
1758 /* The target nation can't be in the group. */
1759 return nation_is_in_group(nation_req->source.value.nation,
1760 group_req->source.value.nationgroup);
1761 }
1762 }
1763
1764 /* No special knowledge. */
1765 return FALSE;
1766}
1767
1768/**********************************************************************/
1772static bool city_center_contra(const struct requirement *cc_req,
1773 const struct requirement *ct_req)
1774{
1775 /* The input is sane. */
1776 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1777 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1778
1779 if (cc_req->source.value.citytile == CITYT_CENTER
1780 && cc_req->present && cc_req->range <= ct_req->range) {
1781 switch (ct_req->source.value.citytile) {
1782 case CITYT_CENTER:
1783 case CITYT_CLAIMED:
1784 case CITYT_EXTRAS_OWNED:
1785 case CITYT_WORKED:
1787 /* Should be always on city center */
1788 return !ct_req->present;
1790 /* Handled later */
1791 break;
1792 case CITYT_LAST:
1793 /* Error */
1794 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1795 }
1796 }
1797 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1798 || cc_req->source.value.citytile == CITYT_CENTER)
1799 && ct_req->source.value.citytile
1801 && REQ_RANGE_TILE == cc_req->range
1802 && REQ_RANGE_TILE == ct_req->range) {
1803 /* Can't coexist */
1804 return cc_req->present ? ct_req->present : !ct_req->present;
1805 }
1806
1807 return FALSE;
1808}
1809
1810/**********************************************************************/
1815static bool present_implies_not_present(const struct requirement *req1,
1816 const struct requirement *req2)
1817{
1818 const struct requirement *absent, *present;
1819
1820 if (req1->present == req2->present) {
1821 /* Can't use the knowledge in universal_found_function when both are
1822 * required to be absent or when both are required to be present.
1823 * It is no contradiction to require !Spy unit and !Missile unit class.
1824 * It is no contradiction to require River and Irrigation at the same
1825 * tile. */
1826 return FALSE;
1827 }
1828
1829 if (req1->present) {
1830 absent = req2;
1831 present = req1;
1832 } else {
1833 absent = req1;
1834 present = req2;
1835 }
1836
1837 if (!universal_found_function[present->source.kind]) {
1838 /* No knowledge to exploit. */
1839 return FALSE;
1840 }
1841
1842 if (present->range != absent->range) {
1843 /* Larger ranges are not always strict supersets of smaller ranges.
1844 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1845 * but not in Trade Route. */
1846 return FALSE;
1847 }
1848
1850 &present->source);
1851}
1852
1853/**********************************************************************/
1856bool req_implies_req(const struct requirement *req1,
1857 const struct requirement *req2)
1858{
1859 struct requirement nreq2;
1860
1861 req_copy(&nreq2, req2);
1862 nreq2.present = !nreq2.present;
1864}
1865
1866/**********************************************************************/
1871static inline bool are_bounds_contradictions(int bound1, bool is_upper1,
1872 int bound2, bool is_upper2)
1873{
1874 /* If the bounds are on opposite sides, and one is inclusive, the other
1875 * exclusive, the number of values that satisfy both bounds is exactly
1876 * their difference, (upper bound) - (lower bound).
1877 * The bounds contradict each other iff this difference is 0 or less,
1878 * i.e. iff (upper bound) <= (lower bound) */
1879 if (is_upper1 && !is_upper2) {
1880 return bound1 <= bound2;
1881 } else if (!is_upper1 && is_upper2) {
1882 return bound1 >= bound2;
1883 }
1884 /* Both are upper or both are lower ~> no contradiction possible */
1885 return FALSE;
1886}
1887
1888/**********************************************************************/
1896 const struct requirement *req2)
1897{
1898 if (are_requirements_opposites(req1, req2)) {
1899 /* The exact opposite. */
1900 return TRUE;
1901 }
1902
1903 if (present_implies_not_present(req1, req2)) {
1904 return TRUE;
1905 }
1906
1907 switch (req1->source.kind) {
1908 case VUT_IMPROVEMENT:
1909 case VUT_SITE:
1910 if (req2->source.kind == VUT_IMPR_GENUS) {
1911 return impr_contra_genus(req1, req2);
1912 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1913 return impr_contra_flag(req1, req2);
1914 } else if (req2->source.kind == VUT_CITYTILE
1915 && req2->source.value.citytile == CITYT_CENTER
1916 && REQ_RANGE_TILE == req2->range
1917 && REQ_RANGE_TILE == req1->range
1918 && req1->present) {
1919 /* A building must be in a city */
1920 return !req2->present;
1921 }
1922
1923 /* No special knowledge. */
1924 return FALSE;
1925 case VUT_IMPR_GENUS:
1926 if (req2->source.kind == VUT_IMPROVEMENT
1927 || req2->source.kind == VUT_SITE) {
1928 return impr_contra_genus(req2, req1);
1929 }
1930
1931 /* No special knowledge. */
1932 return FALSE;
1933 case VUT_IMPR_FLAG:
1934 if (req2->source.kind == VUT_IMPROVEMENT
1935 || req2->source.kind == VUT_SITE) {
1936 return impr_contra_flag(req2, req1);
1937 }
1938
1939 /* No special knowledge. */
1940 return FALSE;
1941 case VUT_DIPLREL:
1942 case VUT_DIPLREL_TILE:
1943 case VUT_DIPLREL_TILE_O:
1946 if (req2->source.kind != req1->source.kind) {
1947 /* Finding contradictions across requirement kinds aren't supported
1948 * for DiplRel requirements. */
1949 return FALSE;
1950 } else {
1951 /* Use the special knowledge about DiplRel requirements to find
1952 * contradictions. */
1953
1955 int req2_pos;
1956
1959 req2->range,
1960 req2->present);
1961
1962 return BV_ISSET(req1_contra, req2_pos);
1963 }
1964 break;
1965 case VUT_MINMOVES:
1966 if (req2->source.kind != VUT_MINMOVES) {
1967 /* Finding contradictions across requirement kinds aren't supported
1968 * for MinMoveFrags requirements. */
1969 return FALSE;
1970 }
1972 req1->source.value.minmoves, !req1->present,
1973 req2->source.value.minmoves, !req2->present);
1974 case VUT_MINLATITUDE:
1975 case VUT_MAXLATITUDE:
1976 if (req2->source.kind != VUT_MINLATITUDE
1977 && req2->source.kind != VUT_MAXLATITUDE) {
1978 /* Finding contradictions across requirement kinds other than each
1979 * other is not supported for MinLatitude and MaxLatitude. */
1980 return FALSE;
1981 } else {
1982 /* For a contradiction, we need
1983 * - a minimum (present MinLatitude or negated MaxLatitude)
1984 * - a maximum (negated MinLatitude or present MaxLatitude)
1985 * - the maximum to be less than the minimum
1986 * - a requirement at the larger range that applies to the entire
1987 * range (i.e. a negated requirement, unless the range is Tile)
1988 * Otherwise, the two requirements could still be fulfilled
1989 * simultaneously by different tiles in the range */
1990
1991 /* Initial values beyond the boundaries to avoid edge cases */
1992 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
1994
1995#define EXTRACT_INFO(req) \
1996 if (req->present) { \
1997 if (req->source.kind == VUT_MINLATITUDE) { \
1998 /* present MinLatitude */ \
1999 minimum = MAX(minimum, req->source.value.latitude); \
2000 } else { \
2001 /* present MaxLatitude */ \
2002 maximum = MIN(maximum, req->source.value.latitude); \
2003 } \
2004 } else { \
2005 covered_range = MAX(covered_range, req->range); \
2006 if (req->source.kind == VUT_MINLATITUDE) { \
2007 /* negated MinLatitude */ \
2008 maximum = MIN(maximum, req->source.value.latitude - 1); \
2009 } else { \
2010 /* negated MaxLatitude */ \
2011 minimum = MAX(minimum, req->source.value.latitude + 1); \
2012 } \
2013 }
2014
2015 EXTRACT_INFO(req1);
2016 EXTRACT_INFO(req2);
2017
2018#undef EXTRACT_INFO
2019
2020 return (maximum < minimum
2021 && covered_range >= req1->range
2022 && covered_range >= req2->range);
2023 }
2024 break;
2025 case VUT_NATION:
2026 if (req2->source.kind == VUT_NATIONGROUP) {
2027 return nation_contra_group(req1, req2);
2028 }
2029
2030 /* No special knowledge. */
2031 return FALSE;
2032 break;
2033 case VUT_NATIONGROUP:
2034 if (req2->source.kind == VUT_NATION) {
2035 return nation_contra_group(req2, req1);
2036 }
2037
2038 /* No special knowledge. */
2039 return FALSE;
2040 break;
2041 case VUT_CITYTILE:
2042 if (req2->source.kind == VUT_CITYTILE) {
2043 return city_center_contra(req1, req2)
2044 || city_center_contra(req2, req1);
2045 } else if (req1->source.value.citytile == CITYT_CENTER
2046 && (req2->source.kind == VUT_IMPROVEMENT
2047 || req2->source.kind == VUT_SITE)
2048 && REQ_RANGE_TILE == req2->range
2049 && REQ_RANGE_TILE == req1->range
2050 && req2->present) {
2051 /* A building must be in a city */
2052 return !req1->present;
2053 }
2054
2055 return FALSE;
2057 if (req2->source.kind != VUT_MAX_DISTANCE_SQ) {
2058 /* Finding contradictions across requirement kinds isn't supported
2059 * for MaxDistanceSq requirements. */
2060 return FALSE;
2061 }
2063 req1->source.value.distance_sq, req1->present,
2064 req2->source.value.distance_sq, req2->present);
2066 if (req2->source.kind != VUT_MAX_REGION_TILES) {
2067 /* Finding contradictions across requirement kinds isn't supported
2068 * for MaxRegionTiles requirements. */
2069 return FALSE;
2070 } else if (req1->range != req2->range) {
2071 /* FIXME: Finding contradictions across ranges not yet supported.
2072 * In particular, a max at a small range and a min at a larger range
2073 * needs extra work to figure out. */
2074 return FALSE;
2075 }
2077 req1->source.value.region_tiles, req1->present,
2078 req2->source.value.region_tiles, req2->present);
2079 case VUT_TILE_REL:
2080 if (req2->source.kind != VUT_TILE_REL) {
2081 /* Finding contradictions across requirement kinds isn't supported
2082 * for TileRel requirements. */
2083 return FALSE;
2084 }
2085 if (req1->source.value.tilerel == req2->source.value.tilerel) {
2086 /* Same requirement at different ranges. Note that same range is
2087 * already covered by are_requirements_opposites() above. */
2088 switch (req1->source.value.tilerel) {
2089 case TREL_SAME_TCLASS:
2090 case TREL_SAME_REGION:
2092 /* Negated req at larger range contradicts present req at
2093 * smaller range. */
2094 if (req1->range > req2->range) {
2095 return !req1->present && req2->present;
2096 } else {
2097 return req1->present && !req2->present;
2098 }
2099 break;
2101 /* Present req at larger range contradicts negated req at
2102 * smaller range */
2103 if (req1->range > req2->range) {
2104 return req1->present && !req2->present;
2105 } else {
2106 return !req1->present && req2->present;
2107 }
2108 break;
2109 default:
2110 return FALSE;
2111 }
2112 }
2114 && req2->source.value.tilerel == TREL_SAME_REGION) {
2115 /* Same region at any range implies same terrain class at that range
2116 * and any larger range ~> contradicts negated */
2117 return (!req1->present && req2->present
2118 && (req1->range >= req2->range));
2119 } else if (req2->source.value.tilerel == TREL_SAME_TCLASS
2120 && req1->source.value.tilerel == TREL_SAME_REGION) {
2121 /* Same as above */
2122 return (req1->present && !req2->present
2123 && (req1->range <= req2->range));
2124 } else if (req1->source.value.tilerel == TREL_REGION_SURROUNDED
2126 const struct requirement *surr, *other;
2128 surr = req1;
2129 other = req2;
2130 } else {
2131 surr = req2;
2132 other = req1;
2133 }
2134 if (surr->present && surr->range == REQ_RANGE_TILE) {
2135 /* Target tile must be part of a surrounded region
2136 * ~> not the same terrain class
2137 * ~> not the same region
2138 * ~> not touched by a third region */
2139 switch (other->source.value.tilerel) {
2140 case TREL_SAME_TCLASS:
2141 case TREL_SAME_REGION:
2142 return (other->present && other->range == REQ_RANGE_TILE);
2144 return (!other->present);
2145 default:
2146 break;
2147 }
2148 }
2149 }
2150 /* No further contradictions we can detect */
2151 return FALSE;
2152 default:
2153 /* No special knowledge exists. The requirements aren't the exact
2154 * opposite of each other per the initial check. */
2155 return FALSE;
2156 }
2157}
2158
2159/**********************************************************************/
2167struct requirement *
2169 const struct requirement_vector *vec)
2170{
2171 /* If the requirement is contradicted by any requirement in the vector it
2172 * contradicts the entire requirement vector. */
2175 return preq;
2176 }
2178
2179 /* Not a single requirement in the requirement vector is contradicted to be
2180 * the specified requirement. */
2181 return nullptr;
2182}
2183
2184/**********************************************************************/
2189 const struct requirement_vector *vec)
2190{
2191 return req_vec_first_contradiction_in_vec(req, vec) != nullptr;
2192}
2193
2194/**********************************************************************/
2197static inline bool are_tiles_in_range(const struct tile *tile1,
2198 const struct tile *tile2,
2199 enum req_range range)
2200{
2201 switch (range) {
2202 case REQ_RANGE_ADJACENT:
2204 return TRUE;
2205 }
2207 case REQ_RANGE_TILE:
2208 return same_pos(tile1, tile2);
2210 return map_distance(tile1, tile2) <= 1;
2211 case REQ_RANGE_CITY:
2213 case REQ_RANGE_LOCAL:
2215 case REQ_RANGE_PLAYER:
2216 case REQ_RANGE_TEAM:
2217 case REQ_RANGE_ALLIANCE:
2218 case REQ_RANGE_WORLD:
2219 case REQ_RANGE_COUNT:
2220 /* Invalid */
2222 }
2223 return FALSE;
2224}
2225
2226/**********************************************************************/
2229static inline bool players_in_same_range(const struct player *pplayer1,
2230 const struct player *pplayer2,
2231 enum req_range range)
2232{
2233 switch (range) {
2234 case REQ_RANGE_WORLD:
2235 return TRUE;
2236 case REQ_RANGE_ALLIANCE:
2238 case REQ_RANGE_TEAM:
2240 case REQ_RANGE_PLAYER:
2241 return pplayer1 == pplayer2;
2244 case REQ_RANGE_CITY:
2245 case REQ_RANGE_ADJACENT:
2247 case REQ_RANGE_TILE:
2248 case REQ_RANGE_LOCAL:
2249 case REQ_RANGE_COUNT:
2250 break;
2251 }
2252
2253 fc_assert_msg(FALSE, "Invalid range %d.", range);
2254 return FALSE;
2255}
2256
2257#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
2258{ \
2259 fc_assert_ret_val(req != nullptr, TRI_MAYBE); \
2260 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
2261 fc_assert(context != nullptr); \
2262 fc_assert(other_context != nullptr); \
2263}
2264
2265/**********************************************************************/
2273static enum fc_tristate
2275 const struct req_context *context,
2276 const struct req_context *other_context,
2277 const struct requirement *req)
2278{
2280
2281 return TRI_YES;
2282}
2283
2284/**********************************************************************/
2288static int num_world_buildings_total(const struct impr_type *building)
2289{
2290 if (is_great_wonder(building)) {
2291 return (great_wonder_is_built(building)
2292 || great_wonder_is_destroyed(building) ? 1 : 0);
2293 } else {
2294 log_error("World-ranged requirements are only supported for wonders.");
2295 return 0;
2296 }
2297}
2298
2299/**********************************************************************/
2302static int num_world_buildings(const struct impr_type *building)
2303{
2304 if (is_great_wonder(building)) {
2305 return (great_wonder_is_built(building) ? 1 : 0);
2306 } else {
2307 log_error("World-ranged requirements are only supported for wonders.");
2308 return 0;
2309 }
2310}
2311
2312/**********************************************************************/
2323static bool player_has_ever_built(const struct player *pplayer,
2324 const struct impr_type *building)
2325{
2326 if (is_wonder(building)) {
2327 return (wonder_is_built(pplayer, building)
2328 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2329 } else {
2330 log_error("Player-ranged requirements are only supported for wonders.");
2331 return FALSE;
2332 }
2333}
2334
2335/**********************************************************************/
2338static int num_player_buildings(const struct player *pplayer,
2339 const struct impr_type *building)
2340{
2341 if (is_wonder(building)) {
2342 return (wonder_is_built(pplayer, building) ? 1 : 0);
2343 } else {
2344 log_error("Player-ranged requirements are only supported for wonders.");
2345 return 0;
2346 }
2347}
2348
2349/**********************************************************************/
2352static int num_continent_buildings(const struct player *pplayer,
2353 int continent,
2354 const struct impr_type *building)
2355{
2356 if (is_wonder(building)) {
2357 const struct city *pcity;
2358
2359 pcity = city_from_wonder(pplayer, building);
2360 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2361 return 1;
2362 }
2363 } else {
2364 log_error("Island-ranged requirements are only supported for wonders.");
2365 }
2366 return 0;
2367}
2368
2369/**********************************************************************/
2377static enum fc_tristate
2379 const struct req_context *context,
2380 const struct req_context *other_context,
2381 const struct requirement *req)
2382{
2383 const struct impr_type *building;
2384
2385 /* Can't use this assertion, as both VUT_IMPROVEMENT and VUT_SITE
2386 * are handled here. */
2387 /* IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT); */
2388
2389 building = req->source.value.building;
2390
2391 /* Check if it's certain that the building is obsolete given the
2392 * specification we have */
2393 if (req->source.kind == VUT_IMPROVEMENT
2394 && improvement_obsolete(context->player, building, context->city)) {
2395 return TRI_NO;
2396 }
2397
2398 if (req->survives) {
2399
2400 /* Check whether condition has ever held, using cached information. */
2401 switch (req->range) {
2402 case REQ_RANGE_WORLD:
2403 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2404 case REQ_RANGE_ALLIANCE:
2405 case REQ_RANGE_TEAM:
2406 if (context->player == nullptr) {
2407 return TRI_MAYBE;
2408 }
2409 players_iterate_alive(plr2) {
2410 if (players_in_same_range(context->player, plr2, req->range)
2411 && player_has_ever_built(plr2, building)) {
2412 return TRI_YES;
2413 }
2415 return TRI_NO;
2416 case REQ_RANGE_PLAYER:
2417 if (context->player == nullptr) {
2418 return TRI_MAYBE;
2419 }
2421 building));
2424 case REQ_RANGE_CITY:
2425 case REQ_RANGE_LOCAL:
2426 case REQ_RANGE_TILE:
2428 case REQ_RANGE_ADJACENT:
2429 /* There is no sources cache for this. */
2430 log_error("Surviving requirements are only supported at "
2431 "World/Alliance/Team/Player ranges.");
2432 return TRI_NO;
2433 case REQ_RANGE_COUNT:
2434 break;
2435 }
2436
2437 } else {
2438
2439 /* Non-surviving requirement. */
2440 switch (req->range) {
2441 case REQ_RANGE_WORLD:
2442 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2443 case REQ_RANGE_ALLIANCE:
2444 case REQ_RANGE_TEAM:
2445 if (context->player == nullptr) {
2446 return TRI_MAYBE;
2447 }
2448 players_iterate_alive(plr2) {
2449 if (players_in_same_range(context->player, plr2, req->range)
2450 && num_player_buildings(plr2, building) > 0) {
2451 return TRI_YES;
2452 }
2454 return TRI_NO;
2455 case REQ_RANGE_PLAYER:
2456 if (context->player == nullptr) {
2457 return TRI_MAYBE;
2458 }
2460 building)
2461 > 0);
2463 /* At present, "Continent" effects can affect only
2464 * cities and units in cities. */
2465 if (context->player && context->city) {
2466 int continent = tile_continent(context->city->tile);
2468 continent, building)
2469 > 0);
2470 } else {
2471 return TRI_MAYBE;
2472 }
2474 if (context->city) {
2475 if (city_has_building(context->city, building)) {
2476 return TRI_YES;
2477 } else {
2478 enum fc_tristate ret = TRI_NO;
2479
2481 if (trade_partner == nullptr) {
2482 ret = TRI_MAYBE;
2483 } else if (city_has_building(trade_partner, building)) {
2484 return TRI_YES;
2485 }
2487
2488 return ret;
2489 }
2490 } else {
2491 return TRI_MAYBE;
2492 }
2493 case REQ_RANGE_CITY:
2494 if (context->city) {
2495 return BOOL_TO_TRISTATE(city_has_building(context->city, building));
2496 } else {
2497 return TRI_MAYBE;
2498 }
2499 case REQ_RANGE_LOCAL:
2500 if (context->building) {
2501 if (context->building == building) {
2502 return TRI_YES;
2503 } else {
2504 return TRI_NO;
2505 }
2506 } else {
2507 /* TODO: Other local targets */
2508 return TRI_MAYBE;
2509 }
2510 case REQ_RANGE_TILE:
2511 if (context->tile) {
2512 const struct city *pcity = tile_city(context->tile);
2513
2514 if (pcity) {
2515 return BOOL_TO_TRISTATE(city_has_building(pcity, building));
2516 } else {
2517 return TRI_NO;
2518 }
2519 } else {
2520 return TRI_MAYBE;
2521 }
2523 case REQ_RANGE_ADJACENT:
2524 case REQ_RANGE_COUNT:
2525 break;
2526 }
2527
2528 }
2529
2530 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2531 return TRI_NO;
2532}
2533
2534/**********************************************************************/
2542static enum fc_tristate
2544 const struct req_context *context,
2545 const struct req_context *other_context,
2546 const struct requirement *req)
2547{
2549
2550 return (context->building ? BOOL_TO_TRISTATE(
2551 context->building->genus
2552 == req->source.value.impr_genus)
2553 : TRI_MAYBE);
2554}
2555
2556/**********************************************************************/
2560 enum impr_flag_id flag)
2561{
2562 struct player *owner;
2563
2564 if (pcity == nullptr) {
2565 return TRI_MAYBE;
2566 }
2567
2569 city_built_iterate(pcity, impr) {
2570 if (improvement_has_flag(impr, flag)
2571 && !improvement_obsolete(owner, impr, pcity)) {
2572 return TRI_YES;
2573 }
2575
2576 return TRI_NO;
2577}
2578
2579/**********************************************************************/
2587static enum fc_tristate
2589 const struct req_context *context,
2590 const struct req_context *other_context,
2591 const struct requirement *req)
2592{
2594
2595 switch (req->range) {
2596 case REQ_RANGE_LOCAL:
2597 return (context->building
2599 req->source.value.impr_flag))
2600 : TRI_MAYBE);
2601 case REQ_RANGE_CITY:
2603 case REQ_RANGE_TILE:
2604 if (context->tile == nullptr) {
2605 return TRI_MAYBE;
2606 }
2608 req->source.value.impr_flag);
2610 case REQ_RANGE_ADJACENT:
2613 case REQ_RANGE_PLAYER:
2614 case REQ_RANGE_ALLIANCE:
2615 case REQ_RANGE_TEAM:
2616 case REQ_RANGE_WORLD:
2617 case REQ_RANGE_COUNT:
2618 break;
2619 }
2620
2621 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2622
2623 return TRI_MAYBE;
2624}
2625
2626/**********************************************************************/
2634static enum fc_tristate
2636 const struct req_context *context,
2637 const struct req_context *other_context,
2638 const struct requirement *req)
2639{
2641
2642 switch (req->range) {
2643 case REQ_RANGE_PLAYER:
2644 return (context->player != nullptr
2646 req->source.value.plr_flag))
2647 : TRI_MAYBE);
2648 case REQ_RANGE_LOCAL:
2649 case REQ_RANGE_CITY:
2650 case REQ_RANGE_TILE:
2652 case REQ_RANGE_ADJACENT:
2655 case REQ_RANGE_ALLIANCE:
2656 case REQ_RANGE_TEAM:
2657 case REQ_RANGE_WORLD:
2658 case REQ_RANGE_COUNT:
2659 break;
2660 }
2661
2662 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2663
2664 return TRI_MAYBE;
2665}
2666
2667/**********************************************************************/
2675static enum fc_tristate
2677 const struct req_context *context,
2678 const struct req_context *other_context,
2679 const struct requirement *req)
2680{
2682
2683 switch (req->range) {
2684 case REQ_RANGE_PLAYER:
2685 return (context->player != nullptr
2687 req->source.value.plrstate))
2688 : TRI_MAYBE);
2689 case REQ_RANGE_LOCAL:
2690 case REQ_RANGE_CITY:
2691 case REQ_RANGE_TILE:
2693 case REQ_RANGE_ADJACENT:
2696 case REQ_RANGE_ALLIANCE:
2697 case REQ_RANGE_TEAM:
2698 case REQ_RANGE_WORLD:
2699 case REQ_RANGE_COUNT:
2700 break;
2701 }
2702
2703 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2704
2705 return TRI_MAYBE;
2706}
2707
2708/**********************************************************************/
2716static enum fc_tristate
2718 const struct req_context *context,
2719 const struct req_context *other_context,
2720 const struct requirement *req)
2721{
2722 Tech_type_id tech;
2723
2725
2726 tech = advance_number(req->source.value.advance);
2727
2728 if (req->survives) {
2731 }
2732
2733 /* Not a 'surviving' requirement. */
2734 switch (req->range) {
2735 case REQ_RANGE_PLAYER:
2736 if (context->player != nullptr) {
2738 (research_get(context->player), tech));
2739 } else {
2740 return TRI_MAYBE;
2741 }
2742 case REQ_RANGE_TEAM:
2743 case REQ_RANGE_ALLIANCE:
2744 case REQ_RANGE_WORLD:
2745 if (context->player == nullptr) {
2746 return TRI_MAYBE;
2747 }
2748 players_iterate_alive(plr2) {
2749 if (players_in_same_range(context->player, plr2, req->range)) {
2750 if (research_invention_state(research_get(plr2), tech)
2751 == TECH_KNOWN) {
2752 return TRI_YES;
2753 }
2754 }
2756
2757 return TRI_NO;
2758 case REQ_RANGE_LOCAL:
2759 if (context->player == nullptr) {
2760 return TRI_MAYBE;
2761 }
2762 if (research_get(context->player)->researching == tech) {
2763 return TRI_YES;
2764 }
2765 return TRI_NO;
2766 case REQ_RANGE_TILE:
2768 case REQ_RANGE_ADJACENT:
2769 case REQ_RANGE_CITY:
2772 case REQ_RANGE_COUNT:
2773 break;
2774 }
2775
2776 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2777
2778 return TRI_MAYBE;
2779}
2780
2781/**********************************************************************/
2789static enum fc_tristate
2791 const struct req_context *context,
2792 const struct req_context *other_context,
2793 const struct requirement *req)
2794{
2795 enum tech_flag_id techflag;
2796
2798
2799 techflag = req->source.value.techflag;
2800
2801 switch (req->range) {
2802 case REQ_RANGE_PLAYER:
2803 if (context->player != nullptr) {
2805 techflag));
2806 } else {
2807 return TRI_MAYBE;
2808 }
2809 break;
2810 case REQ_RANGE_TEAM:
2811 case REQ_RANGE_ALLIANCE:
2812 if (context->player == nullptr) {
2813 return TRI_MAYBE;
2814 }
2815 players_iterate_alive(plr2) {
2816 if (players_in_same_range(context->player, plr2, req->range)
2817 && player_knows_techs_with_flag(plr2, techflag)) {
2818 return TRI_YES;
2819 }
2821 return TRI_NO;
2822 case REQ_RANGE_WORLD:
2823 players_iterate(pplayer) {
2824 if (player_knows_techs_with_flag(pplayer, techflag)) {
2825 return TRI_YES;
2826 }
2828
2829 return TRI_NO;
2830 case REQ_RANGE_LOCAL:
2831 if (context->player == nullptr) {
2832 return TRI_MAYBE;
2833 }
2834 if (advance_has_flag(research_get(context->player)->researching, techflag)) {
2835 return TRI_YES;
2836 }
2837 return TRI_NO;
2838 case REQ_RANGE_TILE:
2840 case REQ_RANGE_ADJACENT:
2841 case REQ_RANGE_CITY:
2844 case REQ_RANGE_COUNT:
2845 break;
2846 }
2847
2848 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2849
2850 return TRI_MAYBE;
2851}
2852
2853/**********************************************************************/
2861static enum fc_tristate
2863 const struct req_context *context,
2864 const struct req_context *other_context,
2865 const struct requirement *req)
2866{
2867 int minculture;
2868
2870
2871 minculture = req->source.value.minculture;
2872
2873 switch (req->range) {
2874 case REQ_RANGE_CITY:
2875 if (!context->city) {
2876 return TRI_MAYBE;
2877 }
2878 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2880 if (!context->city) {
2881 return TRI_MAYBE;
2882 }
2883 if (city_culture(context->city) >= minculture) {
2884 return TRI_YES;
2885 } else {
2886 enum fc_tristate ret = TRI_NO;
2887
2889 if (trade_partner == nullptr) {
2890 ret = TRI_MAYBE;
2891 } else if (city_culture(trade_partner) >= minculture) {
2892 return TRI_YES;
2893 }
2895
2896 return ret;
2897 }
2898 case REQ_RANGE_PLAYER:
2899 case REQ_RANGE_TEAM:
2900 case REQ_RANGE_ALLIANCE:
2901 case REQ_RANGE_WORLD:
2902 if (context->player == nullptr) {
2903 return TRI_MAYBE;
2904 }
2905 players_iterate_alive(plr2) {
2906 if (players_in_same_range(context->player, plr2, req->range)) {
2907 if (player_culture(plr2) >= minculture) {
2908 return TRI_YES;
2909 }
2910 }
2912 return TRI_NO;
2913 case REQ_RANGE_LOCAL:
2914 case REQ_RANGE_TILE:
2916 case REQ_RANGE_ADJACENT:
2918 case REQ_RANGE_COUNT:
2919 break;
2920 }
2921
2922 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2923
2924 return TRI_MAYBE;
2925}
2926
2927/**********************************************************************/
2935static enum fc_tristate
2937 const struct req_context *context,
2938 const struct req_context *other_context,
2939 const struct requirement *req)
2940{
2942
2944
2946
2947 switch (req->range) {
2948 case REQ_RANGE_CITY:
2949 if (!context->city) {
2950 return TRI_MAYBE;
2951 }
2953 / city_size_get(context->city);
2956 if (!context->city) {
2957 return TRI_MAYBE;
2958 }
2960 / city_size_get(context->city);
2962 return TRI_YES;
2963 } else {
2964 enum fc_tristate ret = TRI_NO;
2965
2967 if (trade_partner == nullptr) {
2968 ret = TRI_MAYBE;
2969 } else {
2973 return TRI_YES;
2974 }
2975 }
2977
2978 return ret;
2979 }
2980 case REQ_RANGE_PLAYER:
2981 case REQ_RANGE_TEAM:
2982 case REQ_RANGE_ALLIANCE:
2983 case REQ_RANGE_WORLD:
2984 case REQ_RANGE_LOCAL:
2985 case REQ_RANGE_TILE:
2987 case REQ_RANGE_ADJACENT:
2989 case REQ_RANGE_COUNT:
2990 break;
2991 }
2992
2993 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2994
2995 return TRI_MAYBE;
2996}
2997
2998/**********************************************************************/
3006static enum fc_tristate
3008 const struct req_context *context,
3009 const struct req_context *other_context,
3010 const struct requirement *req)
3011{
3012 int max_units;
3013
3015
3017
3018 /* TODO: If can't see V_INVIS -> TRI_MAYBE */
3019 switch (req->range) {
3020 case REQ_RANGE_TILE:
3021 if (!context->tile) {
3022 return TRI_MAYBE;
3023 }
3024 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
3026 if (!context->tile) {
3027 return TRI_MAYBE;
3028 }
3029 if (unit_list_size(context->tile->units) <= max_units) {
3030 return TRI_YES;
3031 }
3033 if (unit_list_size(adjc_tile->units) <= max_units) {
3034 return TRI_YES;
3035 }
3037 return TRI_NO;
3038 case REQ_RANGE_ADJACENT:
3039 if (!context->tile) {
3040 return TRI_MAYBE;
3041 }
3042 if (unit_list_size(context->tile->units) <= max_units) {
3043 return TRI_YES;
3044 }
3046 if (unit_list_size(adjc_tile->units) <= max_units) {
3047 return TRI_YES;
3048 }
3050 return TRI_NO;
3051 case REQ_RANGE_CITY:
3054 case REQ_RANGE_PLAYER:
3055 case REQ_RANGE_TEAM:
3056 case REQ_RANGE_ALLIANCE:
3057 case REQ_RANGE_WORLD:
3058 case REQ_RANGE_LOCAL:
3059 case REQ_RANGE_COUNT:
3060 break;
3061 }
3062
3063 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3064
3065 return TRI_MAYBE;
3066}
3067
3068
3069/**********************************************************************/
3077static enum fc_tristate
3079 const struct req_context *context,
3080 const struct req_context *other_context,
3081 const struct requirement *req)
3082{
3083 int max_units;
3084 int count;
3085
3087
3089
3090 /* TODO: If can't see V_INVIS -> TRI_MAYBE */
3091 switch (req->range) {
3092 case REQ_RANGE_TILE:
3093 if (!context->tile) {
3094 return TRI_MAYBE;
3095 }
3096 count = 0;
3097 unit_list_iterate(context->tile->units, punit) {
3098 if (!unit_transported(punit)) {
3099 count++;
3100 }
3102 return BOOL_TO_TRISTATE(count <= max_units);
3104 if (!context->tile) {
3105 return TRI_MAYBE;
3106 }
3107 count = 0;
3108 unit_list_iterate(context->tile->units, punit) {
3109 if (!unit_transported(punit)) {
3110 count++;
3111 }
3113 if (count <= max_units) {
3114 return TRI_YES;
3115 }
3117 count = 0;
3119 if (!unit_transported(punit)) {
3120 count++;
3121 }
3123 if (count <= max_units) {
3124 return TRI_YES;
3125 }
3127
3128 return TRI_NO;
3129 case REQ_RANGE_ADJACENT:
3130 if (!context->tile) {
3131 return TRI_MAYBE;
3132 }
3133 count = 0;
3134 unit_list_iterate(context->tile->units, punit) {
3135 if (!unit_transported(punit)) {
3136 count++;
3137 }
3139 if (count <= max_units) {
3140 return TRI_YES;
3141 }
3143 count = 0;
3145 if (!unit_transported(punit)) {
3146 count++;
3147 }
3149 if (count <= max_units) {
3150 return TRI_YES;
3151 }
3153 return TRI_NO;
3154 case REQ_RANGE_CITY:
3157 case REQ_RANGE_PLAYER:
3158 case REQ_RANGE_TEAM:
3159 case REQ_RANGE_ALLIANCE:
3160 case REQ_RANGE_WORLD:
3161 case REQ_RANGE_LOCAL:
3162 case REQ_RANGE_COUNT:
3163 break;
3164 }
3165
3166 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3167
3168 return TRI_MAYBE;
3169}
3170
3171/**********************************************************************/
3179static enum fc_tristate
3181 const struct req_context *context,
3182 const struct req_context *other_context,
3183 const struct requirement *req)
3184{
3185 const struct extra_type *pextra;
3186 enum fc_tristate ret;
3187
3189
3190 pextra = req->source.value.extra;
3191
3192 switch (req->range) {
3193 case REQ_RANGE_LOCAL:
3194 if (!context->extra) {
3195 return TRI_MAYBE;
3196 }
3197 return BOOL_TO_TRISTATE(context->extra == pextra);
3198 case REQ_RANGE_TILE:
3199 /* The requirement is filled if the tile has extra of requested type. */
3200 if (!context->tile) {
3201 return TRI_MAYBE;
3202 }
3203 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
3205 if (!context->tile) {
3206 return TRI_MAYBE;
3207 }
3208 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
3209 || is_extra_card_near(nmap, context->tile, pextra));
3210 case REQ_RANGE_ADJACENT:
3211 if (!context->tile) {
3212 return TRI_MAYBE;
3213 }
3214 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
3215 || is_extra_near_tile(nmap, context->tile, pextra));
3216 case REQ_RANGE_CITY:
3217 if (!context->city) {
3218 return TRI_MAYBE;
3219 }
3221 city_tile(context->city), ptile) {
3222 if (tile_has_extra(ptile, pextra)) {
3223 return TRI_YES;
3224 }
3226
3227 return TRI_NO;
3228
3230 if (!context->city) {
3231 return TRI_MAYBE;
3232 }
3234 city_tile(context->city), ptile) {
3235 if (tile_has_extra(ptile, pextra)) {
3236 return TRI_YES;
3237 }
3239
3240 ret = TRI_NO;
3242 if (trade_partner == nullptr) {
3243 ret = TRI_MAYBE;
3244 } else {
3246 city_tile(trade_partner), ptile) {
3247 if (tile_has_extra(ptile, pextra)) {
3248 return TRI_YES;
3249 }
3251 }
3253
3254 return ret;
3255
3257 case REQ_RANGE_PLAYER:
3258 case REQ_RANGE_TEAM:
3259 case REQ_RANGE_ALLIANCE:
3260 case REQ_RANGE_WORLD:
3261 case REQ_RANGE_COUNT:
3262 break;
3263 }
3264
3265 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3266
3267 return TRI_MAYBE;
3268}
3269
3270/**********************************************************************/
3278static enum fc_tristate
3280 const struct req_context *context,
3281 const struct req_context *other_context,
3282 const struct requirement *req)
3283{
3284 const struct tiledef *ptdef;
3285 enum fc_tristate ret;
3286
3288
3289 ptdef = req->source.value.tiledef;
3290
3291 switch (req->range) {
3292 case REQ_RANGE_TILE:
3293 /* The requirement is filled if the tile has tiledef of requested type. */
3294 if (!context->tile) {
3295 return TRI_MAYBE;
3296 }
3299 if (!context->tile) {
3300 return TRI_MAYBE;
3301 }
3304 case REQ_RANGE_ADJACENT:
3305 if (!context->tile) {
3306 return TRI_MAYBE;
3307 }
3310 case REQ_RANGE_CITY:
3311 if (!context->city) {
3312 return TRI_MAYBE;
3313 }
3315 city_tile(context->city), ptile) {
3316 if (tile_matches_tiledef(ptdef, ptile)) {
3317 return TRI_YES;
3318 }
3320
3321 return TRI_NO;
3322
3324 if (!context->city) {
3325 return TRI_MAYBE;
3326 }
3328 city_tile(context->city), ptile) {
3329 if (tile_matches_tiledef(ptdef, ptile)) {
3330 return TRI_YES;
3331 }
3333
3334 ret = TRI_NO;
3336 if (trade_partner == nullptr) {
3337 ret = TRI_MAYBE;
3338 } else {
3340 city_tile(trade_partner), ptile) {
3341 if (tile_matches_tiledef(ptdef, ptile)) {
3342 return TRI_YES;
3343 }
3345 }
3347
3348 return ret;
3349
3350 case REQ_RANGE_LOCAL:
3352 case REQ_RANGE_PLAYER:
3353 case REQ_RANGE_TEAM:
3354 case REQ_RANGE_ALLIANCE:
3355 case REQ_RANGE_WORLD:
3356 case REQ_RANGE_COUNT:
3357 break;
3358 }
3359
3360 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3361
3362 return TRI_MAYBE;
3363}
3364
3365/**********************************************************************/
3373static enum fc_tristate
3375 const struct req_context *context,
3376 const struct req_context *other_context,
3377 const struct requirement *req)
3378{
3379 const struct goods_type *pgood;
3380
3382
3383 pgood = req->source.value.good;
3384
3385 switch (req->range) {
3386 case REQ_RANGE_LOCAL:
3387 case REQ_RANGE_CITY:
3388 /* The requirement is filled if the city imports good of requested type. */
3389 if (!context->city) {
3390 return TRI_MAYBE;
3391 }
3395 nullptr)));
3396 case REQ_RANGE_TILE:
3398 case REQ_RANGE_ADJACENT:
3401 case REQ_RANGE_PLAYER:
3402 case REQ_RANGE_TEAM:
3403 case REQ_RANGE_ALLIANCE:
3404 case REQ_RANGE_WORLD:
3405 case REQ_RANGE_COUNT:
3406 break;
3407 }
3408
3409 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3410
3411 return TRI_MAYBE;
3412}
3413
3414/**********************************************************************/
3422static enum fc_tristate
3424 const struct req_context *context,
3425 const struct req_context *other_context,
3426 const struct requirement *req)
3427{
3429
3430 if (context->action) {
3431 return BOOL_TO_TRISTATE(action_number(context->action)
3432 == action_number(req->source.value.action));
3433 }
3434
3435 if (context->unit != nullptr && context->unit->action != ACTION_NONE) {
3436 log_normal("Unit action %s", action_id_rule_name(context->unit->action));
3437 return BOOL_TO_TRISTATE(context->unit->action
3438 == action_number(req->source.value.action));
3439 }
3440
3441 return TRI_NO;
3442}
3443
3444/**********************************************************************/
3452static enum fc_tristate
3454 const struct req_context *context,
3455 const struct req_context *other_context,
3456 const struct requirement *req)
3457{
3459
3460 return BOOL_TO_TRISTATE(context->output
3461 && context->output->index
3462 == req->source.value.outputtype);
3463}
3464
3465/**********************************************************************/
3473static enum fc_tristate
3475 const struct req_context *context,
3476 const struct req_context *other_context,
3477 const struct requirement *req)
3478{
3480
3481 return BOOL_TO_TRISTATE(context->specialist
3482 && context->specialist
3483 == req->source.value.specialist);
3484}
3485
3486/**********************************************************************/
3494static enum fc_tristate
3496 const struct req_context *context,
3497 const struct req_context *other_context,
3498 const struct requirement *req)
3499{
3500 const struct terrain *pterrain;
3501
3503
3504 pterrain = req->source.value.terrain;
3505
3506 switch (req->range) {
3507 case REQ_RANGE_TILE:
3508 /* The requirement is filled if the tile has the terrain. */
3509 if (!context->tile) {
3510 return TRI_MAYBE;
3511 }
3512 return pterrain && tile_terrain(context->tile) == pterrain;
3514 if (!context->tile) {
3515 return TRI_MAYBE;
3516 }
3517 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
3518 case REQ_RANGE_ADJACENT:
3519 if (!context->tile) {
3520 return TRI_MAYBE;
3521 }
3522 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
3523 case REQ_RANGE_CITY:
3524 if (!context->city) {
3525 return TRI_MAYBE;
3526 }
3527 if (pterrain != nullptr) {
3529 city_tile(context->city), ptile) {
3530 if (tile_terrain(ptile) == pterrain) {
3531 return TRI_YES;
3532 }
3534 }
3535 return TRI_NO;
3537 if (!context->city) {
3538 return TRI_MAYBE;
3539 }
3540 if (pterrain != nullptr) {
3541 enum fc_tristate ret;
3542
3544 city_tile(context->city), ptile) {
3545 if (tile_terrain(ptile) == pterrain) {
3546 return TRI_YES;
3547 }
3549
3550 ret = TRI_NO;
3552 if (trade_partner == nullptr) {
3553 ret = TRI_MAYBE;
3554 } else {
3556 city_tile(trade_partner), ptile) {
3557 if (tile_terrain(ptile) == pterrain) {
3558 return TRI_YES;
3559 }
3561 }
3563
3564 return ret;
3565 }
3566
3567 return TRI_MAYBE;
3569 case REQ_RANGE_PLAYER:
3570 case REQ_RANGE_TEAM:
3571 case REQ_RANGE_ALLIANCE:
3572 case REQ_RANGE_WORLD:
3573 case REQ_RANGE_LOCAL:
3574 case REQ_RANGE_COUNT:
3575 break;
3576 }
3577
3578 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3579
3580 return TRI_MAYBE;
3581}
3582
3583/**********************************************************************/
3591static enum fc_tristate
3593 const struct req_context *context,
3594 const struct req_context *other_context,
3595 const struct requirement *req)
3596{
3597 enum terrain_class pclass;
3598 enum fc_tristate ret;
3599
3601
3603
3604 switch (req->range) {
3605 case REQ_RANGE_TILE:
3606 /* The requirement is filled if the tile has the terrain of correct class. */
3607 if (!context->tile) {
3608 return TRI_MAYBE;
3609 }
3612 if (!context->tile) {
3613 return TRI_MAYBE;
3614 }
3617 case REQ_RANGE_ADJACENT:
3618 if (!context->tile) {
3619 return TRI_MAYBE;
3620 }
3623 case REQ_RANGE_CITY:
3624 if (!context->city) {
3625 return TRI_MAYBE;
3626 }
3628 city_tile(context->city), ptile) {
3629 const struct terrain *pterrain = tile_terrain(ptile);
3630
3631 if (pterrain != T_UNKNOWN
3632 && terrain_type_terrain_class(pterrain) == pclass) {
3633 return TRI_YES;
3634 }
3636
3637 return TRI_NO;
3639 if (!context->city) {
3640 return TRI_MAYBE;
3641 }
3643 city_tile(context->city), ptile) {
3644 const struct terrain *pterrain = tile_terrain(ptile);
3645
3646 if (pterrain != T_UNKNOWN
3647 && terrain_type_terrain_class(pterrain) == pclass) {
3648 return TRI_YES;
3649 }
3651
3652 ret = TRI_NO;
3654 if (trade_partner == nullptr) {
3655 ret = TRI_MAYBE;
3656 } else {
3658 city_tile(trade_partner), ptile) {
3659 const struct terrain *pterrain = tile_terrain(ptile);
3660
3661 if (pterrain != T_UNKNOWN
3662 && terrain_type_terrain_class(pterrain) == pclass) {
3663 return TRI_YES;
3664 }
3666 }
3668
3669 return ret;
3671 case REQ_RANGE_PLAYER:
3672 case REQ_RANGE_TEAM:
3673 case REQ_RANGE_ALLIANCE:
3674 case REQ_RANGE_WORLD:
3675 case REQ_RANGE_LOCAL:
3676 case REQ_RANGE_COUNT:
3677 break;
3678 }
3679
3680 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3681
3682 return TRI_MAYBE;
3683}
3684
3685/**********************************************************************/
3693static enum fc_tristate
3695 const struct req_context *context,
3696 const struct req_context *other_context,
3697 const struct requirement *req)
3698{
3700 enum fc_tristate ret;
3701
3703
3705
3706 switch (req->range) {
3707 case REQ_RANGE_TILE:
3708 /* The requirement is fulfilled if the tile has a terrain with
3709 * correct flag. */
3710 if (!context->tile) {
3711 return TRI_MAYBE;
3712 }
3714 terrflag));
3716 if (!context->tile) {
3717 return TRI_MAYBE;
3718 }
3720 terrflag)
3722 terrflag));
3723 case REQ_RANGE_ADJACENT:
3724 if (!context->tile) {
3725 return TRI_MAYBE;
3726 }
3728 terrflag)
3730 terrflag));
3731 case REQ_RANGE_CITY:
3732 if (!context->city) {
3733 return TRI_MAYBE;
3734 }
3736 city_tile(context->city), ptile) {
3737 const struct terrain *pterrain = tile_terrain(ptile);
3738
3739 if (pterrain != T_UNKNOWN
3740 && terrain_has_flag(pterrain, terrflag)) {
3741 return TRI_YES;
3742 }
3744
3745 return TRI_NO;
3747 if (!context->city) {
3748 return TRI_MAYBE;
3749 }
3751 city_tile(context->city), ptile) {
3752 const struct terrain *pterrain = tile_terrain(ptile);
3753
3754 if (pterrain != T_UNKNOWN
3755 && terrain_has_flag(pterrain, terrflag)) {
3756 return TRI_YES;
3757 }
3759
3760 ret = TRI_NO;
3762 if (trade_partner == nullptr) {
3763 ret = TRI_MAYBE;
3764 } else {
3766 city_tile(trade_partner), ptile) {
3767 const struct terrain *pterrain = tile_terrain(ptile);
3768
3769 if (pterrain != T_UNKNOWN
3770 && terrain_has_flag(pterrain, terrflag)) {
3771 return TRI_YES;
3772 }
3774 }
3776
3777 return ret;
3779 case REQ_RANGE_PLAYER:
3780 case REQ_RANGE_TEAM:
3781 case REQ_RANGE_ALLIANCE:
3782 case REQ_RANGE_WORLD:
3783 case REQ_RANGE_LOCAL:
3784 case REQ_RANGE_COUNT:
3785 break;
3786 }
3787
3788 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3789
3790 return TRI_MAYBE;
3791}
3792
3793/**********************************************************************/
3801static enum fc_tristate
3803 const struct req_context *context,
3804 const struct req_context *other_context,
3805 const struct requirement *req)
3806{
3807 enum road_flag_id roadflag;
3808 enum fc_tristate ret;
3809
3811
3812 roadflag = req->source.value.roadflag;
3813
3814 switch (req->range) {
3815 case REQ_RANGE_LOCAL:
3816 {
3817 if (!context->extra) {
3818 return TRI_MAYBE;
3819 }
3820 struct road_type *r = extra_road_get(context->extra);
3821
3822 return BOOL_TO_TRISTATE(
3823 r && road_has_flag(r, roadflag)
3824 );
3825 }
3826 case REQ_RANGE_TILE:
3827 /* The requirement is filled if the tile has a road with correct flag. */
3828 if (!context->tile) {
3829 return TRI_MAYBE;
3830 }
3831 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3833 if (!context->tile) {
3834 return TRI_MAYBE;
3835 }
3836 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3838 roadflag));
3839 case REQ_RANGE_ADJACENT:
3840 if (!context->tile) {
3841 return TRI_MAYBE;
3842 }
3843 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3845 roadflag));
3846 case REQ_RANGE_CITY:
3847 if (!context->city) {
3848 return TRI_MAYBE;
3849 }
3851 city_tile(context->city), ptile) {
3852 if (tile_has_road_flag(ptile, roadflag)) {
3853 return TRI_YES;
3854 }
3856
3857 return TRI_NO;
3859 if (!context->city) {
3860 return TRI_MAYBE;
3861 }
3863 city_tile(context->city), ptile) {
3864 if (tile_has_road_flag(ptile, roadflag)) {
3865 return TRI_YES;
3866 }
3868
3869 ret = TRI_NO;
3871 if (trade_partner == nullptr) {
3872 ret = TRI_MAYBE;
3873 } else {
3875 city_tile(trade_partner), ptile) {
3876 if (tile_has_road_flag(ptile, roadflag)) {
3877 return TRI_YES;
3878 }
3880 }
3882
3883 return ret;
3885 case REQ_RANGE_PLAYER:
3886 case REQ_RANGE_TEAM:
3887 case REQ_RANGE_ALLIANCE:
3888 case REQ_RANGE_WORLD:
3889 case REQ_RANGE_COUNT:
3890 break;
3891 }
3892
3893 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3894
3895 return TRI_MAYBE;
3896}
3897
3898/**********************************************************************/
3906static enum fc_tristate
3908 const struct req_context *context,
3909 const struct req_context *other_context,
3910 const struct requirement *req)
3911{
3912 enum extra_flag_id extraflag;
3913 enum fc_tristate ret;
3914
3916
3917 extraflag = req->source.value.extraflag;
3918
3919 switch (req->range) {
3920 case REQ_RANGE_LOCAL:
3921 if (!context->extra) {
3922 return TRI_MAYBE;
3923 }
3924 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3925 case REQ_RANGE_TILE:
3926 /* The requirement is filled if the tile has an extra with correct flag. */
3927 if (!context->tile) {
3928 return TRI_MAYBE;
3929 }
3930 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3932 if (!context->tile) {
3933 return TRI_MAYBE;
3934 }
3935 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3936 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3937 case REQ_RANGE_ADJACENT:
3938 if (!context->tile) {
3939 return TRI_MAYBE;
3940 }
3941 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3942 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3943 case REQ_RANGE_CITY:
3944 if (!context->city) {
3945 return TRI_MAYBE;
3946 }
3948 city_tile(context->city), ptile) {
3949 if (tile_has_extra_flag(ptile, extraflag)) {
3950 return TRI_YES;
3951 }
3953
3954 return TRI_NO;
3956 if (!context->city) {
3957 return TRI_MAYBE;
3958 }
3960 city_tile(context->city), ptile) {
3961 if (tile_has_extra_flag(ptile, extraflag)) {
3962 return TRI_YES;
3963 }
3965
3966 ret = TRI_NO;
3968 if (trade_partner == nullptr) {
3969 ret = TRI_MAYBE;
3970 } else {
3972 city_tile(trade_partner), ptile) {
3973 if (tile_has_extra_flag(ptile, extraflag)) {
3974 return TRI_YES;
3975 }
3977 }
3979
3980 return ret;
3982 case REQ_RANGE_PLAYER:
3983 case REQ_RANGE_TEAM:
3984 case REQ_RANGE_ALLIANCE:
3985 case REQ_RANGE_WORLD:
3986 case REQ_RANGE_COUNT:
3987 break;
3988 }
3989
3990 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3991
3992 return TRI_MAYBE;
3993}
3994
3995/**********************************************************************/
4003static enum fc_tristate
4005 const struct req_context *context,
4006 const struct req_context *other_context,
4007 const struct requirement *req)
4008{
4010
4012
4014
4015 if (!context->tile) {
4016 return TRI_MAYBE;
4017 }
4018
4019 switch (req->range) {
4020 case REQ_RANGE_TILE:
4024 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
4025 case REQ_RANGE_CITY:
4028 case REQ_RANGE_PLAYER:
4029 case REQ_RANGE_TEAM:
4030 case REQ_RANGE_ALLIANCE:
4031 case REQ_RANGE_WORLD:
4032 case REQ_RANGE_LOCAL:
4033 case REQ_RANGE_COUNT:
4034 break;
4035 }
4036
4037 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4038
4039 return TRI_MAYBE;
4040}
4041
4042/**********************************************************************/
4050static enum fc_tristate
4052 const struct req_context *context,
4053 const struct req_context *other_context,
4054 const struct requirement *req)
4055{
4057
4058 if (context->player == nullptr) {
4059 return TRI_MAYBE;
4060 } else {
4062 == req->source.value.govern);
4063 }
4064}
4065
4066/**********************************************************************/
4074static enum fc_tristate
4076 const struct req_context *context,
4077 const struct req_context *other_context,
4078 const struct requirement *req)
4079{
4081
4082 if (context->player == nullptr) {
4083 return TRI_MAYBE;
4084 } else {
4086 req->source.value.govflag));
4087 }
4088}
4089
4090/**********************************************************************/
4098static enum fc_tristate
4100 const struct req_context *context,
4101 const struct req_context *other_context,
4102 const struct requirement *req)
4103{
4105
4106 if (context->player == nullptr) {
4107 return TRI_MAYBE;
4108 } else {
4109 return BOOL_TO_TRISTATE(context->player->style
4110 == req->source.value.style);
4111 }
4112}
4113
4114/**********************************************************************/
4122static enum fc_tristate
4124 const struct req_context *context,
4125 const struct req_context *other_context,
4126 const struct requirement *req)
4127{
4129
4130 switch (req->range) {
4131 case REQ_RANGE_WORLD:
4132 /* "None" does not count */
4133 return ((game.info.global_advance_count - 1)
4134 >= req->source.value.min_techs);
4135 case REQ_RANGE_PLAYER:
4136 if (context->player == nullptr) {
4137 return TRI_MAYBE;
4138 } else {
4139 /* "None" does not count */
4140 return BOOL_TO_TRISTATE(
4141 (research_get(context->player)->techs_researched - 1)
4142 >= req->source.value.min_techs
4143 );
4144 }
4145 default:
4146 return TRI_MAYBE;
4147 }
4148}
4149
4150/**********************************************************************/
4158static enum fc_tristate
4160 const struct req_context *context,
4161 const struct req_context *other_context,
4162 const struct requirement *req)
4163{
4165
4166 switch (req->range) {
4167 case REQ_RANGE_WORLD:
4169 if (research_get(plr)->future_tech
4170 >= req->source.value.future_techs) {
4171 return TRI_YES;
4172 }
4174
4175 return TRI_NO;
4176 case REQ_RANGE_PLAYER:
4177 if (context->player == nullptr) {
4178 return TRI_MAYBE;
4179 } else {
4181 >= req->source.value.future_techs);
4182 }
4183 default:
4184 return TRI_MAYBE;
4185 }
4186}
4187
4188/**********************************************************************/
4196static enum fc_tristate
4198 const struct req_context *context,
4199 const struct req_context *other_context,
4200 const struct requirement *req)
4201{
4203
4204 switch (req->range) {
4205 case REQ_RANGE_PLAYER:
4206 if (context->player == nullptr) {
4207 return TRI_MAYBE;
4208 } else {
4209 /* "None" does not count */
4210 return BOOL_TO_TRISTATE(
4211 city_list_size(context->player->cities)
4212 >= req->source.value.min_cities
4213 );
4214 }
4215 default:
4216 return TRI_MAYBE;
4217 }
4218}
4219
4220/**********************************************************************/
4228static enum fc_tristate
4230 const struct req_context *context,
4231 const struct req_context *other_context,
4232 const struct requirement *req)
4233{
4235
4236 if (context->player == nullptr) {
4237 return TRI_MAYBE;
4238 } else {
4239 return BOOL_TO_TRISTATE(is_ai(context->player)
4240 && context->player->ai_common.skill_level
4241 == req->source.value.ai_level);
4242 }
4243}
4244
4245/**********************************************************************/
4253static enum fc_tristate
4255 const struct req_context *context,
4256 const struct req_context *other_context,
4257 const struct requirement *req)
4258{
4259 const struct nation_type *nation;
4260
4262
4263 nation = req->source.value.nation;
4264
4265 switch (req->range) {
4266 case REQ_RANGE_PLAYER:
4267 if (context->player == nullptr) {
4268 return TRI_MAYBE;
4269 }
4270 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
4271 case REQ_RANGE_TEAM:
4272 case REQ_RANGE_ALLIANCE:
4273 if (context->player == nullptr) {
4274 return TRI_MAYBE;
4275 }
4276 players_iterate_alive(plr2) {
4277 if (players_in_same_range(context->player, plr2, req->range)) {
4278 if (nation_of_player(plr2) == nation) {
4279 return TRI_YES;
4280 }
4281 }
4283 return TRI_NO;
4284 case REQ_RANGE_WORLD:
4285 /* NB: if a player is ever removed outright from the game
4286 * (e.g. via /remove), rather than just dying, this 'survives'
4287 * requirement will stop being true for their nation.
4288 * create_command_newcomer() can also cause this to happen. */
4289 return BOOL_TO_TRISTATE(nation->player != nullptr
4290 && (req->survives || nation->player->is_alive));
4291 case REQ_RANGE_LOCAL:
4292 case REQ_RANGE_TILE:
4294 case REQ_RANGE_ADJACENT:
4295 case REQ_RANGE_CITY:
4298 case REQ_RANGE_COUNT:
4299 break;
4300 }
4301
4302 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4303
4304 return TRI_MAYBE;
4305}
4306
4307/**********************************************************************/
4315static enum fc_tristate
4317 const struct req_context *context,
4318 const struct req_context *other_context,
4319 const struct requirement *req)
4320{
4321 const struct nation_group *ngroup;
4322
4324
4326
4327 switch (req->range) {
4328 case REQ_RANGE_PLAYER:
4329 if (context->player == nullptr) {
4330 return TRI_MAYBE;
4331 }
4333 nation_of_player(context->player), ngroup));
4334 case REQ_RANGE_TEAM:
4335 case REQ_RANGE_ALLIANCE:
4336 case REQ_RANGE_WORLD:
4337 if (context->player == nullptr) {
4338 return TRI_MAYBE;
4339 }
4340 players_iterate_alive(plr2) {
4341 if (players_in_same_range(context->player, plr2, req->range)) {
4343 return TRI_YES;
4344 }
4345 }
4347 return TRI_NO;
4348 case REQ_RANGE_LOCAL:
4349 case REQ_RANGE_TILE:
4351 case REQ_RANGE_ADJACENT:
4352 case REQ_RANGE_CITY:
4355 case REQ_RANGE_COUNT:
4356 break;
4357 }
4358
4359 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4360
4361 return TRI_MAYBE;
4362}
4363
4364/**********************************************************************/
4372static enum fc_tristate
4374 const struct req_context *context,
4375 const struct req_context *other_context,
4376 const struct requirement *req)
4377{
4378 const struct nation_type *nationality;
4379 enum fc_tristate ret;
4380
4382
4383 nationality = req->source.value.nationality;
4384
4385 switch (req->range) {
4386 case REQ_RANGE_CITY:
4387 if (context->city == nullptr) {
4388 return TRI_MAYBE;
4389 }
4390 citizens_iterate(context->city, slot, count) {
4391 if (player_slot_get_player(slot)->nation == nationality) {
4392 return TRI_YES;
4393 }
4395
4396 return TRI_NO;
4398 if (context->city == nullptr) {
4399 return TRI_MAYBE;
4400 }
4401 citizens_iterate(context->city, slot, count) {
4402 if (player_slot_get_player(slot)->nation == nationality) {
4403 return TRI_YES;
4404 }
4406
4407 ret = TRI_NO;
4409 if (trade_partner == nullptr) {
4410 ret = TRI_MAYBE;
4411 } else {
4412 citizens_iterate(trade_partner, slot, count) {
4413 if (player_slot_get_player(slot)->nation == nationality) {
4414 return TRI_YES;
4415 }
4417 }
4419
4420 return ret;
4421 case REQ_RANGE_PLAYER:
4422 case REQ_RANGE_TEAM:
4423 case REQ_RANGE_ALLIANCE:
4424 case REQ_RANGE_WORLD:
4425 case REQ_RANGE_LOCAL:
4426 case REQ_RANGE_TILE:
4428 case REQ_RANGE_ADJACENT:
4430 case REQ_RANGE_COUNT:
4431 break;
4432 }
4433
4434 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4435
4436 return TRI_MAYBE;
4437}
4438
4439/**********************************************************************/
4447static enum fc_tristate
4449 const struct req_context *context,
4450 const struct req_context *other_context,
4451 const struct requirement *req)
4452{
4453 const struct nation_type *nation;
4454
4456
4457 nation = req->source.value.origowner;
4458
4459 switch (req->range) {
4460 case REQ_RANGE_CITY:
4461 if (context->city == nullptr || context->city->original == nullptr) {
4462 return TRI_MAYBE;
4463 }
4464 if (player_nation(context->city->original) == nation) {
4465 return TRI_YES;
4466 }
4467
4468 return TRI_NO;
4470 case REQ_RANGE_PLAYER:
4471 case REQ_RANGE_TEAM:
4472 case REQ_RANGE_ALLIANCE:
4473 case REQ_RANGE_WORLD:
4474 case REQ_RANGE_LOCAL:
4475 case REQ_RANGE_TILE:
4477 case REQ_RANGE_ADJACENT:
4479 case REQ_RANGE_COUNT:
4480 break;
4481 }
4482
4483 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4484
4485 return TRI_MAYBE;
4486}
4487
4488/**********************************************************************/
4492 const struct player *other_player,
4493 enum req_range range,
4494 int diplrel)
4495{
4496 switch (range) {
4497 case REQ_RANGE_PLAYER:
4498 if (target_player == nullptr) {
4499 return TRI_MAYBE;
4500 }
4502 case REQ_RANGE_TEAM:
4503 case REQ_RANGE_ALLIANCE:
4504 case REQ_RANGE_WORLD:
4505 if (target_player == nullptr) {
4506 return TRI_MAYBE;
4507 }
4508 players_iterate_alive(plr2) {
4510 if (is_diplrel_to_other(plr2, diplrel)) {
4511 return TRI_YES;
4512 }
4513 }
4515 return TRI_NO;
4516 case REQ_RANGE_LOCAL:
4517 if (target_player == nullptr || other_player == nullptr) {
4518 return TRI_MAYBE;
4519 }
4520 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
4521 case REQ_RANGE_TILE:
4523 case REQ_RANGE_ADJACENT:
4524 case REQ_RANGE_CITY:
4527 case REQ_RANGE_COUNT:
4528 break;
4529 }
4530
4531 fc_assert_msg(FALSE, "Invalid range %d.", range);
4532
4533 return TRI_MAYBE;
4534}
4535
4536/**********************************************************************/
4544static enum fc_tristate
4546 const struct req_context *context,
4547 const struct req_context *other_context,
4548 const struct requirement *req)
4549{
4551
4552 return is_diplrel_in_range(context->player, other_context->player,
4553 req->range, req->source.value.diplrel);
4554}
4555
4556/**********************************************************************/
4564static enum fc_tristate
4566 const struct req_context *context,
4567 const struct req_context *other_context,
4568 const struct requirement *req)
4569{
4571
4572 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4573 : nullptr,
4574 context->player,
4575 req->range,
4576 req->source.value.diplrel);
4577}
4578
4579/**********************************************************************/
4588static enum fc_tristate
4590 const struct req_context *context,
4591 const struct req_context *other_context,
4592 const struct requirement *req)
4593{
4595
4596 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4597 : nullptr,
4598 other_context->player,
4599 req->range,
4600 req->source.value.diplrel);
4601}
4602
4603/**********************************************************************/
4606static enum fc_tristate
4608 const struct player *other_player,
4609 enum req_range range,
4610 int diplrel)
4611{
4612 enum fc_tristate out = TRI_NO;
4613
4614 if (target_tile == nullptr) {
4615 return TRI_MAYBE;
4616 }
4617
4620 unit_owner(target_unit), other_player, range, diplrel);
4621
4624
4625 return out;
4626}
4627
4628/**********************************************************************/
4637static enum fc_tristate
4639 const struct req_context *context,
4640 const struct req_context *other_context,
4641 const struct requirement *req)
4642{
4644
4645 return is_diplrel_unitany_in_range(context->tile, context->player,
4646 req->range,
4647 req->source.value.diplrel);
4648}
4649
4650/**********************************************************************/
4659static enum fc_tristate
4661 const struct req_context *context,
4662 const struct req_context *other_context,
4663 const struct requirement *req)
4664{
4666
4668 req->range,
4669 req->source.value.diplrel);
4670}
4671
4672/**********************************************************************/
4680static enum fc_tristate
4682 const struct req_context *context,
4683 const struct req_context *other_context,
4684 const struct requirement *req)
4685{
4686 const struct unit_type *punittype;
4687
4689
4690 punittype = req->source.value.utype;
4691
4692 switch (req->range) {
4693 case REQ_RANGE_LOCAL:
4694 if (!context->unittype) {
4695 return TRI_MAYBE;
4696 }
4697 return BOOL_TO_TRISTATE(context->unittype == punittype);
4698 case REQ_RANGE_TILE:
4700 case REQ_RANGE_ADJACENT:
4701 if (context->tile == nullptr) {
4702 return TRI_MAYBE;
4703 }
4704
4705 unit_list_iterate(context->tile->units, punit) {
4706 if (punit->utype == punittype) {
4707 return TRI_YES;
4708 }
4710
4711 if (req->range == REQ_RANGE_TILE) {
4712 return TRI_NO;
4713 }
4714
4715 if (req->range == REQ_RANGE_CADJACENT) {
4718 if (punit->utype == punittype) {
4719 return TRI_YES;
4720 }
4723 } else {
4725
4728 if (punit->utype == punittype) {
4729 return TRI_YES;
4730 }
4733 }
4734
4735 return TRI_NO;
4736
4737 case REQ_RANGE_CITY:
4740 case REQ_RANGE_PLAYER:
4741 case REQ_RANGE_TEAM:
4742 case REQ_RANGE_ALLIANCE:
4743 case REQ_RANGE_WORLD:
4744 case REQ_RANGE_COUNT:
4746 break;
4747 }
4748
4749 return TRI_NO;
4750}
4751
4752/**********************************************************************/
4760static enum fc_tristate
4762 const struct req_context *context,
4763 const struct req_context *other_context,
4764 const struct requirement *req)
4765{
4766 enum unit_type_flag_id unitflag;
4767
4769
4770 unitflag = req->source.value.unitflag;
4771
4772 switch (req->range) {
4773 case REQ_RANGE_LOCAL:
4774 if (!context->unittype) {
4775 return TRI_MAYBE;
4776 }
4777 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4778 case REQ_RANGE_TILE:
4780 case REQ_RANGE_ADJACENT:
4781 if (context->tile == nullptr) {
4782 return TRI_MAYBE;
4783 }
4784
4785 unit_list_iterate(context->tile->units, punit) {
4786 if (unit_has_type_flag(punit, unitflag)) {
4787 return TRI_YES;
4788 }
4790
4791 if (req->range == REQ_RANGE_TILE) {
4792 return TRI_NO;
4793 }
4794
4795 if (req->range == REQ_RANGE_CADJACENT) {
4798 if (unit_has_type_flag(punit, unitflag)) {
4799 return TRI_YES;
4800 }
4803 } else {
4805
4808 if (unit_has_type_flag(punit, unitflag)) {
4809 return TRI_YES;
4810 }
4813 }
4814
4815 return TRI_NO;
4816
4817 case REQ_RANGE_CITY:
4820 case REQ_RANGE_PLAYER:
4821 case REQ_RANGE_TEAM:
4822 case REQ_RANGE_ALLIANCE:
4823 case REQ_RANGE_WORLD:
4824 case REQ_RANGE_COUNT:
4826 break;
4827 }
4828
4829 return TRI_NO;
4830}
4831
4832/**********************************************************************/
4840static enum fc_tristate
4842 const struct req_context *context,
4843 const struct req_context *other_context,
4844 const struct requirement *req)
4845{
4846 const struct unit_class *pclass;
4847
4849
4850 pclass = req->source.value.uclass;
4851
4852 switch (req->range) {
4853 case REQ_RANGE_LOCAL:
4854 if (!context->unittype) {
4855 return TRI_MAYBE;
4856 }
4857 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4858 case REQ_RANGE_TILE:
4860 case REQ_RANGE_ADJACENT:
4861 if (context->tile == nullptr) {
4862 return TRI_MAYBE;
4863 }
4864
4865 unit_list_iterate(context->tile->units, punit) {
4866 if (unit_class_get(punit) == pclass) {
4867 return TRI_YES;
4868 }
4870
4871 if (req->range == REQ_RANGE_TILE) {
4872 return TRI_NO;
4873 }
4874
4875 if (req->range == REQ_RANGE_CADJACENT) {
4878 if (unit_class_get(punit) == pclass) {
4879 return TRI_YES;
4880 }
4883 } else {
4885
4888 if (unit_class_get(punit) == pclass) {
4889 return TRI_YES;
4890 }
4893 }
4894
4895 return TRI_NO;
4896
4897 case REQ_RANGE_CITY:
4900 case REQ_RANGE_PLAYER:
4901 case REQ_RANGE_TEAM:
4902 case REQ_RANGE_ALLIANCE:
4903 case REQ_RANGE_WORLD:
4904 case REQ_RANGE_COUNT:
4906 break;
4907 }
4908
4909 return TRI_NO;
4910}
4911
4912/**********************************************************************/
4920static enum fc_tristate
4922 const struct req_context *context,
4923 const struct req_context *other_context,
4924 const struct requirement *req)
4925{
4927
4929
4931
4932 switch (req->range) {
4933 case REQ_RANGE_LOCAL:
4934 if (!context->unittype) {
4935 return TRI_MAYBE;
4936 }
4938 case REQ_RANGE_TILE:
4940 case REQ_RANGE_ADJACENT:
4941 if (context->tile == nullptr) {
4942 return TRI_MAYBE;
4943 }
4944
4945 unit_list_iterate(context->tile->units, punit) {
4947 return TRI_YES;
4948 }
4950
4951 if (req->range == REQ_RANGE_TILE) {
4952 return TRI_NO;
4953 }
4954
4955 if (req->range == REQ_RANGE_CADJACENT) {
4959 return TRI_YES;
4960 }
4963 } else {
4965
4969 return TRI_YES;
4970 }
4973 }
4974
4975 return TRI_NO;
4976
4977 case REQ_RANGE_CITY:
4980 case REQ_RANGE_PLAYER:
4981 case REQ_RANGE_TEAM:
4982 case REQ_RANGE_ALLIANCE:
4983 case REQ_RANGE_WORLD:
4984 case REQ_RANGE_COUNT:
4986 break;
4987 }
4988
4989 return TRI_NO;
4990}
4991
4992/**********************************************************************/
5000static enum fc_tristate
5002 const struct req_context *context,
5003 const struct req_context *other_context,
5004 const struct requirement *req)
5005{
5006 enum ustate_prop uprop;
5007
5009
5011
5013 "Unsupported range \"%s\"",
5014 req_range_name(req->range));
5015
5016 /* Could be asked with incomplete data.
5017 * is_req_active() will handle it based on prob_type. */
5018 if (context->unit == nullptr) {
5019 return TRI_MAYBE;
5020 }
5021
5022 switch (uprop) {
5023 case USP_TRANSPORTED:
5024 return BOOL_TO_TRISTATE(context->unit->transporter != nullptr);
5025 case USP_LIVABLE_TILE:
5026 return BOOL_TO_TRISTATE(
5028 unit_tile(context->unit)));
5029 break;
5030 case USP_TRANSPORTING:
5032 case USP_HAS_HOME_CITY:
5033 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
5034 case USP_NATIVE_TILE:
5035 return BOOL_TO_TRISTATE(
5037 unit_tile(context->unit)));
5038 break;
5039 case USP_NATIVE_EXTRA:
5040 return BOOL_TO_TRISTATE(
5042 unit_type_get(context->unit)));
5043 break;
5045 return BOOL_TO_TRISTATE(context->unit->moved);
5046 case USP_COUNT:
5047 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
5048 /* Invalid property is unknowable. */
5049 return TRI_NO;
5050 }
5051
5052 /* Should never be reached */
5053 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
5054
5055 return TRI_NO;
5056}
5057
5058/**********************************************************************/
5066static enum fc_tristate
5068 const struct req_context *context,
5069 const struct req_context *other_context,
5070 const struct requirement *req)
5071{
5072 enum unit_activity activity;
5073
5075
5076 activity = req->source.value.activity;
5077
5079 "Unsupported range \"%s\"",
5080 req_range_name(req->range));
5081
5082 if (context->unit == nullptr) {
5083 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
5084 * it's the zero value that context has by default - so many callers
5085 * who meant not to set specific activity actually have ACTIVITY_IDLE
5086 * instead of ACTIVITY_LAST */
5087 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
5088 return BOOL_TO_TRISTATE(activity == context->activity);
5089 }
5090
5091 /* Could be asked with incomplete data.
5092 * is_req_active() will handle it based on prob_type. */
5093 return TRI_MAYBE;
5094 }
5095
5096 switch (context->unit->activity) {
5097 case ACTIVITY_IDLE:
5098 case ACTIVITY_SENTRY:
5099 case ACTIVITY_GOTO:
5100 case ACTIVITY_EXPLORE:
5101 /* Seen as idle. */
5102 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
5103 default:
5104 /* Handled below. */
5105 break;
5106 }
5107
5108 return BOOL_TO_TRISTATE(context->unit->activity == activity);
5109}
5110
5111/**********************************************************************/
5119static enum fc_tristate
5121 const struct req_context *context,
5122 const struct req_context *other_context,
5123 const struct requirement *req)
5124{
5126
5127 if (context->unit == nullptr) {
5128 return TRI_MAYBE;
5129 } else {
5130 return BOOL_TO_TRISTATE(context->unit->veteran
5131 >= req->source.value.minveteran);
5132 }
5133}
5134
5135/**********************************************************************/
5143static enum fc_tristate
5145 const struct req_context *context,
5146 const struct req_context *other_context,
5147 const struct requirement *req)
5148{
5150
5151 if (context->unit == nullptr) {
5152 return TRI_MAYBE;
5153 } else {
5155 <= context->unit->moves_left);
5156 }
5157}
5158
5159/**********************************************************************/
5167static enum fc_tristate
5169 const struct req_context *context,
5170 const struct req_context *other_context,
5171 const struct requirement *req)
5172{
5174
5175 if (context->unit == nullptr) {
5176 return TRI_MAYBE;
5177 } else {
5179 <= context->unit->hp);
5180 }
5181}
5182
5183/**********************************************************************/
5191static enum fc_tristate
5193 const struct req_context *context,
5194 const struct req_context *other_context,
5195 const struct requirement *req)
5196{
5198
5199 switch (req->range) {
5200 case REQ_RANGE_LOCAL:
5201 if (context->unit == nullptr || !is_server()) {
5202 return TRI_MAYBE;
5203 } else {
5204 return BOOL_TO_TRISTATE(
5205 req->source.value.age <=
5206 game.info.turn - context->unit->birth_turn);
5207 }
5208 break;
5209 case REQ_RANGE_CITY:
5210 if (context->city == nullptr) {
5211 return TRI_MAYBE;
5212 } else {
5213 return BOOL_TO_TRISTATE(
5214 req->source.value.age <=
5215 game.info.turn - context->city->turn_founded);
5216 }
5217 break;
5218 case REQ_RANGE_PLAYER:
5219 if (context->player == nullptr) {
5220 return TRI_MAYBE;
5221 } else {
5222 return BOOL_TO_TRISTATE(req->source.value.age
5223 <= player_age(context->player));
5224 }
5225 break;
5226 default:
5227 return TRI_MAYBE;
5228 break;
5229 }
5230}
5231
5232/**********************************************************************/
5240static enum fc_tristate
5242 const struct req_context *context,
5243 const struct req_context *other_context,
5244 const struct requirement *req)
5245{
5247
5248 switch (req->range) {
5249 case REQ_RANGE_LOCAL:
5250 if (context->unit == nullptr || !is_server()) {
5251 return TRI_MAYBE;
5252 } else {
5253 return BOOL_TO_TRISTATE(
5254 req->source.value.form_age <=
5255 game.info.turn - context->unit->current_form_turn);
5256 }
5257 break;
5258 default:
5259 return TRI_MAYBE;
5260 break;
5261 }
5262}
5263
5264/**********************************************************************/
5268static inline enum fc_tristate
5270{
5272 bool whole_known;
5273
5274 if (cont > 0) {
5277
5278 if (actual_surrounder > 0) {
5279 return TRI_NO;
5280 }
5281 } else if (cont < 0) {
5284
5285 if (actual_surrounder < 0) {
5286 return TRI_NO;
5287 }
5288 } else {
5289 return TRI_MAYBE;
5290 }
5291
5292 if (actual_surrounder == 0 || surrounder == 0) {
5293 return TRI_MAYBE;
5294 } else if (actual_surrounder != surrounder) {
5295 return TRI_NO;
5296 } else if (!whole_known) {
5297 return TRI_MAYBE;
5298 } else {
5299 return TRI_YES;
5300 }
5301}
5302
5303/**********************************************************************/
5311static enum fc_tristate
5313 const struct req_context *context,
5314 const struct req_context *other_context,
5315 const struct requirement *req)
5316{
5318
5319 if (context->tile == nullptr || other_context->tile == nullptr) {
5320 /* Note: For some values, we might be able to give a definitive
5321 * TRI_NO answer even if one of the tiles is missing, but that's
5322 * probably not worth the added effort. */
5323 return TRI_MAYBE;
5324 }
5325
5326 switch (req->source.value.tilerel) {
5327 case TREL_SAME_TCLASS:
5328 if (tile_terrain(other_context->tile) == T_UNKNOWN) {
5329 return TRI_MAYBE;
5330 }
5332 || req->range == REQ_RANGE_CADJACENT
5333 || req->range == REQ_RANGE_ADJACENT),
5334 TRI_MAYBE,
5335 "Invalid range %d for tile relation \"%s\" req",
5337 {
5340 bool seen_unknown = FALSE;
5341 const struct terrain *terr;
5342
5343 if ((terr = tile_terrain(context->tile)) == T_UNKNOWN) {
5345 } else if (terrain_type_terrain_class(terr) == cls) {
5346 return TRUE;
5347 }
5348
5350 if ((terr = tile_terrain(adj_tile)) == T_UNKNOWN) {
5352 } else if (terrain_type_terrain_class(terr) == cls) {
5353 return TRUE;
5354 }
5356
5357 if (seen_unknown) {
5358 return TRI_MAYBE;
5359 } else {
5360 return TRI_NO;
5361 }
5362 }
5363 break;
5364 case TREL_SAME_REGION:
5365 if (tile_continent(other_context->tile) == 0) {
5366 return TRI_MAYBE;
5367 }
5369 || req->range == REQ_RANGE_CADJACENT
5370 || req->range == REQ_RANGE_ADJACENT),
5371 TRI_MAYBE,
5372 "Invalid range %d for tile relation \"%s\" req",
5374
5375 if (tile_continent(context->tile)
5376 == tile_continent(other_context->tile)) {
5377 return TRI_YES;
5378 } else {
5379 bool seen_unknown = (tile_continent(context->tile) == 0);
5381
5384
5385 if (adj_cont == cont) {
5386 return TRI_YES;
5387 } else if (adj_cont == 0) {
5389 }
5391
5392 if (seen_unknown) {
5393 return TRI_MAYBE;
5394 } else {
5395 return TRI_NO;
5396 }
5397 }
5398 break;
5400 if (tile_continent(context->tile) == 0
5401 || tile_continent(other_context->tile) == 0) {
5402 /* Note: We could still give a definitive TRI_NO answer if there are
5403 * too many different adjacent continents, but that's probably not
5404 * worth the added effort. */
5405 return TRI_MAYBE;
5406 }
5408 || req->range == REQ_RANGE_ADJACENT),
5409 TRI_MAYBE,
5410 "Invalid range %d for tile relation \"%s\" req",
5411 req->range,
5413
5414 {
5415 bool seen_unknown = FALSE;
5416 Continent_id cont = tile_continent(context->tile);
5418
5421
5422 if (adj_cont == 0) {
5424 } else if (adj_cont != cont && adj_cont != other_cont) {
5425 return TRI_NO;
5426 }
5428
5429 if (seen_unknown) {
5430 return TRI_MAYBE;
5431 } else {
5432 return TRI_YES;
5433 }
5434 }
5435 break;
5438 || req->range == REQ_RANGE_CADJACENT
5439 || req->range == REQ_RANGE_ADJACENT),
5440 TRI_MAYBE,
5441 "Invalid range %d for tile relation \"%s\" req",
5442 req->range,
5444
5445 {
5446 bool seen_maybe = FALSE;
5448
5450 wanted)) {
5451 case TRI_YES:
5452 return TRI_YES;
5453 case TRI_MAYBE:
5454 seen_maybe = TRUE;
5455 break;
5456 default:
5457 break;
5458 }
5459
5462 wanted)) {
5463 case TRI_YES:
5464 return TRI_YES;
5465 case TRI_MAYBE:
5466 seen_maybe = TRUE;
5467 break;
5468 default:
5469 break;
5470 }
5472
5473 if (seen_maybe) {
5474 return TRI_MAYBE;
5475 } else {
5476 return TRI_NO;
5477 }
5478 }
5479 break;
5480 default:
5481 break;
5482 }
5483
5485 "Illegal value %d for tile relationship requirement.",
5486 req->source.value.tilerel);
5487 return TRI_MAYBE;
5488}
5489
5490/**********************************************************************/
5493static bool is_city_in_tile(const struct tile *ptile,
5494 const struct city *pcity)
5495{
5496 if (pcity == nullptr) {
5497 return tile_city(ptile) != nullptr;
5498 } else {
5499 return is_city_center(pcity, ptile);
5500 }
5501}
5502
5503/**********************************************************************/
5511static enum fc_tristate
5513 const struct req_context *context,
5514 const struct req_context *other_context,
5515 const struct requirement *req)
5516{
5517 enum citytile_type citytile;
5518
5520
5521 citytile = req->source.value.citytile;
5522
5524 if (context->tile == nullptr) {
5525 return TRI_MAYBE;
5526 }
5527
5528 switch (citytile) {
5529 case CITYT_CENTER:
5530 switch (req->range) {
5531 case REQ_RANGE_TILE:
5533 context->city));
5535 if (is_city_in_tile(context->tile, context->city)) {
5536 return TRI_YES;
5537 }
5539 if (is_city_in_tile(adjc_tile, context->city)) {
5540 return TRI_YES;
5541 }
5543
5544 return TRI_NO;
5545 case REQ_RANGE_ADJACENT:
5546 if (is_city_in_tile(context->tile, context->city)) {
5547 return TRI_YES;
5548 }
5550 if (is_city_in_tile(adjc_tile, context->city)) {
5551 return TRI_YES;
5552 }
5554
5555 return TRI_NO;
5556 case REQ_RANGE_CITY:
5559 case REQ_RANGE_PLAYER:
5560 case REQ_RANGE_TEAM:
5561 case REQ_RANGE_ALLIANCE:
5562 case REQ_RANGE_WORLD:
5563 case REQ_RANGE_LOCAL:
5564 case REQ_RANGE_COUNT:
5565 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5566 break;
5567 }
5568
5569 return TRI_MAYBE;
5570 case CITYT_CLAIMED:
5571 switch (req->range) {
5572 case REQ_RANGE_TILE:
5573 return BOOL_TO_TRISTATE(context->tile->owner != nullptr);
5575 if (context->tile->owner != nullptr) {
5576 return TRI_YES;
5577 }
5579 if (adjc_tile->owner != nullptr) {
5580 return TRI_YES;
5581 }
5583
5584 return TRI_NO;
5585 case REQ_RANGE_ADJACENT:
5586 if (context->tile->owner != nullptr) {
5587 return TRI_YES;
5588 }
5590 if (adjc_tile->owner != nullptr) {
5591 return TRI_YES;
5592 }
5594
5595 return TRI_NO;
5596 case REQ_RANGE_CITY:
5599 case REQ_RANGE_PLAYER:
5600 case REQ_RANGE_TEAM:
5601 case REQ_RANGE_ALLIANCE:
5602 case REQ_RANGE_WORLD:
5603 case REQ_RANGE_LOCAL:
5604 case REQ_RANGE_COUNT:
5605 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5606 break;
5607 }
5608
5609 return TRI_MAYBE;
5610 case CITYT_EXTRAS_OWNED:
5611 switch (req->range) {
5612 case REQ_RANGE_TILE:
5613 return BOOL_TO_TRISTATE(context->tile->extras_owner != nullptr);
5615 if (context->tile->extras_owner != nullptr) {
5616 return TRI_YES;
5617 }
5619 if (adjc_tile->extras_owner != nullptr) {
5620 return TRI_YES;
5621 }
5623
5624 return TRI_NO;
5625 case REQ_RANGE_ADJACENT:
5626 if (context->tile->extras_owner != nullptr) {
5627 return TRI_YES;
5628 }
5630 if (adjc_tile->extras_owner != nullptr) {
5631 return TRI_YES;
5632 }
5634
5635 return TRI_NO;
5636 case REQ_RANGE_CITY:
5639 case REQ_RANGE_PLAYER:
5640 case REQ_RANGE_TEAM:
5641 case REQ_RANGE_ALLIANCE:
5642 case REQ_RANGE_WORLD:
5643 case REQ_RANGE_LOCAL:
5644 case REQ_RANGE_COUNT:
5645 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5646 break;
5647 }
5648
5649 return TRI_MAYBE;
5650 case CITYT_WORKED:
5651 switch (req->range) {
5652 case REQ_RANGE_TILE:
5653 return BOOL_TO_TRISTATE(context->tile->worked != nullptr);
5655 if (context->tile->worked != nullptr) {
5656 return TRI_YES;
5657 }
5659 if (adjc_tile->worked != nullptr) {
5660 return TRI_YES;
5661 }
5663
5664 return TRI_NO;
5665 case REQ_RANGE_ADJACENT:
5666 if (context->tile->worked != nullptr) {
5667 return TRI_YES;
5668 }
5670 if (adjc_tile->worked != nullptr) {
5671 return TRI_YES;
5672 }
5674
5675 return TRI_NO;
5676 case REQ_RANGE_CITY:
5679 case REQ_RANGE_PLAYER:
5680 case REQ_RANGE_TEAM:
5681 case REQ_RANGE_ALLIANCE:
5682 case REQ_RANGE_WORLD:
5683 case REQ_RANGE_LOCAL:
5684 case REQ_RANGE_COUNT:
5685 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5686 break;
5687 }
5688
5689 return TRI_MAYBE;
5691 {
5693 const struct tile *target_tile = context->tile, *cc_tile;
5694
5695 if (!context->city) {
5696 return TRI_MAYBE;
5697 }
5698 cc_tile = city_tile(context->city);
5699 if (!cc_tile) {
5700 /* Unplaced virtual city */
5701 return TRI_MAYBE;
5702 }
5704 /* Note: No special treatment of 0 == cc here*/
5705 switch (req->range) {
5706 case REQ_RANGE_TILE:
5709 if (tile_continent(target_tile) == cc) {
5710 return TRI_YES;
5711 }
5713 if (tile_continent(adjc_tile) == cc) {
5714 return TRI_YES;
5715 }
5717
5718 return TRI_NO;
5719 case REQ_RANGE_ADJACENT:
5720 if (tile_continent(target_tile) == cc) {
5721 return TRI_YES;
5722 }
5724 if (tile_continent(adjc_tile) == cc) {
5725 return TRI_YES;
5726 }
5728
5729 return TRI_NO;
5730 case REQ_RANGE_CITY:
5733 case REQ_RANGE_PLAYER:
5734 case REQ_RANGE_TEAM:
5735 case REQ_RANGE_ALLIANCE:
5736 case REQ_RANGE_WORLD:
5737 case REQ_RANGE_LOCAL:
5738 case REQ_RANGE_COUNT:
5739 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5740 break;
5741 }
5742 }
5743
5744 return TRI_MAYBE;
5746 {
5747 int n = 0;
5749 bool ukt = FALSE;
5750 const struct tile *target_tile = context->tile, *cc_tile;
5751
5752 if (!context->city) {
5753 return TRI_MAYBE;
5754 }
5755 cc_tile = city_tile(context->city);
5756 if (!cc_tile) {
5757 /* Unplaced virtual city */
5758 return TRI_MAYBE;
5759 }
5761 if (!cc) {
5762 /* Don't know the city center terrain class.
5763 * Maybe, the city floats? Even if the rules prohibit it... */
5764 return TRI_MAYBE;
5765 }
5768
5769 if (0 != tc) {
5770 bool seen = FALSE;
5771 int i = n;
5772
5773 if (tc == cc) {
5774 continue;
5775 }
5776 while (--i >= 0) {
5777 if (adjc_cont[i] == tc) {
5778 seen = TRUE;
5779 break;
5780 }
5781 }
5782 if (seen) {
5783 continue;
5784 }
5786 } else {
5787 /* Likely, it's a black tile in client and we don't know
5788 * We possibly can calculate, but keep it simple. */
5789 ukt = TRUE;
5790 }
5792 if (0 == n) {
5793 return ukt ? TRI_MAYBE : TRI_NO;
5794 }
5795
5796 switch (req->range) {
5797 case REQ_RANGE_TILE:
5798 {
5800
5801 if (cc == tc) {
5802 return TRI_NO;
5803 }
5804 if (0 == tc || ukt) {
5805 return TRI_MAYBE;
5806 }
5807 for (int i = 0; i < n; i++) {
5808 if (tc == adjc_cont[i]) {
5809 return TRI_YES;
5810 }
5811 }
5812 }
5813
5814 return TRI_NO;
5815 case REQ_RANGE_ADJACENT:
5816 if (ukt) {
5817 /* If ALL the tiles in range are on cc, we can say it's false */
5819 if (tile_continent(adjc_tile) != cc) {
5820 return TRI_MAYBE;
5821 }
5823
5824 return TRI_NO;
5825 } else {
5828
5829 if (0 == tc) {
5830 return TRI_MAYBE;
5831 }
5832 for (int i = 0; i < n; i++) {
5833 if (tc == adjc_cont[i]) {
5834 return TRI_YES;
5835 }
5836 }
5838 }
5839
5840 return TRI_NO;
5842 if (ukt) {
5843 /* If ALL the tiles in range are on cc, we can say it's false */
5845 if (tile_continent(cadjc_tile) != cc) {
5846 return TRI_MAYBE;
5847 }
5849 } else {
5852
5853 if (0 == tc) {
5854 return TRI_MAYBE;
5855 }
5856 for (int i = 0; i < n; i++) {
5857 if (tc == adjc_cont[i]) {
5858 return TRI_YES;
5859 }
5860 }
5862 }
5863
5864 return TRI_NO;
5865 case REQ_RANGE_CITY:
5868 case REQ_RANGE_PLAYER:
5869 case REQ_RANGE_TEAM:
5870 case REQ_RANGE_ALLIANCE:
5871 case REQ_RANGE_WORLD:
5872 case REQ_RANGE_LOCAL:
5873 case REQ_RANGE_COUNT:
5874 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5875 break;
5876 }
5877 }
5878
5879 return TRI_MAYBE;
5880 case CITYT_LAST:
5881 /* Handled below */
5882 break;
5883 }
5884
5885 /* Not implemented */
5886 log_error("is_req_active(): citytile %d not supported.",
5887 citytile);
5888 return TRI_MAYBE;
5889}
5890
5891/**********************************************************************/
5899static enum fc_tristate
5901 const struct req_context *context,
5902 const struct req_context *other_context,
5903 const struct requirement *req)
5904{
5905 enum citystatus_type citystatus;
5906
5908
5909 citystatus = req->source.value.citystatus;
5910
5911 if (context->city == nullptr) {
5912 return TRI_MAYBE;
5913 }
5914
5915 switch (citystatus) {
5917 switch (req->range) {
5918 case REQ_RANGE_CITY:
5919 if (context->city->original == nullptr) {
5920 return TRI_MAYBE;
5921 }
5922 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
5924 {
5925 enum fc_tristate ret;
5926
5927 if (city_owner(context->city) == context->city->original) {
5928 return TRI_YES;
5929 }
5930
5931 ret = TRI_NO;
5933 if (trade_partner == nullptr || trade_partner->original == nullptr) {
5934 ret = TRI_MAYBE;
5935 } else if (city_owner(trade_partner) == trade_partner->original) {
5936 return TRI_YES;
5937 }
5939
5940 return ret;
5941 }
5942 case REQ_RANGE_LOCAL:
5943 case REQ_RANGE_TILE:
5945 case REQ_RANGE_ADJACENT:
5947 case REQ_RANGE_PLAYER:
5948 case REQ_RANGE_TEAM:
5949 case REQ_RANGE_ALLIANCE:
5950 case REQ_RANGE_WORLD:
5951 case REQ_RANGE_COUNT:
5952 break;
5953 }
5954
5955 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
5956 req->range);
5957
5958 return TRI_MAYBE;
5959
5960 case CITYS_STARVED:
5961 switch (req->range) {
5962 case REQ_RANGE_CITY:
5963 return BOOL_TO_TRISTATE(context->city->had_famine);
5965 {
5966 enum fc_tristate ret;
5967
5968 if (context->city->had_famine) {
5969 return TRI_YES;
5970 }
5971
5972 ret = TRI_NO;
5974 if (trade_partner == nullptr) {
5975 ret = TRI_MAYBE;
5976 } else if (trade_partner->had_famine) {
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 Starved.",
5997 req->range);
5998
5999 return TRI_MAYBE;
6000
6001 case CITYS_DISORDER:
6002 switch (req->range) {
6003 case REQ_RANGE_CITY:
6004 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
6006 {
6007 enum fc_tristate ret;
6008
6009 if (context->city->anarchy > 0) {
6010 return TRI_YES;
6011 }
6012
6013 ret = TRI_NO;
6015 if (trade_partner == nullptr) {
6016 ret = TRI_MAYBE;
6017 } else if (trade_partner->anarchy > 0) {
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 Disorder.",
6038 req->range);
6039
6040 return TRI_MAYBE;
6041
6042 case CITYS_CELEBRATION:
6043 switch (req->range) {
6044 case REQ_RANGE_CITY:
6045 return BOOL_TO_TRISTATE(context->city->rapture > 0);
6047 {
6048 enum fc_tristate ret;
6049
6050 if (context->city->rapture > 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->rapture > 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 Celebration.",
6079 req->range);
6080
6081 return TRI_MAYBE;
6082
6083 case CITYS_TRANSFERRED:
6084 switch (req->range) {
6085 case REQ_RANGE_CITY:
6086 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
6088 {
6089 enum fc_tristate ret;
6090
6091 if (context->city->acquire_t != CACQ_FOUNDED) {
6092 return TRI_YES;
6093 }
6094
6095 ret = TRI_NO;
6097 if (trade_partner == nullptr) {
6098 ret = TRI_MAYBE;
6099 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
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 Transferred.",
6120 req->range);
6121
6122 return TRI_MAYBE;
6123
6125 if (!is_server()) {
6126 /* Client has no idea. */
6127 return TRI_MAYBE;
6128 }
6129
6130 switch (req->range) {
6131 case REQ_RANGE_CITY:
6132 return BOOL_TO_TRISTATE(context->city->server.aarea != nullptr
6133 && context->city->server.aarea->capital);
6135 {
6136 enum fc_tristate ret;
6137
6138 if (context->city->server.aarea != nullptr
6139 && context->city->server.aarea->capital) {
6140 return TRI_YES;
6141 }
6142
6143 ret = TRI_NO;
6145 if (trade_partner == nullptr) {
6146 ret = TRI_MAYBE;
6147 } else if (trade_partner->server.aarea != nullptr
6148 && trade_partner->server.aarea->capital) {
6149 return TRI_YES;
6150 }
6152
6153 return ret;
6154 }
6155 case REQ_RANGE_LOCAL:
6156 case REQ_RANGE_TILE:
6158 case REQ_RANGE_ADJACENT:
6160 case REQ_RANGE_PLAYER:
6161 case REQ_RANGE_TEAM:
6162 case REQ_RANGE_ALLIANCE:
6163 case REQ_RANGE_WORLD:
6164 case REQ_RANGE_COUNT:
6165 break;
6166 }
6167
6168 fc_assert_msg(FALSE, "Invalid range %d for citystatus CapitalConnected.",
6169 req->range);
6170
6171 return TRI_MAYBE;
6172
6173 case CITYS_LAST:
6174 break;
6175 }
6176
6177 /* Not implemented */
6178 log_error("is_req_active(): citystatus %d not supported.",
6179 citystatus);
6180
6181 return TRI_MAYBE;
6182}
6183
6184/**********************************************************************/
6192static enum fc_tristate
6194 const struct req_context *context,
6195 const struct req_context *other_context,
6196 const struct requirement *req)
6197{
6199
6200 if (context->city == nullptr) {
6201 return TRI_MAYBE;
6202 } else {
6203 if (req->range == REQ_RANGE_TRADE_ROUTE) {
6204 enum fc_tristate ret;
6205
6206 if (city_size_get(context->city) >= req->source.value.minsize) {
6207 return TRI_YES;
6208 }
6209
6210 ret = TRI_NO;
6212 if (trade_partner == nullptr) {
6213 ret = TRI_MAYBE;
6214 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
6215 return TRI_YES;
6216 }
6218
6219 return ret;
6220 } else {
6222 >= req->source.value.minsize);
6223 }
6224 }
6225}
6226
6227/**********************************************************************/
6235static enum fc_tristate
6237 const struct req_context *context,
6238 const struct req_context *other_context,
6239 const struct requirement *req)
6240{
6241 const struct counter *count;
6242
6244
6245 count = req->source.value.counter;
6246
6247 if (context->city == nullptr) {
6248 return TRI_MAYBE;
6249 }
6250 return BOOL_TO_TRISTATE(count->checkpoint <=
6251 context->city->counter_values[
6252 counter_index(count)]);
6253}
6254
6255/**********************************************************************/
6263static enum fc_tristate
6265 const struct req_context *context,
6266 const struct req_context *other_context,
6267 const struct requirement *req)
6268{
6269 const struct achievement *achievement;
6270
6272
6274
6275 if (req->range == REQ_RANGE_WORLD) {
6277 } else if (context->player == nullptr) {
6278 return TRI_MAYBE;
6279 } else if (req->range == REQ_RANGE_ALLIANCE
6280 || req->range == REQ_RANGE_TEAM) {
6281 players_iterate_alive(plr2) {
6282 if (players_in_same_range(context->player, plr2, req->range)
6284 return TRI_YES;
6285 }
6287 return TRI_NO;
6288 } else if (req->range == REQ_RANGE_PLAYER) {
6290 return TRI_YES;
6291 } else {
6292 return TRI_NO;
6293 }
6294 }
6295
6296 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
6297
6298 return TRI_MAYBE;
6299}
6300
6301/**********************************************************************/
6309static enum fc_tristate
6311 const struct req_context *context,
6312 const struct req_context *other_context,
6313 const struct requirement *req)
6314{
6315 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
6316
6317 fc_assert_ret_val(req != nullptr, TRI_MAYBE);
6318 fc_assert(context != nullptr);
6319
6320 switch (req->source.kind) {
6321 case VUT_MINLATITUDE:
6322 min = req->source.value.latitude;
6323 break;
6324 case VUT_MAXLATITUDE:
6325 max = req->source.value.latitude;
6326 break;
6327 default:
6329 || req->source.kind == VUT_MAXLATITUDE);
6330 break;
6331 }
6332
6333 switch (req->range) {
6334 case REQ_RANGE_WORLD:
6336 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
6337
6338 case REQ_RANGE_TILE:
6339 if (context->tile == nullptr) {
6340 return TRI_MAYBE;
6341 } else {
6343
6345 }
6346
6348 if (context->tile == nullptr) {
6349 return TRI_MAYBE;
6350 }
6351
6354
6356 return TRI_YES;
6357 }
6359 return TRI_NO;
6360
6361 case REQ_RANGE_ADJACENT:
6362 if (!context->tile) {
6363 return TRI_MAYBE;
6364 }
6365
6368
6370 return TRI_YES;
6371 }
6373 return TRI_NO;
6374
6375 case REQ_RANGE_CITY:
6378 case REQ_RANGE_PLAYER:
6379 case REQ_RANGE_TEAM:
6380 case REQ_RANGE_ALLIANCE:
6381 case REQ_RANGE_LOCAL:
6382 case REQ_RANGE_COUNT:
6383 break;
6384 }
6385
6387 "Illegal range %d for latitude requirement.", req->range);
6388
6389 return TRI_MAYBE;
6390}
6391
6392/**********************************************************************/
6400static enum fc_tristate
6402 const struct req_context *context,
6403 const struct req_context *other_context,
6404 const struct requirement *req)
6405{
6407
6408 switch (req->range) {
6409 case REQ_RANGE_TILE:
6410 if (context->tile == nullptr || other_context->tile == nullptr) {
6411 return TRI_MAYBE;
6412 }
6413 return BOOL_TO_TRISTATE(
6415 <= req->source.value.distance_sq
6416 );
6417 default:
6418 break;
6419 }
6420
6422 "Illegal range %d for max squared distance requirement.",
6423 req->range);
6424
6425 return TRI_MAYBE;
6426}
6427
6428/**********************************************************************/
6436static enum fc_tristate
6438 const struct req_context *context,
6439 const struct req_context *other_context,
6440 const struct requirement *req)
6441{
6442 int max_tiles, min_tiles = 1;
6443
6445
6446 switch (req->range) {
6448 case REQ_RANGE_ADJACENT:
6449 if (context->tile == nullptr) {
6450 /* The tile itself is included in the range */
6451 max_tiles = 1 + ((req->range == REQ_RANGE_CADJACENT)
6452 ? nmap->num_cardinal_dirs
6453 : nmap->num_valid_dirs);
6454
6455 break;
6456 } else {
6457 Continent_id cont = tile_continent(context->tile);
6458
6459 /* Count how many adjacent tiles there actually are as we go along */
6460 max_tiles = 1;
6461
6464
6465 if (adj_cont == 0 || cont == 0) {
6466 max_tiles++;
6467 } else if (adj_cont == cont) {
6468 min_tiles++;
6469 max_tiles++;
6470 }
6472 }
6473 break;
6475 {
6476 Continent_id cont = context->tile ? tile_continent(context->tile) : 0;
6477
6480
6481 /* Note: We could come up with a better upper bound by subtracting
6482 * all other continent/ocean sizes, or all except the largest if we
6483 * don't know the tile.
6484 * We could even do a flood-fill count of the unknown area bordered
6485 * by known tiles of the continent.
6486 * Probably not worth the effort though. */
6487 max_tiles = nmap->xsize * nmap->ysize;
6488
6489 if (cont > 0) {
6490 min_tiles = nmap->continent_sizes[cont];
6491 if (is_whole_continent_known(cont)) {
6493 }
6494 } else if (cont < 0) {
6495 min_tiles = nmap->ocean_sizes[-cont];
6496 if (is_whole_ocean_known(-cont)) {
6498 }
6499 }
6500 }
6501 break;
6502 default:
6504 "Illegal range %d for max region tiles requirement.",
6505 req->range);
6506 return TRI_MAYBE;
6507 }
6508
6509 if (min_tiles > req->source.value.region_tiles) {
6510 return TRI_NO;
6511 } else if (max_tiles <= req->source.value.region_tiles) {
6512 return TRI_YES;
6513 }
6514 return TRI_MAYBE;
6515}
6516
6517/**********************************************************************/
6525static enum fc_tristate
6527 const struct req_context *context,
6528 const struct req_context *other_context,
6529 const struct requirement *req)
6530{
6532
6534}
6535
6536/**********************************************************************/
6544static enum fc_tristate
6546 const struct req_context *context,
6547 const struct req_context *other_context,
6548 const struct requirement *req)
6549{
6551
6553 >= req->source.value.mincalfrag);
6554}
6555
6556/**********************************************************************/
6564static enum fc_tristate
6566 const struct req_context *context,
6567 const struct req_context *other_context,
6568 const struct requirement *req)
6569{
6571
6572 return BOOL_TO_TRISTATE(
6574}
6575
6576/**********************************************************************/
6584static enum fc_tristate
6586 const struct req_context *context,
6587 const struct req_context *other_context,
6588 const struct requirement *req)
6589{
6591
6592 return BOOL_TO_TRISTATE(
6594}
6595
6596/**********************************************************************/
6604static enum fc_tristate
6606 const struct req_context *context,
6607 const struct req_context *other_context,
6608 const struct requirement *req)
6609{
6611
6613 req->source.value.ssetval));
6614}
6615
6616/* Not const for potential ruleset-related adjustment */
6619
6620 /* Alphabetical order of enum constant */
6687};
6688
6689/**********************************************************************/
6703 const struct req_context *other_context,
6704 const struct requirement *req,
6705 const enum req_problem_type prob_type)
6706{
6707 const struct civ_map *nmap = &(wld.map);
6708 enum fc_tristate eval;
6710 struct thr_req_data *trdata = NULL;
6711
6714 if (fc_threads_equal(self, data->thr_id)) {
6715 trdata = data;
6716 }
6718
6719 if (trdata == NULL) {
6720 trdata = fc_malloc(sizeof(struct thr_req_data));
6721 trdata->thr_id = self;
6723 }
6725
6727
6728 if (eval == TRI_MAYBE) {
6729 if (prob_type == RPT_POSSIBLE) {
6730 return TRUE;
6731 } else {
6732 return FALSE;
6733 }
6734 }
6735
6736 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
6737}
6738
6739/**********************************************************************/
6748static
6750 const struct req_context *context,
6751 const struct req_context *other_context,
6752 const struct requirement *req)
6753{
6754 if (!context) {
6756 }
6757 if (!other_context) {
6759 }
6760
6761 if (req->source.kind >= VUT_COUNT) {
6762 log_error("tri_req_present(): invalid source kind %d.",
6763 req->source.kind);
6764 return TRI_NO;
6765 }
6766
6768
6769 return req_definitions[req->source.kind].cb(nmap, context,
6770 other_context, req);
6771}
6772
6773/**********************************************************************/
6783 const struct req_context *other_context,
6784 const struct requirement *req)
6785{
6786 const struct civ_map *nmap = &(wld.map);
6788
6789 if (!req->present) {
6790 if (TRI_NO == eval) {
6791 return TRI_YES;
6792 }
6793 if (TRI_YES == eval) {
6794 return TRI_NO;
6795 }
6796 }
6797
6798 return eval;
6799}
6800
6801/**********************************************************************/
6817 const struct req_context *other_context,
6818 const struct requirement_vector *reqs,
6819 const enum req_problem_type prob_type)
6820{
6823 return FALSE;
6824 }
6826
6827 return TRUE;
6828}
6829
6830/**********************************************************************/
6835 const enum req_range max_range,
6836 const struct req_context *context,
6837 const struct req_context *other_context,
6838 const struct requirement_vector *reqs,
6839 const enum req_problem_type prob_type)
6840{
6842 if (preq->range >= min_range && preq->range <= max_range) {
6844 return FALSE;
6845 }
6846 }
6848
6849 return TRUE;
6850}
6851
6852/**********************************************************************/
6858enum fc_tristate
6860 const struct req_context *context,
6861 const struct req_context *other_context,
6862 const struct requirement *req)
6863{
6864 /* FIXME: Doubles code from calendar.c */
6868 int fragment1 = fragment; /* If fragments don't advance */
6869 int year_inc, year_inc1;
6872 bool present, present1;
6873
6874 fc_assert(pass >= 0 && period >= 0);
6875 if (slowdown >= 3) {
6876 if (ypt > 1) {
6877 ypt = 1;
6878 }
6879 } else if (slowdown >= 2) {
6880 if (ypt > 2) {
6881 ypt = 2;
6882 }
6883 } else if (slowdown >= 1) {
6884 if (ypt > 5) {
6885 ypt = 5;
6886 }
6887 }
6888 year_inc = ypt * pass;
6891 int fragment_years;
6892
6893 fragment += fpt * pass;
6901 }
6903 if (year_inc + game.info.year >= 0) {
6904 year_inc++;
6905 year_inc1++;
6906 } else if (year_inc1 + game.info.year >= 0) {
6907 year_inc1++;
6908 }
6909 }
6910
6911 switch (req->source.kind) {
6912 case VUT_AGE:
6913 switch (req->range) {
6914 case REQ_RANGE_LOCAL:
6915 if (context->unit == nullptr || !is_server()) {
6916 return TRI_MAYBE;
6917 } else {
6918 int ua = game.info.turn + pass - context->unit->birth_turn;
6919
6920 present = req->source.value.age <= ua;
6921 present1 = req->source.value.age <= ua + period;
6922 }
6923 break;
6924 case REQ_RANGE_CITY:
6925 if (context->city == nullptr) {
6926 return TRI_MAYBE;
6927 } else {
6928 int ca = game.info.turn + pass - context->city->turn_founded;
6929
6930 present = req->source.value.age <= ca;
6931 present1 = req->source.value.age <= ca + period;
6932 }
6933 break;
6934 case REQ_RANGE_PLAYER:
6935 if (context->player == nullptr) {
6936 return TRI_MAYBE;
6937 } else {
6938 present = req->source.value.age
6939 <= player_age(context->player) + pass;
6940 present1 = req->source.value.age
6941 <= player_age(context->player) + pass + period;
6942 }
6943 break;
6944 default:
6945 return TRI_MAYBE;
6946 }
6947 break;
6948 case VUT_FORM_AGE:
6949 if (context->unit == nullptr || !is_server()) {
6950 return TRI_MAYBE;
6951 } else {
6952 int ua = game.info.turn + pass - context->unit->current_form_turn;
6953
6954 present = req->source.value.form_age <= ua;
6955 present1 = req->source.value.form_age <= ua + period;
6956 }
6957 break;
6958 case VUT_MINYEAR:
6959 present = game.info.year + year_inc >= req->source.value.minyear;
6961 break;
6962 case VUT_MINCALFRAG:
6964 /* Hope that the requirement is valid and fragments advance fine */
6965 return TRI_YES;
6966 }
6967 present = fragment >= req->source.value.mincalfrag;
6969 break;
6970 default:
6971 /* No special handling invented */
6972 return tri_req_active(context, other_context, req);
6973 }
6974 return BOOL_TO_TRISTATE(req->present
6975 ? present || present1 : !(present && present1));
6976}
6977
6978/**********************************************************************/
6984 (const struct req_context *context,
6985 const struct req_context *other_context,
6986 const struct requirement *req,
6987 void *data, int n_data)
6988{
6989 int i;
6990
6991 fc_assert_ret_val(data || n_data == 0, TRI_NO);
6992
6993 for (i = 0; i < n_data; i++) {
6994 if (are_requirements_contradictions(&((struct requirement *) data)[i],
6995 req)) {
6996 return TRI_NO;
6997 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
6998 return TRI_YES;
6999 }
7000 }
7001
7002 return tri_req_active(context, other_context, req);
7003}
7004
7005/**********************************************************************/
7011enum fc_tristate
7013 const struct req_context *other_context,
7014 const struct requirement_vector *reqs,
7017 void *data, int n_data)
7018{
7019 bool active = TRUE;
7020 bool certain = TRUE;
7021
7022 fc_assert_ret_val(tester != nullptr, TRI_NO);
7023
7026 data, n_data)) {
7027 case TRI_NO:
7028 active = FALSE;
7029 certain = TRUE;
7030 break;
7031 case TRI_YES:
7032 break;
7033 case TRI_MAYBE:
7034 certain = FALSE;
7035 if (maybe_reqs) {
7037 }
7038 break;
7039 default:
7041 active = FALSE;
7042 }
7043 if (!active) {
7044 break;
7045 }
7047
7048 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
7049}
7050
7051/**********************************************************************/
7061 const struct requirement *req)
7062{
7063 enum req_unchanging_status s;
7064 const struct civ_map *nmap = &(wld.map);
7065
7068 "Invalid source kind %d.", req->source.kind);
7070
7071 if (req->survives) {
7072 /* Special case for surviving requirements */
7073 /* Buildings may obsolete even here */
7074 if (VUT_IMPROVEMENT == req->source.kind) {
7075 const struct impr_type *b = req->source.value.building;
7076
7078 if (improvement_obsolete(context->player, b, context->city)) {
7079 /* FIXME: Sometimes can unobsolete, but considering it
7080 * may sometimes put the function on endless recursion */
7081 return REQUCH_ACT; /* Mostly about techs */
7082 } else {
7083 /* NOTE: May obsoletion reqs be unchanging? Hardly but why not. */
7084 return REQUCH_NO;
7085 }
7086 }
7087 }
7088 s = unchanging_present(nmap, s, context, req);
7089 if (s != REQUCH_NO) {
7090 return unchanging_noally(nmap, s, context, req);
7091 }
7092 } else {
7095
7096 if (cond) {
7097 return cond(nmap, s, context, req);
7098 }
7099 }
7100
7101 return s;
7102}
7103
7104/**********************************************************************/
7109 const struct req_context *other_context,
7110 const struct requirement *req,
7112{
7114
7115 if (REQUCH_NO != u) {
7116 /* Presence is precalculated */
7117 bool auto_present = (req->survives
7118 && !(VUT_IMPROVEMENT == req->source.kind
7122
7123 if (auto_present ? req->present
7125 /* Unchanging but does not block */
7126 return REQUCH_NO;
7127 }
7128 }
7129
7130 return u;
7131}
7132
7133/**********************************************************************/
7137bool is_req_in_vec(const struct requirement *req,
7138 const struct requirement_vector *vec)
7139{
7141 if (are_requirements_equal(req, preq)) {
7142 return TRUE;
7143 }
7145
7146 return FALSE;
7147}
7148
7149/**********************************************************************/
7157 enum universals_n kind)
7158{
7160 if (preq->present && preq->source.kind == kind) {
7161 return TRUE;
7162 }
7164 return FALSE;
7165}
7166
7167/**********************************************************************/
7176{
7177 switch (source->kind) {
7178 case VUT_ACTION:
7179 return !action_is_in_use(source->value.action);
7180 case VUT_UTFLAG:
7181 return !utype_flag_is_in_use(source->value.unitflag);
7182 case VUT_UCFLAG:
7183 return !uclass_flag_is_in_use(source->value.unitclassflag);
7184 case VUT_EXTRAFLAG:
7185 return !extra_flag_is_in_use(source->value.extraflag);
7186 case VUT_MINLATITUDE:
7187 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
7188 case VUT_MAXLATITUDE:
7189 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
7190 case VUT_COUNTER:
7191 case VUT_OTYPE:
7192 case VUT_SPECIALIST:
7193 case VUT_AI_LEVEL:
7194 case VUT_CITYTILE:
7195 case VUT_CITYSTATUS:
7196 case VUT_STYLE:
7197 case VUT_TOPO:
7198 case VUT_WRAP:
7199 case VUT_SERVERSETTING:
7200 case VUT_NATION:
7201 case VUT_NATIONGROUP:
7202 case VUT_ADVANCE:
7203 case VUT_TECHFLAG:
7204 case VUT_GOVERNMENT:
7205 case VUT_GOVFLAG:
7206 case VUT_ACHIEVEMENT:
7207 case VUT_IMPROVEMENT:
7208 case VUT_SITE:
7209 case VUT_IMPR_GENUS:
7210 case VUT_IMPR_FLAG:
7211 case VUT_PLAYER_FLAG:
7212 case VUT_PLAYER_STATE:
7213 case VUT_MINSIZE:
7214 case VUT_MINCULTURE:
7215 case VUT_MINFOREIGNPCT:
7216 case VUT_MINTECHS:
7217 case VUT_FUTURETECHS:
7218 case VUT_MINCITIES:
7219 case VUT_NATIONALITY:
7220 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
7221 case VUT_DIPLREL:
7222 case VUT_DIPLREL_TILE:
7223 case VUT_DIPLREL_TILE_O:
7228 case VUT_UTYPE:
7229 case VUT_UCLASS:
7230 case VUT_MINVETERAN:
7231 case VUT_UNITSTATE:
7232 case VUT_ACTIVITY:
7233 case VUT_MINMOVES:
7234 case VUT_MINHP:
7235 case VUT_AGE:
7236 case VUT_FORM_AGE:
7237 case VUT_ROADFLAG:
7238 case VUT_MINCALFRAG:
7239 case VUT_TERRAIN:
7240 case VUT_EXTRA:
7241 case VUT_TILEDEF:
7242 case VUT_GOOD:
7243 case VUT_TERRAINCLASS:
7244 case VUT_TERRFLAG:
7245 case VUT_TERRAINALTER:
7246 case VUT_MINYEAR:
7249 case VUT_TILE_REL:
7250 case VUT_NONE:
7251 case VUT_COUNT:
7252 /* Not implemented. */
7253 break;
7254 }
7255
7256 return FALSE;
7257}
7258
7259/**********************************************************************/
7268{
7269 /* Not known to be impossible to fulfill */
7270 return req->present && universal_never_there(&req->source);
7271}
7272
7273/**********************************************************************/
7282{
7285 return TRUE;
7286 }
7288
7289 /* Not known to be impossible to fulfill */
7290 return FALSE;
7291}
7292
7293/**********************************************************************/
7303 const struct requirement_vector *vec)
7304{
7305 if (vec) {
7306 return 0;
7307 } else {
7308 return -1;
7309 }
7310}
7311
7312/********************************************************************/
7321struct requirement_vector *
7323{
7324 fc_assert_ret_val(number == 0, nullptr);
7325
7326 return (struct requirement_vector *)parent_item;
7327}
7328
7329/**********************************************************************/
7340const char *req_vec_change_translation(const struct req_vec_change *change,
7342{
7343 const char *req_vec_description;
7344 static char buf[MAX_LEN_NAME * 3];
7345 struct astring astr;
7346
7347 fc_assert_ret_val(change, nullptr);
7349 nullptr);
7350
7351 /* Get rid of the previous. */
7352 buf[0] = '\0';
7353
7354 if (namer == nullptr) {
7355 /* TRANS: default description of a requirement vector
7356 * (used in ruledit) */
7357 req_vec_description = _("the requirement vector");
7358 } else {
7360 }
7361
7362 switch (change->operation) {
7363 case RVCO_REMOVE:
7364 fc_snprintf(buf, sizeof(buf),
7365 /* TRANS: remove a requirement from a requirement vector
7366 * (in ruledit).
7367 * The first %s is the operation.
7368 * The second %s is the requirement.
7369 * The third %s is a description of the requirement vector,
7370 * like "actor_reqs" */
7371 _("%s %s from %s"),
7373 req_to_fstring(&change->req, &astr),
7375 astr_free(&astr);
7376 break;
7377 case RVCO_APPEND:
7378 fc_snprintf(buf, sizeof(buf),
7379 /* TRANS: append a requirement to a requirement vector
7380 * (in ruledit).
7381 * The first %s is the operation.
7382 * The second %s is the requirement.
7383 * The third %s is a description of the requirement vector,
7384 * like "actor_reqs" */
7385 _("%s %s to %s"),
7387 req_to_fstring(&change->req, &astr),
7389 astr_free(&astr);
7390 break;
7391 case RVCO_NOOP:
7392 fc_snprintf(buf, sizeof(buf),
7393 /* TRANS: do nothing to a requirement vector (in ruledit).
7394 * The first %s is a description of the requirement vector,
7395 * like "actor_reqs" */
7396 _("Do nothing to %s"), req_vec_description);
7397 break;
7398 }
7399
7400 return buf;
7401}
7402
7403/**********************************************************************/
7416 const void *parent_item)
7417{
7418 struct requirement_vector *target
7419 = getter(parent_item, modification->vector_number);
7420 int i = 0;
7421
7422 switch (modification->operation) {
7423 case RVCO_APPEND:
7425 return TRUE;
7426 case RVCO_REMOVE:
7430 return TRUE;
7431 }
7432 i++;
7434 return FALSE;
7435 case RVCO_NOOP:
7436 return FALSE;
7437 }
7438
7439 return FALSE;
7440}
7441
7442/**********************************************************************/
7452struct req_vec_problem *
7454 const char *description,
7455 const char *description_translated)
7456{
7457 struct req_vec_problem *out;
7458 int i;
7459
7460 out = fc_malloc(sizeof(*out));
7461
7462 fc_strlcpy(out->description, description, sizeof(out->description));
7463 fc_strlcpy(out->description_translated, _(description_translated),
7464 sizeof(out->description_translated));
7465
7466 out->num_suggested_solutions = num_suggested_solutions;
7467 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
7468 * sizeof(struct req_vec_change));
7469 for (i = 0; i < out->num_suggested_solutions; i++) {
7470 /* No suggestions are ready yet. */
7471 out->suggested_solutions[i].operation = RVCO_NOOP;
7472 out->suggested_solutions[i].vector_number = -1;
7473 out->suggested_solutions[i].req.source.kind = VUT_NONE;
7474 }
7475
7476 return out;
7477}
7478
7479/**********************************************************************/
7489 const char *descr, ...)
7490{
7491 char description[500];
7492 char description_translated[500];
7493 va_list ap;
7494
7495 va_start(ap, descr);
7496 fc_vsnprintf(description, sizeof(description), descr, ap);
7497 va_end(ap);
7498
7499 va_start(ap, descr);
7501 _(descr), ap);
7502 va_end(ap);
7503
7506}
7507
7508/**********************************************************************/
7515{
7516 FC_FREE(issue->suggested_solutions);
7517 issue->num_suggested_solutions = 0;
7518
7519 FC_FREE(issue);
7520}
7521
7522/**********************************************************************/
7534struct req_vec_problem *
7537 const void *parent_item)
7538{
7539 int i, j;
7541
7542 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7543 /* No vector. */
7544 return nullptr;
7545 }
7546
7547 if (get_num == nullptr || parent_item == nullptr) {
7548 vec_num = 0;
7549 } else {
7550 vec_num = get_num(parent_item, vec);
7551 }
7552
7553 /* Look for contradictions */
7554 for (i = 0; i < requirement_vector_size(vec); i++) {
7555 struct requirement *preq = requirement_vector_get(vec, i);
7556 for (j = 0; j < requirement_vector_size(vec); j++) {
7557 struct requirement *nreq = requirement_vector_get(vec, j);
7558
7560 struct req_vec_problem *problem;
7561 struct astring astr;
7562 struct astring nastr;
7563
7565 N_("Requirements {%s} and {%s} contradict each other."),
7567
7568 astr_free(&astr);
7569 astr_free(&nastr);
7570
7571 /* The solution is to remove one of the contradictions. */
7572 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7573 problem->suggested_solutions[0].vector_number = vec_num;
7574 problem->suggested_solutions[0].req = *preq;
7575
7576 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7577 problem->suggested_solutions[1].vector_number = vec_num;
7578 problem->suggested_solutions[1].req = *nreq;
7579
7580 /* Only the first contradiction is reported. */
7581 return problem;
7582 }
7583 }
7584 }
7585
7586 return nullptr;
7587}
7588
7589/**********************************************************************/
7600struct req_vec_problem *
7603 const void *parent_item)
7604{
7605 /* Check for self contradictins. */
7607}
7608
7609/**********************************************************************/
7622struct req_vec_problem *
7625 const void *parent_item)
7626{
7627 int i;
7629 struct req_vec_problem *problem = nullptr;
7630
7631 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7632 /* No vector. */
7633 return nullptr;
7634 }
7635
7636 if (get_num == nullptr || parent_item == nullptr) {
7637 vec_num = 0;
7638 } else {
7639 vec_num = get_num(parent_item, vec);
7640 }
7641
7642 /* Look for contradictions */
7643 for (i = 0; i < requirement_vector_size(vec); i++) {
7644 struct requirement *preq = requirement_vector_get(vec, i);
7645
7646 if (universal_never_there(&preq->source)) {
7647 struct astring astr;
7648
7649 if (preq->present) {
7650 /* The requirement vector can never be fulfilled. Removing the
7651 * requirement makes it possible to fulfill it. This is a rule
7652 * change and shouldn't be "fixed" without thinking. Don't offer any
7653 * automatic solution to prevent mindless "fixes". */
7654 /* TRANS: Ruledit warns a user about an unused requirement vector
7655 * that never can be fulfilled because it asks for something that
7656 * never will be there. */
7657 if (problem == nullptr) {
7659 N_("Requirement {%s} requires %s but it will never be"
7660 " there."),
7662 astr_free(&astr);
7663 }
7664
7665 /* Continue to check if other problems have a solution proposal,
7666 * and prefer to return those. */
7667 continue;
7668 }
7669
7670 if (problem != nullptr) {
7671 /* Free previous one (one with no solution proposals) */
7673 }
7674
7676 N_("Requirement {%s} mentions %s but it will never be there."),
7678
7679 astr_free(&astr);
7680
7681 /* The solution is to remove the reference to the missing
7682 * universal. */
7683 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7684 problem->suggested_solutions[0].vector_number = vec_num;
7685 problem->suggested_solutions[0].req = *preq;
7686
7687 /* Only the first missing universal is reported. */
7688 return problem;
7689 }
7690 }
7691
7692 return problem;
7693}
7694
7695/**********************************************************************/
7708struct req_vec_problem *
7711 const void *parent_item)
7712{
7713 int i, j;
7715
7716 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7717 /* No vector. */
7718 return nullptr;
7719 }
7720
7721 if (get_num == nullptr || parent_item == nullptr) {
7722 vec_num = 0;
7723 } else {
7724 vec_num = get_num(parent_item, vec);
7725 }
7726
7727 /* Look for repeated requirements */
7728 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
7729 struct requirement *preq = requirement_vector_get(vec, i);
7730 for (j = i + 1; j < requirement_vector_size(vec); j++) {
7731 struct requirement *nreq = requirement_vector_get(vec, j);
7732
7734 struct req_vec_problem *problem;
7735 struct astring astr;
7736 struct astring nastr;
7737
7739 N_("Requirements {%s} and {%s} are the same."),
7741
7742 astr_free(&astr);
7743 astr_free(&nastr);
7744
7745 /* The solution is to remove one of the redundant requirements. */
7746 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7747 problem->suggested_solutions[0].vector_number = vec_num;
7748 problem->suggested_solutions[0].req = *preq;
7749
7750 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7751 problem->suggested_solutions[1].vector_number = vec_num;
7752 problem->suggested_solutions[1].req = *nreq;
7753
7754 /* Only the first redundancy is reported. */
7755 return problem;
7756 }
7757 }
7758 }
7759
7760 return nullptr;
7761}
7762
7763/**********************************************************************/
7775struct req_vec_problem *
7778 const void *parent_item)
7779{
7780 struct req_vec_problem *out;
7781
7783 if (out != nullptr) {
7784 /* A bug, not just a potential improvement */
7785 return out;
7786 }
7787
7788 /* Check if a universal that never will appear in the game is checked. */
7790 if (out != nullptr) {
7791 return out;
7792 }
7793
7794 /* Check if a requirement is redundant. */
7796 return out;
7797}
7798
7799/**********************************************************************/
7804 const struct universal *psource2)
7805{
7806 if (psource1->kind != psource2->kind) {
7807 return FALSE;
7808 }
7809 switch (psource1->kind) {
7810 case VUT_NONE:
7811 return TRUE;
7812 case VUT_COUNTER:
7813 return psource1->value.counter == psource2->value.counter;
7814 case VUT_ADVANCE:
7815 return psource1->value.advance == psource2->value.advance;
7816 case VUT_TECHFLAG:
7817 return psource1->value.techflag == psource2->value.techflag;
7818 case VUT_GOVERNMENT:
7819 return psource1->value.govern == psource2->value.govern;
7820 case VUT_GOVFLAG:
7821 return psource1->value.govflag == psource2->value.govflag;
7822 case VUT_ACHIEVEMENT:
7823 return psource1->value.achievement == psource2->value.achievement;
7824 case VUT_STYLE:
7825 return psource1->value.style == psource2->value.style;
7826 case VUT_IMPROVEMENT:
7827 case VUT_SITE:
7828 return psource1->value.building == psource2->value.building;
7829 case VUT_IMPR_GENUS:
7830 return psource1->value.impr_genus == psource2->value.impr_genus;
7831 case VUT_IMPR_FLAG:
7832 return psource1->value.impr_flag == psource2->value.impr_flag;
7833 case VUT_PLAYER_FLAG:
7834 return psource1->value.plr_flag == psource2->value.plr_flag;
7835 case VUT_PLAYER_STATE:
7836 return psource1->value.plrstate == psource2->value.plrstate;
7837 case VUT_EXTRA:
7838 return psource1->value.extra == psource2->value.extra;
7839 case VUT_TILEDEF:
7840 return psource1->value.tiledef == psource2->value.tiledef;
7841 case VUT_GOOD:
7842 return psource1->value.good == psource2->value.good;
7843 case VUT_TERRAIN:
7844 return psource1->value.terrain == psource2->value.terrain;
7845 case VUT_TERRFLAG:
7846 return psource1->value.terrainflag == psource2->value.terrainflag;
7847 case VUT_NATION:
7848 return psource1->value.nation == psource2->value.nation;
7849 case VUT_NATIONGROUP:
7850 return psource1->value.nationgroup == psource2->value.nationgroup;
7851 case VUT_NATIONALITY:
7852 return psource1->value.nationality == psource2->value.nationality;
7853 case VUT_ORIGINAL_OWNER:
7854 return psource1->value.origowner == psource2->value.origowner;
7855 case VUT_DIPLREL:
7856 case VUT_DIPLREL_TILE:
7857 case VUT_DIPLREL_TILE_O:
7860 return psource1->value.diplrel == psource2->value.diplrel;
7861 case VUT_UTYPE:
7862 return psource1->value.utype == psource2->value.utype;
7863 case VUT_UTFLAG:
7864 return psource1->value.unitflag == psource2->value.unitflag;
7865 case VUT_UCLASS:
7866 return psource1->value.uclass == psource2->value.uclass;
7867 case VUT_UCFLAG:
7868 return psource1->value.unitclassflag == psource2->value.unitclassflag;
7869 case VUT_MINVETERAN:
7870 return psource1->value.minveteran == psource2->value.minveteran;
7871 case VUT_UNITSTATE:
7872 return psource1->value.unit_state == psource2->value.unit_state;
7873 case VUT_ACTIVITY:
7874 return psource1->value.activity == psource2->value.activity;
7875 case VUT_MINMOVES:
7876 return psource1->value.minmoves == psource2->value.minmoves;
7877 case VUT_MINHP:
7878 return psource1->value.min_hit_points == psource2->value.min_hit_points;
7879 case VUT_AGE:
7880 return psource1->value.age == psource2->value.age;
7881 case VUT_FORM_AGE:
7882 return psource1->value.form_age == psource2->value.form_age;
7883 case VUT_MINTECHS:
7884 return psource1->value.min_techs == psource2->value.min_techs;
7885 case VUT_FUTURETECHS:
7886 return psource1->value.future_techs == psource2->value.future_techs;
7887 case VUT_MINCITIES:
7888 return psource1->value.min_cities == psource2->value.min_cities;
7889 case VUT_ACTION:
7890 return (action_number(psource1->value.action)
7891 == action_number(psource2->value.action));
7892 case VUT_OTYPE:
7893 return psource1->value.outputtype == psource2->value.outputtype;
7894 case VUT_SPECIALIST:
7895 return psource1->value.specialist == psource2->value.specialist;
7896 case VUT_MINSIZE:
7897 return psource1->value.minsize == psource2->value.minsize;
7898 case VUT_MINCULTURE:
7899 return psource1->value.minculture == psource2->value.minculture;
7900 case VUT_MINFOREIGNPCT:
7901 return psource1->value.minforeignpct == psource2->value.minforeignpct;
7902 case VUT_AI_LEVEL:
7903 return psource1->value.ai_level == psource2->value.ai_level;
7905 return psource1->value.max_tile_total_units == psource2->value.max_tile_total_units;
7907 return psource1->value.max_tile_top_units == psource2->value.max_tile_top_units;
7908 case VUT_TERRAINCLASS:
7909 return psource1->value.terrainclass == psource2->value.terrainclass;
7910 case VUT_ROADFLAG:
7911 return psource1->value.roadflag == psource2->value.roadflag;
7912 case VUT_EXTRAFLAG:
7913 return psource1->value.extraflag == psource2->value.extraflag;
7914 case VUT_MINYEAR:
7915 return psource1->value.minyear == psource2->value.minyear;
7916 case VUT_MINCALFRAG:
7917 return psource1->value.mincalfrag == psource2->value.mincalfrag;
7918 case VUT_TOPO:
7919 return psource1->value.topo_property == psource2->value.topo_property;
7920 case VUT_WRAP:
7921 return psource1->value.wrap_property == psource2->value.wrap_property;
7922 case VUT_SERVERSETTING:
7923 return psource1->value.ssetval == psource2->value.ssetval;
7924 case VUT_TERRAINALTER:
7925 return psource1->value.terrainalter == psource2->value.terrainalter;
7926 case VUT_CITYTILE:
7927 return psource1->value.citytile == psource2->value.citytile;
7928 case VUT_CITYSTATUS:
7929 return psource1->value.citystatus == psource2->value.citystatus;
7930 case VUT_TILE_REL:
7931 return psource1->value.tilerel == psource2->value.tilerel;
7932 case VUT_MINLATITUDE:
7933 case VUT_MAXLATITUDE:
7934 return psource1->value.latitude == psource2->value.latitude;
7936 return psource1->value.distance_sq == psource2->value.distance_sq;
7938 return psource1->value.region_tiles == psource2->value.region_tiles;
7939 case VUT_COUNT:
7940 break;
7941 }
7942
7943 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
7944 return FALSE;
7945}
7946
7947/**********************************************************************/
7951const char *universal_rule_name(const struct universal *psource)
7952{
7953 static char buffer[10];
7954
7955 switch (psource->kind) {
7956 case VUT_NONE:
7957 return "(none)";
7958 case VUT_COUNTER:
7959 return counter_rule_name(psource->value.counter);
7960 case VUT_CITYTILE:
7961 return citytile_type_name(psource->value.citytile);
7962 case VUT_CITYSTATUS:
7963 return citystatus_type_name(psource->value.citystatus);
7964 case VUT_TILE_REL:
7965 return tilerel_type_name(psource->value.tilerel);
7966 case VUT_MINYEAR:
7967 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
7968
7969 return buffer;
7970 case VUT_MINCALFRAG:
7971 /* Rule name is 0-based number, not pretty name from ruleset */
7972 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
7973
7974 return buffer;
7975 case VUT_TOPO:
7976 return topo_flag_name(psource->value.topo_property);
7977 case VUT_WRAP:
7978 return wrap_flag_name(psource->value.wrap_property);
7979 case VUT_SERVERSETTING:
7980 return ssetv_rule_name(psource->value.ssetval);
7981 case VUT_ADVANCE:
7982 return advance_rule_name(psource->value.advance);
7983 case VUT_TECHFLAG:
7984 return tech_flag_id_name(psource->value.techflag);
7985 case VUT_GOVERNMENT:
7986 return government_rule_name(psource->value.govern);
7987 case VUT_GOVFLAG:
7988 return gov_flag_id_name(psource->value.govflag);
7989 case VUT_ACHIEVEMENT:
7990 return achievement_rule_name(psource->value.achievement);
7991 case VUT_STYLE:
7992 return style_rule_name(psource->value.style);
7993 case VUT_IMPROVEMENT:
7994 case VUT_SITE:
7995 return improvement_rule_name(psource->value.building);
7996 case VUT_IMPR_GENUS:
7997 return impr_genus_id_name(psource->value.impr_genus);
7998 case VUT_IMPR_FLAG:
7999 return impr_flag_id_name(psource->value.impr_flag);
8000 case VUT_PLAYER_FLAG:
8001 return plr_flag_id_name(psource->value.plr_flag);
8002 case VUT_PLAYER_STATE:
8003 return plrstate_type_name(psource->value.plrstate);
8004 case VUT_EXTRA:
8005 return extra_rule_name(psource->value.extra);
8006 case VUT_TILEDEF:
8007 return tiledef_rule_name(psource->value.tiledef);
8008 case VUT_GOOD:
8009 return goods_rule_name(psource->value.good);
8010 case VUT_TERRAIN:
8011 return terrain_rule_name(psource->value.terrain);
8012 case VUT_TERRFLAG:
8013 return terrain_flag_id_name(psource->value.terrainflag);
8014 case VUT_NATION:
8015 return nation_rule_name(psource->value.nation);
8016 case VUT_NATIONGROUP:
8017 return nation_group_rule_name(psource->value.nationgroup);
8018 case VUT_DIPLREL:
8019 case VUT_DIPLREL_TILE:
8020 case VUT_DIPLREL_TILE_O:
8023 return diplrel_rule_name(psource->value.diplrel);
8024 case VUT_NATIONALITY:
8025 return nation_rule_name(psource->value.nationality);
8026 case VUT_ORIGINAL_OWNER:
8027 return nation_rule_name(psource->value.origowner);
8028 case VUT_UTYPE:
8029 return utype_rule_name(psource->value.utype);
8030 case VUT_UTFLAG:
8031 return unit_type_flag_id_name(psource->value.unitflag);
8032 case VUT_UCLASS:
8033 return uclass_rule_name(psource->value.uclass);
8034 case VUT_UCFLAG:
8035 return unit_class_flag_id_name(psource->value.unitclassflag);
8036 case VUT_MINVETERAN:
8037 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
8038
8039 return buffer;
8040 case VUT_UNITSTATE:
8041 return ustate_prop_name(psource->value.unit_state);
8042 case VUT_ACTIVITY:
8043 return unit_activity_name(psource->value.activity);
8044 case VUT_MINMOVES:
8045 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
8046
8047 return buffer;
8048 case VUT_MINHP:
8049 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
8050
8051 return buffer;
8052 case VUT_AGE:
8053 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
8054
8055 return buffer;
8056 case VUT_FORM_AGE:
8057 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
8058
8059 return buffer;
8060 case VUT_MINTECHS:
8061 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
8062
8063 return buffer;
8064 case VUT_FUTURETECHS:
8065 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.future_techs);
8066
8067 return buffer;
8068 case VUT_MINCITIES:
8069 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_cities);
8070
8071 return buffer;
8072 case VUT_ACTION:
8073 return action_rule_name(psource->value.action);
8074 case VUT_OTYPE:
8075 return get_output_identifier(psource->value.outputtype);
8076 case VUT_SPECIALIST:
8077 return specialist_rule_name(psource->value.specialist);
8078 case VUT_MINSIZE:
8079 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
8080
8081 return buffer;
8082 case VUT_MINCULTURE:
8083 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
8084
8085 return buffer;
8086 case VUT_MINFOREIGNPCT:
8087 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
8088
8089 return buffer;
8090 case VUT_AI_LEVEL:
8091 return ai_level_name(psource->value.ai_level);
8093 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_total_units);
8094 return buffer;
8096 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_top_units);
8097 return buffer;
8098 case VUT_TERRAINCLASS:
8099 return terrain_class_name(psource->value.terrainclass);
8100 case VUT_ROADFLAG:
8101 return road_flag_id_name(psource->value.roadflag);
8102 case VUT_EXTRAFLAG:
8103 return extra_flag_id_name(psource->value.extraflag);
8104 case VUT_TERRAINALTER:
8105 return terrain_alteration_name(psource->value.terrainalter);
8106 case VUT_MINLATITUDE:
8107 case VUT_MAXLATITUDE:
8108 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
8109
8110 return buffer;
8112 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.distance_sq);
8113
8114 return buffer;
8116 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.region_tiles);
8117
8118 return buffer;
8119 case VUT_COUNT:
8120 break;
8121 }
8122
8123 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8124
8125 return nullptr;
8126}
8127
8128/**********************************************************************/
8137 char *buf, size_t bufsz)
8138{
8139 buf[0] = '\0'; /* to be safe. */
8140 switch (psource->kind) {
8141 case VUT_NONE:
8142 /* TRANS: missing value */
8143 fc_strlcat(buf, _("(none)"), bufsz);
8144 return buf;
8145 case VUT_ADVANCE:
8147 return buf;
8148 case VUT_COUNTER:
8150 return buf;
8151 case VUT_TECHFLAG:
8152 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
8153 tech_flag_id_translated_name(psource->value.techflag));
8154 return buf;
8155 case VUT_GOVERNMENT:
8157 bufsz);
8158 return buf;
8159 case VUT_GOVFLAG:
8160 cat_snprintf(buf, bufsz, _("\"%s\" gov"),
8161 gov_flag_id_translated_name(psource->value.govflag));
8162 return buf;
8163 case VUT_ACHIEVEMENT:
8165 bufsz);
8166 return buf;
8167 case VUT_STYLE:
8169 bufsz);
8170 return buf;
8171 case VUT_IMPROVEMENT:
8173 bufsz);
8174 return buf;
8175 case VUT_SITE:
8176 {
8177 char local_buf[1024];
8178
8179 fc_snprintf(local_buf, sizeof(local_buf), _("%s site"),
8180 improvement_name_translation(psource->value.building));
8182 }
8183
8184 return buf;
8185 case VUT_IMPR_GENUS:
8187 impr_genus_id_translated_name(psource->value.impr_genus),
8188 bufsz);
8189 return buf;
8190 case VUT_IMPR_FLAG:
8192 impr_flag_id_translated_name(psource->value.impr_flag),
8193 bufsz);
8194 return buf;
8195 case VUT_PLAYER_FLAG:
8197 plr_flag_id_translated_name(psource->value.plr_flag),
8198 bufsz);
8199 return buf;
8200 case VUT_PLAYER_STATE:
8202 plrstate_type_translated_name(psource->value.plrstate),
8203 bufsz);
8204 return buf;
8205 case VUT_EXTRA:
8207 return buf;
8208 case VUT_TILEDEF:
8210 return buf;
8211 case VUT_GOOD:
8213 return buf;
8214 case VUT_TERRAIN:
8216 return buf;
8217 case VUT_NATION:
8219 bufsz);
8220 return buf;
8221 case VUT_NATIONGROUP:
8223 bufsz);
8224 return buf;
8225 case VUT_NATIONALITY:
8226 cat_snprintf(buf, bufsz, _("%s citizens"),
8227 nation_adjective_translation(psource->value.nationality));
8228 return buf;
8229 case VUT_ORIGINAL_OWNER:
8230 /* TRANS: Keep short. City founding nation. */
8231 cat_snprintf(buf, bufsz, _("%s original owner"),
8232 nation_adjective_translation(psource->value.origowner));
8233 return buf;
8234 case VUT_DIPLREL:
8235 case VUT_DIPLREL_TILE:
8236 case VUT_DIPLREL_TILE_O:
8240 bufsz);
8241 return buf;
8242 case VUT_UTYPE:
8244 return buf;
8245 case VUT_UTFLAG:
8247 /* TRANS: Unit type flag */
8248 Q_("?utflag:\"%s\" units"),
8250 psource->value.unitflag));
8251 return buf;
8252 case VUT_UCLASS:
8254 /* TRANS: Unit class */
8255 _("%s units"),
8256 uclass_name_translation(psource->value.uclass));
8257 return buf;
8258 case VUT_UCFLAG:
8260 /* TRANS: Unit class flag */
8261 Q_("?ucflag:\"%s\" units"),
8263 psource->value.unitclassflag));
8264 return buf;
8265 case VUT_MINVETERAN:
8266 /* FIXME */
8267 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
8268 psource->value.minveteran);
8269 return buf;
8270 case VUT_UNITSTATE:
8271 switch (psource->value.unit_state) {
8272 case USP_TRANSPORTED:
8273 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
8274 cat_snprintf(buf, bufsz, _("Transported"));
8275 break;
8276 case USP_LIVABLE_TILE:
8278 /* TRANS: unit state. (appears in strings like
8279 * "Missile+On livable tile") */
8280 _("On livable tile"));
8281 break;
8282 case USP_TRANSPORTING:
8283 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
8284 cat_snprintf(buf, bufsz, _("Transporting"));
8285 break;
8286 case USP_HAS_HOME_CITY:
8287 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
8288 cat_snprintf(buf, bufsz, _("Has a home city"));
8289 break;
8290 case USP_NATIVE_TILE:
8292 /* TRANS: unit state. (appears in strings like
8293 * "Missile+On native tile") */
8294 _("On native tile"));
8295 break;
8296 case USP_NATIVE_EXTRA:
8298 /* TRANS: unit state. (appears in strings like
8299 * "Missile+In native extra") */
8300 _("In native extra"));
8301 break;
8303 /* TRANS: unit state. (appears in strings like
8304 * "Missile+Has moved this turn") */
8305 cat_snprintf(buf, bufsz, _("Has moved this turn"));
8306 break;
8307 case USP_COUNT:
8308 fc_assert_msg(psource->value.unit_state != USP_COUNT,
8309 "Invalid unit state property.");
8310 break;
8311 }
8312 return buf;
8313 case VUT_ACTIVITY:
8314 cat_snprintf(buf, bufsz, _("%s activity"),
8315 Q_(unit_activity_name(psource->value.activity)));
8316 return buf;
8317 case VUT_MINMOVES:
8318 /* TRANS: Minimum unit movement points left for requirement to be met
8319 * (%s is a string like "1" or "2 1/3") */
8320 cat_snprintf(buf, bufsz, _("%s MP"),
8321 move_points_text(psource->value.minmoves, TRUE));
8322 return buf;
8323 case VUT_MINHP:
8324 /* TRANS: HP = hit points */
8325 cat_snprintf(buf, bufsz, _("%d HP"),
8326 psource->value.min_hit_points);
8327 return buf;
8328 case VUT_AGE:
8329 cat_snprintf(buf, bufsz, _("Age %d"),
8330 psource->value.age);
8331 return buf;
8332 case VUT_FORM_AGE:
8333 cat_snprintf(buf, bufsz, _("Form age %d"),
8334 psource->value.form_age);
8335 return buf;
8336 case VUT_MINTECHS:
8337 cat_snprintf(buf, bufsz, _("%d Techs"),
8338 psource->value.min_techs);
8339 return buf;
8340 case VUT_FUTURETECHS:
8341 cat_snprintf(buf, bufsz, _("%d Future techs"),
8342 psource->value.future_techs);
8343 return buf;
8344 case VUT_MINCITIES:
8345 cat_snprintf(buf, bufsz, _("%d Cities"),
8346 psource->value.min_cities);
8347 return buf;
8348 case VUT_ACTION:
8350 bufsz);
8351 return buf;
8352 case VUT_OTYPE:
8353 /* FIXME */
8354 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
8355 return buf;
8356 case VUT_SPECIALIST:
8358 bufsz);
8359 return buf;
8360 case VUT_MINSIZE:
8361 cat_snprintf(buf, bufsz, _("Size %d"),
8362 psource->value.minsize);
8363 return buf;
8364 case VUT_MINCULTURE:
8365 cat_snprintf(buf, bufsz, _("Culture %d"),
8366 psource->value.minculture);
8367 return buf;
8368 case VUT_MINFOREIGNPCT:
8369 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
8370 psource->value.minforeignpct);
8371 return buf;
8372 case VUT_AI_LEVEL:
8373 /* TRANS: "Hard AI" */
8374 cat_snprintf(buf, bufsz, _("%s AI"),
8375 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
8376 return buf;
8378 /* TRANS: here <= means 'less than or equal' */
8379 cat_snprintf(buf, bufsz, PL_("<=%d total unit",
8380 "<=%d total units",
8381 psource->value.max_tile_total_units),
8382 psource->value.max_tile_total_units);
8383 return buf;
8385 /* TRANS: here <= means 'less than or equal' */
8386 cat_snprintf(buf, bufsz, PL_("<=%d unit",
8387 "<=%d units", psource->value.max_tile_top_units),
8388 psource->value.max_tile_top_units);
8389 return buf;
8390 case VUT_TERRAINCLASS:
8391 /* TRANS: Terrain class: "Land terrain" */
8392 cat_snprintf(buf, bufsz, _("%s terrain"),
8393 terrain_class_name_translation(psource->value.terrainclass));
8394 return buf;
8395 case VUT_TERRFLAG:
8397 /* TRANS: Terrain flag */
8398 Q_("?terrflag:\"%s\" terrain"),
8400 psource->value.terrainflag));
8401 return buf;
8402 case VUT_ROADFLAG:
8404 /* TRANS: Road flag */
8405 Q_("?roadflag:\"%s\" road"),
8406 road_flag_id_translated_name(psource->value.roadflag));
8407 return buf;
8408 case VUT_EXTRAFLAG:
8410 /* TRANS: Extra flag */
8411 Q_("?extraflag:\"%s\" extra"),
8412 extra_flag_id_translated_name(psource->value.extraflag));
8413 return buf;
8414 case VUT_MINYEAR:
8415 cat_snprintf(buf, bufsz, _("After %s"),
8416 textyear(psource->value.minyear));
8417 return buf;
8418 case VUT_MINCALFRAG:
8419 /* TRANS: here >= means 'greater than or equal'.
8420 * %s identifies a calendar fragment (may be bare number). */
8421 cat_snprintf(buf, bufsz, _(">=%s"),
8422 textcalfrag(psource->value.mincalfrag));
8423 return buf;
8424 case VUT_TOPO:
8425 /* TRANS: topology flag name ("Hex", "ISO") */
8426 cat_snprintf(buf, bufsz, _("%s map"),
8427 _(topo_flag_name(psource->value.topo_property)));
8428 return buf;
8429 case VUT_WRAP:
8430 /* TRANS: wrap flag name ("WrapX", "WrapY") */
8431 cat_snprintf(buf, bufsz, _("%s map"),
8432 _(wrap_flag_name(psource->value.wrap_property)));
8433 return buf;
8434 case VUT_SERVERSETTING:
8436 bufsz);
8437 return buf;
8438 case VUT_TERRAINALTER:
8439 /* TRANS: "Irrigation possible" */
8440 cat_snprintf(buf, bufsz, _("%s possible"),
8441 Q_(terrain_alteration_name(psource->value.terrainalter)));
8442 return buf;
8443 case VUT_CITYTILE:
8444 switch (psource->value.citytile) {
8445 case CITYT_CENTER:
8446 fc_strlcat(buf, _("City center"), bufsz);
8447 break;
8448 case CITYT_CLAIMED:
8449 fc_strlcat(buf, _("Tile claimed"), bufsz);
8450 break;
8451 case CITYT_EXTRAS_OWNED:
8452 fc_strlcat(buf, _("Extras owned"), bufsz);
8453 break;
8454 case CITYT_WORKED:
8455 fc_strlcat(buf, _("Worked tile"), bufsz);
8456 break;
8458 fc_strlcat(buf, _("Same continent tile"), bufsz);
8459 break;
8461 /* TRANS: Short for "a tile of other terrain class mass near city" */
8462 fc_strlcat(buf, _("Port reachable tile"), bufsz);
8463 break;
8464 case CITYT_LAST:
8465 fc_assert(psource->value.citytile != CITYT_LAST);
8466 fc_strlcat(buf, "error", bufsz);
8467 break;
8468 }
8469 return buf;
8470 case VUT_CITYSTATUS:
8471 switch (psource->value.citystatus) {
8473 fc_strlcat(buf, _("Owned by original"), bufsz);
8474 break;
8475 case CITYS_STARVED:
8476 fc_strlcat(buf, _("Starved"), bufsz);
8477 break;
8478 case CITYS_DISORDER:
8479 fc_strlcat(buf, _("Disorder"), bufsz);
8480 break;
8481 case CITYS_CELEBRATION:
8482 fc_strlcat(buf, _("Celebration"), bufsz);
8483 break;
8484 case CITYS_TRANSFERRED:
8485 /* TRANS: CityStatus value - city has changed hands */
8486 fc_strlcat(buf, _("Transferred"), bufsz);
8487 break;
8489 fc_strlcat(buf, _("CapitalConnected"), bufsz);
8490 break;
8491 case CITYS_LAST:
8492 fc_assert(psource->value.citystatus != CITYS_LAST);
8493 fc_strlcat(buf, "error", bufsz);
8494 break;
8495 }
8496 return buf;
8497 case VUT_TILE_REL:
8498 switch (psource->value.tilerel) {
8499 case TREL_SAME_TCLASS:
8500 fc_strlcat(buf, _("Same terrain class"), bufsz);
8501 break;
8502 case TREL_SAME_REGION:
8503 fc_strlcat(buf, _("Same continent/ocean"), bufsz);
8504 break;
8506 fc_strlcat(buf, _("Only other continent/ocean"), bufsz);
8507 break;
8509 fc_strlcat(buf, _("Lake/island surrounded"), bufsz);
8510 break;
8511 case TREL_COUNT:
8512 fc_assert(psource->value.tilerel != TREL_COUNT);
8513 fc_strlcat(buf, "error", bufsz);
8514 break;
8515 }
8516 return buf;
8517 case VUT_MINLATITUDE:
8518 /* TRANS: here >= means 'greater than or equal'. */
8519 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
8520 psource->value.latitude);
8521 return buf;
8522 case VUT_MAXLATITUDE:
8523 /* TRANS: here <= means 'less than or equal'. */
8524 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
8525 psource->value.latitude);
8526 return buf;
8528 /* TRANS: here <= means 'less than or equal'. */
8529 cat_snprintf(buf, bufsz, _("Squared distance <= %d"),
8530 psource->value.distance_sq);
8531 return buf;
8533 cat_snprintf(buf, bufsz, _("%d or fewer region tiles"),
8534 psource->value.region_tiles);
8535 return buf;
8536 case VUT_COUNT:
8537 break;
8538 }
8539
8540 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8541 return buf;
8542}
8543
8544/**********************************************************************/
8548{
8549 return universals_n_name(psource->kind);
8550}
8551
8552/**********************************************************************/
8556 const struct universal *target)
8557{
8558 switch (target->kind) {
8559 case VUT_IMPROVEMENT:
8560 case VUT_SITE:
8561 return impr_build_shield_cost(pcity, target->value.building);
8562 case VUT_UTYPE:
8563 return utype_build_shield_cost(pcity, nullptr, target->value.utype);
8564 default:
8565 break;
8566 }
8567 return FC_INFINITY;
8568}
8569
8570/**********************************************************************/
8576 const struct universal *to_replace,
8577 const struct universal *replacement)
8578{
8579 bool changed = FALSE;
8580
8583 preq->source = *replacement;
8584 changed = TRUE;
8585 }
8587
8588 return changed;
8589}
8590
8591/**********************************************************************/
8596 const struct requirement_vector *reqs,
8597 const struct universal *psource)
8598{
8601 return TRUE;
8602 }
8604
8605 return FALSE;
8606}
8607
8608/**********************************************************************/
8619 struct universal *unis,
8620 size_t n_unis)
8621{
8622 int i;
8623
8624 for (i = 0; i < n_unis; i++) {
8626 /* This universal makes it impossible to fulfill the specified
8627 * requirement vector */
8628 return TRUE;
8629 }
8630 }
8631
8632 /* No specified universal is known to guarantee that the requirement
8633 * vector never will be fulfilled. */
8634 return FALSE;
8635}
8636
8637/**********************************************************************/
8653 struct universal *unis,
8654 size_t n_unis)
8655{
8657 int i;
8659
8660 for (i = 0; i < n_unis; i++) {
8661 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
8662 case ITF_NO:
8663 case ITF_YES:
8664 /* this req matched this source */
8666 break;
8667 case ITF_NOT_APPLICABLE:
8668 /* Not a mention. */
8669 break;
8670 }
8671 }
8672
8674 /* A requirement not relevant to any of the specified universals was
8675 * found in the requirement vector. */
8676 return FALSE;
8677 }
8679
8680 /* No requirement not relevant to any of the specified universals was
8681 * found in the requirement vector. */
8682 return TRUE;
8683}
8684
8685/**********************************************************************/
8688enum req_item_found
8690 const struct universal *source)
8691{
8694 "No req item found function for %s",
8696
8697 return (*universal_found_function[source->kind])(preq, source);
8698}
8699
8700/**********************************************************************/
8711 const struct requirement_vector *reqs,
8712 const struct universal *source)
8713{
8714 bool necessary = FALSE;
8715
8718 "No req item found function for %s",
8720
8722 switch ((*universal_found_function[source->kind])(preq, source)) {
8723 case ITF_NOT_APPLICABLE:
8724 continue;
8725 case ITF_NO:
8726 if (preq->present) {
8727 return FALSE;
8728 }
8729 break;
8730 case ITF_YES:
8731 if (preq->present) {
8732 necessary = TRUE;
8733 } else {
8734 return FALSE;
8735 }
8736 break;
8737 }
8739
8740 return (!check_necessary || necessary);
8741}
8742
8743/**********************************************************************/
8748 const struct universal *source)
8749{
8750 switch (universal_fulfills_requirement(req, source)) {
8751 case ITF_NOT_APPLICABLE:
8752 return FALSE;
8753 case ITF_NO:
8754 case ITF_YES:
8755 return TRUE;
8756 }
8757
8758 log_error("Unhandled item_found value");
8759 return FALSE;
8760}
8761
8762/**********************************************************************/
8766 const struct universal *source)
8767{
8768 fc_assert(source->value.nation);
8769
8770 switch (preq->source.kind) {
8771 case VUT_NATION:
8772 return preq->source.value.nation == source->value.nation ? ITF_YES
8773 : ITF_NO;
8774 case VUT_NATIONGROUP:
8775 return nation_is_in_group(source->value.nation,
8776 preq->source.value.nationgroup) ? ITF_YES
8777 : ITF_NO;
8778 default:
8779 break;
8780 }
8781
8782 return ITF_NOT_APPLICABLE;
8783}
8784
8785/**********************************************************************/
8789 const struct universal *source)
8790{
8791 fc_assert(source->value.govern);
8792
8793 if (preq->source.kind == VUT_GOVERNMENT) {
8794 return preq->source.value.govern == source->value.govern ? ITF_YES
8795 : ITF_NO;
8796 } else if (preq->source.kind == VUT_GOVFLAG) {
8797 return BV_ISSET(source->value.govern->flags, preq->source.value.govflag)
8798 ? ITF_YES : ITF_NO;
8799 }
8800
8801 return ITF_NOT_APPLICABLE;
8802}
8803
8804/**********************************************************************/
8808 const struct universal *source)
8809{
8810 fc_assert(source->value.min_cities);
8811
8812 if (preq->source.kind == VUT_MINCITIES) {
8813 return preq->source.value.min_cities <= source->value.min_cities ? ITF_YES
8814 : ITF_NO;
8815 }
8816
8817 return ITF_NOT_APPLICABLE;
8818}
8819
8820/**********************************************************************/
8824 const struct universal *source)
8825{
8826 fc_assert(source->value.building);
8827
8828 /* We only ever return ITF_YES, because requiring a different
8829 * improvement does not mean that the improvement under consideration
8830 * cannot fulfill the requirements. This is necessary to allow
8831 * requirement vectors to specify multiple required improvements. */
8832
8833 switch (preq->source.kind) {
8834 case VUT_IMPROVEMENT:
8835 case VUT_SITE:
8836 if (source->value.building == preq->source.value.building) {
8837 return ITF_YES;
8838 }
8839 break;
8840 case VUT_IMPR_GENUS:
8841 if (source->value.building->genus == preq->source.value.impr_genus) {
8842 return ITF_YES;
8843 }
8844 break;
8845 case VUT_IMPR_FLAG:
8846 if (improvement_has_flag(source->value.building,
8847 preq->source.value.impr_flag)) {
8848 return ITF_YES;
8849 }
8850 break;
8851 default:
8852 break;
8853 }
8854
8855 return ITF_NOT_APPLICABLE;
8856}
8857
8858/**********************************************************************/
8862 const struct universal *source)
8863{
8864 fc_assert(source->value.uclass);
8865
8866 switch (preq->source.kind) {
8867 case VUT_UCLASS:
8868 return source->value.uclass == preq->source.value.uclass ? ITF_YES
8869 : ITF_NO;
8870 case VUT_UCFLAG:
8871 return uclass_has_flag(source->value.uclass,
8872 preq->source.value.unitclassflag) ? ITF_YES
8873 : ITF_NO;
8874
8875 default:
8876 /* Not found and not relevant. */
8877 return ITF_NOT_APPLICABLE;
8878 };
8879}
8880
8881/**********************************************************************/
8885 const struct universal *source)
8886{
8887 fc_assert(source->value.utype);
8888
8889 switch (preq->source.kind) {
8890 case VUT_UTYPE:
8891 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
8892 case VUT_UCLASS:
8893 return utype_class(source->value.utype) == preq->source.value.uclass
8894 ? ITF_YES : ITF_NO;
8895 case VUT_UTFLAG:
8896 return utype_has_flag(source->value.utype,
8897 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
8898 case VUT_UCFLAG:
8899 return uclass_has_flag(utype_class(source->value.utype),
8900 preq->source.value.unitclassflag) ? ITF_YES
8901 : ITF_NO;
8902 default:
8903 /* Not found and not relevant. */
8904 return ITF_NOT_APPLICABLE;
8905 };
8906}
8907
8908/**********************************************************************/
8911static enum req_item_found
8913 const struct universal *source)
8914{
8917
8918 switch (preq->source.kind) {
8919 case VUT_ACTIVITY:
8920 return source->value.activity == preq->source.value.activity ? ITF_YES
8921 : ITF_NO;
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.terrain);
8935
8936 switch (preq->source.kind) {
8937 case VUT_TERRAIN:
8938 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
8939 case VUT_TERRAINCLASS:
8940 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
8941 ? ITF_YES : ITF_NO;
8942 case VUT_TERRFLAG:
8943 return terrain_has_flag(source->value.terrain,
8944 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
8945 case VUT_TERRAINALTER:
8946 return (terrain_can_support_alteration(source->value.terrain,
8947 preq->source.value.terrainalter)
8948 ? ITF_YES : ITF_NO);
8949 default:
8950 /* Not found and not relevant. */
8951 return ITF_NOT_APPLICABLE;
8952 };
8953}
8954
8955/**********************************************************************/
8959 const struct universal *source)
8960{
8963
8964 switch (preq->source.kind) {
8965 case VUT_CITYTILE:
8966 return (source->value.citytile == preq->source.value.citytile
8967 ? ITF_YES
8968 /* The presence of one tile state doesn't block another */
8970 default:
8971 /* Not found and not relevant. */
8972 return ITF_NOT_APPLICABLE;
8973 };
8974}
8975
8976/**********************************************************************/
8982 const struct universal *source)
8983{
8984 fc_assert(source->value.extra);
8985
8986 switch (preq->source.kind) {
8987 case VUT_EXTRA:
8988 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
8989 case VUT_EXTRAFLAG:
8990 return extra_has_flag(source->value.extra,
8991 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
8992 case VUT_ROADFLAG:
8993 {
8994 struct road_type *r = extra_road_get(source->value.extra);
8995 return r && road_has_flag(r, preq->source.value.roadflag)
8996 ? ITF_YES : ITF_NO;
8997 }
8998 default:
8999 /* Not found and not relevant. */
9000 return ITF_NOT_APPLICABLE;
9001 }
9002}
9003
9004/**********************************************************************/
9008 const struct universal *source)
9009{
9010 fc_assert(source->value.action);
9011
9012 if (preq->source.kind == VUT_ACTION) {
9013 return preq->source.value.action == source->value.action ? ITF_YES
9014 : ITF_NO;
9015 }
9016
9017 return ITF_NOT_APPLICABLE;
9018}
9019
9020/**********************************************************************/
9024 const struct universal *source)
9025{
9027 || source->kind == VUT_DIPLREL_TILE
9028 || source->kind == VUT_DIPLREL_TILE_O
9029 || source->kind == VUT_DIPLREL_UNITANY
9030 || source->kind == VUT_DIPLREL_UNITANY_O),
9032
9033 if (preq->source.kind == source->kind) {
9034 if (preq->source.value.diplrel == source->value.diplrel) {
9035 /* The diplrel itself. */
9036 return ITF_YES;
9037 }
9038 if (preq->source.value.diplrel == DRO_FOREIGN
9039 && source->value.diplrel < DS_LAST) {
9040 /* All diplstate_type values are to foreigners. */
9041 return ITF_YES;
9042 }
9043 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
9044 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
9045 /* A real embassy is an embassy. */
9046 return ITF_YES;
9047 }
9048 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
9049 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
9050 /* A real embassy is an embassy. */
9051 return ITF_YES;
9052 }
9053 if (preq->source.value.diplrel < DS_LAST
9054 && source->value.diplrel < DS_LAST
9055 && preq->range == REQ_RANGE_LOCAL) {
9056 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
9057 ITF_YES);
9058 /* Can only have one diplstate_type to a specific player. */
9059 return ITF_NO;
9060 }
9061 /* Can't say this diplrel blocks the other diplrel. */
9062 return ITF_NOT_APPLICABLE;
9063 }
9064
9065 /* Not relevant. */
9066 return ITF_NOT_APPLICABLE;
9067}
9068
9069/**********************************************************************/
9073 const struct universal *source)
9074{
9075 switch (preq->source.kind) {
9076 case VUT_OTYPE:
9077 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
9078 : ITF_NO;
9079 default:
9080 /* Not found and not relevant. */
9081 return ITF_NOT_APPLICABLE;
9082 }
9083}
9084
9085/**********************************************************************/
9089 const struct universal *source)
9090{
9091 if (preq->range != REQ_RANGE_LOCAL) {
9092 return ITF_NOT_APPLICABLE;
9093 }
9094
9095 if (preq->source.kind == VUT_UNITSTATE) {
9096 switch (source->value.unit_state) {
9097 case USP_TRANSPORTED:
9098 case USP_TRANSPORTING:
9099 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
9100 case USP_LIVABLE_TILE:
9101 case USP_NATIVE_TILE:
9102 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
9103 * UTYF_COAST_STRICT. */
9104 case USP_HAS_HOME_CITY:
9105 case USP_NATIVE_EXTRA:
9107 if (source->value.unit_state == preq->source.value.unit_state) {
9108 /* The other unit states doesn't contradict */
9109 return ITF_YES;
9110 }
9111 break;
9112 case USP_COUNT:
9113 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
9115 }
9116 }
9117
9118 /* Not found and not relevant. */
9119 return ITF_NOT_APPLICABLE;
9120}
9121
9122/**********************************************************************/
9147
9148/**********************************************************************/
9156int requirement_kind_ereq(const int value,
9157 const enum req_range range,
9158 const bool present,
9159 const int max_value)
9160{
9161 /* The enumerators in each range starts with present for every possible
9162 * value followed by !present for every possible value. */
9163 const int pres_start = (present ? 0 : max_value);
9164
9165 /* The enumerators for every range follows all the positions of the
9166 * previous range(s). */
9167 const int range_start = ((max_value - 1) * 2) * range;
9168
9169 return range_start + pres_start + value;
9170}
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:1276
Output_type_id output_type_by_identifier(const char *id)
Definition city.c:647
const char * get_output_identifier(Output_type_id output)
Definition city.c:619
const char * get_output_name(Output_type_id output)
Definition city.c:629
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
#define city_tile(_pcity_)
Definition city.h:565
static citizens city_size_get(const struct city *pcity)
Definition city.h:570
#define city_owner(_pcity_)
Definition city.h:564
static bool is_city_center(const struct city *pcity, const struct tile *ptile)
Definition city.h:870
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:228
#define city_tile_iterate_end
Definition city.h:236
#define city_built_iterate(_pcity, _p)
Definition city.h:836
#define city_built_iterate_end
Definition city.h:842
static struct ai_type * self
Definition classicai.c:46
char * incite_cost
Definition comments.c:77
int counter_index(const struct counter *pcount)
Definition counters.c:176
const char * counter_name_translation(const struct counter *counter)
Definition counters.c:158
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:116
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:166
struct counter * counter_by_id(int id)
Definition counters.c:82
int counter_id(struct counter *pcount)
Definition counters.c:105
int city_culture(const struct city *pcity)
Definition culture.c:29
int player_culture(const struct player *plr)
Definition culture.c:49
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:56
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:57
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
struct @22::@23 reqs
int get_world_bonus(enum effect_type effect_type)
Definition effects.c:812
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
bool extra_flag_is_in_use(enum extra_flag_id id)
Definition extras.c:1001
bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:904
bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:884
bool is_extra_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:379
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:875
bool is_extra_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:363
struct extra_type * extra_by_number(int id)
Definition extras.c:183
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:194
#define extra_road_get(_e_)
Definition extras.h:191
static bool is_server(void)
int Tech_type_id
Definition fc_types.h:238
req_problem_type
Definition fc_types.h:514
@ RPT_POSSIBLE
Definition fc_types.h:515
#define MAX_LEN_NAME
Definition fc_types.h:68
@ VC_SPACERACE
Definition fc_types.h:966
@ O_LAST
Definition fc_types.h:103
signed short Continent_id
Definition fc_types.h:233
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
void fc_mutex_allocate(fc_mutex *mutex)
Definition fcthread.c:144
void fc_mutex_init(fc_mutex *mutex)
Definition fcthread.c:128
void fc_mutex_release(fc_mutex *mutex)
Definition fcthread.c:152
fc_thread_id fc_thread_self(void)
Definition fcthread.c:112
bool register_at_thread_exit_callback(at_thread_exit_cb *cb)
Definition fcthread.c:32
bool fc_threads_equal(fc_thread_id thr1, fc_thread_id thr2)
Definition fcthread.c:120
void fc_mutex_destroy(fc_mutex *mutex)
Definition fcthread.c:136
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
const char * government_name_translation(const struct government *pgovern)
Definition government.c:145
struct government * government_by_number(const Government_type_id gov)
Definition government.c:105
struct government * government_of_player(const struct player *pplayer)
Definition government.c:116
Government_type_id government_number(const struct government *pgovern)
Definition government.c:93
const char * government_rule_name(const struct government *pgovern)
Definition government.c:135
struct government * government_by_rule_name(const char *name)
Definition government.c:57
struct city * owner
Definition citydlg.c:226
static GtkWidget * source
Definition gotodlg.c:58
GType type
Definition repodlgs.c:1313
static const int bufsz
Definition helpdlg.c:70
struct impr_type * improvement_by_number(const Impr_type_id id)
bool great_wonder_is_built(const struct impr_type *pimprove)
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
bool wonder_is_built(const struct player *pplayer, const struct impr_type *pimprove)
Impr_type_id improvement_number(const struct impr_type *pimprove)
bool can_improvement_go_obsolete(const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
struct city * city_from_wonder(const struct player *pplayer, const struct impr_type *pimprove)
int impr_build_shield_cost(const struct city *pcity, const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
bool improvement_obsolete(const struct player *pplayer, const struct impr_type *pimprove, const struct city *pcity)
bool improvement_has_flag(const struct impr_type *pimprove, enum impr_flag_id flag)
struct impr_type * improvement_by_rule_name(const char *name)
const char * improvement_name_translation(const struct impr_type *pimprove)
bool great_wonder_is_available(const struct impr_type *pimprove)
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition log.h:209
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:686
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:1067
int map_signed_latitude(const struct tile *ptile)
Definition map.c:1692
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:1076
int get_island_surrounder(Continent_id id)
Definition map.c:842
int get_lake_surrounder(Continent_id id)
Definition map.c:875
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:699
#define current_topo_has_flag(flag)
Definition map.h:43
#define range_adjc_iterate(nmap, center_tile, range, itr_tile)
Definition map.h: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_ai_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_noally(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_max_distance_sq_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_vec_change_apply(const struct req_vec_change *modification, requirement_vector_by_number getter, const void *parent_item)
void universal_copy(struct universal *dst, const struct universal *src)
static enum fc_tristate is_minculture_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_building(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_terrain_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_requirements_equal(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_minforeignpct_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_minyear_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found extra_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_buildingflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_in_range(const struct tile *target_tile, const struct player *other_player, enum req_range range, int diplrel)
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
struct requirement req_from_str(const char *type, const char *range, bool survives, bool present, bool quiet, const char *value)
struct req_vec_problem * req_vec_suggest_repair(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum fc_tristate is_wrap_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void universal_value_from_str(struct universal *source, const char *value)
static enum fc_tristate is_buildingflag_in_city(const struct city *pcity, enum impr_flag_id flag)
static enum fc_tristate is_latitude_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_get_values(const struct requirement *req, int *type, int *range, bool *survives, bool *present, bool *quiet, int *value)
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
static enum fc_tristate is_nationality_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * universal_rule_name(const struct universal *psource)
static enum req_unchanging_status unchanging_present(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
bool universal_replace_in_req_vec(struct requirement_vector *reqs, const struct universal *to_replace, const struct universal *replacement)
static enum req_item_found action_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_minmovefrags_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_requirements_contradictions(const struct requirement *req1, const struct requirement *req2)
#define REQUC_IMPR
struct req_vec_problem * req_vec_problem_new(int num_suggested_solutions, const char *descr,...)
static enum fc_tristate is_buildinggenus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_in_range(const struct player *target_player, const struct player *other_player, enum req_range range, int diplrel)
static enum fc_tristate is_mintechs_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool is_req_active(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, const enum req_problem_type prob_type)
static enum fc_tristate is_originalowner_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool are_bounds_contradictions(int bound1, bool is_upper1, int bound2, bool is_upper2)
static enum fc_tristate is_diplrel_tile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_legal_in_requirement(const struct universal *univ)
enum fc_tristate default_tester_cb(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, void *data, int n_data)
static enum fc_tristate tri_req_present(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
int requirement_kind_ereq(const int value, const enum req_range range, const bool present, const int max_value)
static enum fc_tristate is_achievement_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_vec_problem_free(struct req_vec_problem *issue)
static struct req_def req_definitions[VUT_COUNT]
static bool impr_contra_flag(const struct requirement *impr_req, const struct requirement *flag_req)
bool are_reqs_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
static enum req_item_found improvement_found(const struct requirement *preq, const struct universal *source)
struct req_vec_problem * req_vec_get_first_missing_univ(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum req_item_found mincities_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_extraflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum req_unchanging_status is_req_preventing(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, enum req_problem_type prob_type)
static enum fc_tristate is_plr_state_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool players_in_same_range(const struct player *pplayer1, const struct player *pplayer2, enum req_range range)
struct requirement * req_vec_first_contradiction_in_vec(const struct requirement *req, const struct requirement_vector *vec)
enum req_item_found(* universal_found)(const struct requirement *, const struct universal *)
static enum fc_tristate is_terrainclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct universal universal_by_number(const enum universals_n kind, const int value)
static enum fc_tristate is_roadflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum req_item_found universal_fulfills_requirement(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_building_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void requirements_free(void)
bool are_reqs_active_ranges(const enum req_range min_range, const enum req_range max_range, const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
static enum fc_tristate is_gov_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_tile_o_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_good_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unitstate_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool city_center_contra(const struct requirement *cc_req, const struct requirement *ct_req)
static enum req_item_found ustate_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_terrainalter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unittype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_vec_wants_type(const struct requirement_vector *reqs, enum universals_n kind)
static int num_world_buildings_total(const struct impr_type *building)
static enum req_unchanging_status unchanging_citytile(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_tiledef_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found output_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_citystatus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_tile_rel_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct req_vec_problem * req_vec_get_first_redundant_req(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum fc_tristate is_mincities_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool is_city_in_tile(const struct tile *ptile, const struct city *pcity)
bool does_req_contradicts_reqs(const struct requirement *req, const struct requirement_vector *vec)
static enum req_item_found government_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate does_region_surrounder_match(Continent_id cont, Continent_id surrounder)
static enum fc_tristate is_extra_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_world(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_mincalfrag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_maxtopunitsontile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_activity_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
static enum fc_tristate is_max_region_tiles_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct req_vec_problem * req_vec_problem_new_transl(int num_suggested_solutions, const char *description, const char *description_translated)
static enum fc_tristate is_nationgroup_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define REQUC_NALLY
static enum req_item_found unit_activity_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_minhitpoints_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum fc_tristate tri_req_active_turns(int pass, int period, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_outputtype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define REQUC_LOCAL
bool universals_say_everything(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
static enum fc_tristate is_unitclassflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define thr_req_data_list_iterate(trlist, ptrdata)
static enum req_item_found nation_found(const struct requirement *preq, const struct universal *source)
#define REQUC_WORLD
static enum fc_tristate is_govflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * universal_type_rule_name(const struct universal *psource)
#define REQUC_PRESENT
static enum fc_tristate is_maxtotalunitsontile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void universal_found_functions_init(void)
static enum fc_tristate is_style_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found unit_class_found(const struct requirement *preq, const struct universal *source)
#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind)
int universal_number(const struct universal *source)
static enum fc_tristate is_techflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_mentioned_by_requirements(const struct requirement_vector *reqs, const struct universal *psource)
#define REQUC_CITYTILE
static enum fc_tristate is_citytile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found diplrel_found(const struct requirement *preq, const struct universal *source)
bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
void requirements_init(void)
bool req_implies_req(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_specialist_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define thr_req_data_list_iterate_end
void req_copy(struct requirement *dst, const struct requirement *src)
enum req_unchanging_status is_req_unchanging(const struct req_context *context, const struct requirement *req)
static bool player_has_ever_built(const struct player *pplayer, const struct impr_type *building)
enum fc_tristate(* is_req_active_cb)(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool nation_contra_group(const struct requirement *nation_req, const struct requirement *group_req)
static enum fc_tristate is_serversetting_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_plr_flag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_nation_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_is_impossible_to_fulfill(const struct requirement *req)
static bool are_tiles_in_range(const struct tile *tile1, const struct tile *tile2, enum req_range range)
static fc_mutex trmutex
static struct thr_req_data_list * trdatas
static bool are_requirements_opposites(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_form_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static int num_world_buildings(const struct impr_type *building)
static enum req_unchanging_status unchanging_citystatus(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_topology_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_o_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
static void thr_exit_cb(void)
struct universal universal_by_rule_name(const char *kind, const char *value)
bool universals_mean_unfulfilled(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
struct req_vec_problem * req_vec_suggest_improvement(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static bool impr_contra_genus(const struct requirement *impr_req, const struct requirement *genus_req)
enum fc_tristate(* req_tester_cb)(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, void *data, int n_data)
#define requirement_diplrel_ereq(_id_, _range_, _present_)
signed char req_vec_num_in_item
req_vec_num_in_item a requirement vectors number in an item.
req_vec_num_in_item(* requirement_vector_number)(const void *parent_item, const struct requirement_vector *vec)
const char *(* requirement_vector_namer)(req_vec_num_in_item number)
#define universal_is_mentioned_by_requirement(preq, psource)
enum req_unchanging_status(* req_unchanging_cond_cb)(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
#define requirement_vector_iterate_end
struct universal universal_by_number(const enum universals_n kind, const int value)
struct requirement_vector *(* requirement_vector_by_number)(const void *parent_item, req_vec_num_in_item number)
#define requirement_vector_iterate(req_vec, preq)
req_item_found
@ ITF_NO
@ ITF_YES
@ ITF_NOT_APPLICABLE
req_unchanging_status
@ REQUCH_ACT
@ REQUCH_NO
@ REQUCH_SCRIPTS
@ REQUCH_YES
@ REQUCH_HACK
@ REQUCH_CTRL
struct research * research_get(const struct player *pplayer)
Definition research.c:130
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:622
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Definition road.c:416
bool is_road_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:446
bool is_road_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:425
bool ssetv_setting_has_value(ssetv val)
ssetv ssetv_by_rule_name(const char *name)
const char * ssetv_rule_name(ssetv val)
const char * ssetv_human_readable(ssetv val, bool present)
#define SSETV_NONE
enum fc_tristate fc_tristate_or(enum fc_tristate one, enum fc_tristate two)
Definition shared.c:143
fc_tristate
Definition shared.h:46
@ TRI_YES
Definition shared.h:46
@ TRI_NO
Definition shared.h:46
@ TRI_MAYBE
Definition shared.h:46
#define BOOL_TO_TRISTATE(tri)
Definition shared.h:47
#define FC_INFINITY
Definition shared.h:36
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c:123
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:110
Specialist_type_id specialist_number(const struct specialist *sp)
Definition specialist.c:100
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:157
const char * specialist_plural_translation(const struct specialist *sp)
Definition specialist.c:166
Definition city.h:318
struct packet_game_info info
Definition game.h:89
struct packet_calendar_info calendar
Definition game.h:90
int checkpoint
Definition counters.h:33
bv_gov_flags flags
Definition government.h:67
struct player * player
Definition nation.h:118
bool global_advances[A_LAST]
bool is_alive
Definition player.h:268
enum req_unchanging_status unchanging
req_unchanging_cond_cb unchanging_cond
const is_req_active_cb cb
req_vec_num_in_item vector_number
enum req_vec_change_operation operation
struct requirement req
char description[500]
char description_translated[500]
enum req_range range
struct universal source
Tech_type_id researching
Definition research.h:52
int future_tech
Definition research.h:42
int techs_researched
Definition research.h:42
fc_thread_id thr_id
Definition tile.h:50
struct tile * tile
Definition unit.h:142
const struct unit_type * utype
Definition unit.h:141
enum universals_n kind
Definition fc_types.h:595
universals_u value
Definition fc_types.h:594
struct civ_map map
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
struct nation_style * style_by_number(int id)
Definition style.c:88
const char * style_name_translation(const struct nation_style *pstyle)
Definition style.c:99
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:108
int style_number(const struct nation_style *pstyle)
Definition style.c:68
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:822
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define bool
Definition support.h:71
#define fc__fallthrough
Definition support.h:119
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:110
bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag)
Definition tech.c:221
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:305
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:314
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:205
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:100
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:188
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:615
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:594
const char * terrain_class_name_translation(enum terrain_class tclass)
Definition terrain.c:664
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:240
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:157
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Definition terrain.c:676
bool is_terrain_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:330
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:249
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:585
bool is_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:461
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:148
bool is_terrain_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:441
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:351
#define T_UNKNOWN
Definition terrain.h:62
#define terrain_has_flag(terr, flag)
Definition terrain.h:177
bool tile_has_extra_flag(const struct tile *ptile, enum extra_flag_id flag)
Definition tile.c:887
bool tile_has_native_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:325
bool tile_has_road_flag(const struct tile *ptile, enum road_flag_id flag)
Definition tile.c:869
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_terrain(_tile)
Definition tile.h:115
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#define tile_owner(_tile)
Definition tile.h:97
const char * tiledef_rule_name(const struct tiledef *td)
Definition tiledef.c:104
int tiledef_number(const struct tiledef *td)
Definition tiledef.c:62
struct tiledef * tiledef_by_number(int id)
Definition tiledef.c:84
struct tiledef * tiledef_by_rule_name(const char *name)
Definition tiledef.c:113
bool tile_matches_tiledef(const struct tiledef *td, const struct tile *ptile)
Definition tiledef.c:150
bool is_tiledef_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct tiledef *ptd)
Definition tiledef.c:165
bool is_tiledef_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct tiledef *ptd)
Definition tiledef.c:181
const char * tiledef_name_translation(const struct tiledef *td)
Definition tiledef.c:95
bool goods_can_be_provided(const struct city *pcity, const struct goods_type *pgood, const struct unit *punit)
Goods_type_id goods_number(const struct goods_type *pgood)
bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
const char * goods_name_translation(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
#define trade_partners_iterate_end
#define trade_partners_iterate(c, p)
const struct unit_type * utype
Definition fc_types.h:536
struct tiledef * tiledef
Definition fc_types.h:538
int region_tiles
Definition fc_types.h:584
struct nation_style * style
Definition fc_types.h:541
enum ai_level ai_level
Definition fc_types.h:545
struct specialist * specialist
Definition fc_types.h:533
enum impr_genus_id impr_genus
Definition fc_types.h:569
enum citytile_type citytile
Definition fc_types.h:546
struct nation_group * nationgroup
Definition fc_types.h:540
struct extra_type * extra
Definition fc_types.h:537
enum wrap_flag wrap_property
Definition fc_types.h:587
enum plrstate_type plrstate
Definition fc_types.h:548
enum tilerel_type tilerel
Definition fc_types.h:549
struct nation_type * nation
Definition fc_types.h:530
int terrainclass
Definition fc_types.h:556
int unitclassflag
Definition fc_types.h:559
struct government * govern
Definition fc_types.h:528
struct nation_type * origowner
Definition fc_types.h:532
enum impr_flag_id impr_flag
Definition fc_types.h:570
int terrainalter
Definition fc_types.h:557
enum citystatus_type citystatus
Definition fc_types.h:547
int minforeignpct
Definition fc_types.h:552
const struct impr_type * building
Definition fc_types.h:529
int max_tile_total_units
Definition fc_types.h:573
int max_tile_top_units
Definition fc_types.h:574
struct achievement * achievement
Definition fc_types.h:539
ssetv ssetval
Definition fc_types.h:588
struct advance * advance
Definition fc_types.h:526
enum unit_activity activity
Definition fc_types.h:568
struct goods_type * good
Definition fc_types.h:543
struct terrain * terrain
Definition fc_types.h:534
int terrainflag
Definition fc_types.h:561
enum ustate_prop unit_state
Definition fc_types.h:567
Output_type_id outputtype
Definition fc_types.h:555
int distance_sq
Definition fc_types.h:583
enum topo_flag topo_property
Definition fc_types.h:586
struct counter * counter
Definition fc_types.h:527
int min_hit_points
Definition fc_types.h:576
struct unit_class * uclass
Definition fc_types.h:535
struct nation_type * nationality
Definition fc_types.h:531
struct action * action
Definition fc_types.h:542
int future_techs
Definition fc_types.h:580
enum plr_flag_id plr_flag
Definition fc_types.h:571
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1847
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2529
#define unit_tile(_pu)
Definition unit.h:407
#define unit_owner(_pu)
Definition unit.h:406
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const char * uclass_name_translation(const struct unit_class *pclass)
Definition unittype.c:1658
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126
bool unit_has_class_flag(const struct unit *punit, enum unit_class_flag_id flag)
Definition unittype.c:1675
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1793
bool uclass_flag_is_in_use(enum unit_class_flag_id ucflag)
Definition unittype.c:3013
struct unit_class * uclass_by_number(const Unit_Class_id id)
Definition unittype.c:2506
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1604
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2530
struct unit_type * utype_by_number(const Unit_type_id id)
Definition unittype.c:114
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:215
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1667
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:102
struct unit_class * unit_class_by_rule_name(const char *s)
Definition unittype.c:1810
bool utype_flag_is_in_use(enum unit_type_flag_id uflag)
Definition unittype.c:3032
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1463
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2497
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1586
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:773
#define utype_class(_t_)
Definition unittype.h:756
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
bool victory_enabled(enum victory_condition_type victory)
Definition victory.c:26