Freeciv-3.3
Loading...
Searching...
No Matches
requirements.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2004 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17#include <stdarg.h>
18
19/* utility */
20#include "astring.h"
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "achievements.h"
27#include "calendar.h"
28#include "citizens.h"
29#include "counters.h"
30#include "culture.h"
31#include "game.h"
32#include "government.h"
33#include "improvement.h"
34#include "movement.h"
35#include "nation.h"
36#include "player.h"
37#include "map.h"
38#include "research.h"
39#include "road.h"
40#include "server_settings.h"
41#include "specialist.h"
42#include "style.h"
43#include "victory.h" /* victory_enabled() */
44
45#include "requirements.h"
46
51
52/* get 'struct thr_req_data_list' and related functions: */
53#define SPECLIST_TAG thr_req_data
54#define SPECLIST_TYPE struct thr_req_data
55#include "speclist.h"
56
57#define thr_req_data_list_iterate(trlist, ptrdata) \
58 TYPED_LIST_ITERATE(struct thr_req_data, trlist, ptrdata)
59#define thr_req_data_list_iterate_end LIST_ITERATE_END
60
63
64/************************************************************************
65 Container for req_item_found functions
66************************************************************************/
67typedef enum req_item_found (*universal_found)(const struct requirement *,
68 const struct universal *);
70
71static
73 const struct req_context *context,
74 const struct req_context *other_context,
75 const struct requirement *req);
76
77/* Function pointer for requirement-type-specific is_req_active handlers */
78typedef enum fc_tristate
79(*is_req_active_cb)(const struct civ_map *nmap,
80 const struct req_context *context,
81 const struct req_context *other_context,
82 const struct requirement *req);
83
84static inline bool are_tiles_in_range(const struct tile *tile1,
85 const struct tile *tile2,
86 enum req_range range);
87
88/**********************************************************************/
93static enum req_unchanging_status
95 enum req_unchanging_status def,
96 const struct req_context *context,
97 const struct requirement *req)
98{
99 return req->range == REQ_RANGE_LOCAL ? REQUCH_YES : def;
100}
101#define REQUC_LOCAL unchanging_local
102
103/**********************************************************************/
106static enum req_unchanging_status
108 enum req_unchanging_status def,
109 const struct req_context *context,
110 const struct requirement *req)
111{
112 if (TRI_YES != tri_req_present(nmap, context, nullptr, req)) {
113 return REQUCH_NO;
114 }
115 return def;
116}
117#define REQUC_PRESENT unchanging_present
118
119/**********************************************************************/
122static enum req_unchanging_status
124 enum req_unchanging_status def,
125 const struct req_context *context,
126 const struct requirement *req)
127{
128 return
130 context, req);
131}
132#define REQUC_WORLD unchanging_world
133
134/**********************************************************************/
138static enum req_unchanging_status
140 enum req_unchanging_status def,
141 const struct req_context *context,
142 const struct requirement *req)
143{
144 if (REQ_RANGE_ALLIANCE == req->range
145 || REQ_RANGE_TEAM == req->range) {
146 struct requirement preq;
147
148 req_copy(&preq, req);
149 preq.range = REQ_RANGE_PLAYER;
150 if (TRI_YES != tri_req_present(nmap, context, nullptr, &preq)) {
151 return REQ_RANGE_TEAM == req->range ? REQUCH_ACT : REQUCH_NO;
152 }
153 }
154 return def;
155}
156#define REQUC_NALLY unchanging_noally
157
158/**********************************************************************/
161static enum req_unchanging_status
163 enum req_unchanging_status def,
164 const struct req_context *context,
165 const struct requirement *req)
166{
170 && context->city != nullptr && context->tile != nullptr
171 && city_tile(context->city) != nullptr
173 req->range))){
174 /* Cities don't move, and most reqs are present on city center */
175 return REQUCH_YES;
176 }
177 return def;
178}
179#define REQUC_CITYTILE unchanging_citytile
180
181/**********************************************************************/
184static enum req_unchanging_status
186 enum req_unchanging_status def,
187 const struct req_context *context,
188 const struct requirement *req)
189{
191
192 if (REQ_RANGE_CITY == req->range
195 return REQUCH_CTRL;
196 }
197
198 return def;
199}
200#define REQUC_CITYSTATUS unchanging_citystatus
201
202/**********************************************************************/
207static enum req_unchanging_status
209 enum req_unchanging_status def,
210 const struct req_context *context,
211 const struct requirement *req)
212{
213 const struct impr_type *b = req->source.value.building;
214
216 || VUT_SITE == req->source.kind, REQUCH_NO);
217 if (REQ_RANGE_LOCAL == req->range) {
218 /* Likely, won't be questioned for an obsolete building */
219 return REQUCH_YES;
220 }
221
222 if (req->source.kind == VUT_IMPROVEMENT
223 && improvement_obsolete(context->player, b, context->city)) {
224 /* FIXME: Sometimes can unobsolete, but considering it
225 * may sometimes put the function on endless recursion */
226 return REQUCH_ACT; /* Mostly about techs */
227 }
228 if (is_great_wonder(b)) {
231 && (req->range <= REQ_RANGE_CITY && TRI_YES
232 == tri_req_present(nmap, context, nullptr, req)))) {
233 /* If the wonder stays somewhere, it may either remain there
234 * or be destroyed. If it is destroyed, it is nowhere. */
235 return REQUCH_SCRIPTS;
236 }
237 }
238 return def;
239}
240#define REQUC_IMPR unchanging_building
241
247
248/**********************************************************************/
251static void thr_exit_cb(void)
252{
254
257 if (fc_threads_equal(self, data->thr_id)) {
259 free(data);
260 break;
261 }
264}
265
266/**********************************************************************/
275
276/**********************************************************************/
284
285/**********************************************************************/
293 const char *value)
294{
295 struct universal source;
296
298 if (!universals_n_is_valid(source.kind)) {
299 return source;
300 }
301
303
304 return source;
305}
306
307/**********************************************************************/
312{
313 return unit_activity_is_valid(act)
314 && act != ACTIVITY_SENTRY
315 && act != ACTIVITY_GOTO
316 && act != ACTIVITY_EXPLORE;
317}
318
319/**********************************************************************/
324{
325 if (univ->kind == VUT_ACTIVITY) {
327 }
328
329 return TRUE;
330}
331
332/**********************************************************************/
337{
338 /* Finally scan the value string based on the type of the source. */
339 switch (source->kind) {
340 case VUT_NONE:
341 return;
342 case VUT_ADVANCE:
343 source->value.advance = advance_by_rule_name(value);
344 if (source->value.advance != nullptr) {
345 return;
346 }
347 break;
348 case VUT_TECHFLAG:
349 source->value.techflag
351 if (tech_flag_id_is_valid(source->value.techflag)) {
352 return;
353 }
354 break;
355 case VUT_GOVERNMENT:
356 source->value.govern = government_by_rule_name(value);
357 if (source->value.govern != nullptr) {
358 return;
359 }
360 break;
361 case VUT_ACHIEVEMENT:
362 source->value.achievement = achievement_by_rule_name(value);
363 if (source->value.achievement != nullptr) {
364 return;
365 }
366 break;
367 case VUT_STYLE:
368 source->value.style = style_by_rule_name(value);
369 if (source->value.style != nullptr) {
370 return;
371 }
372 break;
373 case VUT_IMPROVEMENT:
374 case VUT_SITE:
375 source->value.building = improvement_by_rule_name(value);
376 if (source->value.building != nullptr) {
377 return;
378 }
379 break;
380 case VUT_IMPR_GENUS:
381 source->value.impr_genus = impr_genus_id_by_name(value, fc_strcasecmp);
382 if (impr_genus_id_is_valid(source->value.impr_genus)) {
383 return;
384 }
385 break;
386 case VUT_IMPR_FLAG:
387 source->value.impr_flag = impr_flag_id_by_name(value, fc_strcasecmp);
388 if (impr_flag_id_is_valid(source->value.impr_flag)) {
389 return;
390 }
391 break;
392 case VUT_PLAYER_FLAG:
393 source->value.plr_flag = plr_flag_id_by_name(value, fc_strcasecmp);
394 if (plr_flag_id_is_valid(source->value.plr_flag)) {
395 return;
396 }
397 break;
398 case VUT_EXTRA:
399 source->value.extra = extra_type_by_rule_name(value);
400 if (source->value.extra != nullptr) {
401 return;
402 }
403 break;
404 case VUT_GOOD:
405 source->value.good = goods_by_rule_name(value);
406 if (source->value.good != nullptr) {
407 return;
408 }
409 break;
410 case VUT_TERRAIN:
411 source->value.terrain = terrain_by_rule_name(value);
412 if (source->value.terrain != T_UNKNOWN) {
413 return;
414 }
415 break;
416 case VUT_TERRFLAG:
417 source->value.terrainflag
419 if (terrain_flag_id_is_valid(source->value.terrainflag)) {
420 return;
421 }
422 break;
423 case VUT_NATION:
424 source->value.nation = nation_by_rule_name(value);
425 if (source->value.nation != NO_NATION_SELECTED) {
426 return;
427 }
428 break;
429 case VUT_NATIONGROUP:
430 source->value.nationgroup = nation_group_by_rule_name(value);
431 if (source->value.nationgroup != nullptr) {
432 return;
433 }
434 break;
435 case VUT_NATIONALITY:
436 source->value.nationality = nation_by_rule_name(value);
437 if (source->value.nationality != NO_NATION_SELECTED) {
438 return;
439 }
440 break;
442 source->value.origowner = nation_by_rule_name(value);
443 if (source->value.origowner != NO_NATION_SELECTED) {
444 return;
445 }
446 break;
447 case VUT_DIPLREL:
448 case VUT_DIPLREL_TILE:
452 source->value.diplrel = diplrel_by_rule_name(value);
453 if (source->value.diplrel != diplrel_other_invalid()) {
454 return;
455 }
456 break;
457 case VUT_UTYPE:
458 source->value.utype = unit_type_by_rule_name(value);
459 if (source->value.utype) {
460 return;
461 }
462 break;
463 case VUT_UTFLAG:
465 if (unit_type_flag_id_is_valid(source->value.unitflag)) {
466 return;
467 }
468 break;
469 case VUT_UCLASS:
470 source->value.uclass = unit_class_by_rule_name(value);
471 if (source->value.uclass) {
472 return;
473 }
474 break;
475 case VUT_UCFLAG:
476 source->value.unitclassflag
478 if (unit_class_flag_id_is_valid(source->value.unitclassflag)) {
479 return;
480 }
481 break;
482 case VUT_MINVETERAN:
483 source->value.minveteran = atoi(value);
484 if (source->value.minveteran > 0) {
485 return;
486 }
487 break;
488 case VUT_UNITSTATE:
489 source->value.unit_state = ustate_prop_by_name(value, fc_strcasecmp);
490 if (ustate_prop_is_valid(source->value.unit_state)) {
491 return;
492 }
493 break;
494 case VUT_ACTIVITY:
496 if (activity_is_valid_in_requirement(source->value.activity)) {
497 return;
498 }
499 break;
500 case VUT_MINMOVES:
501 source->value.minmoves = atoi(value);
502 if (source->value.minmoves > 0) {
503 return;
504 }
505 break;
506 case VUT_MINHP:
507 source->value.min_hit_points = atoi(value);
508 if (source->value.min_hit_points > 0) {
509 return;
510 }
511 break;
512 case VUT_AGE:
513 source->value.age = atoi(value);
514 if (source->value.age > 0) {
515 return;
516 }
517 break;
518 case VUT_FORM_AGE:
519 source->value.form_age = atoi(value);
520 if (source->value.form_age > 0) {
521 return;
522 }
523 break;
524 case VUT_MINTECHS:
525 source->value.min_techs = atoi(value);
526 if (source->value.min_techs > 0) {
527 return;
528 }
529 break;
530 case VUT_MINCITIES:
531 source->value.min_cities = atoi(value);
532 if (source->value.min_cities > 0) {
533 return;
534 }
535 break;
536 case VUT_ACTION:
537 source->value.action = action_by_rule_name(value);
538 if (source->value.action != nullptr) {
539 return;
540 }
541 break;
542 case VUT_OTYPE:
543 source->value.outputtype = output_type_by_identifier(value);
544 if (source->value.outputtype != O_LAST) {
545 return;
546 }
547 break;
548 case VUT_SPECIALIST:
549 source->value.specialist = specialist_by_rule_name(value);
550 if (source->value.specialist) {
551 return;
552 }
553 break;
554 case VUT_MINSIZE:
555 source->value.minsize = atoi(value);
556 if (source->value.minsize > 0) {
557 return;
558 }
559 break;
560 case VUT_MINCULTURE:
561 source->value.minculture = atoi(value);
562 if (source->value.minculture > 0) {
563 return;
564 }
565 break;
567 source->value.minforeignpct = atoi(value);
568 if (source->value.minforeignpct > 0) {
569 return;
570 }
571 break;
572 case VUT_AI_LEVEL:
573 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
574 if (ai_level_is_valid(source->value.ai_level)) {
575 return;
576 }
577 break;
578 case VUT_MAXTILEUNITS:
579 source->value.max_tile_units = atoi(value);
580 if (0 <= source->value.max_tile_units) {
581 return;
582 }
583 break;
584 case VUT_TERRAINCLASS:
585 source->value.terrainclass
587 if (terrain_class_is_valid(source->value.terrainclass)) {
588 return;
589 }
590 break;
591 case VUT_ROADFLAG:
593 if (road_flag_id_is_valid(source->value.roadflag)) {
594 return;
595 }
596 break;
597 case VUT_EXTRAFLAG:
598 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
599 if (extra_flag_id_is_valid(source->value.extraflag)) {
600 return;
601 }
602 break;
603 case VUT_MINYEAR:
604 source->value.minyear = atoi(value);
605 return;
606 case VUT_MINCALFRAG:
607 /* Rule names are 0-based numbers, not pretty names from ruleset */
608 source->value.mincalfrag = atoi(value);
609 if (source->value.mincalfrag >= 0) {
610 /* More range checking done later, in sanity_check_req_individual() */
611 return;
612 }
613 break;
614 case VUT_TOPO:
615 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
616 if (topo_flag_is_valid(source->value.topo_property)) {
617 return;
618 }
619 break;
620 case VUT_WRAP:
621 source->value.wrap_property = wrap_flag_by_name(value, fc_strcasecmp);
622 if (wrap_flag_is_valid(source->value.wrap_property)) {
623 return;
624 }
625 break;
627 source->value.ssetval = ssetv_by_rule_name(value);
628 if (source->value.ssetval != SSETV_NONE) {
629 return;
630 }
631 break;
632 case VUT_TERRAINALTER:
633 source->value.terrainalter
635 if (terrain_alteration_is_valid(source->value.terrainalter)) {
636 return;
637 }
638 break;
639 case VUT_CITYTILE:
641 if (source->value.citytile != CITYT_LAST) {
642 return;
643 }
644 break;
645 case VUT_CITYSTATUS:
647 if (source->value.citystatus != CITYS_LAST) {
648 return;
649 }
650 break;
651 case VUT_PLAYER_STATE:
653 if (source->value.plrstate != PLRS_LAST) {
654 return;
655 }
656 break;
657 case VUT_MINLATITUDE:
658 case VUT_MAXLATITUDE:
659 source->value.latitude = atoi(value);
660 if (source->value.latitude >= -MAP_MAX_LATITUDE
661 && source->value.latitude <= MAP_MAX_LATITUDE) {
662 return;
663 }
664 break;
665 case VUT_COUNTER:
666 source->value.counter = counter_by_rule_name(value);
667 if (source->value.counter != nullptr) {
668 return;
669 }
670 break;
672 source->value.distance_sq = atoi(value);
673 if (0 <= source->value.distance_sq) {
674 return;
675 }
676 break;
678 source->value.region_tiles = atoi(value);
679 if (0 < source->value.region_tiles) {
680 return;
681 }
682 break;
683 case VUT_TILE_REL:
685 if (source->value.tilerel != TREL_COUNT) {
686 return;
687 }
688 break;
689 case VUT_COUNT:
690 break;
691 }
692
693 /* If we reach here there's been an error. */
695}
696
697/**********************************************************************/
704{
705 struct universal source;
706
707 source.kind = kind;
708
709 switch (source.kind) {
710 case VUT_NONE:
711 /* Avoid compiler warning about uninitialized source.value */
712 source.value.advance = nullptr;
713
714 return source;
715 case VUT_ADVANCE:
716 source.value.advance = advance_by_number(value);
717 if (source.value.advance != nullptr) {
718 return source;
719 }
720 break;
721 case VUT_TECHFLAG:
722 source.value.techflag = value;
723 return source;
724 case VUT_GOVERNMENT:
726 if (source.value.govern != nullptr) {
727 return source;
728 }
729 break;
730 case VUT_ACHIEVEMENT:
731 source.value.achievement = achievement_by_number(value);
732 if (source.value.achievement != nullptr) {
733 return source;
734 }
735 break;
736 case VUT_STYLE:
737 source.value.style = style_by_number(value);
738 if (source.value.style != nullptr) {
739 return source;
740 }
741 break;
742 case VUT_IMPROVEMENT:
743 case VUT_SITE:
744 source.value.building = improvement_by_number(value);
745 if (source.value.building != nullptr) {
746 return source;
747 }
748 break;
749 case VUT_IMPR_GENUS:
750 source.value.impr_genus = value;
751 return source;
752 case VUT_IMPR_FLAG:
753 source.value.impr_flag = value;
754 return source;
755 case VUT_PLAYER_FLAG:
756 source.value.plr_flag = value;
757 return source;
758 case VUT_EXTRA:
760 return source;
761 case VUT_GOOD:
762 source.value.good = goods_by_number(value);
763 return source;
764 case VUT_TERRAIN:
765 source.value.terrain = terrain_by_number(value);
766 if (source.value.terrain != nullptr) {
767 return source;
768 }
769 break;
770 case VUT_TERRFLAG:
771 source.value.terrainflag = value;
772 return source;
773 case VUT_NATION:
775 if (source.value.nation != nullptr) {
776 return source;
777 }
778 break;
779 case VUT_NATIONGROUP:
780 source.value.nationgroup = nation_group_by_number(value);
781 if (source.value.nationgroup != nullptr) {
782 return source;
783 }
784 break;
785 case VUT_DIPLREL:
786 case VUT_DIPLREL_TILE:
790 source.value.diplrel = value;
791 if (source.value.diplrel != diplrel_other_invalid()) {
792 return source;
793 }
794 break;
795 case VUT_NATIONALITY:
797 if (source.value.nationality != nullptr) {
798 return source;
799 }
800 break;
802 source.value.origowner = nation_by_number(value);
803 if (source.value.origowner != nullptr) {
804 return source;
805 }
806 break;
807 case VUT_UTYPE:
808 source.value.utype = utype_by_number(value);
809 if (source.value.utype != nullptr) {
810 return source;
811 }
812 break;
813 case VUT_UTFLAG:
814 source.value.unitflag = value;
815 return source;
816 case VUT_UCLASS:
818 if (source.value.uclass != nullptr) {
819 return source;
820 }
821 break;
822 case VUT_UCFLAG:
823 source.value.unitclassflag = value;
824 return source;
825 case VUT_MINVETERAN:
826 source.value.minveteran = value;
827 return source;
828 case VUT_UNITSTATE:
829 source.value.unit_state = value;
830 return source;
831 case VUT_ACTIVITY:
832 source.value.activity = value;
833 return source;
834 case VUT_MINMOVES:
835 source.value.minmoves = value;
836 return source;
837 case VUT_MINHP:
839 return source;
840 case VUT_AGE:
841 source.value.age = value;
842 return source;
843 case VUT_FORM_AGE:
844 source.value.form_age = value;
845 return source;
846 case VUT_MINTECHS:
847 source.value.min_techs = value;
848 return source;
849 case VUT_MINCITIES:
850 source.value.min_cities = value;
851 return source;
852 case VUT_ACTION:
854 if (source.value.action != nullptr) {
855 return source;
856 }
857 break;
858 case VUT_OTYPE:
859 source.value.outputtype = value;
860 return source;
861 case VUT_SPECIALIST:
863 return source;
864 case VUT_MINSIZE:
865 source.value.minsize = value;
866 return source;
867 case VUT_MINCULTURE:
868 source.value.minculture = value;
869 return source;
871 source.value.minforeignpct = value;
872 return source;
873 case VUT_AI_LEVEL:
874 source.value.ai_level = value;
875 return source;
876 case VUT_MAXTILEUNITS:
878 return source;
879 case VUT_TERRAINCLASS:
880 source.value.terrainclass = value;
881 return source;
882 case VUT_ROADFLAG:
883 source.value.roadflag = value;
884 return source;
885 case VUT_EXTRAFLAG:
886 source.value.extraflag = value;
887 return source;
888 case VUT_MINYEAR:
889 source.value.minyear = value;
890 return source;
891 case VUT_MINCALFRAG:
892 source.value.mincalfrag = value;
893 return source;
894 case VUT_TOPO:
895 source.value.topo_property = value;
896 return source;
897 case VUT_WRAP:
898 source.value.wrap_property = value;
899 return source;
901 source.value.ssetval = value;
902 return source;
903 case VUT_TERRAINALTER:
904 source.value.terrainalter = value;
905 return source;
906 case VUT_CITYTILE:
907 source.value.citytile = value;
908 return source;
909 case VUT_CITYSTATUS:
910 source.value.citystatus = value;
911 return source;
912 case VUT_PLAYER_STATE:
913 source.value.plrstate = value;
914 return source;
915 case VUT_COUNTER:
917 return source;
918 case VUT_MINLATITUDE:
919 case VUT_MAXLATITUDE:
920 source.value.latitude = value;
921 return source;
923 source.value.distance_sq = value;
924 return source;
926 source.value.region_tiles = value;
927 return source;
928 case VUT_TILE_REL:
929 source.value.tilerel = value;
930 return source;
931 case VUT_COUNT:
932 break;
933 }
934
935 /* If we reach here there's been an error. */
937 /* Avoid compiler warning about uninitialized source.value */
938 source.value.advance = nullptr;
939
940 return source;
941}
942
943/**********************************************************************/
946void universal_copy(struct universal *dst, const struct universal *src)
947{
948 dst->value = src->value;
949 dst->kind = src->kind;
950}
951
952/**********************************************************************/
957 int *kind, int *value)
958{
959 *kind = source->kind;
961}
962
963/**********************************************************************/
967{
968 switch (source->kind) {
969 case VUT_NONE:
970 return 0;
971 case VUT_ADVANCE:
972 return advance_number(source->value.advance);
973 case VUT_TECHFLAG:
974 return source->value.techflag;
975 case VUT_GOVERNMENT:
976 return government_number(source->value.govern);
977 case VUT_ACHIEVEMENT:
978 return achievement_number(source->value.achievement);
979 case VUT_STYLE:
980 return style_number(source->value.style);
981 case VUT_IMPROVEMENT:
982 case VUT_SITE:
983 return improvement_number(source->value.building);
984 case VUT_IMPR_GENUS:
985 return source->value.impr_genus;
986 case VUT_IMPR_FLAG:
987 return source->value.impr_flag;
988 case VUT_PLAYER_FLAG:
989 return source->value.plr_flag;
990 case VUT_EXTRA:
991 return extra_number(source->value.extra);
992 case VUT_GOOD:
993 return goods_number(source->value.good);
994 case VUT_TERRAIN:
995 return terrain_number(source->value.terrain);
996 case VUT_TERRFLAG:
997 return source->value.terrainflag;
998 case VUT_NATION:
999 return nation_number(source->value.nation);
1000 case VUT_NATIONGROUP:
1001 return nation_group_number(source->value.nationgroup);
1002 case VUT_NATIONALITY:
1003 return nation_number(source->value.nationality);
1004 case VUT_ORIGINAL_OWNER:
1005 return nation_number(source->value.origowner);
1006 case VUT_DIPLREL:
1007 case VUT_DIPLREL_TILE:
1008 case VUT_DIPLREL_TILE_O:
1011 return source->value.diplrel;
1012 case VUT_UTYPE:
1013 return utype_number(source->value.utype);
1014 case VUT_UTFLAG:
1015 return source->value.unitflag;
1016 case VUT_UCLASS:
1017 return uclass_number(source->value.uclass);
1018 case VUT_UCFLAG:
1019 return source->value.unitclassflag;
1020 case VUT_MINVETERAN:
1021 return source->value.minveteran;
1022 case VUT_UNITSTATE:
1023 return source->value.unit_state;
1024 case VUT_ACTIVITY:
1025 return source->value.activity;
1026 case VUT_MINMOVES:
1027 return source->value.minmoves;
1028 case VUT_MINHP:
1029 return source->value.min_hit_points;
1030 case VUT_AGE:
1031 return source->value.age;
1032 case VUT_FORM_AGE:
1033 return source->value.form_age;
1034 case VUT_MINTECHS:
1035 return source->value.min_techs;
1036 case VUT_MINCITIES:
1037 return source->value.min_cities;
1038 case VUT_ACTION:
1039 return action_number(source->value.action);
1040 case VUT_OTYPE:
1041 return source->value.outputtype;
1042 case VUT_SPECIALIST:
1043 return specialist_number(source->value.specialist);
1044 case VUT_MINSIZE:
1045 return source->value.minsize;
1046 case VUT_MINCULTURE:
1047 return source->value.minculture;
1048 case VUT_MINFOREIGNPCT:
1049 return source->value.minforeignpct;
1050 case VUT_AI_LEVEL:
1051 return source->value.ai_level;
1052 case VUT_MAXTILEUNITS:
1053 return source->value.max_tile_units;
1054 case VUT_TERRAINCLASS:
1055 return source->value.terrainclass;
1056 case VUT_ROADFLAG:
1057 return source->value.roadflag;
1058 case VUT_EXTRAFLAG:
1059 return source->value.extraflag;
1060 case VUT_MINYEAR:
1061 return source->value.minyear;
1062 case VUT_MINCALFRAG:
1063 return source->value.mincalfrag;
1064 case VUT_TOPO:
1065 return source->value.topo_property;
1066 case VUT_WRAP:
1067 return source->value.wrap_property;
1068 case VUT_SERVERSETTING:
1069 return source->value.ssetval;
1070 case VUT_TERRAINALTER:
1071 return source->value.terrainalter;
1072 case VUT_CITYTILE:
1073 return source->value.citytile;
1074 case VUT_CITYSTATUS:
1075 return source->value.citystatus;
1076 case VUT_PLAYER_STATE:
1077 return source->value.plrstate;
1078 case VUT_COUNTER:
1079 return counter_id(source->value.counter);
1080 case VUT_MINLATITUDE:
1081 case VUT_MAXLATITUDE:
1082 return source->value.latitude;
1084 return source->value.distance_sq;
1086 return source->value.region_tiles;
1087 case VUT_TILE_REL:
1088 return source->value.tilerel;
1089 case VUT_COUNT:
1090 break;
1091 }
1092
1093 /* If we reach here there's been an error. */
1094 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
1095 source->kind);
1096 return 0;
1097}
1098
1099
1100/**********************************************************************/
1104{
1105 static const struct req_context empty = {};
1106 return &empty;
1107}
1108
1109
1110/**********************************************************************/
1118const char *req_to_fstring(const struct requirement *req,
1119 struct astring *astr)
1120{
1121 astr_init(astr);
1122
1123 astr_set(astr, "%s%s %s %s%s",
1124 req->survives ? "surviving " : "",
1125 req_range_name(req->range),
1127 req->present ? "" : "!",
1129
1130 return astr_str(astr);
1131}
1132
1133/**********************************************************************/
1141 bool survives, bool present, bool quiet,
1142 const char *value)
1143{
1144 struct requirement req;
1145 bool invalid;
1146 const char *error = nullptr;
1147
1148 req.source = universal_by_rule_name(type, value);
1149
1151 if (invalid) {
1152 error = "bad type or name";
1153 } else {
1154 /* Scan the range string to find the range. If no range is given a
1155 * default fallback is used rather than giving an error. */
1156 if (range != nullptr) {
1158 if (!req_range_is_valid(req.range)) {
1159 invalid = TRUE;
1160 }
1161 } else {
1162 switch (req.source.kind) {
1163 case VUT_NONE:
1164 case VUT_COUNT:
1165 break;
1166 case VUT_IMPROVEMENT:
1167 case VUT_SITE:
1168 case VUT_IMPR_GENUS:
1169 case VUT_IMPR_FLAG:
1170 case VUT_UTYPE:
1171 case VUT_UTFLAG:
1172 case VUT_UCLASS:
1173 case VUT_UCFLAG:
1174 case VUT_MINVETERAN:
1175 case VUT_UNITSTATE:
1176 case VUT_ACTIVITY:
1177 case VUT_MINMOVES:
1178 case VUT_MINHP:
1179 case VUT_AGE:
1180 case VUT_FORM_AGE:
1181 case VUT_ACTION:
1182 case VUT_OTYPE:
1183 case VUT_SPECIALIST:
1184 case VUT_DIPLREL_TILE_O:
1186 req.range = REQ_RANGE_LOCAL;
1187 break;
1188 case VUT_EXTRA:
1189 case VUT_ROADFLAG:
1190 case VUT_EXTRAFLAG:
1191 /* Keep old behavior */
1192 req.range = REQ_RANGE_TILE;
1193 break;
1194 case VUT_TERRAIN:
1195 case VUT_TERRFLAG:
1196 case VUT_TERRAINCLASS:
1197 case VUT_TERRAINALTER:
1198 case VUT_CITYTILE:
1199 case VUT_MAXTILEUNITS:
1200 case VUT_MINLATITUDE:
1201 case VUT_MAXLATITUDE:
1203 req.range = REQ_RANGE_TILE;
1204 break;
1205 case VUT_COUNTER:
1206 case VUT_MINSIZE:
1207 case VUT_MINCULTURE:
1208 case VUT_MINFOREIGNPCT:
1209 case VUT_NATIONALITY:
1210 case VUT_ORIGINAL_OWNER:
1211 case VUT_CITYSTATUS:
1212 case VUT_GOOD:
1213 req.range = REQ_RANGE_CITY;
1214 break;
1215 case VUT_GOVERNMENT:
1216 case VUT_ACHIEVEMENT:
1217 case VUT_STYLE:
1218 case VUT_ADVANCE:
1219 case VUT_TECHFLAG:
1220 case VUT_NATION:
1221 case VUT_NATIONGROUP:
1222 case VUT_DIPLREL:
1223 case VUT_DIPLREL_TILE:
1225 case VUT_AI_LEVEL:
1226 case VUT_PLAYER_FLAG:
1227 case VUT_PLAYER_STATE:
1228 case VUT_MINCITIES:
1229 req.range = REQ_RANGE_PLAYER;
1230 break;
1231 case VUT_MINYEAR:
1232 case VUT_MINCALFRAG:
1233 case VUT_TOPO:
1234 case VUT_WRAP:
1235 case VUT_MINTECHS:
1236 case VUT_SERVERSETTING:
1237 req.range = REQ_RANGE_WORLD;
1238 break;
1241 break;
1242 case VUT_TILE_REL:
1243 req.range = REQ_RANGE_TILE;
1245 /* Not available at Tile range */
1247 }
1248 break;
1249 }
1250 }
1251
1252 req.survives = survives;
1253 req.present = present;
1254 req.quiet = quiet;
1255
1256 /* These checks match what combinations are supported inside
1257 * is_req_active(). However, it's only possible to do basic checks,
1258 * not anything that might depend on the rest of the ruleset which
1259 * might not have been loaded yet. */
1260 switch (req.source.kind) {
1261 case VUT_TERRAIN:
1262 case VUT_TERRAINCLASS:
1263 case VUT_TERRFLAG:
1264 invalid = (req.range != REQ_RANGE_TILE
1265 && req.range != REQ_RANGE_CADJACENT
1266 && req.range != REQ_RANGE_ADJACENT
1267 && req.range != REQ_RANGE_CITY
1268 && req.range != REQ_RANGE_TRADE_ROUTE);
1269 break;
1270 case VUT_EXTRA:
1271 case VUT_ROADFLAG:
1272 case VUT_EXTRAFLAG:
1274 break;
1275 case VUT_ACHIEVEMENT:
1276 case VUT_MINTECHS:
1277 invalid = (req.range < REQ_RANGE_PLAYER);
1278 break;
1279 case VUT_ADVANCE:
1280 case VUT_TECHFLAG:
1282 && req.range != REQ_RANGE_LOCAL);
1283 break;
1284 case VUT_GOVERNMENT:
1285 case VUT_AI_LEVEL:
1286 case VUT_STYLE:
1287 case VUT_MINCITIES:
1288 invalid = (req.range != REQ_RANGE_PLAYER);
1289 break;
1290 case VUT_MINSIZE:
1291 case VUT_MINFOREIGNPCT:
1292 case VUT_NATIONALITY:
1293 case VUT_CITYSTATUS:
1294 invalid = (req.range != REQ_RANGE_CITY
1295 && req.range != REQ_RANGE_TRADE_ROUTE);
1296 break;
1297 case VUT_GOOD:
1298 case VUT_ORIGINAL_OWNER:
1299 invalid = (req.range != REQ_RANGE_CITY);
1300 break;
1301 case VUT_MINCULTURE:
1302 invalid = (req.range != REQ_RANGE_CITY
1304 && req.range != REQ_RANGE_PLAYER
1305 && req.range != REQ_RANGE_TEAM
1306 && req.range != REQ_RANGE_ALLIANCE
1307 && req.range != REQ_RANGE_WORLD);
1308 break;
1309 case VUT_DIPLREL:
1310 invalid = (req.range != REQ_RANGE_LOCAL
1311 && req.range != REQ_RANGE_PLAYER
1312 && req.range != REQ_RANGE_TEAM
1313 && req.range != REQ_RANGE_ALLIANCE
1314 && req.range != REQ_RANGE_WORLD)
1315 /* Non local foreign makes no sense. */
1316 || (req.source.value.diplrel == DRO_FOREIGN
1317 && req.range != REQ_RANGE_LOCAL);
1318 break;
1319 case VUT_DIPLREL_TILE:
1320 invalid = (req.range != REQ_RANGE_LOCAL
1321 && req.range != REQ_RANGE_PLAYER
1322 && req.range != REQ_RANGE_TEAM
1323 && req.range != REQ_RANGE_ALLIANCE)
1324 /* Non local foreign makes no sense. */
1325 || (req.source.value.diplrel == DRO_FOREIGN
1326 && req.range != REQ_RANGE_LOCAL);
1327 break;
1328 case VUT_DIPLREL_TILE_O:
1329 invalid = (req.range != REQ_RANGE_LOCAL);
1330 break;
1332 invalid = (req.range != REQ_RANGE_LOCAL
1333 && req.range != REQ_RANGE_PLAYER
1334 && req.range != REQ_RANGE_TEAM
1335 && req.range != REQ_RANGE_ALLIANCE)
1336 /* Non local foreign makes no sense. */
1337 || (req.source.value.diplrel == DRO_FOREIGN
1338 && req.range != REQ_RANGE_LOCAL);
1339 break;
1341 invalid = (req.range != REQ_RANGE_LOCAL);
1342 break;
1343 case VUT_NATION:
1344 case VUT_NATIONGROUP:
1346 && req.range != REQ_RANGE_TEAM
1347 && req.range != REQ_RANGE_ALLIANCE
1348 && req.range != REQ_RANGE_WORLD);
1349 break;
1350 case VUT_MINVETERAN:
1351 case VUT_UNITSTATE:
1352 case VUT_ACTIVITY:
1353 case VUT_MINMOVES:
1354 case VUT_MINHP:
1355 case VUT_ACTION:
1356 case VUT_OTYPE:
1357 case VUT_SPECIALIST:
1358 invalid = (req.range != REQ_RANGE_LOCAL);
1359 break;
1360 case VUT_UTYPE:
1361 case VUT_UTFLAG:
1362 case VUT_UCLASS:
1363 case VUT_UCFLAG:
1364 invalid = (req.range != REQ_RANGE_LOCAL
1365 && req.range != REQ_RANGE_TILE
1366 && req.range != REQ_RANGE_CADJACENT
1367 && req.range != REQ_RANGE_ADJACENT);
1368 break;
1369 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1371 invalid = (req.range != REQ_RANGE_TILE);
1372 break;
1373 case VUT_CITYTILE:
1374 case VUT_MAXTILEUNITS:
1375 invalid = (req.range != REQ_RANGE_TILE
1376 && req.range != REQ_RANGE_CADJACENT
1377 && req.range != REQ_RANGE_ADJACENT);
1378 break;
1379 case VUT_MINLATITUDE:
1380 case VUT_MAXLATITUDE:
1381 invalid = (req.range != REQ_RANGE_TILE
1382 && req.range != REQ_RANGE_CADJACENT
1383 && req.range != REQ_RANGE_ADJACENT
1384 && req.range != REQ_RANGE_WORLD)
1385 /* Avoid redundancy at tile range: no negated requirements
1386 * that could be emulated by a present requirement of the
1387 * other type */
1388 || (req.range == REQ_RANGE_TILE && !req.present);
1389 break;
1390 case VUT_MINYEAR:
1391 case VUT_MINCALFRAG:
1392 case VUT_TOPO:
1393 case VUT_WRAP:
1394 case VUT_SERVERSETTING:
1395 invalid = (req.range != REQ_RANGE_WORLD);
1396 break;
1397 case VUT_AGE:
1398 /* FIXME: Could support TRADE_ROUTE, TEAM, etc */
1399 invalid = (req.range != REQ_RANGE_LOCAL
1400 && req.range != REQ_RANGE_CITY
1401 && req.range != REQ_RANGE_PLAYER);
1402 break;
1403 case VUT_FORM_AGE:
1404 invalid = (req.range != REQ_RANGE_LOCAL);
1405 break;
1406 case VUT_IMPR_GENUS:
1407 /* TODO: Support other ranges too. */
1408 invalid = (req.range != REQ_RANGE_LOCAL);
1409 break;
1410 case VUT_IMPR_FLAG:
1411 invalid = (req.range != REQ_RANGE_LOCAL
1412 && req.range != REQ_RANGE_TILE
1413 && req.range != REQ_RANGE_CITY);
1414 break;
1415 case VUT_COUNTER:
1416 invalid = req.range != REQ_RANGE_CITY;
1417 break;
1418 case VUT_PLAYER_FLAG:
1419 case VUT_PLAYER_STATE:
1420 invalid = (req.range != REQ_RANGE_PLAYER);
1421 break;
1424 && req.range != REQ_RANGE_CADJACENT
1425 && req.range != REQ_RANGE_ADJACENT);
1426 break;
1427 case VUT_TILE_REL:
1429 && req.range != REQ_RANGE_CADJACENT
1430 && req.range != REQ_RANGE_TILE)
1431 /* TREL_ONLY_OTHER_REGION not supported at Tile range */
1433 && req.range == REQ_RANGE_TILE);
1434 break;
1435 case VUT_IMPROVEMENT:
1436 case VUT_SITE:
1437 /* Valid ranges depend on the building genus (wonder/improvement),
1438 * which might not have been loaded from the ruleset yet.
1439 * So we allow anything here, and do a proper check once ruleset
1440 * loading is complete, in sanity_check_req_individual(). */
1441 case VUT_NONE:
1442 invalid = FALSE;
1443 break;
1444 case VUT_COUNT:
1445 break;
1446 }
1447 if (invalid) {
1448 error = "bad range";
1449 }
1450 }
1451
1452 if (!invalid) {
1453 /* Check 'survives'. */
1454 switch (req.source.kind) {
1455 case VUT_IMPROVEMENT:
1456 case VUT_SITE:
1457 /* See buildings_in_range(). */
1459 break;
1460 case VUT_NATION:
1461 case VUT_ADVANCE:
1463 break;
1464 case VUT_COUNTER:
1465 case VUT_IMPR_GENUS:
1466 case VUT_IMPR_FLAG:
1467 case VUT_PLAYER_FLAG:
1468 case VUT_PLAYER_STATE:
1469 case VUT_GOVERNMENT:
1470 case VUT_TERRAIN:
1471 case VUT_UTYPE:
1472 case VUT_UTFLAG:
1473 case VUT_UCLASS:
1474 case VUT_UCFLAG:
1475 case VUT_MINVETERAN:
1476 case VUT_UNITSTATE:
1477 case VUT_ACTIVITY:
1478 case VUT_MINMOVES:
1479 case VUT_MINHP:
1480 case VUT_AGE:
1481 case VUT_FORM_AGE:
1482 case VUT_ACTION:
1483 case VUT_OTYPE:
1484 case VUT_SPECIALIST:
1485 case VUT_MINSIZE:
1486 case VUT_MINCULTURE:
1487 case VUT_MINFOREIGNPCT:
1488 case VUT_AI_LEVEL:
1489 case VUT_TERRAINCLASS:
1490 case VUT_MINYEAR:
1491 case VUT_MINCALFRAG:
1492 case VUT_TOPO:
1493 case VUT_WRAP:
1494 case VUT_SERVERSETTING:
1495 case VUT_TERRAINALTER:
1496 case VUT_CITYTILE:
1497 case VUT_CITYSTATUS:
1498 case VUT_TERRFLAG:
1499 case VUT_NATIONALITY:
1500 case VUT_ORIGINAL_OWNER:
1501 case VUT_ROADFLAG:
1502 case VUT_EXTRAFLAG:
1503 case VUT_EXTRA:
1504 case VUT_GOOD:
1505 case VUT_TECHFLAG:
1506 case VUT_ACHIEVEMENT:
1507 case VUT_NATIONGROUP:
1508 case VUT_STYLE:
1509 case VUT_DIPLREL:
1510 case VUT_DIPLREL_TILE:
1511 case VUT_DIPLREL_TILE_O:
1514 case VUT_MAXTILEUNITS:
1515 case VUT_MINTECHS:
1516 case VUT_MINCITIES:
1517 case VUT_MINLATITUDE:
1518 case VUT_MAXLATITUDE:
1521 case VUT_TILE_REL:
1522 /* Most requirements don't support 'survives'. */
1523 invalid = survives;
1524 break;
1525 case VUT_NONE:
1526 case VUT_COUNT:
1527 break;
1528 }
1529 if (invalid) {
1530 error = "bad 'survives'";
1531 }
1532 }
1533
1534 if (invalid) {
1535 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1536 type, range, survives ? "survives" : "",
1537 present ? "present" : "", value, error);
1539 }
1540
1541 return req;
1542}
1543
1544/**********************************************************************/
1550 int value)
1551{
1552 struct requirement req;
1553
1554 req.source = universal_by_number(type, value);
1555 req.range = range;
1556 req.survives = survives;
1557 req.present = present;
1558 req.quiet = quiet;
1559
1560 return req;
1561}
1562
1563/**********************************************************************/
1567void req_get_values(const struct requirement *req,
1568 int *type, int *range,
1569 bool *survives, bool *present, bool *quiet,
1570 int *value)
1571{
1572 universal_extraction(&req->source, type, value);
1573 *range = req->range;
1574 *survives = req->survives;
1575 *present = req->present;
1576 *quiet = req->quiet;
1577}
1578
1579/**********************************************************************/
1582void req_copy(struct requirement *dst, const struct requirement *src)
1583{
1584 universal_copy(&(dst->source), &(src->source));
1585 dst->range = src->range;
1586 dst->survives = src->survives;
1587 dst->present = src->present;
1588 dst->quiet = src->quiet;
1589}
1590
1591/**********************************************************************/
1595bool are_requirements_equal(const struct requirement *req1,
1596 const struct requirement *req2)
1597{
1598 return (are_universals_equal(&req1->source, &req2->source)
1599 && req1->range == req2->range
1600 && req1->survives == req2->survives
1601 && req1->present == req2->present);
1602}
1603
1604/**********************************************************************/
1607static bool are_requirements_opposites(const struct requirement *req1,
1608 const struct requirement *req2)
1609{
1610 return (are_universals_equal(&req1->source, &req2->source)
1611 && req1->range == req2->range
1612 && req1->survives == req2->survives
1613 && req1->present != req2->present);
1614}
1615
1616/**********************************************************************/
1620static bool impr_contra_genus(const struct requirement *impr_req,
1621 const struct requirement *genus_req)
1622{
1623 /* The input is sane. */
1625 || impr_req->source.kind == VUT_SITE, FALSE);
1627
1628 if (impr_req->range == REQ_RANGE_LOCAL
1629 && genus_req->range == REQ_RANGE_LOCAL) {
1630 /* Applies to the same target building. */
1631
1632 if (impr_req->present && !genus_req->present) {
1633 /* The target building can't not have the genus it has. */
1634 return (impr_req->source.value.building->genus
1635 == genus_req->source.value.impr_genus);
1636 }
1637
1638 if (impr_req->present && genus_req->present) {
1639 /* The target building can't have another genus than it has. */
1640 return (impr_req->source.value.building->genus
1641 != genus_req->source.value.impr_genus);
1642 }
1643 }
1644
1645 /* No special knowledge. */
1646 return FALSE;
1647}
1648
1649/**********************************************************************/
1653static bool impr_contra_flag(const struct requirement *impr_req,
1654 const struct requirement *flag_req)
1655{
1656 /* The input is sane. */
1658 || impr_req->source.kind == VUT_SITE, FALSE);
1660
1661 if (impr_req->range == REQ_RANGE_LOCAL
1662 && flag_req->range == REQ_RANGE_LOCAL) {
1663 /* Applies to the same target building. */
1664
1665 if (impr_req->present && !flag_req->present) {
1666 /* The target building can't not have the flag it has. */
1667 return improvement_has_flag(impr_req->source.value.building,
1668 flag_req->source.value.impr_flag);
1669 }
1670
1671 if (impr_req->present && flag_req->present) {
1672 /* The target building can't have another flag than it has. */
1673 return !improvement_has_flag(impr_req->source.value.building,
1674 flag_req->source.value.impr_flag);
1675 }
1676 }
1677
1678 /* No special knowledge. */
1679 return FALSE;
1680}
1681
1682/**********************************************************************/
1687 const struct requirement *group_req)
1688{
1689 /* The input is sane. */
1690 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1692
1693 if (nation_req->range == REQ_RANGE_PLAYER
1694 && group_req->range == REQ_RANGE_PLAYER) {
1695 /* Applies to the same target building. */
1696
1697 if (nation_req->present && !group_req->present) {
1698 /* The target nation can't be in the group. */
1699 return nation_is_in_group(nation_req->source.value.nation,
1700 group_req->source.value.nationgroup);
1701 }
1702 }
1703
1704 /* No special knowledge. */
1705 return FALSE;
1706}
1707
1708/**********************************************************************/
1712static bool city_center_contra(const struct requirement *cc_req,
1713 const struct requirement *ct_req)
1714{
1715 /* The input is sane. */
1716 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1717 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1718
1719 if (cc_req->source.value.citytile == CITYT_CENTER
1720 && cc_req->present && cc_req->range <= ct_req->range) {
1721 switch (ct_req->source.value.citytile) {
1722 case CITYT_CENTER:
1723 case CITYT_CLAIMED:
1724 case CITYT_EXTRAS_OWNED:
1725 case CITYT_WORKED:
1727 /* Should be always on city center */
1728 return !ct_req->present;
1730 /* Handled later */
1731 break;
1732 case CITYT_LAST:
1733 /* Error */
1734 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1735 }
1736 }
1737 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1738 || cc_req->source.value.citytile == CITYT_CENTER)
1739 && ct_req->source.value.citytile
1741 && REQ_RANGE_TILE == cc_req->range
1742 && REQ_RANGE_TILE == ct_req->range) {
1743 /* Can't coexist */
1744 return cc_req->present ? ct_req->present : !ct_req->present;
1745 }
1746
1747 return FALSE;
1748}
1749
1750/**********************************************************************/
1755static bool present_implies_not_present(const struct requirement *req1,
1756 const struct requirement *req2)
1757{
1758 const struct requirement *absent, *present;
1759
1760 if (req1->present == req2->present) {
1761 /* Can't use the knowledge in universal_found_function when both are
1762 * required to be absent or when both are required to be present.
1763 * It is no contradiction to require !Spy unit and !Missile unit class.
1764 * It is no contradiction to require River and Irrigation at the same
1765 * tile. */
1766 return FALSE;
1767 }
1768
1769 if (req1->present) {
1770 absent = req2;
1771 present = req1;
1772 } else {
1773 absent = req1;
1774 present = req2;
1775 }
1776
1777 if (!universal_found_function[present->source.kind]) {
1778 /* No knowledge to exploit. */
1779 return FALSE;
1780 }
1781
1782 if (present->range != absent->range) {
1783 /* Larger ranges are not always strict supersets of smaller ranges.
1784 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1785 * but not in Trade Route. */
1786 return FALSE;
1787 }
1788
1790 &present->source);
1791}
1792
1793/**********************************************************************/
1796bool req_implies_req(const struct requirement *req1,
1797 const struct requirement *req2)
1798{
1799 struct requirement nreq2;
1800
1801 req_copy(&nreq2, req2);
1802 nreq2.present = !nreq2.present;
1804}
1805
1806/**********************************************************************/
1811static inline bool are_bounds_contradictions(int bound1, bool is_upper1,
1812 int bound2, bool is_upper2)
1813{
1814 /* If the bounds are on opposite sides, and one is inclusive, the other
1815 * exclusive, the number of values that satisfy both bounds is exactly
1816 * their difference, (upper bound) - (lower bound).
1817 * The bounds contradict each other iff this difference is 0 or less,
1818 * i.e. iff (upper bound) <= (lower bound) */
1819 if (is_upper1 && !is_upper2) {
1820 return bound1 <= bound2;
1821 } else if (!is_upper1 && is_upper2) {
1822 return bound1 >= bound2;
1823 }
1824 /* Both are upper or both are lower ~> no contradiction possible */
1825 return FALSE;
1826}
1827
1828/**********************************************************************/
1836 const struct requirement *req2)
1837{
1838 if (are_requirements_opposites(req1, req2)) {
1839 /* The exact opposite. */
1840 return TRUE;
1841 }
1842
1843 if (present_implies_not_present(req1, req2)) {
1844 return TRUE;
1845 }
1846
1847 switch (req1->source.kind) {
1848 case VUT_IMPROVEMENT:
1849 case VUT_SITE:
1850 if (req2->source.kind == VUT_IMPR_GENUS) {
1851 return impr_contra_genus(req1, req2);
1852 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1853 return impr_contra_flag(req1, req2);
1854 } else if (req2->source.kind == VUT_CITYTILE
1855 && req2->source.value.citytile == CITYT_CENTER
1856 && REQ_RANGE_TILE == req2->range
1857 && REQ_RANGE_TILE == req1->range
1858 && req1->present) {
1859 /* A building must be in a city */
1860 return !req2->present;
1861 }
1862
1863 /* No special knowledge. */
1864 return FALSE;
1865 case VUT_IMPR_GENUS:
1866 if (req2->source.kind == VUT_IMPROVEMENT
1867 || req2->source.kind == VUT_SITE) {
1868 return impr_contra_genus(req2, req1);
1869 }
1870
1871 /* No special knowledge. */
1872 return FALSE;
1873 case VUT_IMPR_FLAG:
1874 if (req2->source.kind == VUT_IMPROVEMENT
1875 || req2->source.kind == VUT_SITE) {
1876 return impr_contra_flag(req2, req1);
1877 }
1878
1879 /* No special knowledge. */
1880 return FALSE;
1881 case VUT_DIPLREL:
1882 case VUT_DIPLREL_TILE:
1883 case VUT_DIPLREL_TILE_O:
1886 if (req2->source.kind != req1->source.kind) {
1887 /* Finding contradictions across requirement kinds aren't supported
1888 * for DiplRel requirements. */
1889 return FALSE;
1890 } else {
1891 /* Use the special knowledge about DiplRel requirements to find
1892 * contradictions. */
1893
1895 int req2_pos;
1896
1899 req2->range,
1900 req2->present);
1901
1902 return BV_ISSET(req1_contra, req2_pos);
1903 }
1904 break;
1905 case VUT_MINMOVES:
1906 if (req2->source.kind != VUT_MINMOVES) {
1907 /* Finding contradictions across requirement kinds aren't supported
1908 * for MinMoveFrags requirements. */
1909 return FALSE;
1910 }
1912 req1->source.value.minmoves, !req1->present,
1913 req2->source.value.minmoves, !req2->present);
1914 case VUT_MINLATITUDE:
1915 case VUT_MAXLATITUDE:
1916 if (req2->source.kind != VUT_MINLATITUDE
1917 && req2->source.kind != VUT_MAXLATITUDE) {
1918 /* Finding contradictions across requirement kinds other than each
1919 * other is not supported for MinLatitude and MaxLatitude. */
1920 return FALSE;
1921 } else {
1922 /* For a contradiction, we need
1923 * - a minimum (present MinLatitude or negated MaxLatitude)
1924 * - a maximum (negated MinLatitude or present MaxLatitude)
1925 * - the maximum to be less than the minimum
1926 * - a requirement at the larger range that applies to the entire
1927 * range (i.e. a negated requirement, unless the range is Tile)
1928 * Otherwise, the two requirements could still be fulfilled
1929 * simultaneously by different tiles in the range */
1930
1931 /* Initial values beyond the boundaries to avoid edge cases */
1932 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
1934
1935#define EXTRACT_INFO(req) \
1936 if (req->present) { \
1937 if (req->source.kind == VUT_MINLATITUDE) { \
1938 /* present MinLatitude */ \
1939 minimum = MAX(minimum, req->source.value.latitude); \
1940 } else { \
1941 /* present MaxLatitude */ \
1942 maximum = MIN(maximum, req->source.value.latitude); \
1943 } \
1944 } else { \
1945 covered_range = MAX(covered_range, req->range); \
1946 if (req->source.kind == VUT_MINLATITUDE) { \
1947 /* negated MinLatitude */ \
1948 maximum = MIN(maximum, req->source.value.latitude - 1); \
1949 } else { \
1950 /* negated MaxLatitude */ \
1951 minimum = MAX(minimum, req->source.value.latitude + 1); \
1952 } \
1953 }
1954
1955 EXTRACT_INFO(req1);
1956 EXTRACT_INFO(req2);
1957
1958#undef EXTRACT_INFO
1959
1960 return (maximum < minimum
1961 && covered_range >= req1->range
1962 && covered_range >= req2->range);
1963 }
1964 break;
1965 case VUT_NATION:
1966 if (req2->source.kind == VUT_NATIONGROUP) {
1967 return nation_contra_group(req1, req2);
1968 }
1969
1970 /* No special knowledge. */
1971 return FALSE;
1972 break;
1973 case VUT_NATIONGROUP:
1974 if (req2->source.kind == VUT_NATION) {
1975 return nation_contra_group(req2, req1);
1976 }
1977
1978 /* No special knowledge. */
1979 return FALSE;
1980 break;
1981 case VUT_CITYTILE:
1982 if (req2->source.kind == VUT_CITYTILE) {
1983 return city_center_contra(req1, req2)
1984 || city_center_contra(req2, req1);
1985 } else if (req1->source.value.citytile == CITYT_CENTER
1986 && (req2->source.kind == VUT_IMPROVEMENT
1987 || req2->source.kind == VUT_SITE)
1988 && REQ_RANGE_TILE == req2->range
1989 && REQ_RANGE_TILE == req1->range
1990 && req2->present) {
1991 /* A building must be in a city */
1992 return !req1->present;
1993 }
1994
1995 return FALSE;
1997 if (req2->source.kind != VUT_MAX_DISTANCE_SQ) {
1998 /* Finding contradictions across requirement kinds isn't supported
1999 * for MaxDistanceSq requirements. */
2000 return FALSE;
2001 }
2003 req1->source.value.distance_sq, req1->present,
2004 req2->source.value.distance_sq, req2->present);
2006 if (req2->source.kind != VUT_MAX_REGION_TILES) {
2007 /* Finding contradictions across requirement kinds isn't supported
2008 * for MaxRegionTiles requirements. */
2009 return FALSE;
2010 } else if (req1->range != req2->range) {
2011 /* FIXME: Finding contradictions across ranges not yet supported.
2012 * In particular, a max at a small range and a min at a larger range
2013 * needs extra work to figure out. */
2014 return FALSE;
2015 }
2017 req1->source.value.region_tiles, req1->present,
2018 req2->source.value.region_tiles, req2->present);
2019 case VUT_TILE_REL:
2020 if (req2->source.kind != VUT_TILE_REL) {
2021 /* Finding contradictions across requirement kinds isn't supported
2022 * for TileRel requirements. */
2023 return FALSE;
2024 }
2025 if (req1->source.value.tilerel == req2->source.value.tilerel) {
2026 /* Same requirement at different ranges. Note that same range is
2027 * already covered by are_requirements_opposites() above. */
2028 switch (req1->source.value.tilerel) {
2029 case TREL_SAME_TCLASS:
2030 case TREL_SAME_REGION:
2032 /* Negated req at larger range contradicts present req at
2033 * smaller range. */
2034 if (req1->range > req2->range) {
2035 return !req1->present && req2->present;
2036 } else {
2037 return req1->present && !req2->present;
2038 }
2039 break;
2041 /* Present req at larger range contradicts negated req at
2042 * smaller range */
2043 if (req1->range > req2->range) {
2044 return req1->present && !req2->present;
2045 } else {
2046 return !req1->present && req2->present;
2047 }
2048 break;
2049 default:
2050 return FALSE;
2051 }
2052 }
2054 && req2->source.value.tilerel == TREL_SAME_REGION) {
2055 /* Same region at any range implies same terrain class at that range
2056 * and any larger range ~> contradicts negated */
2057 return (!req1->present && req2->present
2058 && (req1->range >= req2->range));
2059 } else if (req2->source.value.tilerel == TREL_SAME_TCLASS
2060 && req1->source.value.tilerel == TREL_SAME_REGION) {
2061 /* Same as above */
2062 return (req1->present && !req2->present
2063 && (req1->range <= req2->range));
2064 } else if (req1->source.value.tilerel == TREL_REGION_SURROUNDED
2066 const struct requirement *surr, *other;
2068 surr = req1;
2069 other = req2;
2070 } else {
2071 surr = req2;
2072 other = req1;
2073 }
2074 if (surr->present && surr->range == REQ_RANGE_TILE) {
2075 /* Target tile must be part of a surrounded region
2076 * ~> not the same terrain class
2077 * ~> not the same region
2078 * ~> not touched by a third region */
2079 switch (other->source.value.tilerel) {
2080 case TREL_SAME_TCLASS:
2081 case TREL_SAME_REGION:
2082 return (other->present && other->range == REQ_RANGE_TILE);
2084 return (!other->present);
2085 default:
2086 break;
2087 }
2088 }
2089 }
2090 /* No further contradictions we can detect */
2091 return FALSE;
2092 default:
2093 /* No special knowledge exists. The requirements aren't the exact
2094 * opposite of each other per the initial check. */
2095 return FALSE;
2096 }
2097}
2098
2099/**********************************************************************/
2107struct requirement *
2109 const struct requirement_vector *vec)
2110{
2111 /* If the requirement is contradicted by any requirement in the vector it
2112 * contradicts the entire requirement vector. */
2115 return preq;
2116 }
2118
2119 /* Not a single requirement in the requirement vector is contradicted to be
2120 * the specified requirement. */
2121 return nullptr;
2122}
2123
2124/**********************************************************************/
2129 const struct requirement_vector *vec)
2130{
2131 return req_vec_first_contradiction_in_vec(req, vec) != nullptr;
2132}
2133
2134/**********************************************************************/
2137static inline bool are_tiles_in_range(const struct tile *tile1,
2138 const struct tile *tile2,
2139 enum req_range range)
2140{
2141 switch (range) {
2142 case REQ_RANGE_ADJACENT:
2144 return TRUE;
2145 }
2147 case REQ_RANGE_TILE:
2148 return same_pos(tile1, tile2);
2150 return map_distance(tile1, tile2) <= 1;
2151 case REQ_RANGE_CITY:
2153 case REQ_RANGE_LOCAL:
2155 case REQ_RANGE_PLAYER:
2156 case REQ_RANGE_TEAM:
2157 case REQ_RANGE_ALLIANCE:
2158 case REQ_RANGE_WORLD:
2159 case REQ_RANGE_COUNT:
2160 /* Invalid */
2162 }
2163 return FALSE;
2164}
2165
2166/**********************************************************************/
2169static inline bool players_in_same_range(const struct player *pplayer1,
2170 const struct player *pplayer2,
2171 enum req_range range)
2172{
2173 switch (range) {
2174 case REQ_RANGE_WORLD:
2175 return TRUE;
2176 case REQ_RANGE_ALLIANCE:
2178 case REQ_RANGE_TEAM:
2180 case REQ_RANGE_PLAYER:
2181 return pplayer1 == pplayer2;
2184 case REQ_RANGE_CITY:
2185 case REQ_RANGE_ADJACENT:
2187 case REQ_RANGE_TILE:
2188 case REQ_RANGE_LOCAL:
2189 case REQ_RANGE_COUNT:
2190 break;
2191 }
2192
2193 fc_assert_msg(FALSE, "Invalid range %d.", range);
2194 return FALSE;
2195}
2196
2197#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
2198{ \
2199 fc_assert_ret_val(req != nullptr, TRI_MAYBE); \
2200 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
2201 fc_assert(context != nullptr); \
2202 fc_assert(other_context != nullptr); \
2203}
2204
2205/**********************************************************************/
2213static enum fc_tristate
2215 const struct req_context *context,
2216 const struct req_context *other_context,
2217 const struct requirement *req)
2218{
2220
2221 return TRI_YES;
2222}
2223
2224/**********************************************************************/
2228static int num_world_buildings_total(const struct impr_type *building)
2229{
2230 if (is_great_wonder(building)) {
2231 return (great_wonder_is_built(building)
2232 || great_wonder_is_destroyed(building) ? 1 : 0);
2233 } else {
2234 log_error("World-ranged requirements are only supported for wonders.");
2235 return 0;
2236 }
2237}
2238
2239/**********************************************************************/
2242static int num_world_buildings(const struct impr_type *building)
2243{
2244 if (is_great_wonder(building)) {
2245 return (great_wonder_is_built(building) ? 1 : 0);
2246 } else {
2247 log_error("World-ranged requirements are only supported for wonders.");
2248 return 0;
2249 }
2250}
2251
2252/**********************************************************************/
2263static bool player_has_ever_built(const struct player *pplayer,
2264 const struct impr_type *building)
2265{
2266 if (is_wonder(building)) {
2267 return (wonder_is_built(pplayer, building)
2268 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2269 } else {
2270 log_error("Player-ranged requirements are only supported for wonders.");
2271 return FALSE;
2272 }
2273}
2274
2275/**********************************************************************/
2278static int num_player_buildings(const struct player *pplayer,
2279 const struct impr_type *building)
2280{
2281 if (is_wonder(building)) {
2282 return (wonder_is_built(pplayer, building) ? 1 : 0);
2283 } else {
2284 log_error("Player-ranged requirements are only supported for wonders.");
2285 return 0;
2286 }
2287}
2288
2289/**********************************************************************/
2292static int num_continent_buildings(const struct player *pplayer,
2293 int continent,
2294 const struct impr_type *building)
2295{
2296 if (is_wonder(building)) {
2297 const struct city *pcity;
2298
2299 pcity = city_from_wonder(pplayer, building);
2300 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2301 return 1;
2302 }
2303 } else {
2304 log_error("Island-ranged requirements are only supported for wonders.");
2305 }
2306 return 0;
2307}
2308
2309/**********************************************************************/
2317static enum fc_tristate
2319 const struct req_context *context,
2320 const struct req_context *other_context,
2321 const struct requirement *req)
2322{
2323 const struct impr_type *building;
2324
2325 /* Can't use this assertion, as both VUT_IMPROVEMENT and VUT_SITE
2326 * are handled here. */
2327 /* IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT); */
2328
2329 building = req->source.value.building;
2330
2331 /* Check if it's certain that the building is obsolete given the
2332 * specification we have */
2333 if (req->source.kind == VUT_IMPROVEMENT
2334 && improvement_obsolete(context->player, building, context->city)) {
2335 return TRI_NO;
2336 }
2337
2338 if (req->survives) {
2339
2340 /* Check whether condition has ever held, using cached information. */
2341 switch (req->range) {
2342 case REQ_RANGE_WORLD:
2343 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2344 case REQ_RANGE_ALLIANCE:
2345 case REQ_RANGE_TEAM:
2346 if (context->player == nullptr) {
2347 return TRI_MAYBE;
2348 }
2349 players_iterate_alive(plr2) {
2350 if (players_in_same_range(context->player, plr2, req->range)
2351 && player_has_ever_built(plr2, building)) {
2352 return TRI_YES;
2353 }
2355 return TRI_NO;
2356 case REQ_RANGE_PLAYER:
2357 if (context->player == nullptr) {
2358 return TRI_MAYBE;
2359 }
2361 building));
2364 case REQ_RANGE_CITY:
2365 case REQ_RANGE_LOCAL:
2366 case REQ_RANGE_TILE:
2368 case REQ_RANGE_ADJACENT:
2369 /* There is no sources cache for this. */
2370 log_error("Surviving requirements are only supported at "
2371 "World/Alliance/Team/Player ranges.");
2372 return TRI_NO;
2373 case REQ_RANGE_COUNT:
2374 break;
2375 }
2376
2377 } else {
2378
2379 /* Non-surviving requirement. */
2380 switch (req->range) {
2381 case REQ_RANGE_WORLD:
2382 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2383 case REQ_RANGE_ALLIANCE:
2384 case REQ_RANGE_TEAM:
2385 if (context->player == nullptr) {
2386 return TRI_MAYBE;
2387 }
2388 players_iterate_alive(plr2) {
2389 if (players_in_same_range(context->player, plr2, req->range)
2390 && num_player_buildings(plr2, building) > 0) {
2391 return TRI_YES;
2392 }
2394 return TRI_NO;
2395 case REQ_RANGE_PLAYER:
2396 if (context->player == nullptr) {
2397 return TRI_MAYBE;
2398 }
2400 building)
2401 > 0);
2403 /* At present, "Continent" effects can affect only
2404 * cities and units in cities. */
2405 if (context->player && context->city) {
2406 int continent = tile_continent(context->city->tile);
2408 continent, building)
2409 > 0);
2410 } else {
2411 return TRI_MAYBE;
2412 }
2414 if (context->city) {
2415 if (city_has_building(context->city, building)) {
2416 return TRI_YES;
2417 } else {
2418 enum fc_tristate ret = TRI_NO;
2419
2421 if (trade_partner == nullptr) {
2422 ret = TRI_MAYBE;
2423 } else if (city_has_building(trade_partner, building)) {
2424 return TRI_YES;
2425 }
2427
2428 return ret;
2429 }
2430 } else {
2431 return TRI_MAYBE;
2432 }
2433 case REQ_RANGE_CITY:
2434 if (context->city) {
2435 return BOOL_TO_TRISTATE(city_has_building(context->city, building));
2436 } else {
2437 return TRI_MAYBE;
2438 }
2439 case REQ_RANGE_LOCAL:
2440 if (context->building) {
2441 if (context->building == building) {
2442 return TRI_YES;
2443 } else {
2444 return TRI_NO;
2445 }
2446 } else {
2447 /* TODO: Other local targets */
2448 return TRI_MAYBE;
2449 }
2450 case REQ_RANGE_TILE:
2451 if (context->tile) {
2452 const struct city *pcity = tile_city(context->tile);
2453
2454 if (pcity) {
2455 return BOOL_TO_TRISTATE(city_has_building(pcity, building));
2456 } else {
2457 return TRI_NO;
2458 }
2459 } else {
2460 return TRI_MAYBE;
2461 }
2463 case REQ_RANGE_ADJACENT:
2464 case REQ_RANGE_COUNT:
2465 break;
2466 }
2467
2468 }
2469
2470 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2471 return TRI_NO;
2472}
2473
2474/**********************************************************************/
2482static enum fc_tristate
2484 const struct req_context *context,
2485 const struct req_context *other_context,
2486 const struct requirement *req)
2487{
2489
2490 return (context->building ? BOOL_TO_TRISTATE(
2491 context->building->genus
2492 == req->source.value.impr_genus)
2493 : TRI_MAYBE);
2494}
2495
2496/**********************************************************************/
2500 enum impr_flag_id flag)
2501{
2502 struct player *owner;
2503
2504 if (pcity == nullptr) {
2505 return TRI_MAYBE;
2506 }
2507
2509 city_built_iterate(pcity, impr) {
2510 if (improvement_has_flag(impr, flag)
2511 && !improvement_obsolete(owner, impr, pcity)) {
2512 return TRI_YES;
2513 }
2515
2516 return TRI_NO;
2517}
2518
2519/**********************************************************************/
2527static enum fc_tristate
2529 const struct req_context *context,
2530 const struct req_context *other_context,
2531 const struct requirement *req)
2532{
2534
2535 switch (req->range) {
2536 case REQ_RANGE_LOCAL:
2537 return (context->building
2539 req->source.value.impr_flag))
2540 : TRI_MAYBE);
2541 case REQ_RANGE_CITY:
2543 case REQ_RANGE_TILE:
2544 if (context->tile == nullptr) {
2545 return TRI_MAYBE;
2546 }
2548 req->source.value.impr_flag);
2550 case REQ_RANGE_ADJACENT:
2553 case REQ_RANGE_PLAYER:
2554 case REQ_RANGE_ALLIANCE:
2555 case REQ_RANGE_TEAM:
2556 case REQ_RANGE_WORLD:
2557 case REQ_RANGE_COUNT:
2558 break;
2559 }
2560
2561 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2562
2563 return TRI_MAYBE;
2564}
2565
2566/**********************************************************************/
2574static enum fc_tristate
2576 const struct req_context *context,
2577 const struct req_context *other_context,
2578 const struct requirement *req)
2579{
2581
2582 switch (req->range) {
2583 case REQ_RANGE_PLAYER:
2584 return (context->player != nullptr
2586 req->source.value.plr_flag))
2587 : TRI_MAYBE);
2588 case REQ_RANGE_LOCAL:
2589 case REQ_RANGE_CITY:
2590 case REQ_RANGE_TILE:
2592 case REQ_RANGE_ADJACENT:
2595 case REQ_RANGE_ALLIANCE:
2596 case REQ_RANGE_TEAM:
2597 case REQ_RANGE_WORLD:
2598 case REQ_RANGE_COUNT:
2599 break;
2600 }
2601
2602 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2603
2604 return TRI_MAYBE;
2605}
2606
2607/**********************************************************************/
2615static enum fc_tristate
2617 const struct req_context *context,
2618 const struct req_context *other_context,
2619 const struct requirement *req)
2620{
2622
2623 switch (req->range) {
2624 case REQ_RANGE_PLAYER:
2625 return (context->player != nullptr
2627 req->source.value.plrstate))
2628 : TRI_MAYBE);
2629 case REQ_RANGE_LOCAL:
2630 case REQ_RANGE_CITY:
2631 case REQ_RANGE_TILE:
2633 case REQ_RANGE_ADJACENT:
2636 case REQ_RANGE_ALLIANCE:
2637 case REQ_RANGE_TEAM:
2638 case REQ_RANGE_WORLD:
2639 case REQ_RANGE_COUNT:
2640 break;
2641 }
2642
2643 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2644
2645 return TRI_MAYBE;
2646}
2647
2648/**********************************************************************/
2656static enum fc_tristate
2658 const struct req_context *context,
2659 const struct req_context *other_context,
2660 const struct requirement *req)
2661{
2662 Tech_type_id tech;
2663
2665
2666 tech = advance_number(req->source.value.advance);
2667
2668 if (req->survives) {
2671 }
2672
2673 /* Not a 'surviving' requirement. */
2674 switch (req->range) {
2675 case REQ_RANGE_PLAYER:
2676 if (context->player != nullptr) {
2678 (research_get(context->player), tech));
2679 } else {
2680 return TRI_MAYBE;
2681 }
2682 case REQ_RANGE_TEAM:
2683 case REQ_RANGE_ALLIANCE:
2684 case REQ_RANGE_WORLD:
2685 if (context->player == nullptr) {
2686 return TRI_MAYBE;
2687 }
2688 players_iterate_alive(plr2) {
2689 if (players_in_same_range(context->player, plr2, req->range)) {
2690 if (research_invention_state(research_get(plr2), tech)
2691 == TECH_KNOWN) {
2692 return TRI_YES;
2693 }
2694 }
2696
2697 return TRI_NO;
2698 case REQ_RANGE_LOCAL:
2699 if (context->player == nullptr) {
2700 return TRI_MAYBE;
2701 }
2702 if (research_get(context->player)->researching == tech) {
2703 return TRI_YES;
2704 }
2705 return TRI_NO;
2706 case REQ_RANGE_TILE:
2708 case REQ_RANGE_ADJACENT:
2709 case REQ_RANGE_CITY:
2712 case REQ_RANGE_COUNT:
2713 break;
2714 }
2715
2716 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2717
2718 return TRI_MAYBE;
2719}
2720
2721/**********************************************************************/
2729static enum fc_tristate
2731 const struct req_context *context,
2732 const struct req_context *other_context,
2733 const struct requirement *req)
2734{
2735 enum tech_flag_id techflag;
2736
2738
2739 techflag = req->source.value.techflag;
2740
2741 switch (req->range) {
2742 case REQ_RANGE_PLAYER:
2743 if (context->player != nullptr) {
2745 techflag));
2746 } else {
2747 return TRI_MAYBE;
2748 }
2749 break;
2750 case REQ_RANGE_TEAM:
2751 case REQ_RANGE_ALLIANCE:
2752 if (context->player == nullptr) {
2753 return TRI_MAYBE;
2754 }
2755 players_iterate_alive(plr2) {
2756 if (players_in_same_range(context->player, plr2, req->range)
2757 && player_knows_techs_with_flag(plr2, techflag)) {
2758 return TRI_YES;
2759 }
2761 return TRI_NO;
2762 case REQ_RANGE_WORLD:
2763 players_iterate(pplayer) {
2764 if (player_knows_techs_with_flag(pplayer, techflag)) {
2765 return TRI_YES;
2766 }
2768
2769 return TRI_NO;
2770 case REQ_RANGE_LOCAL:
2771 if (context->player == nullptr) {
2772 return TRI_MAYBE;
2773 }
2774 if (advance_has_flag(research_get(context->player)->researching, techflag)) {
2775 return TRI_YES;
2776 }
2777 return TRI_NO;
2778 case REQ_RANGE_TILE:
2780 case REQ_RANGE_ADJACENT:
2781 case REQ_RANGE_CITY:
2784 case REQ_RANGE_COUNT:
2785 break;
2786 }
2787
2788 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2789
2790 return TRI_MAYBE;
2791}
2792
2793/**********************************************************************/
2801static enum fc_tristate
2803 const struct req_context *context,
2804 const struct req_context *other_context,
2805 const struct requirement *req)
2806{
2807 int minculture;
2808
2810
2811 minculture = req->source.value.minculture;
2812
2813 switch (req->range) {
2814 case REQ_RANGE_CITY:
2815 if (!context->city) {
2816 return TRI_MAYBE;
2817 }
2818 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2820 if (!context->city) {
2821 return TRI_MAYBE;
2822 }
2823 if (city_culture(context->city) >= minculture) {
2824 return TRI_YES;
2825 } else {
2826 enum fc_tristate ret = TRI_NO;
2827
2829 if (trade_partner == nullptr) {
2830 ret = TRI_MAYBE;
2831 } else if (city_culture(trade_partner) >= minculture) {
2832 return TRI_YES;
2833 }
2835
2836 return ret;
2837 }
2838 case REQ_RANGE_PLAYER:
2839 case REQ_RANGE_TEAM:
2840 case REQ_RANGE_ALLIANCE:
2841 case REQ_RANGE_WORLD:
2842 if (context->player == nullptr) {
2843 return TRI_MAYBE;
2844 }
2845 players_iterate_alive(plr2) {
2846 if (players_in_same_range(context->player, plr2, req->range)) {
2847 if (player_culture(plr2) >= minculture) {
2848 return TRI_YES;
2849 }
2850 }
2852 return TRI_NO;
2853 case REQ_RANGE_LOCAL:
2854 case REQ_RANGE_TILE:
2856 case REQ_RANGE_ADJACENT:
2858 case REQ_RANGE_COUNT:
2859 break;
2860 }
2861
2862 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2863
2864 return TRI_MAYBE;
2865}
2866
2867/**********************************************************************/
2875static enum fc_tristate
2877 const struct req_context *context,
2878 const struct req_context *other_context,
2879 const struct requirement *req)
2880{
2882
2884
2886
2887 switch (req->range) {
2888 case REQ_RANGE_CITY:
2889 if (!context->city) {
2890 return TRI_MAYBE;
2891 }
2893 / city_size_get(context->city);
2896 if (!context->city) {
2897 return TRI_MAYBE;
2898 }
2900 / city_size_get(context->city);
2902 return TRI_YES;
2903 } else {
2904 enum fc_tristate ret = TRI_NO;
2905
2907 if (trade_partner == nullptr) {
2908 ret = TRI_MAYBE;
2909 } else {
2913 return TRI_YES;
2914 }
2915 }
2917
2918 return ret;
2919 }
2920 case REQ_RANGE_PLAYER:
2921 case REQ_RANGE_TEAM:
2922 case REQ_RANGE_ALLIANCE:
2923 case REQ_RANGE_WORLD:
2924 case REQ_RANGE_LOCAL:
2925 case REQ_RANGE_TILE:
2927 case REQ_RANGE_ADJACENT:
2929 case REQ_RANGE_COUNT:
2930 break;
2931 }
2932
2933 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2934
2935 return TRI_MAYBE;
2936}
2937
2938/**********************************************************************/
2946static enum fc_tristate
2948 const struct req_context *context,
2949 const struct req_context *other_context,
2950 const struct requirement *req)
2951{
2952 int max_units;
2953
2955
2957
2958 /* TODO: If can't see V_INVIS -> TRI_MAYBE */
2959 switch (req->range) {
2960 case REQ_RANGE_TILE:
2961 if (!context->tile) {
2962 return TRI_MAYBE;
2963 }
2964 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
2966 if (!context->tile) {
2967 return TRI_MAYBE;
2968 }
2969 if (unit_list_size(context->tile->units) <= max_units) {
2970 return TRI_YES;
2971 }
2973 if (unit_list_size(adjc_tile->units) <= max_units) {
2974 return TRI_YES;
2975 }
2977 return TRI_NO;
2978 case REQ_RANGE_ADJACENT:
2979 if (!context->tile) {
2980 return TRI_MAYBE;
2981 }
2982 if (unit_list_size(context->tile->units) <= max_units) {
2983 return TRI_YES;
2984 }
2986 if (unit_list_size(adjc_tile->units) <= max_units) {
2987 return TRI_YES;
2988 }
2990 return TRI_NO;
2991 case REQ_RANGE_CITY:
2994 case REQ_RANGE_PLAYER:
2995 case REQ_RANGE_TEAM:
2996 case REQ_RANGE_ALLIANCE:
2997 case REQ_RANGE_WORLD:
2998 case REQ_RANGE_LOCAL:
2999 case REQ_RANGE_COUNT:
3000 break;
3001 }
3002
3003 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3004
3005 return TRI_MAYBE;
3006}
3007
3008/**********************************************************************/
3016static enum fc_tristate
3018 const struct req_context *context,
3019 const struct req_context *other_context,
3020 const struct requirement *req)
3021{
3022 const struct extra_type *pextra;
3023 enum fc_tristate ret;
3024
3026
3027 pextra = req->source.value.extra;
3028
3029 switch (req->range) {
3030 case REQ_RANGE_LOCAL:
3031 if (!context->extra) {
3032 return TRI_MAYBE;
3033 }
3034 return BOOL_TO_TRISTATE(context->extra == pextra);
3035 case REQ_RANGE_TILE:
3036 /* The requirement is filled if the tile has extra of requested type. */
3037 if (!context->tile) {
3038 return TRI_MAYBE;
3039 }
3040 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
3042 if (!context->tile) {
3043 return TRI_MAYBE;
3044 }
3045 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
3046 || is_extra_card_near(nmap, context->tile, pextra));
3047 case REQ_RANGE_ADJACENT:
3048 if (!context->tile) {
3049 return TRI_MAYBE;
3050 }
3051 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
3052 || is_extra_near_tile(nmap, context->tile, pextra));
3053 case REQ_RANGE_CITY:
3054 if (!context->city) {
3055 return TRI_MAYBE;
3056 }
3058 city_tile(context->city), ptile) {
3059 if (tile_has_extra(ptile, pextra)) {
3060 return TRI_YES;
3061 }
3063
3064 return TRI_NO;
3065
3067 if (!context->city) {
3068 return TRI_MAYBE;
3069 }
3071 city_tile(context->city), ptile) {
3072 if (tile_has_extra(ptile, pextra)) {
3073 return TRI_YES;
3074 }
3076
3077 ret = TRI_NO;
3079 if (trade_partner == nullptr) {
3080 ret = TRI_MAYBE;
3081 } else {
3083 city_tile(trade_partner), ptile) {
3084 if (tile_has_extra(ptile, pextra)) {
3085 return TRI_YES;
3086 }
3088 }
3090
3091 return ret;
3092
3094 case REQ_RANGE_PLAYER:
3095 case REQ_RANGE_TEAM:
3096 case REQ_RANGE_ALLIANCE:
3097 case REQ_RANGE_WORLD:
3098 case REQ_RANGE_COUNT:
3099 break;
3100 }
3101
3102 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3103
3104 return TRI_MAYBE;
3105}
3106
3107/**********************************************************************/
3115static enum fc_tristate
3117 const struct req_context *context,
3118 const struct req_context *other_context,
3119 const struct requirement *req)
3120{
3121 const struct goods_type *pgood;
3122
3124
3125 pgood = req->source.value.good;
3126
3127 switch (req->range) {
3128 case REQ_RANGE_LOCAL:
3129 case REQ_RANGE_CITY:
3130 /* The requirement is filled if the city imports good of requested type. */
3131 if (!context->city) {
3132 return TRI_MAYBE;
3133 }
3137 nullptr)));
3138 case REQ_RANGE_TILE:
3140 case REQ_RANGE_ADJACENT:
3143 case REQ_RANGE_PLAYER:
3144 case REQ_RANGE_TEAM:
3145 case REQ_RANGE_ALLIANCE:
3146 case REQ_RANGE_WORLD:
3147 case REQ_RANGE_COUNT:
3148 break;
3149 }
3150
3151 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3152
3153 return TRI_MAYBE;
3154}
3155
3156/**********************************************************************/
3164static enum fc_tristate
3166 const struct req_context *context,
3167 const struct req_context *other_context,
3168 const struct requirement *req)
3169{
3171
3172 if (context->action) {
3173 return BOOL_TO_TRISTATE(action_number(context->action)
3174 == action_number(req->source.value.action));
3175 }
3176
3177 if (context->unit != nullptr && context->unit->action != ACTION_NONE) {
3178 log_normal("Unit action %s", action_id_rule_name(context->unit->action));
3179 return BOOL_TO_TRISTATE(context->unit->action
3180 == action_number(req->source.value.action));
3181 }
3182
3183 return TRI_NO;
3184}
3185
3186/**********************************************************************/
3194static enum fc_tristate
3196 const struct req_context *context,
3197 const struct req_context *other_context,
3198 const struct requirement *req)
3199{
3201
3202 return BOOL_TO_TRISTATE(context->output
3203 && context->output->index
3204 == req->source.value.outputtype);
3205}
3206
3207/**********************************************************************/
3215static enum fc_tristate
3217 const struct req_context *context,
3218 const struct req_context *other_context,
3219 const struct requirement *req)
3220{
3222
3223 return BOOL_TO_TRISTATE(context->specialist
3224 && context->specialist
3225 == req->source.value.specialist);
3226}
3227
3228/**********************************************************************/
3236static enum fc_tristate
3238 const struct req_context *context,
3239 const struct req_context *other_context,
3240 const struct requirement *req)
3241{
3242 const struct terrain *pterrain;
3243
3245
3246 pterrain = req->source.value.terrain;
3247
3248 switch (req->range) {
3249 case REQ_RANGE_TILE:
3250 /* The requirement is filled if the tile has the terrain. */
3251 if (!context->tile) {
3252 return TRI_MAYBE;
3253 }
3254 return pterrain && tile_terrain(context->tile) == pterrain;
3256 if (!context->tile) {
3257 return TRI_MAYBE;
3258 }
3259 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
3260 case REQ_RANGE_ADJACENT:
3261 if (!context->tile) {
3262 return TRI_MAYBE;
3263 }
3264 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
3265 case REQ_RANGE_CITY:
3266 if (!context->city) {
3267 return TRI_MAYBE;
3268 }
3269 if (pterrain != nullptr) {
3271 city_tile(context->city), ptile) {
3272 if (tile_terrain(ptile) == pterrain) {
3273 return TRI_YES;
3274 }
3276 }
3277 return TRI_NO;
3279 if (!context->city) {
3280 return TRI_MAYBE;
3281 }
3282 if (pterrain != nullptr) {
3283 enum fc_tristate ret;
3284
3286 city_tile(context->city), ptile) {
3287 if (tile_terrain(ptile) == pterrain) {
3288 return TRI_YES;
3289 }
3291
3292 ret = TRI_NO;
3294 if (trade_partner == nullptr) {
3295 ret = TRI_MAYBE;
3296 } else {
3298 city_tile(trade_partner), ptile) {
3299 if (tile_terrain(ptile) == pterrain) {
3300 return TRI_YES;
3301 }
3303 }
3305
3306 return ret;
3307 }
3308
3309 return TRI_MAYBE;
3311 case REQ_RANGE_PLAYER:
3312 case REQ_RANGE_TEAM:
3313 case REQ_RANGE_ALLIANCE:
3314 case REQ_RANGE_WORLD:
3315 case REQ_RANGE_LOCAL:
3316 case REQ_RANGE_COUNT:
3317 break;
3318 }
3319
3320 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3321
3322 return TRI_MAYBE;
3323}
3324
3325/**********************************************************************/
3333static enum fc_tristate
3335 const struct req_context *context,
3336 const struct req_context *other_context,
3337 const struct requirement *req)
3338{
3339 enum terrain_class pclass;
3340 enum fc_tristate ret;
3341
3343
3345
3346 switch (req->range) {
3347 case REQ_RANGE_TILE:
3348 /* The requirement is filled if the tile has the terrain of correct class. */
3349 if (!context->tile) {
3350 return TRI_MAYBE;
3351 }
3354 if (!context->tile) {
3355 return TRI_MAYBE;
3356 }
3359 case REQ_RANGE_ADJACENT:
3360 if (!context->tile) {
3361 return TRI_MAYBE;
3362 }
3365 case REQ_RANGE_CITY:
3366 if (!context->city) {
3367 return TRI_MAYBE;
3368 }
3370 city_tile(context->city), ptile) {
3371 const struct terrain *pterrain = tile_terrain(ptile);
3372
3373 if (pterrain != T_UNKNOWN
3374 && terrain_type_terrain_class(pterrain) == pclass) {
3375 return TRI_YES;
3376 }
3378
3379 return TRI_NO;
3381 if (!context->city) {
3382 return TRI_MAYBE;
3383 }
3385 city_tile(context->city), ptile) {
3386 const struct terrain *pterrain = tile_terrain(ptile);
3387
3388 if (pterrain != T_UNKNOWN
3389 && terrain_type_terrain_class(pterrain) == pclass) {
3390 return TRI_YES;
3391 }
3393
3394 ret = TRI_NO;
3396 if (trade_partner == nullptr) {
3397 ret = TRI_MAYBE;
3398 } else {
3400 city_tile(trade_partner), ptile) {
3401 const struct terrain *pterrain = tile_terrain(ptile);
3402
3403 if (pterrain != T_UNKNOWN
3404 && terrain_type_terrain_class(pterrain) == pclass) {
3405 return TRI_YES;
3406 }
3408 }
3410
3411 return ret;
3413 case REQ_RANGE_PLAYER:
3414 case REQ_RANGE_TEAM:
3415 case REQ_RANGE_ALLIANCE:
3416 case REQ_RANGE_WORLD:
3417 case REQ_RANGE_LOCAL:
3418 case REQ_RANGE_COUNT:
3419 break;
3420 }
3421
3422 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3423
3424 return TRI_MAYBE;
3425}
3426
3427/**********************************************************************/
3435static enum fc_tristate
3437 const struct req_context *context,
3438 const struct req_context *other_context,
3439 const struct requirement *req)
3440{
3442 enum fc_tristate ret;
3443
3445
3447
3448 switch (req->range) {
3449 case REQ_RANGE_TILE:
3450 /* The requirement is fulfilled if the tile has a terrain with
3451 * correct flag. */
3452 if (!context->tile) {
3453 return TRI_MAYBE;
3454 }
3456 terrflag));
3458 if (!context->tile) {
3459 return TRI_MAYBE;
3460 }
3462 terrflag)
3464 terrflag));
3465 case REQ_RANGE_ADJACENT:
3466 if (!context->tile) {
3467 return TRI_MAYBE;
3468 }
3470 terrflag)
3472 terrflag));
3473 case REQ_RANGE_CITY:
3474 if (!context->city) {
3475 return TRI_MAYBE;
3476 }
3478 city_tile(context->city), ptile) {
3479 const struct terrain *pterrain = tile_terrain(ptile);
3480
3481 if (pterrain != T_UNKNOWN
3482 && terrain_has_flag(pterrain, terrflag)) {
3483 return TRI_YES;
3484 }
3486
3487 return TRI_NO;
3489 if (!context->city) {
3490 return TRI_MAYBE;
3491 }
3493 city_tile(context->city), ptile) {
3494 const struct terrain *pterrain = tile_terrain(ptile);
3495
3496 if (pterrain != T_UNKNOWN
3497 && terrain_has_flag(pterrain, terrflag)) {
3498 return TRI_YES;
3499 }
3501
3502 ret = TRI_NO;
3504 if (trade_partner == nullptr) {
3505 ret = TRI_MAYBE;
3506 } else {
3508 city_tile(trade_partner), ptile) {
3509 const struct terrain *pterrain = tile_terrain(ptile);
3510
3511 if (pterrain != T_UNKNOWN
3512 && terrain_has_flag(pterrain, terrflag)) {
3513 return TRI_YES;
3514 }
3516 }
3518
3519 return ret;
3521 case REQ_RANGE_PLAYER:
3522 case REQ_RANGE_TEAM:
3523 case REQ_RANGE_ALLIANCE:
3524 case REQ_RANGE_WORLD:
3525 case REQ_RANGE_LOCAL:
3526 case REQ_RANGE_COUNT:
3527 break;
3528 }
3529
3530 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3531
3532 return TRI_MAYBE;
3533}
3534
3535/**********************************************************************/
3543static enum fc_tristate
3545 const struct req_context *context,
3546 const struct req_context *other_context,
3547 const struct requirement *req)
3548{
3549 enum road_flag_id roadflag;
3550 enum fc_tristate ret;
3551
3553
3554 roadflag = req->source.value.roadflag;
3555
3556 switch (req->range) {
3557 case REQ_RANGE_LOCAL:
3558 {
3559 if (!context->extra) {
3560 return TRI_MAYBE;
3561 }
3562 struct road_type *r = extra_road_get(context->extra);
3563
3564 return BOOL_TO_TRISTATE(
3565 r && road_has_flag(r, roadflag)
3566 );
3567 }
3568 case REQ_RANGE_TILE:
3569 /* The requirement is filled if the tile has a road with correct flag. */
3570 if (!context->tile) {
3571 return TRI_MAYBE;
3572 }
3573 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3575 if (!context->tile) {
3576 return TRI_MAYBE;
3577 }
3578 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3580 roadflag));
3581 case REQ_RANGE_ADJACENT:
3582 if (!context->tile) {
3583 return TRI_MAYBE;
3584 }
3585 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3587 roadflag));
3588 case REQ_RANGE_CITY:
3589 if (!context->city) {
3590 return TRI_MAYBE;
3591 }
3593 city_tile(context->city), ptile) {
3594 if (tile_has_road_flag(ptile, roadflag)) {
3595 return TRI_YES;
3596 }
3598
3599 return TRI_NO;
3601 if (!context->city) {
3602 return TRI_MAYBE;
3603 }
3605 city_tile(context->city), ptile) {
3606 if (tile_has_road_flag(ptile, roadflag)) {
3607 return TRI_YES;
3608 }
3610
3611 ret = TRI_NO;
3613 if (trade_partner == nullptr) {
3614 ret = TRI_MAYBE;
3615 } else {
3617 city_tile(trade_partner), ptile) {
3618 if (tile_has_road_flag(ptile, roadflag)) {
3619 return TRI_YES;
3620 }
3622 }
3624
3625 return ret;
3627 case REQ_RANGE_PLAYER:
3628 case REQ_RANGE_TEAM:
3629 case REQ_RANGE_ALLIANCE:
3630 case REQ_RANGE_WORLD:
3631 case REQ_RANGE_COUNT:
3632 break;
3633 }
3634
3635 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3636
3637 return TRI_MAYBE;
3638}
3639
3640/**********************************************************************/
3648static enum fc_tristate
3650 const struct req_context *context,
3651 const struct req_context *other_context,
3652 const struct requirement *req)
3653{
3654 enum extra_flag_id extraflag;
3655 enum fc_tristate ret;
3656
3658
3659 extraflag = req->source.value.extraflag;
3660
3661 switch (req->range) {
3662 case REQ_RANGE_LOCAL:
3663 if (!context->extra) {
3664 return TRI_MAYBE;
3665 }
3666 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3667 case REQ_RANGE_TILE:
3668 /* The requirement is filled if the tile has an extra with correct flag. */
3669 if (!context->tile) {
3670 return TRI_MAYBE;
3671 }
3672 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3674 if (!context->tile) {
3675 return TRI_MAYBE;
3676 }
3677 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3678 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3679 case REQ_RANGE_ADJACENT:
3680 if (!context->tile) {
3681 return TRI_MAYBE;
3682 }
3683 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3684 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3685 case REQ_RANGE_CITY:
3686 if (!context->city) {
3687 return TRI_MAYBE;
3688 }
3690 city_tile(context->city), ptile) {
3691 if (tile_has_extra_flag(ptile, extraflag)) {
3692 return TRI_YES;
3693 }
3695
3696 return TRI_NO;
3698 if (!context->city) {
3699 return TRI_MAYBE;
3700 }
3702 city_tile(context->city), ptile) {
3703 if (tile_has_extra_flag(ptile, extraflag)) {
3704 return TRI_YES;
3705 }
3707
3708 ret = TRI_NO;
3710 if (trade_partner == nullptr) {
3711 ret = TRI_MAYBE;
3712 } else {
3714 city_tile(trade_partner), ptile) {
3715 if (tile_has_extra_flag(ptile, extraflag)) {
3716 return TRI_YES;
3717 }
3719 }
3721
3722 return ret;
3724 case REQ_RANGE_PLAYER:
3725 case REQ_RANGE_TEAM:
3726 case REQ_RANGE_ALLIANCE:
3727 case REQ_RANGE_WORLD:
3728 case REQ_RANGE_COUNT:
3729 break;
3730 }
3731
3732 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3733
3734 return TRI_MAYBE;
3735}
3736
3737/**********************************************************************/
3745static enum fc_tristate
3747 const struct req_context *context,
3748 const struct req_context *other_context,
3749 const struct requirement *req)
3750{
3752
3754
3756
3757 if (!context->tile) {
3758 return TRI_MAYBE;
3759 }
3760
3761 switch (req->range) {
3762 case REQ_RANGE_TILE:
3766 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
3767 case REQ_RANGE_CITY:
3770 case REQ_RANGE_PLAYER:
3771 case REQ_RANGE_TEAM:
3772 case REQ_RANGE_ALLIANCE:
3773 case REQ_RANGE_WORLD:
3774 case REQ_RANGE_LOCAL:
3775 case REQ_RANGE_COUNT:
3776 break;
3777 }
3778
3779 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3780
3781 return TRI_MAYBE;
3782}
3783
3784/**********************************************************************/
3792static enum fc_tristate
3794 const struct req_context *context,
3795 const struct req_context *other_context,
3796 const struct requirement *req)
3797{
3799
3800 if (context->player == nullptr) {
3801 return TRI_MAYBE;
3802 } else {
3804 == req->source.value.govern);
3805 }
3806}
3807
3808/**********************************************************************/
3816static enum fc_tristate
3818 const struct req_context *context,
3819 const struct req_context *other_context,
3820 const struct requirement *req)
3821{
3823
3824 if (context->player == nullptr) {
3825 return TRI_MAYBE;
3826 } else {
3827 return BOOL_TO_TRISTATE(context->player->style
3828 == req->source.value.style);
3829 }
3830}
3831
3832/**********************************************************************/
3840static enum fc_tristate
3842 const struct req_context *context,
3843 const struct req_context *other_context,
3844 const struct requirement *req)
3845{
3847
3848 switch (req->range) {
3849 case REQ_RANGE_WORLD:
3850 /* "None" does not count */
3851 return ((game.info.global_advance_count - 1)
3852 >= req->source.value.min_techs);
3853 case REQ_RANGE_PLAYER:
3854 if (context->player == nullptr) {
3855 return TRI_MAYBE;
3856 } else {
3857 /* "None" does not count */
3858 return BOOL_TO_TRISTATE(
3859 (research_get(context->player)->techs_researched - 1)
3860 >= req->source.value.min_techs
3861 );
3862 }
3863 default:
3864 return TRI_MAYBE;
3865 }
3866}
3867
3868/**********************************************************************/
3876static enum fc_tristate
3878 const struct req_context *context,
3879 const struct req_context *other_context,
3880 const struct requirement *req)
3881{
3883
3884 switch (req->range) {
3885 case REQ_RANGE_PLAYER:
3886 if (context->player == nullptr) {
3887 return TRI_MAYBE;
3888 } else {
3889 /* "None" does not count */
3890 return BOOL_TO_TRISTATE(
3891 city_list_size(context->player->cities)
3892 >= req->source.value.min_cities
3893 );
3894 }
3895 default:
3896 return TRI_MAYBE;
3897 }
3898}
3899
3900/**********************************************************************/
3908static enum fc_tristate
3910 const struct req_context *context,
3911 const struct req_context *other_context,
3912 const struct requirement *req)
3913{
3915
3916 if (context->player == nullptr) {
3917 return TRI_MAYBE;
3918 } else {
3919 return BOOL_TO_TRISTATE(is_ai(context->player)
3920 && context->player->ai_common.skill_level
3921 == req->source.value.ai_level);
3922 }
3923}
3924
3925/**********************************************************************/
3933static enum fc_tristate
3935 const struct req_context *context,
3936 const struct req_context *other_context,
3937 const struct requirement *req)
3938{
3939 const struct nation_type *nation;
3940
3942
3943 nation = req->source.value.nation;
3944
3945 switch (req->range) {
3946 case REQ_RANGE_PLAYER:
3947 if (context->player == nullptr) {
3948 return TRI_MAYBE;
3949 }
3950 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
3951 case REQ_RANGE_TEAM:
3952 case REQ_RANGE_ALLIANCE:
3953 if (context->player == nullptr) {
3954 return TRI_MAYBE;
3955 }
3956 players_iterate_alive(plr2) {
3957 if (players_in_same_range(context->player, plr2, req->range)) {
3958 if (nation_of_player(plr2) == nation) {
3959 return TRI_YES;
3960 }
3961 }
3963 return TRI_NO;
3964 case REQ_RANGE_WORLD:
3965 /* NB: if a player is ever removed outright from the game
3966 * (e.g. via /remove), rather than just dying, this 'survives'
3967 * requirement will stop being true for their nation.
3968 * create_command_newcomer() can also cause this to happen. */
3969 return BOOL_TO_TRISTATE(nation->player != nullptr
3970 && (req->survives || nation->player->is_alive));
3971 case REQ_RANGE_LOCAL:
3972 case REQ_RANGE_TILE:
3974 case REQ_RANGE_ADJACENT:
3975 case REQ_RANGE_CITY:
3978 case REQ_RANGE_COUNT:
3979 break;
3980 }
3981
3982 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3983
3984 return TRI_MAYBE;
3985}
3986
3987/**********************************************************************/
3995static enum fc_tristate
3997 const struct req_context *context,
3998 const struct req_context *other_context,
3999 const struct requirement *req)
4000{
4001 const struct nation_group *ngroup;
4002
4004
4006
4007 switch (req->range) {
4008 case REQ_RANGE_PLAYER:
4009 if (context->player == nullptr) {
4010 return TRI_MAYBE;
4011 }
4013 nation_of_player(context->player), ngroup));
4014 case REQ_RANGE_TEAM:
4015 case REQ_RANGE_ALLIANCE:
4016 case REQ_RANGE_WORLD:
4017 if (context->player == nullptr) {
4018 return TRI_MAYBE;
4019 }
4020 players_iterate_alive(plr2) {
4021 if (players_in_same_range(context->player, plr2, req->range)) {
4023 return TRI_YES;
4024 }
4025 }
4027 return TRI_NO;
4028 case REQ_RANGE_LOCAL:
4029 case REQ_RANGE_TILE:
4031 case REQ_RANGE_ADJACENT:
4032 case REQ_RANGE_CITY:
4035 case REQ_RANGE_COUNT:
4036 break;
4037 }
4038
4039 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4040
4041 return TRI_MAYBE;
4042}
4043
4044/**********************************************************************/
4052static enum fc_tristate
4054 const struct req_context *context,
4055 const struct req_context *other_context,
4056 const struct requirement *req)
4057{
4058 const struct nation_type *nationality;
4059 enum fc_tristate ret;
4060
4062
4063 nationality = req->source.value.nationality;
4064
4065 switch (req->range) {
4066 case REQ_RANGE_CITY:
4067 if (context->city == nullptr) {
4068 return TRI_MAYBE;
4069 }
4070 citizens_iterate(context->city, slot, count) {
4071 if (player_slot_get_player(slot)->nation == nationality) {
4072 return TRI_YES;
4073 }
4075
4076 return TRI_NO;
4078 if (context->city == nullptr) {
4079 return TRI_MAYBE;
4080 }
4081 citizens_iterate(context->city, slot, count) {
4082 if (player_slot_get_player(slot)->nation == nationality) {
4083 return TRI_YES;
4084 }
4086
4087 ret = TRI_NO;
4089 if (trade_partner == nullptr) {
4090 ret = TRI_MAYBE;
4091 } else {
4092 citizens_iterate(trade_partner, slot, count) {
4093 if (player_slot_get_player(slot)->nation == nationality) {
4094 return TRI_YES;
4095 }
4097 }
4099
4100 return ret;
4101 case REQ_RANGE_PLAYER:
4102 case REQ_RANGE_TEAM:
4103 case REQ_RANGE_ALLIANCE:
4104 case REQ_RANGE_WORLD:
4105 case REQ_RANGE_LOCAL:
4106 case REQ_RANGE_TILE:
4108 case REQ_RANGE_ADJACENT:
4110 case REQ_RANGE_COUNT:
4111 break;
4112 }
4113
4114 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4115
4116 return TRI_MAYBE;
4117}
4118
4119/**********************************************************************/
4127static enum fc_tristate
4129 const struct req_context *context,
4130 const struct req_context *other_context,
4131 const struct requirement *req)
4132{
4133 const struct nation_type *nation;
4134
4136
4137 nation = req->source.value.origowner;
4138
4139 switch (req->range) {
4140 case REQ_RANGE_CITY:
4141 if (context->city == nullptr || context->city->original == nullptr) {
4142 return TRI_MAYBE;
4143 }
4144 if (player_nation(context->city->original) == nation) {
4145 return TRI_YES;
4146 }
4147
4148 return TRI_NO;
4150 case REQ_RANGE_PLAYER:
4151 case REQ_RANGE_TEAM:
4152 case REQ_RANGE_ALLIANCE:
4153 case REQ_RANGE_WORLD:
4154 case REQ_RANGE_LOCAL:
4155 case REQ_RANGE_TILE:
4157 case REQ_RANGE_ADJACENT:
4159 case REQ_RANGE_COUNT:
4160 break;
4161 }
4162
4163 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4164
4165 return TRI_MAYBE;
4166}
4167
4168/**********************************************************************/
4172 const struct player *other_player,
4173 enum req_range range,
4174 int diplrel)
4175{
4176 switch (range) {
4177 case REQ_RANGE_PLAYER:
4178 if (target_player == nullptr) {
4179 return TRI_MAYBE;
4180 }
4182 case REQ_RANGE_TEAM:
4183 case REQ_RANGE_ALLIANCE:
4184 case REQ_RANGE_WORLD:
4185 if (target_player == nullptr) {
4186 return TRI_MAYBE;
4187 }
4188 players_iterate_alive(plr2) {
4190 if (is_diplrel_to_other(plr2, diplrel)) {
4191 return TRI_YES;
4192 }
4193 }
4195 return TRI_NO;
4196 case REQ_RANGE_LOCAL:
4197 if (target_player == nullptr || other_player == nullptr) {
4198 return TRI_MAYBE;
4199 }
4200 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
4201 case REQ_RANGE_TILE:
4203 case REQ_RANGE_ADJACENT:
4204 case REQ_RANGE_CITY:
4207 case REQ_RANGE_COUNT:
4208 break;
4209 }
4210
4211 fc_assert_msg(FALSE, "Invalid range %d.", range);
4212
4213 return TRI_MAYBE;
4214}
4215
4216/**********************************************************************/
4224static enum fc_tristate
4226 const struct req_context *context,
4227 const struct req_context *other_context,
4228 const struct requirement *req)
4229{
4231
4232 return is_diplrel_in_range(context->player, other_context->player,
4233 req->range, req->source.value.diplrel);
4234}
4235
4236/**********************************************************************/
4244static enum fc_tristate
4246 const struct req_context *context,
4247 const struct req_context *other_context,
4248 const struct requirement *req)
4249{
4251
4252 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4253 : nullptr,
4254 context->player,
4255 req->range,
4256 req->source.value.diplrel);
4257}
4258
4259/**********************************************************************/
4268static enum fc_tristate
4270 const struct req_context *context,
4271 const struct req_context *other_context,
4272 const struct requirement *req)
4273{
4275
4276 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4277 : nullptr,
4278 other_context->player,
4279 req->range,
4280 req->source.value.diplrel);
4281}
4282
4283/**********************************************************************/
4286static enum fc_tristate
4288 const struct player *other_player,
4289 enum req_range range,
4290 int diplrel)
4291{
4292 enum fc_tristate out = TRI_NO;
4293
4294 if (target_tile == nullptr) {
4295 return TRI_MAYBE;
4296 }
4297
4300 unit_owner(target_unit), other_player, range, diplrel);
4301
4304
4305 return out;
4306}
4307
4308/**********************************************************************/
4317static enum fc_tristate
4319 const struct req_context *context,
4320 const struct req_context *other_context,
4321 const struct requirement *req)
4322{
4324
4325 return is_diplrel_unitany_in_range(context->tile, context->player,
4326 req->range,
4327 req->source.value.diplrel);
4328}
4329
4330/**********************************************************************/
4339static enum fc_tristate
4341 const struct req_context *context,
4342 const struct req_context *other_context,
4343 const struct requirement *req)
4344{
4346
4348 req->range,
4349 req->source.value.diplrel);
4350}
4351
4352/**********************************************************************/
4360static enum fc_tristate
4362 const struct req_context *context,
4363 const struct req_context *other_context,
4364 const struct requirement *req)
4365{
4366 const struct unit_type *punittype;
4367
4369
4370 punittype = req->source.value.utype;
4371
4372 switch (req->range) {
4373 case REQ_RANGE_LOCAL:
4374 if (!context->unittype) {
4375 return TRI_MAYBE;
4376 }
4377 return BOOL_TO_TRISTATE(context->unittype == punittype);
4378 case REQ_RANGE_TILE:
4380 case REQ_RANGE_ADJACENT:
4381 if (context->tile == nullptr) {
4382 return TRI_MAYBE;
4383 }
4384
4385 unit_list_iterate(context->tile->units, punit) {
4386 if (punit->utype == punittype) {
4387 return TRI_YES;
4388 }
4390
4391 if (req->range == REQ_RANGE_TILE) {
4392 return TRI_NO;
4393 }
4394
4395 if (req->range == REQ_RANGE_CADJACENT) {
4398 if (punit->utype == punittype) {
4399 return TRI_YES;
4400 }
4403 } else {
4405
4408 if (punit->utype == punittype) {
4409 return TRI_YES;
4410 }
4413 }
4414
4415 return TRI_NO;
4416
4417 case REQ_RANGE_CITY:
4420 case REQ_RANGE_PLAYER:
4421 case REQ_RANGE_TEAM:
4422 case REQ_RANGE_ALLIANCE:
4423 case REQ_RANGE_WORLD:
4424 case REQ_RANGE_COUNT:
4426 break;
4427 }
4428
4429 return TRI_NO;
4430}
4431
4432/**********************************************************************/
4440static enum fc_tristate
4442 const struct req_context *context,
4443 const struct req_context *other_context,
4444 const struct requirement *req)
4445{
4446 enum unit_type_flag_id unitflag;
4447
4449
4450 unitflag = req->source.value.unitflag;
4451
4452 switch (req->range) {
4453 case REQ_RANGE_LOCAL:
4454 if (!context->unittype) {
4455 return TRI_MAYBE;
4456 }
4457 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4458 case REQ_RANGE_TILE:
4460 case REQ_RANGE_ADJACENT:
4461 if (context->tile == nullptr) {
4462 return TRI_MAYBE;
4463 }
4464
4465 unit_list_iterate(context->tile->units, punit) {
4466 if (unit_has_type_flag(punit, unitflag)) {
4467 return TRI_YES;
4468 }
4470
4471 if (req->range == REQ_RANGE_TILE) {
4472 return TRI_NO;
4473 }
4474
4475 if (req->range == REQ_RANGE_CADJACENT) {
4478 if (unit_has_type_flag(punit, unitflag)) {
4479 return TRI_YES;
4480 }
4483 } else {
4485
4488 if (unit_has_type_flag(punit, unitflag)) {
4489 return TRI_YES;
4490 }
4493 }
4494
4495 return TRI_NO;
4496
4497 case REQ_RANGE_CITY:
4500 case REQ_RANGE_PLAYER:
4501 case REQ_RANGE_TEAM:
4502 case REQ_RANGE_ALLIANCE:
4503 case REQ_RANGE_WORLD:
4504 case REQ_RANGE_COUNT:
4506 break;
4507 }
4508
4509 return TRI_NO;
4510}
4511
4512/**********************************************************************/
4520static enum fc_tristate
4522 const struct req_context *context,
4523 const struct req_context *other_context,
4524 const struct requirement *req)
4525{
4526 const struct unit_class *pclass;
4527
4529
4530 pclass = req->source.value.uclass;
4531
4532 switch (req->range) {
4533 case REQ_RANGE_LOCAL:
4534 if (!context->unittype) {
4535 return TRI_MAYBE;
4536 }
4537 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4538 case REQ_RANGE_TILE:
4540 case REQ_RANGE_ADJACENT:
4541 if (context->tile == nullptr) {
4542 return TRI_MAYBE;
4543 }
4544
4545 unit_list_iterate(context->tile->units, punit) {
4546 if (unit_class_get(punit) == pclass) {
4547 return TRI_YES;
4548 }
4550
4551 if (req->range == REQ_RANGE_TILE) {
4552 return TRI_NO;
4553 }
4554
4555 if (req->range == REQ_RANGE_CADJACENT) {
4558 if (unit_class_get(punit) == pclass) {
4559 return TRI_YES;
4560 }
4563 } else {
4565
4568 if (unit_class_get(punit) == pclass) {
4569 return TRI_YES;
4570 }
4573 }
4574
4575 return TRI_NO;
4576
4577 case REQ_RANGE_CITY:
4580 case REQ_RANGE_PLAYER:
4581 case REQ_RANGE_TEAM:
4582 case REQ_RANGE_ALLIANCE:
4583 case REQ_RANGE_WORLD:
4584 case REQ_RANGE_COUNT:
4586 break;
4587 }
4588
4589 return TRI_NO;
4590}
4591
4592/**********************************************************************/
4600static enum fc_tristate
4602 const struct req_context *context,
4603 const struct req_context *other_context,
4604 const struct requirement *req)
4605{
4607
4609
4611
4612 switch (req->range) {
4613 case REQ_RANGE_LOCAL:
4614 if (!context->unittype) {
4615 return TRI_MAYBE;
4616 }
4618 case REQ_RANGE_TILE:
4620 case REQ_RANGE_ADJACENT:
4621 if (context->tile == nullptr) {
4622 return TRI_MAYBE;
4623 }
4624
4625 unit_list_iterate(context->tile->units, punit) {
4627 return TRI_YES;
4628 }
4630
4631 if (req->range == REQ_RANGE_TILE) {
4632 return TRI_NO;
4633 }
4634
4635 if (req->range == REQ_RANGE_CADJACENT) {
4639 return TRI_YES;
4640 }
4643 } else {
4645
4649 return TRI_YES;
4650 }
4653 }
4654
4655 return TRI_NO;
4656
4657 case REQ_RANGE_CITY:
4660 case REQ_RANGE_PLAYER:
4661 case REQ_RANGE_TEAM:
4662 case REQ_RANGE_ALLIANCE:
4663 case REQ_RANGE_WORLD:
4664 case REQ_RANGE_COUNT:
4666 break;
4667 }
4668
4669 return TRI_NO;
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 enum ustate_prop uprop;
4687
4689
4691
4693 "Unsupported range \"%s\"",
4694 req_range_name(req->range));
4695
4696 /* Could be asked with incomplete data.
4697 * is_req_active() will handle it based on prob_type. */
4698 if (context->unit == nullptr) {
4699 return TRI_MAYBE;
4700 }
4701
4702 switch (uprop) {
4703 case USP_TRANSPORTED:
4704 return BOOL_TO_TRISTATE(context->unit->transporter != nullptr);
4705 case USP_LIVABLE_TILE:
4706 return BOOL_TO_TRISTATE(
4708 unit_tile(context->unit)));
4709 break;
4710 case USP_TRANSPORTING:
4712 case USP_HAS_HOME_CITY:
4713 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
4714 case USP_NATIVE_TILE:
4715 return BOOL_TO_TRISTATE(
4717 unit_tile(context->unit)));
4718 break;
4719 case USP_NATIVE_EXTRA:
4720 return BOOL_TO_TRISTATE(
4722 unit_type_get(context->unit)));
4723 break;
4725 return BOOL_TO_TRISTATE(context->unit->moved);
4726 case USP_COUNT:
4727 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
4728 /* Invalid property is unknowable. */
4729 return TRI_NO;
4730 }
4731
4732 /* Should never be reached */
4733 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
4734
4735 return TRI_NO;
4736}
4737
4738/**********************************************************************/
4746static enum fc_tristate
4748 const struct req_context *context,
4749 const struct req_context *other_context,
4750 const struct requirement *req)
4751{
4752 enum unit_activity activity;
4753
4755
4756 activity = req->source.value.activity;
4757
4759 "Unsupported range \"%s\"",
4760 req_range_name(req->range));
4761
4762 if (context->unit == nullptr) {
4763 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
4764 * it's the zero value that context has by default - so many callers
4765 * who meant not to set specific activity actually have ACTIVITY_IDLE
4766 * instead of ACTIVITY_LAST */
4767 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
4768 return BOOL_TO_TRISTATE(activity == context->activity);
4769 }
4770
4771 /* Could be asked with incomplete data.
4772 * is_req_active() will handle it based on prob_type. */
4773 return TRI_MAYBE;
4774 }
4775
4776 switch (context->unit->activity) {
4777 case ACTIVITY_IDLE:
4778 case ACTIVITY_SENTRY:
4779 case ACTIVITY_GOTO:
4780 case ACTIVITY_EXPLORE:
4781 /* Seen as idle. */
4782 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
4783 default:
4784 /* Handled below. */
4785 break;
4786 }
4787
4788 return BOOL_TO_TRISTATE(context->unit->activity == activity);
4789}
4790
4791/**********************************************************************/
4799static enum fc_tristate
4801 const struct req_context *context,
4802 const struct req_context *other_context,
4803 const struct requirement *req)
4804{
4806
4807 if (context->unit == nullptr) {
4808 return TRI_MAYBE;
4809 } else {
4810 return BOOL_TO_TRISTATE(context->unit->veteran
4811 >= req->source.value.minveteran);
4812 }
4813}
4814
4815/**********************************************************************/
4823static enum fc_tristate
4825 const struct req_context *context,
4826 const struct req_context *other_context,
4827 const struct requirement *req)
4828{
4830
4831 if (context->unit == nullptr) {
4832 return TRI_MAYBE;
4833 } else {
4835 <= context->unit->moves_left);
4836 }
4837}
4838
4839/**********************************************************************/
4847static enum fc_tristate
4849 const struct req_context *context,
4850 const struct req_context *other_context,
4851 const struct requirement *req)
4852{
4854
4855 if (context->unit == nullptr) {
4856 return TRI_MAYBE;
4857 } else {
4859 <= context->unit->hp);
4860 }
4861}
4862
4863/**********************************************************************/
4871static enum fc_tristate
4873 const struct req_context *context,
4874 const struct req_context *other_context,
4875 const struct requirement *req)
4876{
4878
4879 switch (req->range) {
4880 case REQ_RANGE_LOCAL:
4881 if (context->unit == nullptr || !is_server()) {
4882 return TRI_MAYBE;
4883 } else {
4884 return BOOL_TO_TRISTATE(
4885 req->source.value.age <=
4886 game.info.turn - context->unit->birth_turn);
4887 }
4888 break;
4889 case REQ_RANGE_CITY:
4890 if (context->city == nullptr) {
4891 return TRI_MAYBE;
4892 } else {
4893 return BOOL_TO_TRISTATE(
4894 req->source.value.age <=
4895 game.info.turn - context->city->turn_founded);
4896 }
4897 break;
4898 case REQ_RANGE_PLAYER:
4899 if (context->player == nullptr) {
4900 return TRI_MAYBE;
4901 } else {
4902 return BOOL_TO_TRISTATE(req->source.value.age
4903 <= player_age(context->player));
4904 }
4905 break;
4906 default:
4907 return TRI_MAYBE;
4908 break;
4909 }
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
4928 switch (req->range) {
4929 case REQ_RANGE_LOCAL:
4930 if (context->unit == nullptr || !is_server()) {
4931 return TRI_MAYBE;
4932 } else {
4933 return BOOL_TO_TRISTATE(
4934 req->source.value.form_age <=
4935 game.info.turn - context->unit->current_form_turn);
4936 }
4937 break;
4938 default:
4939 return TRI_MAYBE;
4940 break;
4941 }
4942}
4943
4944/**********************************************************************/
4948static inline enum fc_tristate
4950{
4952 bool whole_known;
4953
4954 if (cont > 0) {
4957
4958 if (actual_surrounder > 0) {
4959 return TRI_NO;
4960 }
4961 } else if (cont < 0) {
4964
4965 if (actual_surrounder < 0) {
4966 return TRI_NO;
4967 }
4968 } else {
4969 return TRI_MAYBE;
4970 }
4971
4972 if (actual_surrounder == 0 || surrounder == 0) {
4973 return TRI_MAYBE;
4974 } else if (actual_surrounder != surrounder) {
4975 return TRI_NO;
4976 } else if (!whole_known) {
4977 return TRI_MAYBE;
4978 } else {
4979 return TRI_YES;
4980 }
4981}
4982
4983/**********************************************************************/
4991static enum fc_tristate
4993 const struct req_context *context,
4994 const struct req_context *other_context,
4995 const struct requirement *req)
4996{
4998
4999 if (context->tile == nullptr || other_context->tile == nullptr) {
5000 /* Note: For some values, we might be able to give a definitive
5001 * TRI_NO answer even if one of the tiles is missing, but that's
5002 * probably not worth the added effort. */
5003 return TRI_MAYBE;
5004 }
5005
5006 switch (req->source.value.tilerel) {
5007 case TREL_SAME_TCLASS:
5008 if (tile_terrain(other_context->tile) == T_UNKNOWN) {
5009 return TRI_MAYBE;
5010 }
5012 || req->range == REQ_RANGE_CADJACENT
5013 || req->range == REQ_RANGE_ADJACENT),
5014 TRI_MAYBE,
5015 "Invalid range %d for tile relation \"%s\" req",
5017 {
5020 bool seen_unknown = FALSE;
5021 const struct terrain *terr;
5022
5023 if ((terr = tile_terrain(context->tile)) == T_UNKNOWN) {
5025 } else if (terrain_type_terrain_class(terr) == cls) {
5026 return TRUE;
5027 }
5028
5030 if ((terr = tile_terrain(adj_tile)) == T_UNKNOWN) {
5032 } else if (terrain_type_terrain_class(terr) == cls) {
5033 return TRUE;
5034 }
5036
5037 if (seen_unknown) {
5038 return TRI_MAYBE;
5039 } else {
5040 return TRI_NO;
5041 }
5042 }
5043 break;
5044 case TREL_SAME_REGION:
5045 if (tile_continent(other_context->tile) == 0) {
5046 return TRI_MAYBE;
5047 }
5049 || req->range == REQ_RANGE_CADJACENT
5050 || req->range == REQ_RANGE_ADJACENT),
5051 TRI_MAYBE,
5052 "Invalid range %d for tile relation \"%s\" req",
5054
5055 if (tile_continent(context->tile)
5056 == tile_continent(other_context->tile)) {
5057 return TRI_YES;
5058 } else {
5059 bool seen_unknown = (tile_continent(context->tile) == 0);
5061
5064
5065 if (adj_cont == cont) {
5066 return TRI_YES;
5067 } else if (adj_cont == 0) {
5069 }
5071
5072 if (seen_unknown) {
5073 return TRI_MAYBE;
5074 } else {
5075 return TRI_NO;
5076 }
5077 }
5078 break;
5080 if (tile_continent(context->tile) == 0
5081 || tile_continent(other_context->tile) == 0) {
5082 /* Note: We could still give a definitive TRI_NO answer if there are
5083 * too many different adjacent continents, but that's probably not
5084 * worth the added effort. */
5085 return TRI_MAYBE;
5086 }
5088 || req->range == REQ_RANGE_ADJACENT),
5089 TRI_MAYBE,
5090 "Invalid range %d for tile relation \"%s\" req",
5091 req->range,
5093
5094 {
5095 bool seen_unknown = FALSE;
5096 Continent_id cont = tile_continent(context->tile);
5098
5101
5102 if (adj_cont == 0) {
5104 } else if (adj_cont != cont && adj_cont != other_cont) {
5105 return TRI_NO;
5106 }
5108
5109 if (seen_unknown) {
5110 return TRI_MAYBE;
5111 } else {
5112 return TRI_YES;
5113 }
5114 }
5115 break;
5118 || req->range == REQ_RANGE_CADJACENT
5119 || req->range == REQ_RANGE_ADJACENT),
5120 TRI_MAYBE,
5121 "Invalid range %d for tile relation \"%s\" req",
5122 req->range,
5124
5125 {
5126 bool seen_maybe = FALSE;
5128
5130 wanted)) {
5131 case TRI_YES:
5132 return TRI_YES;
5133 case TRI_MAYBE:
5134 seen_maybe = TRUE;
5135 break;
5136 default:
5137 break;
5138 }
5139
5142 wanted)) {
5143 case TRI_YES:
5144 return TRI_YES;
5145 case TRI_MAYBE:
5146 seen_maybe = TRUE;
5147 break;
5148 default:
5149 break;
5150 }
5152
5153 if (seen_maybe) {
5154 return TRI_MAYBE;
5155 } else {
5156 return TRI_NO;
5157 }
5158 }
5159 break;
5160 default:
5161 break;
5162 }
5163
5165 "Illegal value %d for tile relationship requirement.",
5166 req->source.value.tilerel);
5167 return TRI_MAYBE;
5168}
5169
5170/**********************************************************************/
5173static bool is_city_in_tile(const struct tile *ptile,
5174 const struct city *pcity)
5175{
5176 if (pcity == nullptr) {
5177 return tile_city(ptile) != nullptr;
5178 } else {
5179 return is_city_center(pcity, ptile);
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{
5197 enum citytile_type citytile;
5198
5200
5201 citytile = req->source.value.citytile;
5202
5204 if (context->tile == nullptr) {
5205 return TRI_MAYBE;
5206 }
5207
5208 switch (citytile) {
5209 case CITYT_CENTER:
5210 switch (req->range) {
5211 case REQ_RANGE_TILE:
5213 context->city));
5215 if (is_city_in_tile(context->tile, context->city)) {
5216 return TRI_YES;
5217 }
5219 if (is_city_in_tile(adjc_tile, context->city)) {
5220 return TRI_YES;
5221 }
5223
5224 return TRI_NO;
5225 case REQ_RANGE_ADJACENT:
5226 if (is_city_in_tile(context->tile, context->city)) {
5227 return TRI_YES;
5228 }
5230 if (is_city_in_tile(adjc_tile, context->city)) {
5231 return TRI_YES;
5232 }
5234
5235 return TRI_NO;
5236 case REQ_RANGE_CITY:
5239 case REQ_RANGE_PLAYER:
5240 case REQ_RANGE_TEAM:
5241 case REQ_RANGE_ALLIANCE:
5242 case REQ_RANGE_WORLD:
5243 case REQ_RANGE_LOCAL:
5244 case REQ_RANGE_COUNT:
5245 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5246 break;
5247 }
5248
5249 return TRI_MAYBE;
5250 case CITYT_CLAIMED:
5251 switch (req->range) {
5252 case REQ_RANGE_TILE:
5253 return BOOL_TO_TRISTATE(context->tile->owner != nullptr);
5255 if (context->tile->owner != nullptr) {
5256 return TRI_YES;
5257 }
5259 if (adjc_tile->owner != nullptr) {
5260 return TRI_YES;
5261 }
5263
5264 return TRI_NO;
5265 case REQ_RANGE_ADJACENT:
5266 if (context->tile->owner != nullptr) {
5267 return TRI_YES;
5268 }
5270 if (adjc_tile->owner != nullptr) {
5271 return TRI_YES;
5272 }
5274
5275 return TRI_NO;
5276 case REQ_RANGE_CITY:
5279 case REQ_RANGE_PLAYER:
5280 case REQ_RANGE_TEAM:
5281 case REQ_RANGE_ALLIANCE:
5282 case REQ_RANGE_WORLD:
5283 case REQ_RANGE_LOCAL:
5284 case REQ_RANGE_COUNT:
5285 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5286 break;
5287 }
5288
5289 return TRI_MAYBE;
5290 case CITYT_EXTRAS_OWNED:
5291 switch (req->range) {
5292 case REQ_RANGE_TILE:
5293 return BOOL_TO_TRISTATE(context->tile->extras_owner != nullptr);
5295 if (context->tile->extras_owner != nullptr) {
5296 return TRI_YES;
5297 }
5299 if (adjc_tile->extras_owner != nullptr) {
5300 return TRI_YES;
5301 }
5303
5304 return TRI_NO;
5305 case REQ_RANGE_ADJACENT:
5306 if (context->tile->extras_owner != nullptr) {
5307 return TRI_YES;
5308 }
5310 if (adjc_tile->extras_owner != nullptr) {
5311 return TRI_YES;
5312 }
5314
5315 return TRI_NO;
5316 case REQ_RANGE_CITY:
5319 case REQ_RANGE_PLAYER:
5320 case REQ_RANGE_TEAM:
5321 case REQ_RANGE_ALLIANCE:
5322 case REQ_RANGE_WORLD:
5323 case REQ_RANGE_LOCAL:
5324 case REQ_RANGE_COUNT:
5325 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5326 break;
5327 }
5328
5329 return TRI_MAYBE;
5330 case CITYT_WORKED:
5331 switch (req->range) {
5332 case REQ_RANGE_TILE:
5333 return BOOL_TO_TRISTATE(context->tile->worked != nullptr);
5335 if (context->tile->worked != nullptr) {
5336 return TRI_YES;
5337 }
5339 if (adjc_tile->worked != nullptr) {
5340 return TRI_YES;
5341 }
5343
5344 return TRI_NO;
5345 case REQ_RANGE_ADJACENT:
5346 if (context->tile->worked != nullptr) {
5347 return TRI_YES;
5348 }
5350 if (adjc_tile->worked != nullptr) {
5351 return TRI_YES;
5352 }
5354
5355 return TRI_NO;
5356 case REQ_RANGE_CITY:
5359 case REQ_RANGE_PLAYER:
5360 case REQ_RANGE_TEAM:
5361 case REQ_RANGE_ALLIANCE:
5362 case REQ_RANGE_WORLD:
5363 case REQ_RANGE_LOCAL:
5364 case REQ_RANGE_COUNT:
5365 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5366 break;
5367 }
5368
5369 return TRI_MAYBE;
5371 {
5373 const struct tile *target_tile = context->tile, *cc_tile;
5374
5375 if (!context->city) {
5376 return TRI_MAYBE;
5377 }
5378 cc_tile = city_tile(context->city);
5379 if (!cc_tile) {
5380 /* Unplaced virtual city */
5381 return TRI_MAYBE;
5382 }
5384 /* Note: No special treatment of 0 == cc here*/
5385 switch (req->range) {
5386 case REQ_RANGE_TILE:
5389 if (tile_continent(target_tile) == cc) {
5390 return TRI_YES;
5391 }
5393 if (tile_continent(adjc_tile) == cc) {
5394 return TRI_YES;
5395 }
5397
5398 return TRI_NO;
5399 case REQ_RANGE_ADJACENT:
5400 if (tile_continent(target_tile) == cc) {
5401 return TRI_YES;
5402 }
5404 if (tile_continent(adjc_tile) == cc) {
5405 return TRI_YES;
5406 }
5408
5409 return TRI_NO;
5410 case REQ_RANGE_CITY:
5413 case REQ_RANGE_PLAYER:
5414 case REQ_RANGE_TEAM:
5415 case REQ_RANGE_ALLIANCE:
5416 case REQ_RANGE_WORLD:
5417 case REQ_RANGE_LOCAL:
5418 case REQ_RANGE_COUNT:
5419 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5420 break;
5421 }
5422 }
5423
5424 return TRI_MAYBE;
5426 {
5427 int n = 0;
5429 bool ukt = FALSE;
5430 const struct tile *target_tile = context->tile, *cc_tile;
5431
5432 if (!context->city) {
5433 return TRI_MAYBE;
5434 }
5435 cc_tile = city_tile(context->city);
5436 if (!cc_tile) {
5437 /* Unplaced virtual city */
5438 return TRI_MAYBE;
5439 }
5441 if (!cc) {
5442 /* Don't know the city center terrain class.
5443 * Maybe, the city floats? Even if the rules prohibit it... */
5444 return TRI_MAYBE;
5445 }
5448
5449 if (0 != tc) {
5450 bool seen = FALSE;
5451 int i = n;
5452
5453 if (tc == cc) {
5454 continue;
5455 }
5456 while (--i >= 0) {
5457 if (adjc_cont[i] == tc) {
5458 seen = TRUE;
5459 break;
5460 }
5461 }
5462 if (seen) {
5463 continue;
5464 }
5466 } else {
5467 /* Likely, it's a black tile in client and we don't know
5468 * We possibly can calculate, but keep it simple. */
5469 ukt = TRUE;
5470 }
5472 if (0 == n) {
5473 return ukt ? TRI_MAYBE : TRI_NO;
5474 }
5475
5476 switch (req->range) {
5477 case REQ_RANGE_TILE:
5478 {
5480
5481 if (cc == tc) {
5482 return TRI_NO;
5483 }
5484 if (0 == tc || ukt) {
5485 return TRI_MAYBE;
5486 }
5487 for (int i = 0; i < n; i++) {
5488 if (tc == adjc_cont[i]) {
5489 return TRI_YES;
5490 }
5491 }
5492 }
5493
5494 return TRI_NO;
5495 case REQ_RANGE_ADJACENT:
5496 if (ukt) {
5497 /* If ALL the tiles in range are on cc, we can say it's false */
5499 if (tile_continent(adjc_tile) != cc) {
5500 return TRI_MAYBE;
5501 }
5503
5504 return TRI_NO;
5505 } else {
5508
5509 if (0 == tc) {
5510 return TRI_MAYBE;
5511 }
5512 for (int i = 0; i < n; i++) {
5513 if (tc == adjc_cont[i]) {
5514 return TRI_YES;
5515 }
5516 }
5518 }
5519
5520 return TRI_NO;
5522 if (ukt) {
5523 /* If ALL the tiles in range are on cc, we can say it's false */
5525 if (tile_continent(cadjc_tile) != cc) {
5526 return TRI_MAYBE;
5527 }
5529 } else {
5532
5533 if (0 == tc) {
5534 return TRI_MAYBE;
5535 }
5536 for (int i = 0; i < n; i++) {
5537 if (tc == adjc_cont[i]) {
5538 return TRI_YES;
5539 }
5540 }
5542 }
5543
5544 return TRI_NO;
5545 case REQ_RANGE_CITY:
5548 case REQ_RANGE_PLAYER:
5549 case REQ_RANGE_TEAM:
5550 case REQ_RANGE_ALLIANCE:
5551 case REQ_RANGE_WORLD:
5552 case REQ_RANGE_LOCAL:
5553 case REQ_RANGE_COUNT:
5554 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5555 break;
5556 }
5557 }
5558
5559 return TRI_MAYBE;
5560 case CITYT_LAST:
5561 /* Handled below */
5562 break;
5563 }
5564
5565 /* Not implemented */
5566 log_error("is_req_active(): citytile %d not supported.",
5567 citytile);
5568 return TRI_MAYBE;
5569}
5570
5571/**********************************************************************/
5579static enum fc_tristate
5581 const struct req_context *context,
5582 const struct req_context *other_context,
5583 const struct requirement *req)
5584{
5585 enum citystatus_type citystatus;
5586
5588
5589 citystatus = req->source.value.citystatus;
5590
5591 if (context->city == nullptr) {
5592 return TRI_MAYBE;
5593 }
5594
5595 switch (citystatus) {
5597 switch (req->range) {
5598 case REQ_RANGE_CITY:
5599 if (context->city->original == nullptr) {
5600 return TRI_MAYBE;
5601 }
5602 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
5604 {
5605 enum fc_tristate ret;
5606
5607 if (city_owner(context->city) == context->city->original) {
5608 return TRI_YES;
5609 }
5610
5611 ret = TRI_NO;
5613 if (trade_partner == nullptr || trade_partner->original == nullptr) {
5614 ret = TRI_MAYBE;
5615 } else if (city_owner(trade_partner) == trade_partner->original) {
5616 return TRI_YES;
5617 }
5619
5620 return ret;
5621 }
5622 case REQ_RANGE_LOCAL:
5623 case REQ_RANGE_TILE:
5625 case REQ_RANGE_ADJACENT:
5627 case REQ_RANGE_PLAYER:
5628 case REQ_RANGE_TEAM:
5629 case REQ_RANGE_ALLIANCE:
5630 case REQ_RANGE_WORLD:
5631 case REQ_RANGE_COUNT:
5632 break;
5633 }
5634
5635 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
5636 req->range);
5637
5638 return TRI_MAYBE;
5639
5640 case CITYS_STARVED:
5641 switch (req->range) {
5642 case REQ_RANGE_CITY:
5643 return BOOL_TO_TRISTATE(context->city->had_famine);
5645 {
5646 enum fc_tristate ret;
5647
5648 if (context->city->had_famine) {
5649 return TRI_YES;
5650 }
5651
5652 ret = TRI_NO;
5654 if (trade_partner == nullptr) {
5655 ret = TRI_MAYBE;
5656 } else if (trade_partner->had_famine) {
5657 return TRI_YES;
5658 }
5660
5661 return ret;
5662 }
5663 case REQ_RANGE_LOCAL:
5664 case REQ_RANGE_TILE:
5666 case REQ_RANGE_ADJACENT:
5668 case REQ_RANGE_PLAYER:
5669 case REQ_RANGE_TEAM:
5670 case REQ_RANGE_ALLIANCE:
5671 case REQ_RANGE_WORLD:
5672 case REQ_RANGE_COUNT:
5673 break;
5674 }
5675
5676 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
5677 req->range);
5678
5679 return TRI_MAYBE;
5680
5681 case CITYS_DISORDER:
5682 switch (req->range) {
5683 case REQ_RANGE_CITY:
5684 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
5686 {
5687 enum fc_tristate ret;
5688
5689 if (context->city->anarchy > 0) {
5690 return TRI_YES;
5691 }
5692
5693 ret = TRI_NO;
5695 if (trade_partner == nullptr) {
5696 ret = TRI_MAYBE;
5697 } else if (trade_partner->anarchy > 0) {
5698 return TRI_YES;
5699 }
5701
5702 return ret;
5703 }
5704 case REQ_RANGE_LOCAL:
5705 case REQ_RANGE_TILE:
5707 case REQ_RANGE_ADJACENT:
5709 case REQ_RANGE_PLAYER:
5710 case REQ_RANGE_TEAM:
5711 case REQ_RANGE_ALLIANCE:
5712 case REQ_RANGE_WORLD:
5713 case REQ_RANGE_COUNT:
5714 break;
5715 }
5716
5717 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
5718 req->range);
5719
5720 return TRI_MAYBE;
5721
5722 case CITYS_CELEBRATION:
5723 switch (req->range) {
5724 case REQ_RANGE_CITY:
5725 return BOOL_TO_TRISTATE(context->city->rapture > 0);
5727 {
5728 enum fc_tristate ret;
5729
5730 if (context->city->rapture > 0) {
5731 return TRI_YES;
5732 }
5733
5734 ret = TRI_NO;
5736 if (trade_partner == nullptr) {
5737 ret = TRI_MAYBE;
5738 } else if (trade_partner->rapture > 0) {
5739 return TRI_YES;
5740 }
5742
5743 return ret;
5744 }
5745 case REQ_RANGE_LOCAL:
5746 case REQ_RANGE_TILE:
5748 case REQ_RANGE_ADJACENT:
5750 case REQ_RANGE_PLAYER:
5751 case REQ_RANGE_TEAM:
5752 case REQ_RANGE_ALLIANCE:
5753 case REQ_RANGE_WORLD:
5754 case REQ_RANGE_COUNT:
5755 break;
5756 }
5757
5758 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
5759 req->range);
5760
5761 return TRI_MAYBE;
5762
5763 case CITYS_TRANSFERRED:
5764 switch (req->range) {
5765 case REQ_RANGE_CITY:
5766 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
5768 {
5769 enum fc_tristate ret;
5770
5771 if (context->city->acquire_t != CACQ_FOUNDED) {
5772 return TRI_YES;
5773 }
5774
5775 ret = TRI_NO;
5777 if (trade_partner == nullptr) {
5778 ret = TRI_MAYBE;
5779 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
5780 return TRI_YES;
5781 }
5783
5784 return ret;
5785 }
5786 case REQ_RANGE_LOCAL:
5787 case REQ_RANGE_TILE:
5789 case REQ_RANGE_ADJACENT:
5791 case REQ_RANGE_PLAYER:
5792 case REQ_RANGE_TEAM:
5793 case REQ_RANGE_ALLIANCE:
5794 case REQ_RANGE_WORLD:
5795 case REQ_RANGE_COUNT:
5796 break;
5797 }
5798
5799 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
5800 req->range);
5801
5802 return TRI_MAYBE;
5803
5804 case CITYS_LAST:
5805 break;
5806 }
5807
5808 /* Not implemented */
5809 log_error("is_req_active(): citystatus %d not supported.",
5810 citystatus);
5811
5812 return TRI_MAYBE;
5813}
5814
5815/**********************************************************************/
5823static enum fc_tristate
5825 const struct req_context *context,
5826 const struct req_context *other_context,
5827 const struct requirement *req)
5828{
5830
5831 if (context->city == nullptr) {
5832 return TRI_MAYBE;
5833 } else {
5834 if (req->range == REQ_RANGE_TRADE_ROUTE) {
5835 enum fc_tristate ret;
5836
5837 if (city_size_get(context->city) >= req->source.value.minsize) {
5838 return TRI_YES;
5839 }
5840
5841 ret = TRI_NO;
5843 if (trade_partner == nullptr) {
5844 ret = TRI_MAYBE;
5845 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
5846 return TRI_YES;
5847 }
5849
5850 return ret;
5851 } else {
5853 >= req->source.value.minsize);
5854 }
5855 }
5856}
5857
5858/**********************************************************************/
5866static enum fc_tristate
5868 const struct req_context *context,
5869 const struct req_context *other_context,
5870 const struct requirement *req)
5871{
5872 const struct counter *count;
5873
5875
5876 count = req->source.value.counter;
5877
5878 if (context->city == nullptr) {
5879 return TRI_MAYBE;
5880 }
5881 return BOOL_TO_TRISTATE(count->checkpoint <=
5882 context->city->counter_values[
5883 counter_index(count)]);
5884}
5885
5886/**********************************************************************/
5894static enum fc_tristate
5896 const struct req_context *context,
5897 const struct req_context *other_context,
5898 const struct requirement *req)
5899{
5900 const struct achievement *achievement;
5901
5903
5905
5906 if (req->range == REQ_RANGE_WORLD) {
5908 } else if (context->player == nullptr) {
5909 return TRI_MAYBE;
5910 } else if (req->range == REQ_RANGE_ALLIANCE
5911 || req->range == REQ_RANGE_TEAM) {
5912 players_iterate_alive(plr2) {
5913 if (players_in_same_range(context->player, plr2, req->range)
5915 return TRI_YES;
5916 }
5918 return TRI_NO;
5919 } else if (req->range == REQ_RANGE_PLAYER) {
5921 return TRI_YES;
5922 } else {
5923 return TRI_NO;
5924 }
5925 }
5926
5927 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
5928
5929 return TRI_MAYBE;
5930}
5931
5932/**********************************************************************/
5940static enum fc_tristate
5942 const struct req_context *context,
5943 const struct req_context *other_context,
5944 const struct requirement *req)
5945{
5946 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
5947
5948 fc_assert_ret_val(req != nullptr, TRI_MAYBE);
5949 fc_assert(context != nullptr);
5950
5951 switch (req->source.kind) {
5952 case VUT_MINLATITUDE:
5953 min = req->source.value.latitude;
5954 break;
5955 case VUT_MAXLATITUDE:
5956 max = req->source.value.latitude;
5957 break;
5958 default:
5960 || req->source.kind == VUT_MAXLATITUDE);
5961 break;
5962 }
5963
5964 switch (req->range) {
5965 case REQ_RANGE_WORLD:
5967 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
5968
5969 case REQ_RANGE_TILE:
5970 if (context->tile == nullptr) {
5971 return TRI_MAYBE;
5972 } else {
5974
5976 }
5977
5979 if (context->tile == nullptr) {
5980 return TRI_MAYBE;
5981 }
5982
5985
5987 return TRI_YES;
5988 }
5990 return TRI_NO;
5991
5992 case REQ_RANGE_ADJACENT:
5993 if (!context->tile) {
5994 return TRI_MAYBE;
5995 }
5996
5999
6001 return TRI_YES;
6002 }
6004 return TRI_NO;
6005
6006 case REQ_RANGE_CITY:
6009 case REQ_RANGE_PLAYER:
6010 case REQ_RANGE_TEAM:
6011 case REQ_RANGE_ALLIANCE:
6012 case REQ_RANGE_LOCAL:
6013 case REQ_RANGE_COUNT:
6014 break;
6015 }
6016
6018 "Illegal range %d for latitude requirement.", req->range);
6019
6020 return TRI_MAYBE;
6021}
6022
6023/**********************************************************************/
6031static enum fc_tristate
6033 const struct req_context *context,
6034 const struct req_context *other_context,
6035 const struct requirement *req)
6036{
6038
6039 switch (req->range) {
6040 case REQ_RANGE_TILE:
6041 if (context->tile == nullptr || other_context->tile == nullptr) {
6042 return TRI_MAYBE;
6043 }
6044 return BOOL_TO_TRISTATE(
6046 <= req->source.value.distance_sq
6047 );
6048 default:
6049 break;
6050 }
6051
6053 "Illegal range %d for max squared distance requirement.",
6054 req->range);
6055
6056 return TRI_MAYBE;
6057}
6058
6059/**********************************************************************/
6067static enum fc_tristate
6069 const struct req_context *context,
6070 const struct req_context *other_context,
6071 const struct requirement *req)
6072{
6073 int max_tiles, min_tiles = 1;
6074
6076
6077 switch (req->range) {
6079 case REQ_RANGE_ADJACENT:
6080 if (context->tile == nullptr) {
6081 /* The tile itself is included in the range */
6082 max_tiles = 1 + ((req->range == REQ_RANGE_CADJACENT)
6083 ? nmap->num_cardinal_dirs
6084 : nmap->num_valid_dirs);
6085
6086 break;
6087 } else {
6088 Continent_id cont = tile_continent(context->tile);
6089
6090 /* Count how many adjacent tiles there actually are as we go along */
6091 max_tiles = 1;
6092
6095
6096 if (adj_cont == 0 || cont == 0) {
6097 max_tiles++;
6098 } else if (adj_cont == cont) {
6099 min_tiles++;
6100 max_tiles++;
6101 }
6103 }
6104 break;
6106 {
6107 Continent_id cont = context->tile ? tile_continent(context->tile) : 0;
6108
6111
6112 /* Note: We could come up with a better upper bound by subtracting
6113 * all other continent/ocean sizes, or all except the largest if we
6114 * don't know the tile.
6115 * We could even do a flood-fill count of the unknown area bordered
6116 * by known tiles of the continent.
6117 * Probably not worth the effort though. */
6118 max_tiles = nmap->xsize * nmap->ysize;
6119
6120 if (cont > 0) {
6121 min_tiles = nmap->continent_sizes[cont];
6122 if (is_whole_continent_known(cont)) {
6124 }
6125 } else if (cont < 0) {
6126 min_tiles = nmap->ocean_sizes[-cont];
6127 if (is_whole_ocean_known(-cont)) {
6129 }
6130 }
6131 }
6132 break;
6133 default:
6135 "Illegal range %d for max region tiles requirement.",
6136 req->range);
6137 return TRI_MAYBE;
6138 }
6139
6140 if (min_tiles > req->source.value.region_tiles) {
6141 return TRI_NO;
6142 } else if (max_tiles <= req->source.value.region_tiles) {
6143 return TRI_YES;
6144 }
6145 return TRI_MAYBE;
6146}
6147
6148/**********************************************************************/
6156static enum fc_tristate
6158 const struct req_context *context,
6159 const struct req_context *other_context,
6160 const struct requirement *req)
6161{
6163
6165}
6166
6167/**********************************************************************/
6175static enum fc_tristate
6177 const struct req_context *context,
6178 const struct req_context *other_context,
6179 const struct requirement *req)
6180{
6182
6184 >= req->source.value.mincalfrag);
6185}
6186
6187/**********************************************************************/
6195static enum fc_tristate
6197 const struct req_context *context,
6198 const struct req_context *other_context,
6199 const struct requirement *req)
6200{
6202
6203 return BOOL_TO_TRISTATE(
6205}
6206
6207/**********************************************************************/
6215static enum fc_tristate
6217 const struct req_context *context,
6218 const struct req_context *other_context,
6219 const struct requirement *req)
6220{
6222
6223 return BOOL_TO_TRISTATE(
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{
6242
6244 req->source.value.ssetval));
6245}
6246
6247/* Not const for potential ruleset-related adjustment */
6250
6251 /* Alphabetical order of enum constant */
6314};
6315
6316/**********************************************************************/
6330 const struct req_context *other_context,
6331 const struct requirement *req,
6332 const enum req_problem_type prob_type)
6333{
6334 const struct civ_map *nmap = &(wld.map);
6335 enum fc_tristate eval;
6337 struct thr_req_data *trdata = NULL;
6338
6341 if (fc_threads_equal(self, data->thr_id)) {
6342 trdata = data;
6343 }
6345
6346 if (trdata == NULL) {
6347 trdata = fc_malloc(sizeof(struct thr_req_data));
6348 trdata->thr_id = self;
6350 }
6352
6354
6355 if (eval == TRI_MAYBE) {
6356 if (prob_type == RPT_POSSIBLE) {
6357 return TRUE;
6358 } else {
6359 return FALSE;
6360 }
6361 }
6362
6363 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
6364}
6365
6366/**********************************************************************/
6375static
6377 const struct req_context *context,
6378 const struct req_context *other_context,
6379 const struct requirement *req)
6380{
6381 if (!context) {
6383 }
6384 if (!other_context) {
6386 }
6387
6388 if (req->source.kind >= VUT_COUNT) {
6389 log_error("tri_req_present(): invalid source kind %d.",
6390 req->source.kind);
6391 return TRI_NO;
6392 }
6393
6395
6396 return req_definitions[req->source.kind].cb(nmap, context,
6397 other_context, req);
6398}
6399
6400/**********************************************************************/
6410 const struct req_context *other_context,
6411 const struct requirement *req)
6412{
6413 const struct civ_map *nmap = &(wld.map);
6415
6416 if (!req->present) {
6417 if (TRI_NO == eval) {
6418 return TRI_YES;
6419 }
6420 if (TRI_YES == eval) {
6421 return TRI_NO;
6422 }
6423 }
6424
6425 return eval;
6426}
6427
6428/**********************************************************************/
6444 const struct req_context *other_context,
6445 const struct requirement_vector *reqs,
6446 const enum req_problem_type prob_type)
6447{
6450 return FALSE;
6451 }
6453
6454 return TRUE;
6455}
6456
6457/**********************************************************************/
6462 const enum req_range max_range,
6463 const struct req_context *context,
6464 const struct req_context *other_context,
6465 const struct requirement_vector *reqs,
6466 const enum req_problem_type prob_type)
6467{
6469 if (preq->range >= min_range && preq->range <= max_range) {
6471 return FALSE;
6472 }
6473 }
6475
6476 return TRUE;
6477}
6478
6479/**********************************************************************/
6485enum fc_tristate
6487 const struct req_context *context,
6488 const struct req_context *other_context,
6489 const struct requirement *req)
6490{
6491 /* FIXME: Doubles code from calendar.c */
6495 int fragment1 = fragment; /* If fragments don't advance */
6496 int year_inc, year_inc1;
6499 bool present, present1;
6500
6501 fc_assert(pass >= 0 && period >= 0);
6502 if (slowdown >= 3) {
6503 if (ypt > 1) {
6504 ypt = 1;
6505 }
6506 } else if (slowdown >= 2) {
6507 if (ypt > 2) {
6508 ypt = 2;
6509 }
6510 } else if (slowdown >= 1) {
6511 if (ypt > 5) {
6512 ypt = 5;
6513 }
6514 }
6515 year_inc = ypt * pass;
6518 int fragment_years;
6519
6520 fragment += fpt * pass;
6528 }
6530 if (year_inc + game.info.year >= 0) {
6531 year_inc++;
6532 year_inc1++;
6533 } else if (year_inc1 + game.info.year >= 0) {
6534 year_inc1++;
6535 }
6536 }
6537
6538 switch (req->source.kind) {
6539 case VUT_AGE:
6540 switch (req->range) {
6541 case REQ_RANGE_LOCAL:
6542 if (context->unit == nullptr || !is_server()) {
6543 return TRI_MAYBE;
6544 } else {
6545 int ua = game.info.turn + pass - context->unit->birth_turn;
6546
6547 present = req->source.value.age <= ua;
6548 present1 = req->source.value.age <= ua + period;
6549 }
6550 break;
6551 case REQ_RANGE_CITY:
6552 if (context->city == nullptr) {
6553 return TRI_MAYBE;
6554 } else {
6555 int ca = game.info.turn + pass - context->city->turn_founded;
6556
6557 present = req->source.value.age <= ca;
6558 present1 = req->source.value.age <= ca + period;
6559 }
6560 break;
6561 case REQ_RANGE_PLAYER:
6562 if (context->player == nullptr) {
6563 return TRI_MAYBE;
6564 } else {
6565 present = req->source.value.age
6566 <= player_age(context->player) + pass;
6567 present1 = req->source.value.age
6568 <= player_age(context->player) + pass + period;
6569 }
6570 break;
6571 default:
6572 return TRI_MAYBE;
6573 }
6574 break;
6575 case VUT_FORM_AGE:
6576 if (context->unit == nullptr || !is_server()) {
6577 return TRI_MAYBE;
6578 } else {
6579 int ua = game.info.turn + pass - context->unit->current_form_turn;
6580
6581 present = req->source.value.form_age <= ua;
6582 present1 = req->source.value.form_age <= ua + period;
6583 }
6584 break;
6585 case VUT_MINYEAR:
6586 present = game.info.year + year_inc >= req->source.value.minyear;
6588 break;
6589 case VUT_MINCALFRAG:
6591 /* Hope that the requirement is valid and fragments advance fine */
6592 return TRI_YES;
6593 }
6594 present = fragment >= req->source.value.mincalfrag;
6596 break;
6597 default:
6598 /* No special handling invented */
6599 return tri_req_active(context, other_context, req);
6600 }
6601 return BOOL_TO_TRISTATE(req->present
6602 ? present || present1 : !(present && present1));
6603}
6604
6605/**********************************************************************/
6611 (const struct req_context *context,
6612 const struct req_context *other_context,
6613 const struct requirement *req,
6614 void *data, int n_data)
6615{
6616 int i;
6617
6618 fc_assert_ret_val(data || n_data == 0, TRI_NO);
6619
6620 for (i = 0; i < n_data; i++) {
6621 if (are_requirements_contradictions(&((struct requirement *) data)[i],
6622 req)) {
6623 return TRI_NO;
6624 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
6625 return TRI_YES;
6626 }
6627 }
6628
6629 return tri_req_active(context, other_context, req);
6630}
6631
6632/**********************************************************************/
6638enum fc_tristate
6640 const struct req_context *other_context,
6641 const struct requirement_vector *reqs,
6644 void *data, int n_data)
6645{
6646 bool active = TRUE;
6647 bool certain = TRUE;
6648
6649 fc_assert_ret_val(tester != nullptr, TRI_NO);
6650
6653 data, n_data)) {
6654 case TRI_NO:
6655 active = FALSE;
6656 certain = TRUE;
6657 break;
6658 case TRI_YES:
6659 break;
6660 case TRI_MAYBE:
6661 certain = FALSE;
6662 if (maybe_reqs) {
6664 }
6665 break;
6666 default:
6668 active = FALSE;
6669 }
6670 if (!active) {
6671 break;
6672 }
6674
6675 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
6676}
6677
6678/**********************************************************************/
6688 const struct requirement *req)
6689{
6690 enum req_unchanging_status s;
6691 const struct civ_map *nmap = &(wld.map);
6692
6695 "Invalid source kind %d.", req->source.kind);
6697
6698 if (req->survives) {
6699 /* Special case for surviving requirements */
6700 /* Buildings may obsolete even here */
6701 if (VUT_IMPROVEMENT == req->source.kind) {
6702 const struct impr_type *b = req->source.value.building;
6703
6705 if (improvement_obsolete(context->player, b, context->city)) {
6706 /* FIXME: Sometimes can unobsolete, but considering it
6707 * may sometimes put the function on endless recursion */
6708 return REQUCH_ACT; /* Mostly about techs */
6709 } else {
6710 /* NOTE: May obsoletion reqs be unchanging? Hardly but why not. */
6711 return REQUCH_NO;
6712 }
6713 }
6714 }
6715 s = unchanging_present(nmap, s, context, req);
6716 if (s != REQUCH_NO) {
6717 return unchanging_noally(nmap, s, context, req);
6718 }
6719 } else {
6722
6723 if (cond) {
6724 return cond(nmap, s, context, req);
6725 }
6726 }
6727
6728 return s;
6729}
6730
6731/**********************************************************************/
6736 const struct req_context *other_context,
6737 const struct requirement *req,
6739{
6741
6742 if (REQUCH_NO != u) {
6743 /* Presence is precalculated */
6744 bool auto_present = (req->survives
6745 && !(VUT_IMPROVEMENT == req->source.kind
6749
6750 if (auto_present ? req->present
6752 /* Unchanging but does not block */
6753 return REQUCH_NO;
6754 }
6755 }
6756
6757 return u;
6758}
6759
6760/**********************************************************************/
6764bool is_req_in_vec(const struct requirement *req,
6765 const struct requirement_vector *vec)
6766{
6768 if (are_requirements_equal(req, preq)) {
6769 return TRUE;
6770 }
6772
6773 return FALSE;
6774}
6775
6776/**********************************************************************/
6784 enum universals_n kind)
6785{
6787 if (preq->present && preq->source.kind == kind) {
6788 return TRUE;
6789 }
6791 return FALSE;
6792}
6793
6794/**********************************************************************/
6803{
6804 switch (source->kind) {
6805 case VUT_ACTION:
6806 return !action_is_in_use(source->value.action);
6807 case VUT_UTFLAG:
6808 return !utype_flag_is_in_use(source->value.unitflag);
6809 case VUT_UCFLAG:
6810 return !uclass_flag_is_in_use(source->value.unitclassflag);
6811 case VUT_EXTRAFLAG:
6812 return !extra_flag_is_in_use(source->value.extraflag);
6813 case VUT_MINLATITUDE:
6814 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
6815 case VUT_MAXLATITUDE:
6816 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
6817 case VUT_COUNTER:
6818 case VUT_OTYPE:
6819 case VUT_SPECIALIST:
6820 case VUT_AI_LEVEL:
6821 case VUT_CITYTILE:
6822 case VUT_CITYSTATUS:
6823 case VUT_STYLE:
6824 case VUT_TOPO:
6825 case VUT_WRAP:
6826 case VUT_SERVERSETTING:
6827 case VUT_NATION:
6828 case VUT_NATIONGROUP:
6829 case VUT_ADVANCE:
6830 case VUT_TECHFLAG:
6831 case VUT_GOVERNMENT:
6832 case VUT_ACHIEVEMENT:
6833 case VUT_IMPROVEMENT:
6834 case VUT_SITE:
6835 case VUT_IMPR_GENUS:
6836 case VUT_IMPR_FLAG:
6837 case VUT_PLAYER_FLAG:
6838 case VUT_PLAYER_STATE:
6839 case VUT_MINSIZE:
6840 case VUT_MINCULTURE:
6841 case VUT_MINFOREIGNPCT:
6842 case VUT_MINTECHS:
6843 case VUT_MINCITIES:
6844 case VUT_NATIONALITY:
6845 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
6846 case VUT_DIPLREL:
6847 case VUT_DIPLREL_TILE:
6848 case VUT_DIPLREL_TILE_O:
6851 case VUT_MAXTILEUNITS:
6852 case VUT_UTYPE:
6853 case VUT_UCLASS:
6854 case VUT_MINVETERAN:
6855 case VUT_UNITSTATE:
6856 case VUT_ACTIVITY:
6857 case VUT_MINMOVES:
6858 case VUT_MINHP:
6859 case VUT_AGE:
6860 case VUT_FORM_AGE:
6861 case VUT_ROADFLAG:
6862 case VUT_MINCALFRAG:
6863 case VUT_TERRAIN:
6864 case VUT_EXTRA:
6865 case VUT_GOOD:
6866 case VUT_TERRAINCLASS:
6867 case VUT_TERRFLAG:
6868 case VUT_TERRAINALTER:
6869 case VUT_MINYEAR:
6872 case VUT_TILE_REL:
6873 case VUT_NONE:
6874 case VUT_COUNT:
6875 /* Not implemented. */
6876 break;
6877 }
6878
6879 return FALSE;
6880}
6881
6882/**********************************************************************/
6891{
6892 /* Not known to be impossible to fulfill */
6893 return req->present && universal_never_there(&req->source);
6894}
6895
6896/**********************************************************************/
6905{
6908 return TRUE;
6909 }
6911
6912 /* Not known to be impossible to fulfill */
6913 return FALSE;
6914}
6915
6916/**********************************************************************/
6926 const struct requirement_vector *vec)
6927{
6928 if (vec) {
6929 return 0;
6930 } else {
6931 return -1;
6932 }
6933}
6934
6935/********************************************************************/
6944struct requirement_vector *
6946{
6947 fc_assert_ret_val(number == 0, nullptr);
6948
6949 return (struct requirement_vector *)parent_item;
6950}
6951
6952/**********************************************************************/
6963const char *req_vec_change_translation(const struct req_vec_change *change,
6965{
6966 const char *req_vec_description;
6967 static char buf[MAX_LEN_NAME * 3];
6968 struct astring astr;
6969
6970 fc_assert_ret_val(change, nullptr);
6972 nullptr);
6973
6974 /* Get rid of the previous. */
6975 buf[0] = '\0';
6976
6977 if (namer == nullptr) {
6978 /* TRANS: default description of a requirement vector
6979 * (used in ruledit) */
6980 req_vec_description = _("the requirement vector");
6981 } else {
6983 }
6984
6985 switch (change->operation) {
6986 case RVCO_REMOVE:
6987 fc_snprintf(buf, sizeof(buf),
6988 /* TRANS: remove a requirement from a requirement vector
6989 * (in ruledit).
6990 * The first %s is the operation.
6991 * The second %s is the requirement.
6992 * The third %s is a description of the requirement vector,
6993 * like "actor_reqs" */
6994 _("%s %s from %s"),
6996 req_to_fstring(&change->req, &astr),
6998 astr_free(&astr);
6999 break;
7000 case RVCO_APPEND:
7001 fc_snprintf(buf, sizeof(buf),
7002 /* TRANS: append a requirement to a requirement vector
7003 * (in ruledit).
7004 * The first %s is the operation.
7005 * The second %s is the requirement.
7006 * The third %s is a description of the requirement vector,
7007 * like "actor_reqs" */
7008 _("%s %s to %s"),
7010 req_to_fstring(&change->req, &astr),
7012 astr_free(&astr);
7013 break;
7014 case RVCO_NOOP:
7015 fc_snprintf(buf, sizeof(buf),
7016 /* TRANS: do nothing to a requirement vector (in ruledit).
7017 * The first %s is a description of the requirement vector,
7018 * like "actor_reqs" */
7019 _("Do nothing to %s"), req_vec_description);
7020 break;
7021 }
7022
7023 return buf;
7024}
7025
7026/**********************************************************************/
7039 const void *parent_item)
7040{
7041 struct requirement_vector *target
7042 = getter(parent_item, modification->vector_number);
7043 int i = 0;
7044
7045 switch (modification->operation) {
7046 case RVCO_APPEND:
7048 return TRUE;
7049 case RVCO_REMOVE:
7053 return TRUE;
7054 }
7055 i++;
7057 return FALSE;
7058 case RVCO_NOOP:
7059 return FALSE;
7060 }
7061
7062 return FALSE;
7063}
7064
7065/**********************************************************************/
7075struct req_vec_problem *
7077 const char *description,
7078 const char *description_translated)
7079{
7080 struct req_vec_problem *out;
7081 int i;
7082
7083 out = fc_malloc(sizeof(*out));
7084
7085 fc_strlcpy(out->description, description, sizeof(out->description));
7086 fc_strlcpy(out->description_translated, _(description_translated),
7087 sizeof(out->description_translated));
7088
7089 out->num_suggested_solutions = num_suggested_solutions;
7090 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
7091 * sizeof(struct req_vec_change));
7092 for (i = 0; i < out->num_suggested_solutions; i++) {
7093 /* No suggestions are ready yet. */
7094 out->suggested_solutions[i].operation = RVCO_NOOP;
7095 out->suggested_solutions[i].vector_number = -1;
7096 out->suggested_solutions[i].req.source.kind = VUT_NONE;
7097 }
7098
7099 return out;
7100}
7101
7102/**********************************************************************/
7112 const char *descr, ...)
7113{
7114 char description[500];
7115 char description_translated[500];
7116 va_list ap;
7117
7118 va_start(ap, descr);
7119 fc_vsnprintf(description, sizeof(description), descr, ap);
7120 va_end(ap);
7121
7122 va_start(ap, descr);
7124 _(descr), ap);
7125 va_end(ap);
7126
7129}
7130
7131/**********************************************************************/
7138{
7139 FC_FREE(issue->suggested_solutions);
7140 issue->num_suggested_solutions = 0;
7141
7142 FC_FREE(issue);
7143}
7144
7145/**********************************************************************/
7157struct req_vec_problem *
7160 const void *parent_item)
7161{
7162 int i, j;
7164
7165 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7166 /* No vector. */
7167 return nullptr;
7168 }
7169
7170 if (get_num == nullptr || parent_item == nullptr) {
7171 vec_num = 0;
7172 } else {
7173 vec_num = get_num(parent_item, vec);
7174 }
7175
7176 /* Look for contradictions */
7177 for (i = 0; i < requirement_vector_size(vec); i++) {
7178 struct requirement *preq = requirement_vector_get(vec, i);
7179 for (j = 0; j < requirement_vector_size(vec); j++) {
7180 struct requirement *nreq = requirement_vector_get(vec, j);
7181
7183 struct req_vec_problem *problem;
7184 struct astring astr;
7185 struct astring nastr;
7186
7188 N_("Requirements {%s} and {%s} contradict each other."),
7190
7191 astr_free(&astr);
7192 astr_free(&nastr);
7193
7194 /* The solution is to remove one of the contradictions. */
7195 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7196 problem->suggested_solutions[0].vector_number = vec_num;
7197 problem->suggested_solutions[0].req = *preq;
7198
7199 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7200 problem->suggested_solutions[1].vector_number = vec_num;
7201 problem->suggested_solutions[1].req = *nreq;
7202
7203 /* Only the first contradiction is reported. */
7204 return problem;
7205 }
7206 }
7207 }
7208
7209 return nullptr;
7210}
7211
7212/**********************************************************************/
7223struct req_vec_problem *
7226 const void *parent_item)
7227{
7228 /* Check for self contradictins. */
7230}
7231
7232/**********************************************************************/
7245struct req_vec_problem *
7248 const void *parent_item)
7249{
7250 int i;
7252 struct req_vec_problem *problem = nullptr;
7253
7254 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7255 /* No vector. */
7256 return nullptr;
7257 }
7258
7259 if (get_num == nullptr || parent_item == nullptr) {
7260 vec_num = 0;
7261 } else {
7262 vec_num = get_num(parent_item, vec);
7263 }
7264
7265 /* Look for contradictions */
7266 for (i = 0; i < requirement_vector_size(vec); i++) {
7267 struct requirement *preq = requirement_vector_get(vec, i);
7268
7269 if (universal_never_there(&preq->source)) {
7270 struct astring astr;
7271
7272 if (preq->present) {
7273 /* The requirement vector can never be fulfilled. Removing the
7274 * requirement makes it possible to fulfill it. This is a rule
7275 * change and shouldn't be "fixed" without thinking. Don't offer any
7276 * automatic solution to prevent mindless "fixes". */
7277 /* TRANS: Ruledit warns a user about an unused requirement vector
7278 * that never can be fulfilled because it asks for something that
7279 * never will be there. */
7280 if (problem == nullptr) {
7282 N_("Requirement {%s} requires %s but it will never be"
7283 " there."),
7285 astr_free(&astr);
7286 }
7287
7288 /* Continue to check if other problems have a solution proposal,
7289 * and prefer to return those. */
7290 continue;
7291 }
7292
7293 if (problem != nullptr) {
7294 /* Free previous one (one with no solution proposals) */
7296 }
7297
7299 N_("Requirement {%s} mentions %s but it will never be there."),
7301
7302 astr_free(&astr);
7303
7304 /* The solution is to remove the reference to the missing
7305 * universal. */
7306 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7307 problem->suggested_solutions[0].vector_number = vec_num;
7308 problem->suggested_solutions[0].req = *preq;
7309
7310 /* Only the first missing universal is reported. */
7311 return problem;
7312 }
7313 }
7314
7315 return problem;
7316}
7317
7318/**********************************************************************/
7331struct req_vec_problem *
7334 const void *parent_item)
7335{
7336 int i, j;
7338
7339 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7340 /* No vector. */
7341 return nullptr;
7342 }
7343
7344 if (get_num == nullptr || parent_item == nullptr) {
7345 vec_num = 0;
7346 } else {
7347 vec_num = get_num(parent_item, vec);
7348 }
7349
7350 /* Look for repeated requirements */
7351 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
7352 struct requirement *preq = requirement_vector_get(vec, i);
7353 for (j = i + 1; j < requirement_vector_size(vec); j++) {
7354 struct requirement *nreq = requirement_vector_get(vec, j);
7355
7357 struct req_vec_problem *problem;
7358 struct astring astr;
7359 struct astring nastr;
7360
7362 N_("Requirements {%s} and {%s} are the same."),
7364
7365 astr_free(&astr);
7366 astr_free(&nastr);
7367
7368 /* The solution is to remove one of the redundant requirements. */
7369 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7370 problem->suggested_solutions[0].vector_number = vec_num;
7371 problem->suggested_solutions[0].req = *preq;
7372
7373 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7374 problem->suggested_solutions[1].vector_number = vec_num;
7375 problem->suggested_solutions[1].req = *nreq;
7376
7377 /* Only the first redundancy is reported. */
7378 return problem;
7379 }
7380 }
7381 }
7382
7383 return nullptr;
7384}
7385
7386/**********************************************************************/
7398struct req_vec_problem *
7401 const void *parent_item)
7402{
7403 struct req_vec_problem *out;
7404
7406 if (out != nullptr) {
7407 /* A bug, not just a potential improvement */
7408 return out;
7409 }
7410
7411 /* Check if a universal that never will appear in the game is checked. */
7413 if (out != nullptr) {
7414 return out;
7415 }
7416
7417 /* Check if a requirement is redundant. */
7419 return out;
7420}
7421
7422/**********************************************************************/
7427 const struct universal *psource2)
7428{
7429 if (psource1->kind != psource2->kind) {
7430 return FALSE;
7431 }
7432 switch (psource1->kind) {
7433 case VUT_NONE:
7434 return TRUE;
7435 case VUT_COUNTER:
7436 return psource1->value.counter == psource2->value.counter;
7437 case VUT_ADVANCE:
7438 return psource1->value.advance == psource2->value.advance;
7439 case VUT_TECHFLAG:
7440 return psource1->value.techflag == psource2->value.techflag;
7441 case VUT_GOVERNMENT:
7442 return psource1->value.govern == psource2->value.govern;
7443 case VUT_ACHIEVEMENT:
7444 return psource1->value.achievement == psource2->value.achievement;
7445 case VUT_STYLE:
7446 return psource1->value.style == psource2->value.style;
7447 case VUT_IMPROVEMENT:
7448 case VUT_SITE:
7449 return psource1->value.building == psource2->value.building;
7450 case VUT_IMPR_GENUS:
7451 return psource1->value.impr_genus == psource2->value.impr_genus;
7452 case VUT_IMPR_FLAG:
7453 return psource1->value.impr_flag == psource2->value.impr_flag;
7454 case VUT_PLAYER_FLAG:
7455 return psource1->value.plr_flag == psource2->value.plr_flag;
7456 case VUT_PLAYER_STATE:
7457 return psource1->value.plrstate == psource2->value.plrstate;
7458 case VUT_EXTRA:
7459 return psource1->value.extra == psource2->value.extra;
7460 case VUT_GOOD:
7461 return psource1->value.good == psource2->value.good;
7462 case VUT_TERRAIN:
7463 return psource1->value.terrain == psource2->value.terrain;
7464 case VUT_TERRFLAG:
7465 return psource1->value.terrainflag == psource2->value.terrainflag;
7466 case VUT_NATION:
7467 return psource1->value.nation == psource2->value.nation;
7468 case VUT_NATIONGROUP:
7469 return psource1->value.nationgroup == psource2->value.nationgroup;
7470 case VUT_NATIONALITY:
7471 return psource1->value.nationality == psource2->value.nationality;
7472 case VUT_ORIGINAL_OWNER:
7473 return psource1->value.origowner == psource2->value.origowner;
7474 case VUT_DIPLREL:
7475 case VUT_DIPLREL_TILE:
7476 case VUT_DIPLREL_TILE_O:
7479 return psource1->value.diplrel == psource2->value.diplrel;
7480 case VUT_UTYPE:
7481 return psource1->value.utype == psource2->value.utype;
7482 case VUT_UTFLAG:
7483 return psource1->value.unitflag == psource2->value.unitflag;
7484 case VUT_UCLASS:
7485 return psource1->value.uclass == psource2->value.uclass;
7486 case VUT_UCFLAG:
7487 return psource1->value.unitclassflag == psource2->value.unitclassflag;
7488 case VUT_MINVETERAN:
7489 return psource1->value.minveteran == psource2->value.minveteran;
7490 case VUT_UNITSTATE:
7491 return psource1->value.unit_state == psource2->value.unit_state;
7492 case VUT_ACTIVITY:
7493 return psource1->value.activity == psource2->value.activity;
7494 case VUT_MINMOVES:
7495 return psource1->value.minmoves == psource2->value.minmoves;
7496 case VUT_MINHP:
7497 return psource1->value.min_hit_points == psource2->value.min_hit_points;
7498 case VUT_AGE:
7499 return psource1->value.age == psource2->value.age;
7500 case VUT_FORM_AGE:
7501 return psource1->value.form_age == psource2->value.form_age;
7502 case VUT_MINTECHS:
7503 return psource1->value.min_techs == psource2->value.min_techs;
7504 case VUT_MINCITIES:
7505 return psource1->value.min_cities == psource2->value.min_cities;
7506 case VUT_ACTION:
7507 return (action_number(psource1->value.action)
7508 == action_number(psource2->value.action));
7509 case VUT_OTYPE:
7510 return psource1->value.outputtype == psource2->value.outputtype;
7511 case VUT_SPECIALIST:
7512 return psource1->value.specialist == psource2->value.specialist;
7513 case VUT_MINSIZE:
7514 return psource1->value.minsize == psource2->value.minsize;
7515 case VUT_MINCULTURE:
7516 return psource1->value.minculture == psource2->value.minculture;
7517 case VUT_MINFOREIGNPCT:
7518 return psource1->value.minforeignpct == psource2->value.minforeignpct;
7519 case VUT_AI_LEVEL:
7520 return psource1->value.ai_level == psource2->value.ai_level;
7521 case VUT_MAXTILEUNITS:
7522 return psource1->value.max_tile_units == psource2->value.max_tile_units;
7523 case VUT_TERRAINCLASS:
7524 return psource1->value.terrainclass == psource2->value.terrainclass;
7525 case VUT_ROADFLAG:
7526 return psource1->value.roadflag == psource2->value.roadflag;
7527 case VUT_EXTRAFLAG:
7528 return psource1->value.extraflag == psource2->value.extraflag;
7529 case VUT_MINYEAR:
7530 return psource1->value.minyear == psource2->value.minyear;
7531 case VUT_MINCALFRAG:
7532 return psource1->value.mincalfrag == psource2->value.mincalfrag;
7533 case VUT_TOPO:
7534 return psource1->value.topo_property == psource2->value.topo_property;
7535 case VUT_WRAP:
7536 return psource1->value.wrap_property == psource2->value.wrap_property;
7537 case VUT_SERVERSETTING:
7538 return psource1->value.ssetval == psource2->value.ssetval;
7539 case VUT_TERRAINALTER:
7540 return psource1->value.terrainalter == psource2->value.terrainalter;
7541 case VUT_CITYTILE:
7542 return psource1->value.citytile == psource2->value.citytile;
7543 case VUT_CITYSTATUS:
7544 return psource1->value.citystatus == psource2->value.citystatus;
7545 case VUT_TILE_REL:
7546 return psource1->value.tilerel == psource2->value.tilerel;
7547 case VUT_MINLATITUDE:
7548 case VUT_MAXLATITUDE:
7549 return psource1->value.latitude == psource2->value.latitude;
7551 return psource1->value.distance_sq == psource2->value.distance_sq;
7553 return psource1->value.region_tiles == psource2->value.region_tiles;
7554 case VUT_COUNT:
7555 break;
7556 }
7557
7558 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
7559 return FALSE;
7560}
7561
7562/**********************************************************************/
7566const char *universal_rule_name(const struct universal *psource)
7567{
7568 static char buffer[10];
7569
7570 switch (psource->kind) {
7571 case VUT_NONE:
7572 return "(none)";
7573 case VUT_COUNTER:
7574 return counter_rule_name(psource->value.counter);
7575 case VUT_CITYTILE:
7576 return citytile_type_name(psource->value.citytile);
7577 case VUT_CITYSTATUS:
7578 return citystatus_type_name(psource->value.citystatus);
7579 case VUT_TILE_REL:
7580 return tilerel_type_name(psource->value.tilerel);
7581 case VUT_MINYEAR:
7582 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
7583
7584 return buffer;
7585 case VUT_MINCALFRAG:
7586 /* Rule name is 0-based number, not pretty name from ruleset */
7587 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
7588
7589 return buffer;
7590 case VUT_TOPO:
7591 return topo_flag_name(psource->value.topo_property);
7592 case VUT_WRAP:
7593 return wrap_flag_name(psource->value.wrap_property);
7594 case VUT_SERVERSETTING:
7595 return ssetv_rule_name(psource->value.ssetval);
7596 case VUT_ADVANCE:
7597 return advance_rule_name(psource->value.advance);
7598 case VUT_TECHFLAG:
7599 return tech_flag_id_name(psource->value.techflag);
7600 case VUT_GOVERNMENT:
7601 return government_rule_name(psource->value.govern);
7602 case VUT_ACHIEVEMENT:
7603 return achievement_rule_name(psource->value.achievement);
7604 case VUT_STYLE:
7605 return style_rule_name(psource->value.style);
7606 case VUT_IMPROVEMENT:
7607 case VUT_SITE:
7608 return improvement_rule_name(psource->value.building);
7609 case VUT_IMPR_GENUS:
7610 return impr_genus_id_name(psource->value.impr_genus);
7611 case VUT_IMPR_FLAG:
7612 return impr_flag_id_name(psource->value.impr_flag);
7613 case VUT_PLAYER_FLAG:
7614 return plr_flag_id_name(psource->value.plr_flag);
7615 case VUT_PLAYER_STATE:
7616 return plrstate_type_name(psource->value.plrstate);
7617 case VUT_EXTRA:
7618 return extra_rule_name(psource->value.extra);
7619 case VUT_GOOD:
7620 return goods_rule_name(psource->value.good);
7621 case VUT_TERRAIN:
7622 return terrain_rule_name(psource->value.terrain);
7623 case VUT_TERRFLAG:
7624 return terrain_flag_id_name(psource->value.terrainflag);
7625 case VUT_NATION:
7626 return nation_rule_name(psource->value.nation);
7627 case VUT_NATIONGROUP:
7628 return nation_group_rule_name(psource->value.nationgroup);
7629 case VUT_DIPLREL:
7630 case VUT_DIPLREL_TILE:
7631 case VUT_DIPLREL_TILE_O:
7634 return diplrel_rule_name(psource->value.diplrel);
7635 case VUT_NATIONALITY:
7636 return nation_rule_name(psource->value.nationality);
7637 case VUT_ORIGINAL_OWNER:
7638 return nation_rule_name(psource->value.origowner);
7639 case VUT_UTYPE:
7640 return utype_rule_name(psource->value.utype);
7641 case VUT_UTFLAG:
7642 return unit_type_flag_id_name(psource->value.unitflag);
7643 case VUT_UCLASS:
7644 return uclass_rule_name(psource->value.uclass);
7645 case VUT_UCFLAG:
7646 return unit_class_flag_id_name(psource->value.unitclassflag);
7647 case VUT_MINVETERAN:
7648 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
7649
7650 return buffer;
7651 case VUT_UNITSTATE:
7652 return ustate_prop_name(psource->value.unit_state);
7653 case VUT_ACTIVITY:
7654 return unit_activity_name(psource->value.activity);
7655 case VUT_MINMOVES:
7656 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
7657
7658 return buffer;
7659 case VUT_MINHP:
7660 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
7661
7662 return buffer;
7663 case VUT_AGE:
7664 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
7665
7666 return buffer;
7667 case VUT_FORM_AGE:
7668 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
7669
7670 return buffer;
7671 case VUT_MINTECHS:
7672 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
7673
7674 return buffer;
7675 case VUT_MINCITIES:
7676 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_cities);
7677
7678 return buffer;
7679 case VUT_ACTION:
7680 return action_rule_name(psource->value.action);
7681 case VUT_OTYPE:
7682 return get_output_identifier(psource->value.outputtype);
7683 case VUT_SPECIALIST:
7684 return specialist_rule_name(psource->value.specialist);
7685 case VUT_MINSIZE:
7686 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
7687
7688 return buffer;
7689 case VUT_MINCULTURE:
7690 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
7691
7692 return buffer;
7693 case VUT_MINFOREIGNPCT:
7694 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
7695
7696 return buffer;
7697 case VUT_AI_LEVEL:
7698 return ai_level_name(psource->value.ai_level);
7699 case VUT_MAXTILEUNITS:
7700 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_units);
7701 return buffer;
7702 case VUT_TERRAINCLASS:
7703 return terrain_class_name(psource->value.terrainclass);
7704 case VUT_ROADFLAG:
7705 return road_flag_id_name(psource->value.roadflag);
7706 case VUT_EXTRAFLAG:
7707 return extra_flag_id_name(psource->value.extraflag);
7708 case VUT_TERRAINALTER:
7709 return terrain_alteration_name(psource->value.terrainalter);
7710 case VUT_MINLATITUDE:
7711 case VUT_MAXLATITUDE:
7712 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
7713
7714 return buffer;
7716 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.distance_sq);
7717
7718 return buffer;
7720 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.region_tiles);
7721
7722 return buffer;
7723 case VUT_COUNT:
7724 break;
7725 }
7726
7727 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
7728
7729 return nullptr;
7730}
7731
7732/**********************************************************************/
7741 char *buf, size_t bufsz)
7742{
7743 buf[0] = '\0'; /* to be safe. */
7744 switch (psource->kind) {
7745 case VUT_NONE:
7746 /* TRANS: missing value */
7747 fc_strlcat(buf, _("(none)"), bufsz);
7748 return buf;
7749 case VUT_ADVANCE:
7751 return buf;
7752 case VUT_COUNTER:
7754 return buf;
7755 case VUT_TECHFLAG:
7756 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
7757 tech_flag_id_translated_name(psource->value.techflag));
7758 return buf;
7759 case VUT_GOVERNMENT:
7761 bufsz);
7762 return buf;
7763 case VUT_ACHIEVEMENT:
7765 bufsz);
7766 return buf;
7767 case VUT_STYLE:
7769 bufsz);
7770 return buf;
7771 case VUT_IMPROVEMENT:
7773 bufsz);
7774 return buf;
7775 case VUT_SITE:
7776 {
7777 char local_buf[1024];
7778
7779 fc_snprintf(local_buf, sizeof(local_buf), _("%s site"),
7780 improvement_name_translation(psource->value.building));
7782 }
7783
7784 return buf;
7785 case VUT_IMPR_GENUS:
7787 impr_genus_id_translated_name(psource->value.impr_genus),
7788 bufsz);
7789 return buf;
7790 case VUT_IMPR_FLAG:
7792 impr_flag_id_translated_name(psource->value.impr_flag),
7793 bufsz);
7794 return buf;
7795 case VUT_PLAYER_FLAG:
7797 plr_flag_id_translated_name(psource->value.plr_flag),
7798 bufsz);
7799 return buf;
7800 case VUT_PLAYER_STATE:
7802 plrstate_type_translated_name(psource->value.plrstate),
7803 bufsz);
7804 return buf;
7805 case VUT_EXTRA:
7807 return buf;
7808 case VUT_GOOD:
7810 return buf;
7811 case VUT_TERRAIN:
7813 return buf;
7814 case VUT_NATION:
7816 bufsz);
7817 return buf;
7818 case VUT_NATIONGROUP:
7820 bufsz);
7821 return buf;
7822 case VUT_NATIONALITY:
7823 cat_snprintf(buf, bufsz, _("%s citizens"),
7824 nation_adjective_translation(psource->value.nationality));
7825 return buf;
7826 case VUT_ORIGINAL_OWNER:
7827 /* TRANS: Keep short. City founding nation. */
7828 cat_snprintf(buf, bufsz, _("%s original owner"),
7829 nation_adjective_translation(psource->value.origowner));
7830 return buf;
7831 case VUT_DIPLREL:
7832 case VUT_DIPLREL_TILE:
7833 case VUT_DIPLREL_TILE_O:
7837 bufsz);
7838 return buf;
7839 case VUT_UTYPE:
7841 return buf;
7842 case VUT_UTFLAG:
7844 /* TRANS: Unit type flag */
7845 Q_("?utflag:\"%s\" units"),
7847 psource->value.unitflag));
7848 return buf;
7849 case VUT_UCLASS:
7851 /* TRANS: Unit class */
7852 _("%s units"),
7853 uclass_name_translation(psource->value.uclass));
7854 return buf;
7855 case VUT_UCFLAG:
7857 /* TRANS: Unit class flag */
7858 Q_("?ucflag:\"%s\" units"),
7860 psource->value.unitclassflag));
7861 return buf;
7862 case VUT_MINVETERAN:
7863 /* FIXME */
7864 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
7865 psource->value.minveteran);
7866 return buf;
7867 case VUT_UNITSTATE:
7868 switch (psource->value.unit_state) {
7869 case USP_TRANSPORTED:
7870 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7871 cat_snprintf(buf, bufsz, _("Transported"));
7872 break;
7873 case USP_LIVABLE_TILE:
7875 /* TRANS: unit state. (appears in strings like
7876 * "Missile+On livable tile") */
7877 _("On livable tile"));
7878 break;
7879 case USP_TRANSPORTING:
7880 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7881 cat_snprintf(buf, bufsz, _("Transporting"));
7882 break;
7883 case USP_HAS_HOME_CITY:
7884 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
7885 cat_snprintf(buf, bufsz, _("Has a home city"));
7886 break;
7887 case USP_NATIVE_TILE:
7889 /* TRANS: unit state. (appears in strings like
7890 * "Missile+On native tile") */
7891 _("On native tile"));
7892 break;
7893 case USP_NATIVE_EXTRA:
7895 /* TRANS: unit state. (appears in strings like
7896 * "Missile+In native extra") */
7897 _("In native extra"));
7898 break;
7900 /* TRANS: unit state. (appears in strings like
7901 * "Missile+Has moved this turn") */
7902 cat_snprintf(buf, bufsz, _("Has moved this turn"));
7903 break;
7904 case USP_COUNT:
7905 fc_assert_msg(psource->value.unit_state != USP_COUNT,
7906 "Invalid unit state property.");
7907 break;
7908 }
7909 return buf;
7910 case VUT_ACTIVITY:
7911 cat_snprintf(buf, bufsz, _("%s activity"),
7912 Q_(unit_activity_name(psource->value.activity)));
7913 return buf;
7914 case VUT_MINMOVES:
7915 /* TRANS: Minimum unit movement points left for requirement to be met
7916 * (%s is a string like "1" or "2 1/3") */
7917 cat_snprintf(buf, bufsz, _("%s MP"),
7918 move_points_text(psource->value.minmoves, TRUE));
7919 return buf;
7920 case VUT_MINHP:
7921 /* TRANS: HP = hit points */
7922 cat_snprintf(buf, bufsz, _("%d HP"),
7923 psource->value.min_hit_points);
7924 return buf;
7925 case VUT_AGE:
7926 cat_snprintf(buf, bufsz, _("Age %d"),
7927 psource->value.age);
7928 return buf;
7929 case VUT_FORM_AGE:
7930 cat_snprintf(buf, bufsz, _("Form age %d"),
7931 psource->value.form_age);
7932 return buf;
7933 case VUT_MINTECHS:
7934 cat_snprintf(buf, bufsz, _("%d Techs"),
7935 psource->value.min_techs);
7936 return buf;
7937 case VUT_MINCITIES:
7938 cat_snprintf(buf, bufsz, _("%d Cities"),
7939 psource->value.min_cities);
7940 return buf;
7941 case VUT_ACTION:
7943 bufsz);
7944 return buf;
7945 case VUT_OTYPE:
7946 /* FIXME */
7947 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
7948 return buf;
7949 case VUT_SPECIALIST:
7951 bufsz);
7952 return buf;
7953 case VUT_MINSIZE:
7954 cat_snprintf(buf, bufsz, _("Size %d"),
7955 psource->value.minsize);
7956 return buf;
7957 case VUT_MINCULTURE:
7958 cat_snprintf(buf, bufsz, _("Culture %d"),
7959 psource->value.minculture);
7960 return buf;
7961 case VUT_MINFOREIGNPCT:
7962 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
7963 psource->value.minforeignpct);
7964 return buf;
7965 case VUT_AI_LEVEL:
7966 /* TRANS: "Hard AI" */
7967 cat_snprintf(buf, bufsz, _("%s AI"),
7968 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
7969 return buf;
7970 case VUT_MAXTILEUNITS:
7971 /* TRANS: here <= means 'less than or equal' */
7972 cat_snprintf(buf, bufsz, PL_("<=%d unit",
7973 "<=%d units", psource->value.max_tile_units),
7974 psource->value.max_tile_units);
7975 return buf;
7976 case VUT_TERRAINCLASS:
7977 /* TRANS: Terrain class: "Land terrain" */
7978 cat_snprintf(buf, bufsz, _("%s terrain"),
7979 terrain_class_name_translation(psource->value.terrainclass));
7980 return buf;
7981 case VUT_TERRFLAG:
7983 /* TRANS: Terrain flag */
7984 Q_("?terrflag:\"%s\" terrain"),
7986 psource->value.terrainflag));
7987 return buf;
7988 case VUT_ROADFLAG:
7990 /* TRANS: Road flag */
7991 Q_("?roadflag:\"%s\" road"),
7992 road_flag_id_translated_name(psource->value.roadflag));
7993 return buf;
7994 case VUT_EXTRAFLAG:
7996 /* TRANS: Extra flag */
7997 Q_("?extraflag:\"%s\" extra"),
7998 extra_flag_id_translated_name(psource->value.extraflag));
7999 return buf;
8000 case VUT_MINYEAR:
8001 cat_snprintf(buf, bufsz, _("After %s"),
8002 textyear(psource->value.minyear));
8003 return buf;
8004 case VUT_MINCALFRAG:
8005 /* TRANS: here >= means 'greater than or equal'.
8006 * %s identifies a calendar fragment (may be bare number). */
8007 cat_snprintf(buf, bufsz, _(">=%s"),
8008 textcalfrag(psource->value.mincalfrag));
8009 return buf;
8010 case VUT_TOPO:
8011 /* TRANS: topology flag name ("Hex", "ISO") */
8012 cat_snprintf(buf, bufsz, _("%s map"),
8013 _(topo_flag_name(psource->value.topo_property)));
8014 return buf;
8015 case VUT_WRAP:
8016 /* TRANS: wrap flag name ("WrapX", "WrapY") */
8017 cat_snprintf(buf, bufsz, _("%s map"),
8018 _(wrap_flag_name(psource->value.wrap_property)));
8019 return buf;
8020 case VUT_SERVERSETTING:
8022 bufsz);
8023 return buf;
8024 case VUT_TERRAINALTER:
8025 /* TRANS: "Irrigation possible" */
8026 cat_snprintf(buf, bufsz, _("%s possible"),
8027 Q_(terrain_alteration_name(psource->value.terrainalter)));
8028 return buf;
8029 case VUT_CITYTILE:
8030 switch (psource->value.citytile) {
8031 case CITYT_CENTER:
8032 fc_strlcat(buf, _("City center"), bufsz);
8033 break;
8034 case CITYT_CLAIMED:
8035 fc_strlcat(buf, _("Tile claimed"), bufsz);
8036 break;
8037 case CITYT_EXTRAS_OWNED:
8038 fc_strlcat(buf, _("Extras owned"), bufsz);
8039 break;
8040 case CITYT_WORKED:
8041 fc_strlcat(buf, _("Worked tile"), bufsz);
8042 break;
8044 fc_strlcat(buf, _("Same continent tile"), bufsz);
8045 break;
8047 /* TRANS: Short for "a tile of other terrain class mass near city" */
8048 fc_strlcat(buf, _("Port reachable tile"), bufsz);
8049 break;
8050 case CITYT_LAST:
8051 fc_assert(psource->value.citytile != CITYT_LAST);
8052 fc_strlcat(buf, "error", bufsz);
8053 break;
8054 }
8055 return buf;
8056 case VUT_CITYSTATUS:
8057 switch (psource->value.citystatus) {
8059 fc_strlcat(buf, _("Owned by original"), bufsz);
8060 break;
8061 case CITYS_STARVED:
8062 fc_strlcat(buf, _("Starved"), bufsz);
8063 break;
8064 case CITYS_DISORDER:
8065 fc_strlcat(buf, _("Disorder"), bufsz);
8066 break;
8067 case CITYS_CELEBRATION:
8068 fc_strlcat(buf, _("Celebration"), bufsz);
8069 break;
8070 case CITYS_TRANSFERRED:
8071 /* TRANS: CityStatus value - city has changed hands */
8072 fc_strlcat(buf, _("Transferred"), bufsz);
8073 break;
8074 case CITYS_LAST:
8075 fc_assert(psource->value.citystatus != CITYS_LAST);
8076 fc_strlcat(buf, "error", bufsz);
8077 break;
8078 }
8079 return buf;
8080 case VUT_TILE_REL:
8081 switch (psource->value.tilerel) {
8082 case TREL_SAME_TCLASS:
8083 fc_strlcat(buf, _("Same terrain class"), bufsz);
8084 break;
8085 case TREL_SAME_REGION:
8086 fc_strlcat(buf, _("Same continent/ocean"), bufsz);
8087 break;
8089 fc_strlcat(buf, _("Only other continent/ocean"), bufsz);
8090 break;
8092 fc_strlcat(buf, _("Lake/island surrounded"), bufsz);
8093 break;
8094 case TREL_COUNT:
8095 fc_assert(psource->value.tilerel != TREL_COUNT);
8096 fc_strlcat(buf, "error", bufsz);
8097 break;
8098 }
8099 return buf;
8100 case VUT_MINLATITUDE:
8101 /* TRANS: here >= means 'greater than or equal'. */
8102 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
8103 psource->value.latitude);
8104 return buf;
8105 case VUT_MAXLATITUDE:
8106 /* TRANS: here <= means 'less than or equal'. */
8107 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
8108 psource->value.latitude);
8109 return buf;
8111 /* TRANS: here <= means 'less than or equal'. */
8112 cat_snprintf(buf, bufsz, _("Squared distance <= %d"),
8113 psource->value.distance_sq);
8114 return buf;
8116 cat_snprintf(buf, bufsz, _("%d or fewer region tiles"),
8117 psource->value.region_tiles);
8118 return buf;
8119 case VUT_COUNT:
8120 break;
8121 }
8122
8123 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8124 return buf;
8125}
8126
8127/**********************************************************************/
8131{
8132 return universals_n_name(psource->kind);
8133}
8134
8135/**********************************************************************/
8139 const struct universal *target)
8140{
8141 switch (target->kind) {
8142 case VUT_IMPROVEMENT:
8143 case VUT_SITE:
8144 return impr_build_shield_cost(pcity, target->value.building);
8145 case VUT_UTYPE:
8146 return utype_build_shield_cost(pcity, nullptr, target->value.utype);
8147 default:
8148 break;
8149 }
8150 return FC_INFINITY;
8151}
8152
8153/**********************************************************************/
8159 const struct universal *to_replace,
8160 const struct universal *replacement)
8161{
8162 bool changed = FALSE;
8163
8166 preq->source = *replacement;
8167 changed = TRUE;
8168 }
8170
8171 return changed;
8172}
8173
8174/**********************************************************************/
8179 const struct requirement_vector *reqs,
8180 const struct universal *psource)
8181{
8184 return TRUE;
8185 }
8187
8188 return FALSE;
8189}
8190
8191/**********************************************************************/
8202 struct universal *unis,
8203 size_t n_unis)
8204{
8205 int i;
8206
8207 for (i = 0; i < n_unis; i++) {
8209 /* This universal makes it impossible to fulfill the specified
8210 * requirement vector */
8211 return TRUE;
8212 }
8213 }
8214
8215 /* No specified universal is known to guarantee that the requirement
8216 * vector never will be fulfilled. */
8217 return FALSE;
8218}
8219
8220/**********************************************************************/
8236 struct universal *unis,
8237 size_t n_unis)
8238{
8240 int i;
8242
8243 for (i = 0; i < n_unis; i++) {
8244 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
8245 case ITF_NO:
8246 case ITF_YES:
8247 /* this req matched this source */
8249 break;
8250 case ITF_NOT_APPLICABLE:
8251 /* Not a mention. */
8252 break;
8253 }
8254 }
8255
8257 /* A requirement not relevant to any of the specified universals was
8258 * found in the requirement vector. */
8259 return FALSE;
8260 }
8262
8263 /* No requirement not relevant to any of the specified universals was
8264 * found in the requirement vector. */
8265 return TRUE;
8266}
8267
8268/**********************************************************************/
8271enum req_item_found
8273 const struct universal *source)
8274{
8277 "No req item found function for %s",
8279
8280 return (*universal_found_function[source->kind])(preq, source);
8281}
8282
8283/**********************************************************************/
8294 const struct requirement_vector *reqs,
8295 const struct universal *source)
8296{
8297 bool necessary = FALSE;
8298
8301 "No req item found function for %s",
8303
8305 switch ((*universal_found_function[source->kind])(preq, source)) {
8306 case ITF_NOT_APPLICABLE:
8307 continue;
8308 case ITF_NO:
8309 if (preq->present) {
8310 return FALSE;
8311 }
8312 break;
8313 case ITF_YES:
8314 if (preq->present) {
8315 necessary = TRUE;
8316 } else {
8317 return FALSE;
8318 }
8319 break;
8320 }
8322
8323 return (!check_necessary || necessary);
8324}
8325
8326/**********************************************************************/
8331 const struct universal *source)
8332{
8333 switch (universal_fulfills_requirement(req, source)) {
8334 case ITF_NOT_APPLICABLE:
8335 return FALSE;
8336 case ITF_NO:
8337 case ITF_YES:
8338 return TRUE;
8339 }
8340
8341 log_error("Unhandled item_found value");
8342 return FALSE;
8343}
8344
8345/**********************************************************************/
8349 const struct universal *source)
8350{
8351 fc_assert(source->value.nation);
8352
8353 switch (preq->source.kind) {
8354 case VUT_NATION:
8355 return preq->source.value.nation == source->value.nation ? ITF_YES
8356 : ITF_NO;
8357 case VUT_NATIONGROUP:
8358 return nation_is_in_group(source->value.nation,
8359 preq->source.value.nationgroup) ? ITF_YES
8360 : ITF_NO;
8361 default:
8362 break;
8363 }
8364
8365 return ITF_NOT_APPLICABLE;
8366}
8367
8368/**********************************************************************/
8372 const struct universal *source)
8373{
8374 fc_assert(source->value.govern);
8375
8376 if (preq->source.kind == VUT_GOVERNMENT) {
8377 return preq->source.value.govern == source->value.govern ? ITF_YES
8378 : ITF_NO;
8379 }
8380
8381 return ITF_NOT_APPLICABLE;
8382}
8383
8384/**********************************************************************/
8388 const struct universal *source)
8389{
8390 fc_assert(source->value.min_cities);
8391
8392 if (preq->source.kind == VUT_MINCITIES) {
8393 return preq->source.value.min_cities <= source->value.min_cities ? ITF_YES
8394 : ITF_NO;
8395 }
8396
8397 return ITF_NOT_APPLICABLE;
8398}
8399
8400/**********************************************************************/
8404 const struct universal *source)
8405{
8406 fc_assert(source->value.building);
8407
8408 /* We only ever return ITF_YES, because requiring a different
8409 * improvement does not mean that the improvement under consideration
8410 * cannot fulfill the requirements. This is necessary to allow
8411 * requirement vectors to specify multiple required improvements. */
8412
8413 switch (preq->source.kind) {
8414 case VUT_IMPROVEMENT:
8415 case VUT_SITE:
8416 if (source->value.building == preq->source.value.building) {
8417 return ITF_YES;
8418 }
8419 break;
8420 case VUT_IMPR_GENUS:
8421 if (source->value.building->genus == preq->source.value.impr_genus) {
8422 return ITF_YES;
8423 }
8424 break;
8425 case VUT_IMPR_FLAG:
8426 if (improvement_has_flag(source->value.building,
8427 preq->source.value.impr_flag)) {
8428 return ITF_YES;
8429 }
8430 break;
8431 default:
8432 break;
8433 }
8434
8435 return ITF_NOT_APPLICABLE;
8436}
8437
8438/**********************************************************************/
8442 const struct universal *source)
8443{
8444 fc_assert(source->value.uclass);
8445
8446 switch (preq->source.kind) {
8447 case VUT_UCLASS:
8448 return source->value.uclass == preq->source.value.uclass ? ITF_YES
8449 : ITF_NO;
8450 case VUT_UCFLAG:
8451 return uclass_has_flag(source->value.uclass,
8452 preq->source.value.unitclassflag) ? ITF_YES
8453 : ITF_NO;
8454
8455 default:
8456 /* Not found and not relevant. */
8457 return ITF_NOT_APPLICABLE;
8458 };
8459}
8460
8461/**********************************************************************/
8465 const struct universal *source)
8466{
8467 fc_assert(source->value.utype);
8468
8469 switch (preq->source.kind) {
8470 case VUT_UTYPE:
8471 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
8472 case VUT_UCLASS:
8473 return utype_class(source->value.utype) == preq->source.value.uclass
8474 ? ITF_YES : ITF_NO;
8475 case VUT_UTFLAG:
8476 return utype_has_flag(source->value.utype,
8477 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
8478 case VUT_UCFLAG:
8479 return uclass_has_flag(utype_class(source->value.utype),
8480 preq->source.value.unitclassflag) ? ITF_YES
8481 : ITF_NO;
8482 default:
8483 /* Not found and not relevant. */
8484 return ITF_NOT_APPLICABLE;
8485 };
8486}
8487
8488/**********************************************************************/
8491static enum req_item_found
8493 const struct universal *source)
8494{
8497
8498 switch (preq->source.kind) {
8499 case VUT_ACTIVITY:
8500 return source->value.activity == preq->source.value.activity ? ITF_YES
8501 : ITF_NO;
8502 default:
8503 /* Not found and not relevant. */
8504 return ITF_NOT_APPLICABLE;
8505 };
8506}
8507
8508/**********************************************************************/
8512 const struct universal *source)
8513{
8514 fc_assert(source->value.terrain);
8515
8516 switch (preq->source.kind) {
8517 case VUT_TERRAIN:
8518 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
8519 case VUT_TERRAINCLASS:
8520 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
8521 ? ITF_YES : ITF_NO;
8522 case VUT_TERRFLAG:
8523 return terrain_has_flag(source->value.terrain,
8524 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
8525 case VUT_TERRAINALTER:
8526 return (terrain_can_support_alteration(source->value.terrain,
8527 preq->source.value.terrainalter)
8528 ? ITF_YES : ITF_NO);
8529 default:
8530 /* Not found and not relevant. */
8531 return ITF_NOT_APPLICABLE;
8532 };
8533}
8534
8535/**********************************************************************/
8539 const struct universal *source)
8540{
8543
8544 switch (preq->source.kind) {
8545 case VUT_CITYTILE:
8546 return (source->value.citytile == preq->source.value.citytile
8547 ? ITF_YES
8548 /* The presence of one tile state doesn't block another */
8550 default:
8551 /* Not found and not relevant. */
8552 return ITF_NOT_APPLICABLE;
8553 };
8554}
8555
8556/**********************************************************************/
8560 const struct universal *source)
8561{
8562 fc_assert(source->value.extra);
8563
8564 switch (preq->source.kind) {
8565 case VUT_EXTRA:
8566 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
8567 case VUT_EXTRAFLAG:
8568 return extra_has_flag(source->value.extra,
8569 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
8570 case VUT_ROADFLAG:
8571 {
8572 struct road_type *r = extra_road_get(source->value.extra);
8573 return r && road_has_flag(r, preq->source.value.roadflag)
8574 ? ITF_YES : ITF_NO;
8575 }
8576 default:
8577 /* Not found and not relevant. */
8578 return ITF_NOT_APPLICABLE;
8579 }
8580}
8581
8582/**********************************************************************/
8586 const struct universal *source)
8587{
8588 fc_assert(source->value.action);
8589
8590 if (preq->source.kind == VUT_ACTION) {
8591 return preq->source.value.action == source->value.action ? ITF_YES
8592 : ITF_NO;
8593 }
8594
8595 return ITF_NOT_APPLICABLE;
8596}
8597
8598/**********************************************************************/
8602 const struct universal *source)
8603{
8605 || source->kind == VUT_DIPLREL_TILE
8606 || source->kind == VUT_DIPLREL_TILE_O
8607 || source->kind == VUT_DIPLREL_UNITANY
8608 || source->kind == VUT_DIPLREL_UNITANY_O),
8610
8611 if (preq->source.kind == source->kind) {
8612 if (preq->source.value.diplrel == source->value.diplrel) {
8613 /* The diplrel itself. */
8614 return ITF_YES;
8615 }
8616 if (preq->source.value.diplrel == DRO_FOREIGN
8617 && source->value.diplrel < DS_LAST) {
8618 /* All diplstate_type values are to foreigners. */
8619 return ITF_YES;
8620 }
8621 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
8622 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
8623 /* A real embassy is an embassy. */
8624 return ITF_YES;
8625 }
8626 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
8627 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
8628 /* A real embassy is an embassy. */
8629 return ITF_YES;
8630 }
8631 if (preq->source.value.diplrel < DS_LAST
8632 && source->value.diplrel < DS_LAST
8633 && preq->range == REQ_RANGE_LOCAL) {
8634 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
8635 ITF_YES);
8636 /* Can only have one diplstate_type to a specific player. */
8637 return ITF_NO;
8638 }
8639 /* Can't say this diplrel blocks the other diplrel. */
8640 return ITF_NOT_APPLICABLE;
8641 }
8642
8643 /* Not relevant. */
8644 return ITF_NOT_APPLICABLE;
8645}
8646
8647/**********************************************************************/
8651 const struct universal *source)
8652{
8653 switch (preq->source.kind) {
8654 case VUT_OTYPE:
8655 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
8656 : ITF_NO;
8657 default:
8658 /* Not found and not relevant. */
8659 return ITF_NOT_APPLICABLE;
8660 }
8661}
8662
8663/**********************************************************************/
8667 const struct universal *source)
8668{
8669 if (preq->range != REQ_RANGE_LOCAL) {
8670 return ITF_NOT_APPLICABLE;
8671 }
8672
8673 if (preq->source.kind == VUT_UNITSTATE) {
8674 switch (source->value.unit_state) {
8675 case USP_TRANSPORTED:
8676 case USP_TRANSPORTING:
8677 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
8678 case USP_LIVABLE_TILE:
8679 case USP_NATIVE_TILE:
8680 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
8681 * UTYF_COAST_STRICT. */
8682 case USP_HAS_HOME_CITY:
8683 case USP_NATIVE_EXTRA:
8685 if (source->value.unit_state == preq->source.value.unit_state) {
8686 /* The other unit states doesn't contradict */
8687 return ITF_YES;
8688 }
8689 break;
8690 case USP_COUNT:
8691 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
8693 }
8694 }
8695
8696 /* Not found and not relevant. */
8697 return ITF_NOT_APPLICABLE;
8698}
8699
8700/**********************************************************************/
8725
8726/**********************************************************************/
8734int requirement_kind_ereq(const int value,
8735 const enum req_range range,
8736 const bool present,
8737 const int max_value)
8738{
8739 /* The enumerators in each range starts with present for every possible
8740 * value followed by !present for every possible value. */
8741 const int pres_start = (present ? 0 : max_value);
8742
8743 /* The enumerators for every range follows all the positions of the
8744 * previous range(s). */
8745 const int range_start = ((max_value - 1) * 2) * range;
8746
8747 return range_start + pres_start + value;
8748}
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:1230
bool action_is_in_use(struct action *paction)
Definition actions.c:5672
struct action * action_by_rule_name(const char *name)
Definition actions.c:1079
const char * action_rule_name(const struct action *action)
Definition actions.c:1216
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1239
int action_number(const struct action *action)
Definition actions.c:1208
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define ACTION_NONE
Definition actions.h:59
void astr_free(struct astring *astr)
Definition astring.c:148
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:251
void astr_init(struct astring *astr)
Definition astring.c:139
#define n
Definition astring.c:77
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
const char * textcalfrag(int frag)
Definition calendar.c:101
const char * textyear(int year)
Definition calendar.c:121
citizens citizens_nation_foreign(const struct city *pcity)
Definition citizens.c:91
#define citizens_iterate_end
Definition citizens.h:54
#define citizens_iterate(_pcity, _pslot, _nationality)
Definition citizens.h:48
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:1240
Output_type_id output_type_by_identifier(const char *id)
Definition city.c:647
const char * get_output_identifier(Output_type_id output)
Definition city.c:619
const char * get_output_name(Output_type_id output)
Definition city.c:629
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
#define city_tile(_pcity_)
Definition city.h:561
static citizens city_size_get(const struct city *pcity)
Definition city.h:566
#define city_owner(_pcity_)
Definition city.h:560
static bool is_city_center(const struct city *pcity, const struct tile *ptile)
Definition city.h:865
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:227
#define city_tile_iterate_end
Definition city.h:235
#define city_built_iterate(_pcity, _p)
Definition city.h:831
#define city_built_iterate_end
Definition city.h:837
static struct ai_type * self
Definition classicai.c:46
char * incite_cost
Definition comments.c:76
int counter_index(const struct counter *pcount)
Definition counters.c:174
const char * counter_name_translation(const struct counter *counter)
Definition counters.c:157
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:115
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:165
struct counter * counter_by_id(int id)
Definition counters.c:82
int counter_id(struct counter *pcount)
Definition counters.c:105
int city_culture(const struct city *pcity)
Definition culture.c:29
int player_culture(const struct player *plr)
Definition culture.c:49
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:56
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:57
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
struct @22::@23 reqs
int get_world_bonus(enum effect_type effect_type)
Definition effects.c:812
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
bool extra_flag_is_in_use(enum extra_flag_id id)
Definition extras.c:1001
bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:904
bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:884
bool is_extra_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:379
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:875
bool is_extra_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:363
struct extra_type * extra_by_number(int id)
Definition extras.c:183
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:194
#define extra_road_get(_e_)
Definition extras.h:191
static bool is_server(void)
int Tech_type_id
Definition fc_types.h:237
req_problem_type
Definition fc_types.h:532
@ RPT_POSSIBLE
Definition fc_types.h:533
#define MAX_LEN_NAME
Definition fc_types.h:67
@ VC_SPACERACE
Definition fc_types.h:978
@ O_LAST
Definition fc_types.h:102
signed short Continent_id
Definition fc_types.h:232
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
bool register_at_thread_exit_callback(at_thread_exit_cb *cb)
Definition fcthread.c:32
void fc_mutex_allocate(fc_mutex *mutex)
void fc_mutex_init(fc_mutex *mutex)
void fc_mutex_release(fc_mutex *mutex)
fc_thread_id fc_thread_self(void)
bool fc_threads_equal(fc_thread_id thr1, fc_thread_id thr2)
void fc_mutex_destroy(fc_mutex *mutex)
struct civ_game game
Definition game.c:61
struct world wld
Definition game.c:62
const char * government_name_translation(const struct government *pgovern)
Definition government.c:143
struct government * government_by_number(const Government_type_id gov)
Definition government.c:103
struct government * government_of_player(const struct player *pplayer)
Definition government.c:114
Government_type_id government_number(const struct government *pgovern)
Definition government.c:91
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
struct government * government_by_rule_name(const char *name)
Definition government.c:55
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:1021
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:486
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:475
const char * nation_group_rule_name(const struct nation_group *pgroup)
Definition nation.c:1079
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
bool nation_is_in_group(const struct nation_type *pnation, const struct nation_group *pgroup)
Definition nation.c:1099
const char * nation_group_name_translation(const struct nation_group *pgroup)
Definition nation.c:1090
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:1004
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:952
#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:1328
bool player_has_state(const struct player *pplayer, enum plrstate_type state)
Definition player.c:2004
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Definition player.c:1829
int diplrel_by_rule_name(const char *value)
Definition player.c:1585
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1480
bool is_diplrel_to_other(const struct player *pplayer, int diplrel)
Definition player.c:1566
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1996
const char * diplrel_name_translation(int value)
Definition player.c:1631
bool is_diplrel_between(const struct player *player1, const struct player *player2, int diplrel)
Definition player.c:1516
int player_age(const struct player *pplayer)
Definition player.c:954
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1409
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:437
const char * diplrel_rule_name(int value)
Definition player.c:1619
#define players_iterate_end
Definition player.h:542
#define players_iterate(_pplayer)
Definition player.h:537
#define player_nation(_plr_)
Definition player.h:408
#define is_ai(plr)
Definition player.h:232
#define players_iterate_alive_end
Definition player.h:552
#define players_iterate_alive(_pplayer)
Definition player.h:547
static enum req_item_found terrain_type_found(const struct requirement *preq, const struct universal *source)
bool universal_never_there(const struct universal *source)
static enum fc_tristate is_unitclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unitflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_relevant_to_requirement(const struct requirement *req, const struct universal *source)
#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
static enum fc_tristate is_maxunitsontile_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(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 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_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
const char * universal_type_rule_name(const struct universal *psource)
#define REQUC_PRESENT
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:128
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:619
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:112
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:100
Specialist_type_id specialist_number(const struct specialist *sp)
Definition specialist.c:91
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
const char * specialist_plural_translation(const struct specialist *sp)
Definition specialist.c:155
Definition city.h:317
struct packet_game_info info
Definition game.h:89
struct packet_calendar_info calendar
Definition game.h:90
int checkpoint
Definition counters.h:33
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 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:609
universals_u value
Definition fc_types.h:608
struct civ_map map
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
struct nation_style * style_by_number(int id)
Definition style.c:88
const char * style_name_translation(const struct nation_style *pstyle)
Definition style.c:99
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:108
int style_number(const struct nation_style *pstyle)
Definition style.c:68
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:822
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define bool
Definition support.h:71
#define fc__fallthrough
Definition support.h:119
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag)
Definition tech.c:216
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:300
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:309
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:185
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:611
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:590
const char * terrain_class_name_translation(enum terrain_class tclass)
Definition terrain.c:660
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:237
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:155
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Definition terrain.c:672
bool is_terrain_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:326
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:246
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:581
bool is_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:457
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:146
bool is_terrain_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:437
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:347
#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:886
bool tile_has_native_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:324
bool tile_has_road_flag(const struct tile *ptile, enum road_flag_id flag)
Definition tile.c:868
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_terrain(_tile)
Definition tile.h:115
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#define tile_owner(_tile)
Definition tile.h:97
bool goods_can_be_provided(const struct city *pcity, const struct goods_type *pgood, const struct unit *punit)
Goods_type_id goods_number(const struct goods_type *pgood)
bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
const char * goods_name_translation(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
#define trade_partners_iterate_end
#define trade_partners_iterate(c, p)
const struct unit_type * utype
Definition fc_types.h:554
int region_tiles
Definition fc_types.h:598
struct nation_style * style
Definition fc_types.h:558
enum ai_level ai_level
Definition fc_types.h:562
struct specialist * specialist
Definition fc_types.h:551
enum impr_genus_id impr_genus
Definition fc_types.h:585
enum citytile_type citytile
Definition fc_types.h:563
struct nation_group * nationgroup
Definition fc_types.h:557
struct extra_type * extra
Definition fc_types.h:555
enum wrap_flag wrap_property
Definition fc_types.h:601
enum plrstate_type plrstate
Definition fc_types.h:565
enum tilerel_type tilerel
Definition fc_types.h:566
struct nation_type * nation
Definition fc_types.h:548
int terrainclass
Definition fc_types.h:573
int unitclassflag
Definition fc_types.h:575
struct government * govern
Definition fc_types.h:546
struct nation_type * origowner
Definition fc_types.h:550
enum impr_flag_id impr_flag
Definition fc_types.h:586
int max_tile_units
Definition fc_types.h:589
int terrainalter
Definition fc_types.h:574
enum citystatus_type citystatus
Definition fc_types.h:564
int minforeignpct
Definition fc_types.h:569
const struct impr_type * building
Definition fc_types.h:547
struct achievement * achievement
Definition fc_types.h:556
ssetv ssetval
Definition fc_types.h:602
struct advance * advance
Definition fc_types.h:544
enum unit_activity activity
Definition fc_types.h:584
struct goods_type * good
Definition fc_types.h:560
struct terrain * terrain
Definition fc_types.h:552
int terrainflag
Definition fc_types.h:577
enum ustate_prop unit_state
Definition fc_types.h:583
Output_type_id outputtype
Definition fc_types.h:572
int distance_sq
Definition fc_types.h:597
enum topo_flag topo_property
Definition fc_types.h:600
struct counter * counter
Definition fc_types.h:545
int min_hit_points
Definition fc_types.h:591
struct unit_class * uclass
Definition fc_types.h:553
struct nation_type * nationality
Definition fc_types.h:549
struct action * action
Definition fc_types.h:559
enum plr_flag_id plr_flag
Definition fc_types.h:587
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1846
#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:1636
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
bool unit_has_class_flag(const struct unit *punit, enum unit_class_flag_id flag)
Definition unittype.c:1653
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1771
bool uclass_flag_is_in_use(enum unit_class_flag_id ucflag)
Definition unittype.c:2985
struct unit_class * uclass_by_number(const Unit_Class_id id)
Definition unittype.c:2481
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1582
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2503
struct unit_type * utype_by_number(const Unit_type_id id)
Definition unittype.c:112
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:194
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1645
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:100
struct unit_class * unit_class_by_rule_name(const char *s)
Definition unittype.c:1788
bool utype_flag_is_in_use(enum unit_type_flag_id uflag)
Definition unittype.c:3004
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1442
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2472
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1564
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:771
#define utype_class(_t_)
Definition unittype.h:754
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:622
bool victory_enabled(enum victory_condition_type victory)
Definition victory.c:26