Freeciv-3.4
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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
47/************************************************************************
48 Container for req_item_found functions
49************************************************************************/
50typedef enum req_item_found (*universal_found)(const struct requirement *,
51 const struct universal *);
53
54static
56 const struct req_context *context,
57 const struct req_context *other_context,
58 const struct requirement *req);
59
60/* Function pointer for requirement-type-specific is_req_active handlers */
61typedef enum fc_tristate
62(*is_req_active_cb)(const struct civ_map *nmap,
63 const struct req_context *context,
64 const struct req_context *other_context,
65 const struct requirement *req);
66
67static inline bool are_tiles_in_range(const struct tile *tile1,
68 const struct tile *tile2,
69 enum req_range range);
70
71/**********************************************************************/
76static enum req_unchanging_status
78 enum req_unchanging_status def,
79 const struct req_context *context,
80 const struct requirement *req)
81{
82 return req->range == REQ_RANGE_LOCAL ? REQUCH_YES : def;
83}
84#define REQUC_LOCAL unchanging_local
85
86/**********************************************************************/
89static enum req_unchanging_status
91 enum req_unchanging_status def,
92 const struct req_context *context,
93 const struct requirement *req)
94{
95 if (TRI_YES != tri_req_present(nmap, context, nullptr, req)) {
96 return REQUCH_NO;
97 }
98 return def;
99}
100#define REQUC_PRESENT unchanging_present
101
102/**********************************************************************/
105static enum req_unchanging_status
107 enum req_unchanging_status def,
108 const struct req_context *context,
109 const struct requirement *req)
110{
111 return
113 context, req);
114}
115#define REQUC_WORLD unchanging_world
116
117/**********************************************************************/
121static enum req_unchanging_status
123 enum req_unchanging_status def,
124 const struct req_context *context,
125 const struct requirement *req)
126{
127 if (REQ_RANGE_ALLIANCE == req->range
128 || REQ_RANGE_TEAM == req->range) {
129 struct requirement preq;
130
131 req_copy(&preq, req);
132 preq.range = REQ_RANGE_PLAYER;
133 if (TRI_YES != tri_req_present(nmap, context, nullptr, &preq)) {
134 return REQ_RANGE_TEAM == req->range ? REQUCH_ACT : REQUCH_NO;
135 }
136 }
137 return def;
138}
139#define REQUC_NALLY unchanging_noally
140
141/**********************************************************************/
144static enum req_unchanging_status
146 enum req_unchanging_status def,
147 const struct req_context *context,
148 const struct requirement *req)
149{
153 && context->city != nullptr && context->tile != nullptr
154 && city_tile(context->city) != nullptr
156 req->range))){
157 /* Cities don't move, and most reqs are present on city center */
158 return REQUCH_YES;
159 }
160 return def;
161}
162#define REQUC_CITYTILE unchanging_citytile
163
164/**********************************************************************/
167static enum req_unchanging_status
169 enum req_unchanging_status def,
170 const struct req_context *context,
171 const struct requirement *req)
172{
174
175 if (REQ_RANGE_CITY == req->range
178 return REQUCH_CTRL;
179 }
180
181 return def;
182}
183#define REQUC_CITYSTATUS unchanging_citystatus
184
185/**********************************************************************/
190static enum req_unchanging_status
192 enum req_unchanging_status def,
193 const struct req_context *context,
194 const struct requirement *req)
195{
196 const struct impr_type *b = req->source.value.building;
197
199 || VUT_SITE == req->source.kind, REQUCH_NO);
200 if (REQ_RANGE_LOCAL == req->range) {
201 /* Likely, won't be questioned for an obsolete building */
202 return REQUCH_YES;
203 }
204
205 if (req->source.kind == VUT_IMPROVEMENT
206 && improvement_obsolete(context->player, b, context->city)) {
207 /* FIXME: Sometimes can unobsolete, but considering it
208 * may sometimes put the function on endless recursion */
209 return REQUCH_ACT; /* Mostly about techs */
210 }
211 if (is_great_wonder(b)) {
214 && (req->range <= REQ_RANGE_CITY && TRI_YES
215 == tri_req_present(nmap, context, nullptr, req)))) {
216 /* If the wonder stays somewhere, it may either remain there
217 * or be destroyed. If it is destroyed, it is nowhere. */
218 return REQUCH_SCRIPTS;
219 }
220 }
221 return def;
222}
223#define REQUC_IMPR unchanging_building
224
230
231/**********************************************************************/
239 const char *value)
240{
241 struct universal source;
242
244 if (!universals_n_is_valid(source.kind)) {
245 return source;
246 }
247
249
250 return source;
251}
252
253/**********************************************************************/
258{
259 return unit_activity_is_valid(act)
260 && act != ACTIVITY_SENTRY
261 && act != ACTIVITY_GOTO
262 && act != ACTIVITY_EXPLORE;
263}
264
265/**********************************************************************/
270{
271 if (univ->kind == VUT_ACTIVITY) {
273 }
274
275 return TRUE;
276}
277
278/**********************************************************************/
283{
284 /* Finally scan the value string based on the type of the source. */
285 switch (source->kind) {
286 case VUT_NONE:
287 return;
288 case VUT_ADVANCE:
289 source->value.advance = advance_by_rule_name(value);
290 if (source->value.advance != nullptr) {
291 return;
292 }
293 break;
294 case VUT_TECHFLAG:
295 source->value.techflag
297 if (tech_flag_id_is_valid(source->value.techflag)) {
298 return;
299 }
300 break;
301 case VUT_GOVERNMENT:
302 source->value.govern = government_by_rule_name(value);
303 if (source->value.govern != nullptr) {
304 return;
305 }
306 break;
307 case VUT_ACHIEVEMENT:
308 source->value.achievement = achievement_by_rule_name(value);
309 if (source->value.achievement != nullptr) {
310 return;
311 }
312 break;
313 case VUT_STYLE:
314 source->value.style = style_by_rule_name(value);
315 if (source->value.style != nullptr) {
316 return;
317 }
318 break;
319 case VUT_IMPROVEMENT:
320 case VUT_SITE:
321 source->value.building = improvement_by_rule_name(value);
322 if (source->value.building != nullptr) {
323 return;
324 }
325 break;
326 case VUT_IMPR_GENUS:
327 source->value.impr_genus = impr_genus_id_by_name(value, fc_strcasecmp);
328 if (impr_genus_id_is_valid(source->value.impr_genus)) {
329 return;
330 }
331 break;
332 case VUT_IMPR_FLAG:
333 source->value.impr_flag = impr_flag_id_by_name(value, fc_strcasecmp);
334 if (impr_flag_id_is_valid(source->value.impr_flag)) {
335 return;
336 }
337 break;
338 case VUT_PLAYER_FLAG:
339 source->value.plr_flag = plr_flag_id_by_name(value, fc_strcasecmp);
340 if (plr_flag_id_is_valid(source->value.plr_flag)) {
341 return;
342 }
343 break;
344 case VUT_EXTRA:
345 source->value.extra = extra_type_by_rule_name(value);
346 if (source->value.extra != nullptr) {
347 return;
348 }
349 break;
350 case VUT_GOOD:
351 source->value.good = goods_by_rule_name(value);
352 if (source->value.good != nullptr) {
353 return;
354 }
355 break;
356 case VUT_TERRAIN:
357 source->value.terrain = terrain_by_rule_name(value);
358 if (source->value.terrain != T_UNKNOWN) {
359 return;
360 }
361 break;
362 case VUT_TERRFLAG:
363 source->value.terrainflag
365 if (terrain_flag_id_is_valid(source->value.terrainflag)) {
366 return;
367 }
368 break;
369 case VUT_NATION:
370 source->value.nation = nation_by_rule_name(value);
371 if (source->value.nation != NO_NATION_SELECTED) {
372 return;
373 }
374 break;
375 case VUT_NATIONGROUP:
376 source->value.nationgroup = nation_group_by_rule_name(value);
377 if (source->value.nationgroup != nullptr) {
378 return;
379 }
380 break;
381 case VUT_NATIONALITY:
382 source->value.nationality = nation_by_rule_name(value);
383 if (source->value.nationality != NO_NATION_SELECTED) {
384 return;
385 }
386 break;
388 source->value.origowner = nation_by_rule_name(value);
389 if (source->value.origowner != NO_NATION_SELECTED) {
390 return;
391 }
392 break;
393 case VUT_DIPLREL:
394 case VUT_DIPLREL_TILE:
398 source->value.diplrel = diplrel_by_rule_name(value);
399 if (source->value.diplrel != diplrel_other_invalid()) {
400 return;
401 }
402 break;
403 case VUT_UTYPE:
404 source->value.utype = unit_type_by_rule_name(value);
405 if (source->value.utype) {
406 return;
407 }
408 break;
409 case VUT_UTFLAG:
411 if (unit_type_flag_id_is_valid(source->value.unitflag)) {
412 return;
413 }
414 break;
415 case VUT_UCLASS:
416 source->value.uclass = unit_class_by_rule_name(value);
417 if (source->value.uclass) {
418 return;
419 }
420 break;
421 case VUT_UCFLAG:
422 source->value.unitclassflag
424 if (unit_class_flag_id_is_valid(source->value.unitclassflag)) {
425 return;
426 }
427 break;
428 case VUT_MINVETERAN:
429 source->value.minveteran = atoi(value);
430 if (source->value.minveteran > 0) {
431 return;
432 }
433 break;
434 case VUT_UNITSTATE:
435 source->value.unit_state = ustate_prop_by_name(value, fc_strcasecmp);
436 if (ustate_prop_is_valid(source->value.unit_state)) {
437 return;
438 }
439 break;
440 case VUT_ACTIVITY:
442 if (activity_is_valid_in_requirement(source->value.activity)) {
443 return;
444 }
445 break;
446 case VUT_MINMOVES:
447 source->value.minmoves = atoi(value);
448 if (source->value.minmoves > 0) {
449 return;
450 }
451 break;
452 case VUT_MINHP:
453 source->value.min_hit_points = atoi(value);
454 if (source->value.min_hit_points > 0) {
455 return;
456 }
457 break;
458 case VUT_AGE:
459 source->value.age = atoi(value);
460 if (source->value.age > 0) {
461 return;
462 }
463 break;
464 case VUT_FORM_AGE:
465 source->value.form_age = atoi(value);
466 if (source->value.form_age > 0) {
467 return;
468 }
469 break;
470 case VUT_MINTECHS:
471 source->value.min_techs = atoi(value);
472 if (source->value.min_techs > 0) {
473 return;
474 }
475 break;
476 case VUT_MINCITIES:
477 source->value.min_cities = atoi(value);
478 if (source->value.min_cities > 0) {
479 return;
480 }
481 break;
482 case VUT_ACTION:
483 source->value.action = action_by_rule_name(value);
484 if (source->value.action != nullptr) {
485 return;
486 }
487 break;
488 case VUT_OTYPE:
489 source->value.outputtype = output_type_by_identifier(value);
490 if (source->value.outputtype != O_LAST) {
491 return;
492 }
493 break;
494 case VUT_SPECIALIST:
495 source->value.specialist = specialist_by_rule_name(value);
496 if (source->value.specialist) {
497 return;
498 }
499 break;
500 case VUT_MINSIZE:
501 source->value.minsize = atoi(value);
502 if (source->value.minsize > 0) {
503 return;
504 }
505 break;
506 case VUT_MINCULTURE:
507 source->value.minculture = atoi(value);
508 if (source->value.minculture > 0) {
509 return;
510 }
511 break;
513 source->value.minforeignpct = atoi(value);
514 if (source->value.minforeignpct > 0) {
515 return;
516 }
517 break;
518 case VUT_AI_LEVEL:
519 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
520 if (ai_level_is_valid(source->value.ai_level)) {
521 return;
522 }
523 break;
524 case VUT_MAXTILEUNITS:
525 source->value.max_tile_units = atoi(value);
526 if (0 <= source->value.max_tile_units) {
527 return;
528 }
529 break;
530 case VUT_TERRAINCLASS:
531 source->value.terrainclass
533 if (terrain_class_is_valid(source->value.terrainclass)) {
534 return;
535 }
536 break;
537 case VUT_ROADFLAG:
539 if (road_flag_id_is_valid(source->value.roadflag)) {
540 return;
541 }
542 break;
543 case VUT_EXTRAFLAG:
544 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
545 if (extra_flag_id_is_valid(source->value.extraflag)) {
546 return;
547 }
548 break;
549 case VUT_MINYEAR:
550 source->value.minyear = atoi(value);
551 return;
552 case VUT_MINCALFRAG:
553 /* Rule names are 0-based numbers, not pretty names from ruleset */
554 source->value.mincalfrag = atoi(value);
555 if (source->value.mincalfrag >= 0) {
556 /* More range checking done later, in sanity_check_req_individual() */
557 return;
558 }
559 break;
560 case VUT_TOPO:
561 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
562 if (topo_flag_is_valid(source->value.topo_property)) {
563 return;
564 }
565 break;
566 case VUT_WRAP:
567 source->value.wrap_property = wrap_flag_by_name(value, fc_strcasecmp);
568 if (wrap_flag_is_valid(source->value.wrap_property)) {
569 return;
570 }
571 break;
573 source->value.ssetval = ssetv_by_rule_name(value);
574 if (source->value.ssetval != SSETV_NONE) {
575 return;
576 }
577 break;
578 case VUT_TERRAINALTER:
579 source->value.terrainalter
581 if (terrain_alteration_is_valid(source->value.terrainalter)) {
582 return;
583 }
584 break;
585 case VUT_CITYTILE:
587 if (source->value.citytile != CITYT_LAST) {
588 return;
589 }
590 break;
591 case VUT_CITYSTATUS:
593 if (source->value.citystatus != CITYS_LAST) {
594 return;
595 }
596 break;
597 case VUT_PLAYER_STATE:
599 if (source->value.plrstate != PLRS_LAST) {
600 return;
601 }
602 break;
603 case VUT_MINLATITUDE:
604 case VUT_MAXLATITUDE:
605 source->value.latitude = atoi(value);
606 if (source->value.latitude >= -MAP_MAX_LATITUDE
607 && source->value.latitude <= MAP_MAX_LATITUDE) {
608 return;
609 }
610 break;
611 case VUT_COUNTER:
612 source->value.counter = counter_by_rule_name(value);
613 if (source->value.counter != nullptr) {
614 return;
615 }
616 break;
618 source->value.distance_sq = atoi(value);
619 if (0 <= source->value.distance_sq) {
620 return;
621 }
622 break;
624 source->value.region_tiles = atoi(value);
625 if (0 < source->value.region_tiles) {
626 return;
627 }
628 break;
629 case VUT_TILE_REL:
631 if (source->value.tilerel != TREL_COUNT) {
632 return;
633 }
634 break;
635 case VUT_COUNT:
636 break;
637 }
638
639 /* If we reach here there's been an error. */
641}
642
643/**********************************************************************/
650{
651 struct universal source;
652
653 source.kind = kind;
654
655 switch (source.kind) {
656 case VUT_NONE:
657 /* Avoid compiler warning about unitialized source.value */
658 source.value.advance = nullptr;
659
660 return source;
661 case VUT_ADVANCE:
662 source.value.advance = advance_by_number(value);
663 if (source.value.advance != nullptr) {
664 return source;
665 }
666 break;
667 case VUT_TECHFLAG:
668 source.value.techflag = value;
669 return source;
670 case VUT_GOVERNMENT:
672 if (source.value.govern != nullptr) {
673 return source;
674 }
675 break;
676 case VUT_ACHIEVEMENT:
677 source.value.achievement = achievement_by_number(value);
678 if (source.value.achievement != nullptr) {
679 return source;
680 }
681 break;
682 case VUT_STYLE:
683 source.value.style = style_by_number(value);
684 if (source.value.style != nullptr) {
685 return source;
686 }
687 break;
688 case VUT_IMPROVEMENT:
689 case VUT_SITE:
690 source.value.building = improvement_by_number(value);
691 if (source.value.building != nullptr) {
692 return source;
693 }
694 break;
695 case VUT_IMPR_GENUS:
696 source.value.impr_genus = value;
697 return source;
698 case VUT_IMPR_FLAG:
699 source.value.impr_flag = value;
700 return source;
701 case VUT_PLAYER_FLAG:
702 source.value.plr_flag = value;
703 return source;
704 case VUT_EXTRA:
706 return source;
707 case VUT_GOOD:
708 source.value.good = goods_by_number(value);
709 return source;
710 case VUT_TERRAIN:
711 source.value.terrain = terrain_by_number(value);
712 if (source.value.terrain != nullptr) {
713 return source;
714 }
715 break;
716 case VUT_TERRFLAG:
717 source.value.terrainflag = value;
718 return source;
719 case VUT_NATION:
721 if (source.value.nation != nullptr) {
722 return source;
723 }
724 break;
725 case VUT_NATIONGROUP:
726 source.value.nationgroup = nation_group_by_number(value);
727 if (source.value.nationgroup != nullptr) {
728 return source;
729 }
730 break;
731 case VUT_DIPLREL:
732 case VUT_DIPLREL_TILE:
736 source.value.diplrel = value;
737 if (source.value.diplrel != diplrel_other_invalid()) {
738 return source;
739 }
740 break;
741 case VUT_NATIONALITY:
743 if (source.value.nationality != nullptr) {
744 return source;
745 }
746 break;
748 source.value.origowner = nation_by_number(value);
749 if (source.value.origowner != nullptr) {
750 return source;
751 }
752 break;
753 case VUT_UTYPE:
754 source.value.utype = utype_by_number(value);
755 if (source.value.utype != nullptr) {
756 return source;
757 }
758 break;
759 case VUT_UTFLAG:
760 source.value.unitflag = value;
761 return source;
762 case VUT_UCLASS:
764 if (source.value.uclass != nullptr) {
765 return source;
766 }
767 break;
768 case VUT_UCFLAG:
769 source.value.unitclassflag = value;
770 return source;
771 case VUT_MINVETERAN:
772 source.value.minveteran = value;
773 return source;
774 case VUT_UNITSTATE:
775 source.value.unit_state = value;
776 return source;
777 case VUT_ACTIVITY:
778 source.value.activity = value;
779 return source;
780 case VUT_MINMOVES:
781 source.value.minmoves = value;
782 return source;
783 case VUT_MINHP:
785 return source;
786 case VUT_AGE:
787 source.value.age = value;
788 return source;
789 case VUT_FORM_AGE:
790 source.value.form_age = value;
791 return source;
792 case VUT_MINTECHS:
793 source.value.min_techs = value;
794 return source;
795 case VUT_MINCITIES:
796 source.value.min_cities = value;
797 return source;
798 case VUT_ACTION:
800 if (source.value.action != nullptr) {
801 return source;
802 }
803 break;
804 case VUT_OTYPE:
805 source.value.outputtype = value;
806 return source;
807 case VUT_SPECIALIST:
809 return source;
810 case VUT_MINSIZE:
811 source.value.minsize = value;
812 return source;
813 case VUT_MINCULTURE:
814 source.value.minculture = value;
815 return source;
817 source.value.minforeignpct = value;
818 return source;
819 case VUT_AI_LEVEL:
820 source.value.ai_level = value;
821 return source;
822 case VUT_MAXTILEUNITS:
824 return source;
825 case VUT_TERRAINCLASS:
826 source.value.terrainclass = value;
827 return source;
828 case VUT_ROADFLAG:
829 source.value.roadflag = value;
830 return source;
831 case VUT_EXTRAFLAG:
832 source.value.extraflag = value;
833 return source;
834 case VUT_MINYEAR:
835 source.value.minyear = value;
836 return source;
837 case VUT_MINCALFRAG:
838 source.value.mincalfrag = value;
839 return source;
840 case VUT_TOPO:
841 source.value.topo_property = value;
842 return source;
843 case VUT_WRAP:
844 source.value.wrap_property = value;
845 return source;
847 source.value.ssetval = value;
848 return source;
849 case VUT_TERRAINALTER:
850 source.value.terrainalter = value;
851 return source;
852 case VUT_CITYTILE:
853 source.value.citytile = value;
854 return source;
855 case VUT_CITYSTATUS:
856 source.value.citystatus = value;
857 return source;
858 case VUT_PLAYER_STATE:
859 source.value.plrstate = value;
860 return source;
861 case VUT_COUNTER:
863 return source;
864 case VUT_MINLATITUDE:
865 case VUT_MAXLATITUDE:
866 source.value.latitude = value;
867 return source;
869 source.value.distance_sq = value;
870 return source;
872 source.value.region_tiles = value;
873 return source;
874 case VUT_TILE_REL:
875 source.value.tilerel = value;
876 return source;
877 case VUT_COUNT:
878 break;
879 }
880
881 /* If we reach here there's been an error. */
883 /* Avoid compiler warning about unitialized source.value */
884 source.value.advance = nullptr;
885
886 return source;
887}
888
889/**********************************************************************/
892void universal_copy(struct universal *dst, const struct universal *src)
893{
894 dst->value = src->value;
895 dst->kind = src->kind;
896}
897
898/**********************************************************************/
903 int *kind, int *value)
904{
905 *kind = source->kind;
907}
908
909/**********************************************************************/
913{
914 switch (source->kind) {
915 case VUT_NONE:
916 return 0;
917 case VUT_ADVANCE:
918 return advance_number(source->value.advance);
919 case VUT_TECHFLAG:
920 return source->value.techflag;
921 case VUT_GOVERNMENT:
922 return government_number(source->value.govern);
923 case VUT_ACHIEVEMENT:
924 return achievement_number(source->value.achievement);
925 case VUT_STYLE:
926 return style_number(source->value.style);
927 case VUT_IMPROVEMENT:
928 case VUT_SITE:
929 return improvement_number(source->value.building);
930 case VUT_IMPR_GENUS:
931 return source->value.impr_genus;
932 case VUT_IMPR_FLAG:
933 return source->value.impr_flag;
934 case VUT_PLAYER_FLAG:
935 return source->value.plr_flag;
936 case VUT_EXTRA:
937 return extra_number(source->value.extra);
938 case VUT_GOOD:
939 return goods_number(source->value.good);
940 case VUT_TERRAIN:
941 return terrain_number(source->value.terrain);
942 case VUT_TERRFLAG:
943 return source->value.terrainflag;
944 case VUT_NATION:
945 return nation_number(source->value.nation);
946 case VUT_NATIONGROUP:
947 return nation_group_number(source->value.nationgroup);
948 case VUT_NATIONALITY:
949 return nation_number(source->value.nationality);
951 return nation_number(source->value.origowner);
952 case VUT_DIPLREL:
953 case VUT_DIPLREL_TILE:
957 return source->value.diplrel;
958 case VUT_UTYPE:
959 return utype_number(source->value.utype);
960 case VUT_UTFLAG:
961 return source->value.unitflag;
962 case VUT_UCLASS:
963 return uclass_number(source->value.uclass);
964 case VUT_UCFLAG:
965 return source->value.unitclassflag;
966 case VUT_MINVETERAN:
967 return source->value.minveteran;
968 case VUT_UNITSTATE:
969 return source->value.unit_state;
970 case VUT_ACTIVITY:
971 return source->value.activity;
972 case VUT_MINMOVES:
973 return source->value.minmoves;
974 case VUT_MINHP:
975 return source->value.min_hit_points;
976 case VUT_AGE:
977 return source->value.age;
978 case VUT_FORM_AGE:
979 return source->value.form_age;
980 case VUT_MINTECHS:
981 return source->value.min_techs;
982 case VUT_MINCITIES:
983 return source->value.min_cities;
984 case VUT_ACTION:
985 return action_number(source->value.action);
986 case VUT_OTYPE:
987 return source->value.outputtype;
988 case VUT_SPECIALIST:
989 return specialist_number(source->value.specialist);
990 case VUT_MINSIZE:
991 return source->value.minsize;
992 case VUT_MINCULTURE:
993 return source->value.minculture;
995 return source->value.minforeignpct;
996 case VUT_AI_LEVEL:
997 return source->value.ai_level;
998 case VUT_MAXTILEUNITS:
999 return source->value.max_tile_units;
1000 case VUT_TERRAINCLASS:
1001 return source->value.terrainclass;
1002 case VUT_ROADFLAG:
1003 return source->value.roadflag;
1004 case VUT_EXTRAFLAG:
1005 return source->value.extraflag;
1006 case VUT_MINYEAR:
1007 return source->value.minyear;
1008 case VUT_MINCALFRAG:
1009 return source->value.mincalfrag;
1010 case VUT_TOPO:
1011 return source->value.topo_property;
1012 case VUT_WRAP:
1013 return source->value.wrap_property;
1014 case VUT_SERVERSETTING:
1015 return source->value.ssetval;
1016 case VUT_TERRAINALTER:
1017 return source->value.terrainalter;
1018 case VUT_CITYTILE:
1019 return source->value.citytile;
1020 case VUT_CITYSTATUS:
1021 return source->value.citystatus;
1022 case VUT_PLAYER_STATE:
1023 return source->value.plrstate;
1024 case VUT_COUNTER:
1025 return counter_id(source->value.counter);
1026 case VUT_MINLATITUDE:
1027 case VUT_MAXLATITUDE:
1028 return source->value.latitude;
1030 return source->value.distance_sq;
1032 return source->value.region_tiles;
1033 case VUT_TILE_REL:
1034 return source->value.tilerel;
1035 case VUT_COUNT:
1036 break;
1037 }
1038
1039 /* If we reach here there's been an error. */
1040 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
1041 source->kind);
1042 return 0;
1043}
1044
1045
1046/**********************************************************************/
1050{
1051 static const struct req_context empty = {};
1052 return &empty;
1053}
1054
1055
1056/**********************************************************************/
1064const char *req_to_fstring(const struct requirement *req,
1065 struct astring *astr)
1066{
1067 astr_init(astr);
1068
1069 astr_set(astr, "%s%s %s %s%s",
1070 req->survives ? "surviving " : "",
1071 req_range_name(req->range),
1073 req->present ? "" : "!",
1075
1076 return astr_str(astr);
1077}
1078
1079/**********************************************************************/
1087 bool survives, bool present, bool quiet,
1088 const char *value)
1089{
1090 struct requirement req;
1091 bool invalid;
1092 const char *error = nullptr;
1093
1094 req.source = universal_by_rule_name(type, value);
1095
1097 if (invalid) {
1098 error = "bad type or name";
1099 } else {
1100 /* Scan the range string to find the range. If no range is given a
1101 * default fallback is used rather than giving an error. */
1102 if (range != nullptr) {
1104 if (!req_range_is_valid(req.range)) {
1105 invalid = TRUE;
1106 }
1107 } else {
1108 switch (req.source.kind) {
1109 case VUT_NONE:
1110 case VUT_COUNT:
1111 break;
1112 case VUT_IMPROVEMENT:
1113 case VUT_SITE:
1114 case VUT_IMPR_GENUS:
1115 case VUT_IMPR_FLAG:
1116 case VUT_UTYPE:
1117 case VUT_UTFLAG:
1118 case VUT_UCLASS:
1119 case VUT_UCFLAG:
1120 case VUT_MINVETERAN:
1121 case VUT_UNITSTATE:
1122 case VUT_ACTIVITY:
1123 case VUT_MINMOVES:
1124 case VUT_MINHP:
1125 case VUT_AGE:
1126 case VUT_FORM_AGE:
1127 case VUT_ACTION:
1128 case VUT_OTYPE:
1129 case VUT_SPECIALIST:
1130 case VUT_DIPLREL_TILE_O:
1132 req.range = REQ_RANGE_LOCAL;
1133 break;
1134 case VUT_EXTRA:
1135 case VUT_ROADFLAG:
1136 case VUT_EXTRAFLAG:
1137 /* Keep old behavior */
1138 req.range = REQ_RANGE_TILE;
1139 break;
1140 case VUT_TERRAIN:
1141 case VUT_TERRFLAG:
1142 case VUT_TERRAINCLASS:
1143 case VUT_TERRAINALTER:
1144 case VUT_CITYTILE:
1145 case VUT_MAXTILEUNITS:
1146 case VUT_MINLATITUDE:
1147 case VUT_MAXLATITUDE:
1149 req.range = REQ_RANGE_TILE;
1150 break;
1151 case VUT_COUNTER:
1152 case VUT_MINSIZE:
1153 case VUT_MINCULTURE:
1154 case VUT_MINFOREIGNPCT:
1155 case VUT_NATIONALITY:
1156 case VUT_ORIGINAL_OWNER:
1157 case VUT_CITYSTATUS:
1158 case VUT_GOOD:
1159 req.range = REQ_RANGE_CITY;
1160 break;
1161 case VUT_GOVERNMENT:
1162 case VUT_ACHIEVEMENT:
1163 case VUT_STYLE:
1164 case VUT_ADVANCE:
1165 case VUT_TECHFLAG:
1166 case VUT_NATION:
1167 case VUT_NATIONGROUP:
1168 case VUT_DIPLREL:
1169 case VUT_DIPLREL_TILE:
1171 case VUT_AI_LEVEL:
1172 case VUT_PLAYER_FLAG:
1173 case VUT_PLAYER_STATE:
1174 case VUT_MINCITIES:
1175 req.range = REQ_RANGE_PLAYER;
1176 break;
1177 case VUT_MINYEAR:
1178 case VUT_MINCALFRAG:
1179 case VUT_TOPO:
1180 case VUT_WRAP:
1181 case VUT_MINTECHS:
1182 case VUT_SERVERSETTING:
1183 req.range = REQ_RANGE_WORLD;
1184 break;
1187 break;
1188 case VUT_TILE_REL:
1189 req.range = REQ_RANGE_TILE;
1191 /* Not available at Tile range */
1193 }
1194 break;
1195 }
1196 }
1197
1198 req.survives = survives;
1199 req.present = present;
1200 req.quiet = quiet;
1201
1202 /* These checks match what combinations are supported inside
1203 * is_req_active(). However, it's only possible to do basic checks,
1204 * not anything that might depend on the rest of the ruleset which
1205 * might not have been loaded yet. */
1206 switch (req.source.kind) {
1207 case VUT_TERRAIN:
1208 case VUT_TERRAINCLASS:
1209 case VUT_TERRFLAG:
1210 invalid = (req.range != REQ_RANGE_TILE
1211 && req.range != REQ_RANGE_CADJACENT
1212 && req.range != REQ_RANGE_ADJACENT
1213 && req.range != REQ_RANGE_CITY
1214 && req.range != REQ_RANGE_TRADE_ROUTE);
1215 break;
1216 case VUT_EXTRA:
1217 case VUT_ROADFLAG:
1218 case VUT_EXTRAFLAG:
1220 break;
1221 case VUT_ACHIEVEMENT:
1222 case VUT_MINTECHS:
1223 invalid = (req.range < REQ_RANGE_PLAYER);
1224 break;
1225 case VUT_ADVANCE:
1226 case VUT_TECHFLAG:
1228 && req.range != REQ_RANGE_LOCAL);
1229 break;
1230 case VUT_GOVERNMENT:
1231 case VUT_AI_LEVEL:
1232 case VUT_STYLE:
1233 case VUT_MINCITIES:
1234 invalid = (req.range != REQ_RANGE_PLAYER);
1235 break;
1236 case VUT_MINSIZE:
1237 case VUT_MINFOREIGNPCT:
1238 case VUT_NATIONALITY:
1239 case VUT_CITYSTATUS:
1240 invalid = (req.range != REQ_RANGE_CITY
1241 && req.range != REQ_RANGE_TRADE_ROUTE);
1242 break;
1243 case VUT_GOOD:
1244 case VUT_ORIGINAL_OWNER:
1245 invalid = (req.range != REQ_RANGE_CITY);
1246 break;
1247 case VUT_MINCULTURE:
1248 invalid = (req.range != REQ_RANGE_CITY
1250 && req.range != REQ_RANGE_PLAYER
1251 && req.range != REQ_RANGE_TEAM
1252 && req.range != REQ_RANGE_ALLIANCE
1253 && req.range != REQ_RANGE_WORLD);
1254 break;
1255 case VUT_DIPLREL:
1256 invalid = (req.range != REQ_RANGE_LOCAL
1257 && req.range != REQ_RANGE_PLAYER
1258 && req.range != REQ_RANGE_TEAM
1259 && req.range != REQ_RANGE_ALLIANCE
1260 && req.range != REQ_RANGE_WORLD)
1261 /* Non local foreign makes no sense. */
1262 || (req.source.value.diplrel == DRO_FOREIGN
1263 && req.range != REQ_RANGE_LOCAL);
1264 break;
1265 case VUT_DIPLREL_TILE:
1266 invalid = (req.range != REQ_RANGE_LOCAL
1267 && req.range != REQ_RANGE_PLAYER
1268 && req.range != REQ_RANGE_TEAM
1269 && req.range != REQ_RANGE_ALLIANCE)
1270 /* Non local foreign makes no sense. */
1271 || (req.source.value.diplrel == DRO_FOREIGN
1272 && req.range != REQ_RANGE_LOCAL);
1273 break;
1274 case VUT_DIPLREL_TILE_O:
1275 invalid = (req.range != REQ_RANGE_LOCAL);
1276 break;
1278 invalid = (req.range != REQ_RANGE_LOCAL
1279 && req.range != REQ_RANGE_PLAYER
1280 && req.range != REQ_RANGE_TEAM
1281 && req.range != REQ_RANGE_ALLIANCE)
1282 /* Non local foreign makes no sense. */
1283 || (req.source.value.diplrel == DRO_FOREIGN
1284 && req.range != REQ_RANGE_LOCAL);
1285 break;
1287 invalid = (req.range != REQ_RANGE_LOCAL);
1288 break;
1289 case VUT_NATION:
1290 case VUT_NATIONGROUP:
1292 && req.range != REQ_RANGE_TEAM
1293 && req.range != REQ_RANGE_ALLIANCE
1294 && req.range != REQ_RANGE_WORLD);
1295 break;
1296 case VUT_MINVETERAN:
1297 case VUT_UNITSTATE:
1298 case VUT_ACTIVITY:
1299 case VUT_MINMOVES:
1300 case VUT_MINHP:
1301 case VUT_ACTION:
1302 case VUT_OTYPE:
1303 case VUT_SPECIALIST:
1304 invalid = (req.range != REQ_RANGE_LOCAL);
1305 break;
1306 case VUT_UTYPE:
1307 case VUT_UTFLAG:
1308 case VUT_UCLASS:
1309 case VUT_UCFLAG:
1310 invalid = (req.range != REQ_RANGE_LOCAL
1311 && req.range != REQ_RANGE_TILE
1312 && req.range != REQ_RANGE_CADJACENT
1313 && req.range != REQ_RANGE_ADJACENT);
1314 break;
1315 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1317 invalid = (req.range != REQ_RANGE_TILE);
1318 break;
1319 case VUT_CITYTILE:
1320 case VUT_MAXTILEUNITS:
1321 invalid = (req.range != REQ_RANGE_TILE
1322 && req.range != REQ_RANGE_CADJACENT
1323 && req.range != REQ_RANGE_ADJACENT);
1324 break;
1325 case VUT_MINLATITUDE:
1326 case VUT_MAXLATITUDE:
1327 invalid = (req.range != REQ_RANGE_TILE
1328 && req.range != REQ_RANGE_CADJACENT
1329 && req.range != REQ_RANGE_ADJACENT
1330 && req.range != REQ_RANGE_WORLD)
1331 /* Avoid redundancy at tile range: no negated requirements
1332 * that could be emulated by a present requirement of the
1333 * other type */
1334 || (req.range == REQ_RANGE_TILE && !req.present);
1335 break;
1336 case VUT_MINYEAR:
1337 case VUT_MINCALFRAG:
1338 case VUT_TOPO:
1339 case VUT_WRAP:
1340 case VUT_SERVERSETTING:
1341 invalid = (req.range != REQ_RANGE_WORLD);
1342 break;
1343 case VUT_AGE:
1344 /* FIXME: Could support TRADE_ROUTE, TEAM, etc */
1345 invalid = (req.range != REQ_RANGE_LOCAL
1346 && req.range != REQ_RANGE_CITY
1347 && req.range != REQ_RANGE_PLAYER);
1348 break;
1349 case VUT_FORM_AGE:
1350 invalid = (req.range != REQ_RANGE_LOCAL);
1351 break;
1352 case VUT_IMPR_GENUS:
1353 /* TODO: Support other ranges too. */
1354 invalid = (req.range != REQ_RANGE_LOCAL);
1355 break;
1356 case VUT_IMPR_FLAG:
1357 invalid = (req.range != REQ_RANGE_LOCAL
1358 && req.range != REQ_RANGE_TILE
1359 && req.range != REQ_RANGE_CITY);
1360 break;
1361 case VUT_COUNTER:
1362 invalid = req.range != REQ_RANGE_CITY;
1363 break;
1364 case VUT_PLAYER_FLAG:
1365 case VUT_PLAYER_STATE:
1366 invalid = (req.range != REQ_RANGE_PLAYER);
1367 break;
1370 && req.range != REQ_RANGE_CADJACENT
1371 && req.range != REQ_RANGE_ADJACENT);
1372 break;
1373 case VUT_TILE_REL:
1375 && req.range != REQ_RANGE_CADJACENT
1376 && req.range != REQ_RANGE_TILE)
1377 /* TREL_ONLY_OTHER_REGION not supported at Tile range */
1379 && req.range == REQ_RANGE_TILE);
1380 break;
1381 case VUT_IMPROVEMENT:
1382 case VUT_SITE:
1383 /* Valid ranges depend on the building genus (wonder/improvement),
1384 * which might not have been loaded from the ruleset yet.
1385 * So we allow anything here, and do a proper check once ruleset
1386 * loading is complete, in sanity_check_req_individual(). */
1387 case VUT_NONE:
1388 invalid = FALSE;
1389 break;
1390 case VUT_COUNT:
1391 break;
1392 }
1393 if (invalid) {
1394 error = "bad range";
1395 }
1396 }
1397
1398 if (!invalid) {
1399 /* Check 'survives'. */
1400 switch (req.source.kind) {
1401 case VUT_IMPROVEMENT:
1402 case VUT_SITE:
1403 /* See buildings_in_range(). */
1405 break;
1406 case VUT_NATION:
1407 case VUT_ADVANCE:
1409 break;
1410 case VUT_COUNTER:
1411 case VUT_IMPR_GENUS:
1412 case VUT_IMPR_FLAG:
1413 case VUT_PLAYER_FLAG:
1414 case VUT_PLAYER_STATE:
1415 case VUT_GOVERNMENT:
1416 case VUT_TERRAIN:
1417 case VUT_UTYPE:
1418 case VUT_UTFLAG:
1419 case VUT_UCLASS:
1420 case VUT_UCFLAG:
1421 case VUT_MINVETERAN:
1422 case VUT_UNITSTATE:
1423 case VUT_ACTIVITY:
1424 case VUT_MINMOVES:
1425 case VUT_MINHP:
1426 case VUT_AGE:
1427 case VUT_FORM_AGE:
1428 case VUT_ACTION:
1429 case VUT_OTYPE:
1430 case VUT_SPECIALIST:
1431 case VUT_MINSIZE:
1432 case VUT_MINCULTURE:
1433 case VUT_MINFOREIGNPCT:
1434 case VUT_AI_LEVEL:
1435 case VUT_TERRAINCLASS:
1436 case VUT_MINYEAR:
1437 case VUT_MINCALFRAG:
1438 case VUT_TOPO:
1439 case VUT_WRAP:
1440 case VUT_SERVERSETTING:
1441 case VUT_TERRAINALTER:
1442 case VUT_CITYTILE:
1443 case VUT_CITYSTATUS:
1444 case VUT_TERRFLAG:
1445 case VUT_NATIONALITY:
1446 case VUT_ORIGINAL_OWNER:
1447 case VUT_ROADFLAG:
1448 case VUT_EXTRAFLAG:
1449 case VUT_EXTRA:
1450 case VUT_GOOD:
1451 case VUT_TECHFLAG:
1452 case VUT_ACHIEVEMENT:
1453 case VUT_NATIONGROUP:
1454 case VUT_STYLE:
1455 case VUT_DIPLREL:
1456 case VUT_DIPLREL_TILE:
1457 case VUT_DIPLREL_TILE_O:
1460 case VUT_MAXTILEUNITS:
1461 case VUT_MINTECHS:
1462 case VUT_MINCITIES:
1463 case VUT_MINLATITUDE:
1464 case VUT_MAXLATITUDE:
1467 case VUT_TILE_REL:
1468 /* Most requirements don't support 'survives'. */
1469 invalid = survives;
1470 break;
1471 case VUT_NONE:
1472 case VUT_COUNT:
1473 break;
1474 }
1475 if (invalid) {
1476 error = "bad 'survives'";
1477 }
1478 }
1479
1480 if (invalid) {
1481 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1482 type, range, survives ? "survives" : "",
1483 present ? "present" : "", value, error);
1485 }
1486
1487 return req;
1488}
1489
1490/**********************************************************************/
1496 int value)
1497{
1498 struct requirement req;
1499
1500 req.source = universal_by_number(type, value);
1501 req.range = range;
1502 req.survives = survives;
1503 req.present = present;
1504 req.quiet = quiet;
1505
1506 return req;
1507}
1508
1509/**********************************************************************/
1513void req_get_values(const struct requirement *req,
1514 int *type, int *range,
1515 bool *survives, bool *present, bool *quiet,
1516 int *value)
1517{
1518 universal_extraction(&req->source, type, value);
1519 *range = req->range;
1520 *survives = req->survives;
1521 *present = req->present;
1522 *quiet = req->quiet;
1523}
1524
1525/**********************************************************************/
1528void req_copy(struct requirement *dst, const struct requirement *src)
1529{
1530 universal_copy(&(dst->source), &(src->source));
1531 dst->range = src->range;
1532 dst->survives = src->survives;
1533 dst->present = src->present;
1534 dst->quiet = src->quiet;
1535}
1536
1537/**********************************************************************/
1541bool are_requirements_equal(const struct requirement *req1,
1542 const struct requirement *req2)
1543{
1544 return (are_universals_equal(&req1->source, &req2->source)
1545 && req1->range == req2->range
1546 && req1->survives == req2->survives
1547 && req1->present == req2->present);
1548}
1549
1550/**********************************************************************/
1553static bool are_requirements_opposites(const struct requirement *req1,
1554 const struct requirement *req2)
1555{
1556 return (are_universals_equal(&req1->source, &req2->source)
1557 && req1->range == req2->range
1558 && req1->survives == req2->survives
1559 && req1->present != req2->present);
1560}
1561
1562/**********************************************************************/
1566static bool impr_contra_genus(const struct requirement *impr_req,
1567 const struct requirement *genus_req)
1568{
1569 /* The input is sane. */
1571 || impr_req->source.kind == VUT_SITE, FALSE);
1573
1574 if (impr_req->range == REQ_RANGE_LOCAL
1575 && genus_req->range == REQ_RANGE_LOCAL) {
1576 /* Applies to the same target building. */
1577
1578 if (impr_req->present && !genus_req->present) {
1579 /* The target building can't not have the genus it has. */
1580 return (impr_req->source.value.building->genus
1581 == genus_req->source.value.impr_genus);
1582 }
1583
1584 if (impr_req->present && genus_req->present) {
1585 /* The target building can't have another genus than it has. */
1586 return (impr_req->source.value.building->genus
1587 != genus_req->source.value.impr_genus);
1588 }
1589 }
1590
1591 /* No special knowledge. */
1592 return FALSE;
1593}
1594
1595/**********************************************************************/
1599static bool impr_contra_flag(const struct requirement *impr_req,
1600 const struct requirement *flag_req)
1601{
1602 /* The input is sane. */
1604 || impr_req->source.kind == VUT_SITE, FALSE);
1606
1607 if (impr_req->range == REQ_RANGE_LOCAL
1608 && flag_req->range == REQ_RANGE_LOCAL) {
1609 /* Applies to the same target building. */
1610
1611 if (impr_req->present && !flag_req->present) {
1612 /* The target building can't not have the flag it has. */
1613 return improvement_has_flag(impr_req->source.value.building,
1614 flag_req->source.value.impr_flag);
1615 }
1616
1617 if (impr_req->present && flag_req->present) {
1618 /* The target building can't have another flag than it has. */
1619 return !improvement_has_flag(impr_req->source.value.building,
1620 flag_req->source.value.impr_flag);
1621 }
1622 }
1623
1624 /* No special knowledge. */
1625 return FALSE;
1626}
1627
1628/**********************************************************************/
1633 const struct requirement *group_req)
1634{
1635 /* The input is sane. */
1636 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1638
1639 if (nation_req->range == REQ_RANGE_PLAYER
1640 && group_req->range == REQ_RANGE_PLAYER) {
1641 /* Applies to the same target building. */
1642
1643 if (nation_req->present && !group_req->present) {
1644 /* The target nation can't be in the group. */
1645 return nation_is_in_group(nation_req->source.value.nation,
1646 group_req->source.value.nationgroup);
1647 }
1648 }
1649
1650 /* No special knowledge. */
1651 return FALSE;
1652}
1653
1654/**********************************************************************/
1658static bool city_center_contra(const struct requirement *cc_req,
1659 const struct requirement *ct_req)
1660{
1661 /* The input is sane. */
1662 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1663 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1664
1665 if (cc_req->source.value.citytile == CITYT_CENTER
1666 && cc_req->present && cc_req->range <= ct_req->range) {
1667 switch (ct_req->source.value.citytile) {
1668 case CITYT_CENTER:
1669 case CITYT_CLAIMED:
1670 case CITYT_EXTRAS_OWNED:
1671 case CITYT_WORKED:
1673 /* Should be always on city center */
1674 return !ct_req->present;
1676 /* Handled later */
1677 break;
1678 case CITYT_LAST:
1679 /* Error */
1680 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1681 }
1682 }
1683 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1684 || cc_req->source.value.citytile == CITYT_CENTER)
1685 && ct_req->source.value.citytile
1687 && REQ_RANGE_TILE == cc_req->range
1688 && REQ_RANGE_TILE == ct_req->range) {
1689 /* Can't coexist */
1690 return cc_req->present ? ct_req->present : !ct_req->present;
1691 }
1692
1693 return FALSE;
1694}
1695
1696/**********************************************************************/
1701static bool present_implies_not_present(const struct requirement *req1,
1702 const struct requirement *req2)
1703{
1704 const struct requirement *absent, *present;
1705
1706 if (req1->present == req2->present) {
1707 /* Can't use the knowledge in universal_found_function when both are
1708 * required to be absent or when both are required to be present.
1709 * It is no contradiction to require !Spy unit and !Missile unit class.
1710 * It is no contradiction to require River and Irrigation at the same
1711 * tile. */
1712 return FALSE;
1713 }
1714
1715 if (req1->present) {
1716 absent = req2;
1717 present = req1;
1718 } else {
1719 absent = req1;
1720 present = req2;
1721 }
1722
1723 if (!universal_found_function[present->source.kind]) {
1724 /* No knowledge to exploit. */
1725 return FALSE;
1726 }
1727
1728 if (present->range != absent->range) {
1729 /* Larger ranges are not always strict supersets of smaller ranges.
1730 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1731 * but not in Trade Route. */
1732 return FALSE;
1733 }
1734
1736 &present->source);
1737}
1738
1739/**********************************************************************/
1742bool req_implies_req(const struct requirement *req1,
1743 const struct requirement *req2)
1744{
1745 struct requirement nreq2;
1746
1747 req_copy(&nreq2, req2);
1748 nreq2.present = !nreq2.present;
1750}
1751
1752/**********************************************************************/
1757static inline bool are_bounds_contradictions(int bound1, bool is_upper1,
1758 int bound2, bool is_upper2)
1759{
1760 /* If the bounds are on opposite sides, and one is inclusive, the other
1761 * exclusive, the number of values that satisfy both bounds is exactly
1762 * their difference, (upper bound) - (lower bound).
1763 * The bounds contradict each other iff this difference is 0 or less,
1764 * i.e. iff (upper bound) <= (lower bound) */
1765 if (is_upper1 && !is_upper2) {
1766 return bound1 <= bound2;
1767 } else if (!is_upper1 && is_upper2) {
1768 return bound1 >= bound2;
1769 }
1770 /* Both are upper or both are lower ~> no contradiction possible */
1771 return FALSE;
1772}
1773
1774/**********************************************************************/
1782 const struct requirement *req2)
1783{
1784 if (are_requirements_opposites(req1, req2)) {
1785 /* The exact opposite. */
1786 return TRUE;
1787 }
1788
1789 if (present_implies_not_present(req1, req2)) {
1790 return TRUE;
1791 }
1792
1793 switch (req1->source.kind) {
1794 case VUT_IMPROVEMENT:
1795 case VUT_SITE:
1796 if (req2->source.kind == VUT_IMPR_GENUS) {
1797 return impr_contra_genus(req1, req2);
1798 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1799 return impr_contra_flag(req1, req2);
1800 } else if (req2->source.kind == VUT_CITYTILE
1801 && req2->source.value.citytile == CITYT_CENTER
1802 && REQ_RANGE_TILE == req2->range
1803 && REQ_RANGE_TILE == req1->range
1804 && req1->present) {
1805 /* A building must be in a city */
1806 return !req2->present;
1807 }
1808
1809 /* No special knowledge. */
1810 return FALSE;
1811 case VUT_IMPR_GENUS:
1812 if (req2->source.kind == VUT_IMPROVEMENT
1813 || req2->source.kind == VUT_SITE) {
1814 return impr_contra_genus(req2, req1);
1815 }
1816
1817 /* No special knowledge. */
1818 return FALSE;
1819 case VUT_IMPR_FLAG:
1820 if (req2->source.kind == VUT_IMPROVEMENT
1821 || req2->source.kind == VUT_SITE) {
1822 return impr_contra_flag(req2, req1);
1823 }
1824
1825 /* No special knowledge. */
1826 return FALSE;
1827 case VUT_DIPLREL:
1828 case VUT_DIPLREL_TILE:
1829 case VUT_DIPLREL_TILE_O:
1832 if (req2->source.kind != req1->source.kind) {
1833 /* Finding contradictions across requirement kinds aren't supported
1834 * for DiplRel requirements. */
1835 return FALSE;
1836 } else {
1837 /* Use the special knowledge about DiplRel requirements to find
1838 * contradictions. */
1839
1841 int req2_pos;
1842
1845 req2->range,
1846 req2->present);
1847
1848 return BV_ISSET(req1_contra, req2_pos);
1849 }
1850 break;
1851 case VUT_MINMOVES:
1852 if (req2->source.kind != VUT_MINMOVES) {
1853 /* Finding contradictions across requirement kinds aren't supported
1854 * for MinMoveFrags requirements. */
1855 return FALSE;
1856 }
1858 req1->source.value.minmoves, !req1->present,
1859 req2->source.value.minmoves, !req2->present);
1860 case VUT_MINLATITUDE:
1861 case VUT_MAXLATITUDE:
1862 if (req2->source.kind != VUT_MINLATITUDE
1863 && req2->source.kind != VUT_MAXLATITUDE) {
1864 /* Finding contradictions across requirement kinds other than each
1865 * other is not supported for MinLatitude and MaxLatitude. */
1866 return FALSE;
1867 } else {
1868 /* For a contradiction, we need
1869 * - a minimum (present MinLatitude or negated MaxLatitude)
1870 * - a maximum (negated MinLatitude or present MaxLatitude)
1871 * - the maximum to be less than the minimum
1872 * - a requirement at the larger range that applies to the entire
1873 * range (i.e. a negated requirement, unless the range is Tile)
1874 * Otherwise, the two requirements could still be fulfilled
1875 * simultaneously by different tiles in the range */
1876
1877 /* Initial values beyond the boundaries to avoid edge cases */
1878 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
1880
1881#define EXTRACT_INFO(req) \
1882 if (req->present) { \
1883 if (req->source.kind == VUT_MINLATITUDE) { \
1884 /* present MinLatitude */ \
1885 minimum = MAX(minimum, req->source.value.latitude); \
1886 } else { \
1887 /* present MaxLatitude */ \
1888 maximum = MIN(maximum, req->source.value.latitude); \
1889 } \
1890 } else { \
1891 covered_range = MAX(covered_range, req->range); \
1892 if (req->source.kind == VUT_MINLATITUDE) { \
1893 /* negated MinLatitude */ \
1894 maximum = MIN(maximum, req->source.value.latitude - 1); \
1895 } else { \
1896 /* negated MaxLatitude */ \
1897 minimum = MAX(minimum, req->source.value.latitude + 1); \
1898 } \
1899 }
1900
1901 EXTRACT_INFO(req1);
1902 EXTRACT_INFO(req2);
1903
1904#undef EXTRACT_INFO
1905
1906 return (maximum < minimum
1907 && covered_range >= req1->range
1908 && covered_range >= req2->range);
1909 }
1910 break;
1911 case VUT_NATION:
1912 if (req2->source.kind == VUT_NATIONGROUP) {
1913 return nation_contra_group(req1, req2);
1914 }
1915
1916 /* No special knowledge. */
1917 return FALSE;
1918 break;
1919 case VUT_NATIONGROUP:
1920 if (req2->source.kind == VUT_NATION) {
1921 return nation_contra_group(req2, req1);
1922 }
1923
1924 /* No special knowledge. */
1925 return FALSE;
1926 break;
1927 case VUT_CITYTILE:
1928 if (req2->source.kind == VUT_CITYTILE) {
1929 return city_center_contra(req1, req2)
1930 || city_center_contra(req2, req1);
1931 } else if (req1->source.value.citytile == CITYT_CENTER
1932 && (req2->source.kind == VUT_IMPROVEMENT
1933 || req2->source.kind == VUT_SITE)
1934 && REQ_RANGE_TILE == req2->range
1935 && REQ_RANGE_TILE == req1->range
1936 && req2->present) {
1937 /* A building must be in a city */
1938 return !req1->present;
1939 }
1940
1941 return FALSE;
1943 if (req2->source.kind != VUT_MAX_DISTANCE_SQ) {
1944 /* Finding contradictions across requirement kinds isn't supported
1945 * for MaxDistanceSq requirements. */
1946 return FALSE;
1947 }
1949 req1->source.value.distance_sq, req1->present,
1950 req2->source.value.distance_sq, req2->present);
1952 if (req2->source.kind != VUT_MAX_REGION_TILES) {
1953 /* Finding contradictions across requirement kinds isn't supported
1954 * for MaxRegionTiles requirements. */
1955 return FALSE;
1956 } else if (req1->range != req2->range) {
1957 /* FIXME: Finding contradictions across ranges not yet supported.
1958 * In particular, a max at a small range and a min at a larger range
1959 * needs extra work to figure out. */
1960 return FALSE;
1961 }
1963 req1->source.value.region_tiles, req1->present,
1964 req2->source.value.region_tiles, req2->present);
1965 case VUT_TILE_REL:
1966 if (req2->source.kind != VUT_TILE_REL) {
1967 /* Finding contradictions across requirement kinds isn't supported
1968 * for TileRel requirements. */
1969 return FALSE;
1970 }
1971 if (req1->source.value.tilerel == req2->source.value.tilerel) {
1972 /* Same requirement at different ranges. Note that same range is
1973 * already covered by are_requirements_opposites() above. */
1974 switch (req1->source.value.tilerel) {
1975 case TREL_SAME_TCLASS:
1976 case TREL_SAME_REGION:
1978 /* Negated req at larger range contradicts present req at
1979 * smaller range. */
1980 if (req1->range > req2->range) {
1981 return !req1->present && req2->present;
1982 } else {
1983 return req1->present && !req2->present;
1984 }
1985 break;
1987 /* Present req at larger range contradicts negated req at
1988 * smaller range */
1989 if (req1->range > req2->range) {
1990 return req1->present && !req2->present;
1991 } else {
1992 return !req1->present && req2->present;
1993 }
1994 break;
1995 default:
1996 return FALSE;
1997 }
1998 }
2000 && req2->source.value.tilerel == TREL_SAME_REGION) {
2001 /* Same region at any range implies same terrain class at that range
2002 * and any larger range ~> contradicts negated */
2003 return (!req1->present && req2->present
2004 && (req1->range >= req2->range));
2005 } else if (req2->source.value.tilerel == TREL_SAME_TCLASS
2006 && req1->source.value.tilerel == TREL_SAME_REGION) {
2007 /* Same as above */
2008 return (req1->present && !req2->present
2009 && (req1->range <= req2->range));
2010 } else if (req1->source.value.tilerel == TREL_REGION_SURROUNDED
2012 const struct requirement *surr, *other;
2014 surr = req1;
2015 other = req2;
2016 } else {
2017 surr = req2;
2018 other = req1;
2019 }
2020 if (surr->present && surr->range == REQ_RANGE_TILE) {
2021 /* Target tile must be part of a surrounded region
2022 * ~> not the same terrain class
2023 * ~> not the same region
2024 * ~> not touched by a third region */
2025 switch (other->source.value.tilerel) {
2026 case TREL_SAME_TCLASS:
2027 case TREL_SAME_REGION:
2028 return (other->present && other->range == REQ_RANGE_TILE);
2030 return (!other->present);
2031 default:
2032 break;
2033 }
2034 }
2035 }
2036 /* No further contradictions we can detect */
2037 return FALSE;
2038 default:
2039 /* No special knowledge exists. The requirements aren't the exact
2040 * opposite of each other per the initial check. */
2041 return FALSE;
2042 }
2043}
2044
2045/**********************************************************************/
2050 const struct requirement_vector *vec)
2051{
2052 /* If the requirement is contradicted by any requirement in the vector it
2053 * contradicts the entire requirement vector. */
2056 return TRUE;
2057 }
2059
2060 /* Not a singe requirement in the requirement vector is contradicted be
2061 * the specified requirement. */
2062 return FALSE;
2063}
2064
2065/**********************************************************************/
2068static inline bool are_tiles_in_range(const struct tile *tile1,
2069 const struct tile *tile2,
2070 enum req_range range)
2071{
2072 switch (range) {
2073 case REQ_RANGE_ADJACENT:
2075 return TRUE;
2076 }
2078 case REQ_RANGE_TILE:
2079 return same_pos(tile1, tile2);
2081 return map_distance(tile1, tile2) <= 1;
2082 case REQ_RANGE_CITY:
2084 case REQ_RANGE_LOCAL:
2086 case REQ_RANGE_PLAYER:
2087 case REQ_RANGE_TEAM:
2088 case REQ_RANGE_ALLIANCE:
2089 case REQ_RANGE_WORLD:
2090 case REQ_RANGE_COUNT:
2091 /* Invalid */
2093 }
2094 return FALSE;
2095}
2096
2097/**********************************************************************/
2100static inline bool players_in_same_range(const struct player *pplayer1,
2101 const struct player *pplayer2,
2102 enum req_range range)
2103{
2104 switch (range) {
2105 case REQ_RANGE_WORLD:
2106 return TRUE;
2107 case REQ_RANGE_ALLIANCE:
2109 case REQ_RANGE_TEAM:
2111 case REQ_RANGE_PLAYER:
2112 return pplayer1 == pplayer2;
2115 case REQ_RANGE_CITY:
2116 case REQ_RANGE_ADJACENT:
2118 case REQ_RANGE_TILE:
2119 case REQ_RANGE_LOCAL:
2120 case REQ_RANGE_COUNT:
2121 break;
2122 }
2123
2124 fc_assert_msg(FALSE, "Invalid range %d.", range);
2125 return FALSE;
2126}
2127
2128#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
2129{ \
2130 fc_assert_ret_val(req != nullptr, TRI_MAYBE); \
2131 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
2132 fc_assert(context != nullptr); \
2133 fc_assert(other_context != nullptr); \
2134}
2135
2136/**********************************************************************/
2144static enum fc_tristate
2146 const struct req_context *context,
2147 const struct req_context *other_context,
2148 const struct requirement *req)
2149{
2151
2152 return TRI_YES;
2153}
2154
2155/**********************************************************************/
2159static int num_world_buildings_total(const struct impr_type *building)
2160{
2161 if (is_great_wonder(building)) {
2162 return (great_wonder_is_built(building)
2163 || great_wonder_is_destroyed(building) ? 1 : 0);
2164 } else {
2165 log_error("World-ranged requirements are only supported for wonders.");
2166 return 0;
2167 }
2168}
2169
2170/**********************************************************************/
2173static int num_world_buildings(const struct impr_type *building)
2174{
2175 if (is_great_wonder(building)) {
2176 return (great_wonder_is_built(building) ? 1 : 0);
2177 } else {
2178 log_error("World-ranged requirements are only supported for wonders.");
2179 return 0;
2180 }
2181}
2182
2183/**********************************************************************/
2194static bool player_has_ever_built(const struct player *pplayer,
2195 const struct impr_type *building)
2196{
2197 if (is_wonder(building)) {
2198 return (wonder_is_built(pplayer, building)
2199 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2200 } else {
2201 log_error("Player-ranged requirements are only supported for wonders.");
2202 return FALSE;
2203 }
2204}
2205
2206/**********************************************************************/
2209static int num_player_buildings(const struct player *pplayer,
2210 const struct impr_type *building)
2211{
2212 if (is_wonder(building)) {
2213 return (wonder_is_built(pplayer, building) ? 1 : 0);
2214 } else {
2215 log_error("Player-ranged requirements are only supported for wonders.");
2216 return 0;
2217 }
2218}
2219
2220/**********************************************************************/
2223static int num_continent_buildings(const struct player *pplayer,
2224 int continent,
2225 const struct impr_type *building)
2226{
2227 if (is_wonder(building)) {
2228 const struct city *pcity;
2229
2230 pcity = city_from_wonder(pplayer, building);
2231 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2232 return 1;
2233 }
2234 } else {
2235 log_error("Island-ranged requirements are only supported for wonders.");
2236 }
2237 return 0;
2238}
2239
2240/**********************************************************************/
2248static enum fc_tristate
2250 const struct req_context *context,
2251 const struct req_context *other_context,
2252 const struct requirement *req)
2253{
2254 const struct impr_type *building;
2255
2256 /* Can't use this assertion, as both VUT_IMPROVEMENT and VUT_SITE
2257 * are handled here. */
2258 /* IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT); */
2259
2260 building = req->source.value.building;
2261
2262 /* Check if it's certain that the building is obsolete given the
2263 * specification we have */
2264 if (req->source.kind == VUT_IMPROVEMENT
2265 && improvement_obsolete(context->player, building, context->city)) {
2266 return TRI_NO;
2267 }
2268
2269 if (req->survives) {
2270
2271 /* Check whether condition has ever held, using cached information. */
2272 switch (req->range) {
2273 case REQ_RANGE_WORLD:
2274 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2275 case REQ_RANGE_ALLIANCE:
2276 case REQ_RANGE_TEAM:
2277 if (context->player == nullptr) {
2278 return TRI_MAYBE;
2279 }
2280 players_iterate_alive(plr2) {
2281 if (players_in_same_range(context->player, plr2, req->range)
2282 && player_has_ever_built(plr2, building)) {
2283 return TRI_YES;
2284 }
2286 return TRI_NO;
2287 case REQ_RANGE_PLAYER:
2288 if (context->player == nullptr) {
2289 return TRI_MAYBE;
2290 }
2292 building));
2295 case REQ_RANGE_CITY:
2296 case REQ_RANGE_LOCAL:
2297 case REQ_RANGE_TILE:
2299 case REQ_RANGE_ADJACENT:
2300 /* There is no sources cache for this. */
2301 log_error("Surviving requirements are only supported at "
2302 "World/Alliance/Team/Player ranges.");
2303 return TRI_NO;
2304 case REQ_RANGE_COUNT:
2305 break;
2306 }
2307
2308 } else {
2309
2310 /* Non-surviving requirement. */
2311 switch (req->range) {
2312 case REQ_RANGE_WORLD:
2313 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2314 case REQ_RANGE_ALLIANCE:
2315 case REQ_RANGE_TEAM:
2316 if (context->player == nullptr) {
2317 return TRI_MAYBE;
2318 }
2319 players_iterate_alive(plr2) {
2320 if (players_in_same_range(context->player, plr2, req->range)
2321 && num_player_buildings(plr2, building) > 0) {
2322 return TRI_YES;
2323 }
2325 return TRI_NO;
2326 case REQ_RANGE_PLAYER:
2327 if (context->player == nullptr) {
2328 return TRI_MAYBE;
2329 }
2331 building)
2332 > 0);
2334 /* At present, "Continent" effects can affect only
2335 * cities and units in cities. */
2336 if (context->player && context->city) {
2337 int continent = tile_continent(context->city->tile);
2339 continent, building)
2340 > 0);
2341 } else {
2342 return TRI_MAYBE;
2343 }
2345 if (context->city) {
2346 if (city_has_building(context->city, building)) {
2347 return TRI_YES;
2348 } else {
2349 enum fc_tristate ret = TRI_NO;
2350
2352 if (trade_partner == nullptr) {
2353 ret = TRI_MAYBE;
2354 } else if (city_has_building(trade_partner, building)) {
2355 return TRI_YES;
2356 }
2358
2359 return ret;
2360 }
2361 } else {
2362 return TRI_MAYBE;
2363 }
2364 case REQ_RANGE_CITY:
2365 if (context->city) {
2366 return BOOL_TO_TRISTATE(city_has_building(context->city, building));
2367 } else {
2368 return TRI_MAYBE;
2369 }
2370 case REQ_RANGE_LOCAL:
2371 if (context->building) {
2372 if (context->building == building) {
2373 return TRI_YES;
2374 } else {
2375 return TRI_NO;
2376 }
2377 } else {
2378 /* TODO: Other local targets */
2379 return TRI_MAYBE;
2380 }
2381 case REQ_RANGE_TILE:
2382 if (context->tile) {
2383 const struct city *pcity = tile_city(context->tile);
2384
2385 if (pcity) {
2386 return BOOL_TO_TRISTATE(city_has_building(pcity, building));
2387 } else {
2388 return TRI_NO;
2389 }
2390 } else {
2391 return TRI_MAYBE;
2392 }
2394 case REQ_RANGE_ADJACENT:
2395 case REQ_RANGE_COUNT:
2396 break;
2397 }
2398
2399 }
2400
2401 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2402 return TRI_NO;
2403}
2404
2405/**********************************************************************/
2413static enum fc_tristate
2415 const struct req_context *context,
2416 const struct req_context *other_context,
2417 const struct requirement *req)
2418{
2420
2421 return (context->building ? BOOL_TO_TRISTATE(
2422 context->building->genus
2423 == req->source.value.impr_genus)
2424 : TRI_MAYBE);
2425}
2426
2427/**********************************************************************/
2431 enum impr_flag_id flag)
2432{
2433 struct player *owner;
2434
2435 if (pcity == nullptr) {
2436 return TRI_MAYBE;
2437 }
2438
2440 city_built_iterate(pcity, impr) {
2441 if (improvement_has_flag(impr, flag)
2442 && !improvement_obsolete(owner, impr, pcity)) {
2443 return TRI_YES;
2444 }
2446
2447 return TRI_NO;
2448}
2449
2450/**********************************************************************/
2458static enum fc_tristate
2460 const struct req_context *context,
2461 const struct req_context *other_context,
2462 const struct requirement *req)
2463{
2465
2466 switch (req->range) {
2467 case REQ_RANGE_LOCAL:
2468 return (context->building
2470 req->source.value.impr_flag))
2471 : TRI_MAYBE);
2472 case REQ_RANGE_CITY:
2474 case REQ_RANGE_TILE:
2475 if (context->tile == nullptr) {
2476 return TRI_MAYBE;
2477 }
2479 req->source.value.impr_flag);
2481 case REQ_RANGE_ADJACENT:
2484 case REQ_RANGE_PLAYER:
2485 case REQ_RANGE_ALLIANCE:
2486 case REQ_RANGE_TEAM:
2487 case REQ_RANGE_WORLD:
2488 case REQ_RANGE_COUNT:
2489 break;
2490 }
2491
2492 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2493
2494 return TRI_MAYBE;
2495}
2496
2497/**********************************************************************/
2505static enum fc_tristate
2507 const struct req_context *context,
2508 const struct req_context *other_context,
2509 const struct requirement *req)
2510{
2512
2513 switch (req->range) {
2514 case REQ_RANGE_PLAYER:
2515 return (context->player != nullptr
2517 req->source.value.plr_flag))
2518 : TRI_MAYBE);
2519 case REQ_RANGE_LOCAL:
2520 case REQ_RANGE_CITY:
2521 case REQ_RANGE_TILE:
2523 case REQ_RANGE_ADJACENT:
2526 case REQ_RANGE_ALLIANCE:
2527 case REQ_RANGE_TEAM:
2528 case REQ_RANGE_WORLD:
2529 case REQ_RANGE_COUNT:
2530 break;
2531 }
2532
2533 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2534
2535 return TRI_MAYBE;
2536}
2537
2538/**********************************************************************/
2546static enum fc_tristate
2548 const struct req_context *context,
2549 const struct req_context *other_context,
2550 const struct requirement *req)
2551{
2553
2554 switch (req->range) {
2555 case REQ_RANGE_PLAYER:
2556 return (context->player != nullptr
2558 req->source.value.plrstate))
2559 : TRI_MAYBE);
2560 case REQ_RANGE_LOCAL:
2561 case REQ_RANGE_CITY:
2562 case REQ_RANGE_TILE:
2564 case REQ_RANGE_ADJACENT:
2567 case REQ_RANGE_ALLIANCE:
2568 case REQ_RANGE_TEAM:
2569 case REQ_RANGE_WORLD:
2570 case REQ_RANGE_COUNT:
2571 break;
2572 }
2573
2574 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2575
2576 return TRI_MAYBE;
2577}
2578
2579/**********************************************************************/
2587static enum fc_tristate
2589 const struct req_context *context,
2590 const struct req_context *other_context,
2591 const struct requirement *req)
2592{
2593 Tech_type_id tech;
2594
2596
2597 tech = advance_number(req->source.value.advance);
2598
2599 if (req->survives) {
2602 }
2603
2604 /* Not a 'surviving' requirement. */
2605 switch (req->range) {
2606 case REQ_RANGE_PLAYER:
2607 if (context->player != nullptr) {
2609 (research_get(context->player), tech));
2610 } else {
2611 return TRI_MAYBE;
2612 }
2613 case REQ_RANGE_TEAM:
2614 case REQ_RANGE_ALLIANCE:
2615 case REQ_RANGE_WORLD:
2616 if (context->player == nullptr) {
2617 return TRI_MAYBE;
2618 }
2619 players_iterate_alive(plr2) {
2620 if (players_in_same_range(context->player, plr2, req->range)) {
2621 if (research_invention_state(research_get(plr2), tech)
2622 == TECH_KNOWN) {
2623 return TRI_YES;
2624 }
2625 }
2627
2628 return TRI_NO;
2629 case REQ_RANGE_LOCAL:
2630 if (context->player == nullptr) {
2631 return TRI_MAYBE;
2632 }
2633 if (research_get(context->player)->researching == tech) {
2634 return TRI_YES;
2635 }
2636 return TRI_NO;
2637 case REQ_RANGE_TILE:
2639 case REQ_RANGE_ADJACENT:
2640 case REQ_RANGE_CITY:
2643 case REQ_RANGE_COUNT:
2644 break;
2645 }
2646
2647 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2648
2649 return TRI_MAYBE;
2650}
2651
2652/**********************************************************************/
2660static enum fc_tristate
2662 const struct req_context *context,
2663 const struct req_context *other_context,
2664 const struct requirement *req)
2665{
2666 enum tech_flag_id techflag;
2667
2669
2670 techflag = req->source.value.techflag;
2671
2672 switch (req->range) {
2673 case REQ_RANGE_PLAYER:
2674 if (context->player != nullptr) {
2676 techflag));
2677 } else {
2678 return TRI_MAYBE;
2679 }
2680 break;
2681 case REQ_RANGE_TEAM:
2682 case REQ_RANGE_ALLIANCE:
2683 if (context->player == nullptr) {
2684 return TRI_MAYBE;
2685 }
2686 players_iterate_alive(plr2) {
2687 if (players_in_same_range(context->player, plr2, req->range)
2688 && player_knows_techs_with_flag(plr2, techflag)) {
2689 return TRI_YES;
2690 }
2692 return TRI_NO;
2693 case REQ_RANGE_WORLD:
2694 players_iterate(pplayer) {
2695 if (player_knows_techs_with_flag(pplayer, techflag)) {
2696 return TRI_YES;
2697 }
2699
2700 return TRI_NO;
2701 case REQ_RANGE_LOCAL:
2702 if (context->player == nullptr) {
2703 return TRI_MAYBE;
2704 }
2705 if (advance_has_flag(research_get(context->player)->researching, techflag)) {
2706 return TRI_YES;
2707 }
2708 return TRI_NO;
2709 case REQ_RANGE_TILE:
2711 case REQ_RANGE_ADJACENT:
2712 case REQ_RANGE_CITY:
2715 case REQ_RANGE_COUNT:
2716 break;
2717 }
2718
2719 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2720
2721 return TRI_MAYBE;
2722}
2723
2724/**********************************************************************/
2732static enum fc_tristate
2734 const struct req_context *context,
2735 const struct req_context *other_context,
2736 const struct requirement *req)
2737{
2738 int minculture;
2739
2741
2742 minculture = req->source.value.minculture;
2743
2744 switch (req->range) {
2745 case REQ_RANGE_CITY:
2746 if (!context->city) {
2747 return TRI_MAYBE;
2748 }
2749 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2751 if (!context->city) {
2752 return TRI_MAYBE;
2753 }
2754 if (city_culture(context->city) >= minculture) {
2755 return TRI_YES;
2756 } else {
2757 enum fc_tristate ret = TRI_NO;
2758
2760 if (trade_partner == nullptr) {
2761 ret = TRI_MAYBE;
2762 } else if (city_culture(trade_partner) >= minculture) {
2763 return TRI_YES;
2764 }
2766
2767 return ret;
2768 }
2769 case REQ_RANGE_PLAYER:
2770 case REQ_RANGE_TEAM:
2771 case REQ_RANGE_ALLIANCE:
2772 case REQ_RANGE_WORLD:
2773 if (context->player == nullptr) {
2774 return TRI_MAYBE;
2775 }
2776 players_iterate_alive(plr2) {
2777 if (players_in_same_range(context->player, plr2, req->range)) {
2778 if (player_culture(plr2) >= minculture) {
2779 return TRI_YES;
2780 }
2781 }
2783 return TRI_NO;
2784 case REQ_RANGE_LOCAL:
2785 case REQ_RANGE_TILE:
2787 case REQ_RANGE_ADJACENT:
2789 case REQ_RANGE_COUNT:
2790 break;
2791 }
2792
2793 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2794
2795 return TRI_MAYBE;
2796}
2797
2798/**********************************************************************/
2806static enum fc_tristate
2808 const struct req_context *context,
2809 const struct req_context *other_context,
2810 const struct requirement *req)
2811{
2813
2815
2817
2818 switch (req->range) {
2819 case REQ_RANGE_CITY:
2820 if (!context->city) {
2821 return TRI_MAYBE;
2822 }
2824 / city_size_get(context->city);
2827 if (!context->city) {
2828 return TRI_MAYBE;
2829 }
2831 / city_size_get(context->city);
2833 return TRI_YES;
2834 } else {
2835 enum fc_tristate ret = TRI_NO;
2836
2838 if (trade_partner == nullptr) {
2839 ret = TRI_MAYBE;
2840 } else {
2844 return TRI_YES;
2845 }
2846 }
2848
2849 return ret;
2850 }
2851 case REQ_RANGE_PLAYER:
2852 case REQ_RANGE_TEAM:
2853 case REQ_RANGE_ALLIANCE:
2854 case REQ_RANGE_WORLD:
2855 case REQ_RANGE_LOCAL:
2856 case REQ_RANGE_TILE:
2858 case REQ_RANGE_ADJACENT:
2860 case REQ_RANGE_COUNT:
2861 break;
2862 }
2863
2864 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2865
2866 return TRI_MAYBE;
2867}
2868
2869/**********************************************************************/
2877static enum fc_tristate
2879 const struct req_context *context,
2880 const struct req_context *other_context,
2881 const struct requirement *req)
2882{
2883 int max_units;
2884
2886
2888
2889 /* TODO: If can't see V_INVIS -> TRI_MAYBE */
2890 switch (req->range) {
2891 case REQ_RANGE_TILE:
2892 if (!context->tile) {
2893 return TRI_MAYBE;
2894 }
2895 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
2897 if (!context->tile) {
2898 return TRI_MAYBE;
2899 }
2900 if (unit_list_size(context->tile->units) <= max_units) {
2901 return TRI_YES;
2902 }
2904 if (unit_list_size(adjc_tile->units) <= max_units) {
2905 return TRI_YES;
2906 }
2908 return TRI_NO;
2909 case REQ_RANGE_ADJACENT:
2910 if (!context->tile) {
2911 return TRI_MAYBE;
2912 }
2913 if (unit_list_size(context->tile->units) <= max_units) {
2914 return TRI_YES;
2915 }
2917 if (unit_list_size(adjc_tile->units) <= max_units) {
2918 return TRI_YES;
2919 }
2921 return TRI_NO;
2922 case REQ_RANGE_CITY:
2925 case REQ_RANGE_PLAYER:
2926 case REQ_RANGE_TEAM:
2927 case REQ_RANGE_ALLIANCE:
2928 case REQ_RANGE_WORLD:
2929 case REQ_RANGE_LOCAL:
2930 case REQ_RANGE_COUNT:
2931 break;
2932 }
2933
2934 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2935
2936 return TRI_MAYBE;
2937}
2938
2939/**********************************************************************/
2947static enum fc_tristate
2949 const struct req_context *context,
2950 const struct req_context *other_context,
2951 const struct requirement *req)
2952{
2953 const struct extra_type *pextra;
2954 enum fc_tristate ret;
2955
2957
2958 pextra = req->source.value.extra;
2959
2960 switch (req->range) {
2961 case REQ_RANGE_LOCAL:
2962 if (!context->extra) {
2963 return TRI_MAYBE;
2964 }
2965 return BOOL_TO_TRISTATE(context->extra == pextra);
2966 case REQ_RANGE_TILE:
2967 /* The requirement is filled if the tile has extra of requested type. */
2968 if (!context->tile) {
2969 return TRI_MAYBE;
2970 }
2971 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
2973 if (!context->tile) {
2974 return TRI_MAYBE;
2975 }
2976 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2977 || is_extra_card_near(nmap, context->tile, pextra));
2978 case REQ_RANGE_ADJACENT:
2979 if (!context->tile) {
2980 return TRI_MAYBE;
2981 }
2982 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2983 || is_extra_near_tile(nmap, context->tile, pextra));
2984 case REQ_RANGE_CITY:
2985 if (!context->city) {
2986 return TRI_MAYBE;
2987 }
2989 city_tile(context->city), ptile) {
2990 if (tile_has_extra(ptile, pextra)) {
2991 return TRI_YES;
2992 }
2994
2995 return TRI_NO;
2996
2998 if (!context->city) {
2999 return TRI_MAYBE;
3000 }
3002 city_tile(context->city), ptile) {
3003 if (tile_has_extra(ptile, pextra)) {
3004 return TRI_YES;
3005 }
3007
3008 ret = TRI_NO;
3010 if (trade_partner == nullptr) {
3011 ret = TRI_MAYBE;
3012 } else {
3014 city_tile(trade_partner), ptile) {
3015 if (tile_has_extra(ptile, pextra)) {
3016 return TRI_YES;
3017 }
3019 }
3021
3022 return ret;
3023
3025 case REQ_RANGE_PLAYER:
3026 case REQ_RANGE_TEAM:
3027 case REQ_RANGE_ALLIANCE:
3028 case REQ_RANGE_WORLD:
3029 case REQ_RANGE_COUNT:
3030 break;
3031 }
3032
3033 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3034
3035 return TRI_MAYBE;
3036}
3037
3038/**********************************************************************/
3046static enum fc_tristate
3048 const struct req_context *context,
3049 const struct req_context *other_context,
3050 const struct requirement *req)
3051{
3052 const struct goods_type *pgood;
3053
3055
3056 pgood = req->source.value.good;
3057
3058 switch (req->range) {
3059 case REQ_RANGE_LOCAL:
3060 case REQ_RANGE_CITY:
3061 /* The requirement is filled if the city imports good of requested type. */
3062 if (!context->city) {
3063 return TRI_MAYBE;
3064 }
3068 nullptr)));
3069 case REQ_RANGE_TILE:
3071 case REQ_RANGE_ADJACENT:
3074 case REQ_RANGE_PLAYER:
3075 case REQ_RANGE_TEAM:
3076 case REQ_RANGE_ALLIANCE:
3077 case REQ_RANGE_WORLD:
3078 case REQ_RANGE_COUNT:
3079 break;
3080 }
3081
3082 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3083
3084 return TRI_MAYBE;
3085}
3086
3087/**********************************************************************/
3095static enum fc_tristate
3097 const struct req_context *context,
3098 const struct req_context *other_context,
3099 const struct requirement *req)
3100{
3102
3103 if (context->action) {
3104 return BOOL_TO_TRISTATE(action_number(context->action)
3105 == action_number(req->source.value.action));
3106 }
3107
3108 if (context->unit != nullptr && context->unit->action != ACTION_NONE) {
3109 log_normal("Unit action %s", action_id_rule_name(context->unit->action));
3110 return BOOL_TO_TRISTATE(context->unit->action
3111 == action_number(req->source.value.action));
3112 }
3113
3114 return TRI_NO;
3115}
3116
3117/**********************************************************************/
3125static enum fc_tristate
3127 const struct req_context *context,
3128 const struct req_context *other_context,
3129 const struct requirement *req)
3130{
3132
3133 return BOOL_TO_TRISTATE(context->output
3134 && context->output->index
3135 == req->source.value.outputtype);
3136}
3137
3138/**********************************************************************/
3146static enum fc_tristate
3148 const struct req_context *context,
3149 const struct req_context *other_context,
3150 const struct requirement *req)
3151{
3153
3154 return BOOL_TO_TRISTATE(context->specialist
3155 && context->specialist
3156 == req->source.value.specialist);
3157}
3158
3159/**********************************************************************/
3167static enum fc_tristate
3169 const struct req_context *context,
3170 const struct req_context *other_context,
3171 const struct requirement *req)
3172{
3173 const struct terrain *pterrain;
3174
3176
3177 pterrain = req->source.value.terrain;
3178
3179 switch (req->range) {
3180 case REQ_RANGE_TILE:
3181 /* The requirement is filled if the tile has the terrain. */
3182 if (!context->tile) {
3183 return TRI_MAYBE;
3184 }
3185 return pterrain && tile_terrain(context->tile) == pterrain;
3187 if (!context->tile) {
3188 return TRI_MAYBE;
3189 }
3190 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
3191 case REQ_RANGE_ADJACENT:
3192 if (!context->tile) {
3193 return TRI_MAYBE;
3194 }
3195 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
3196 case REQ_RANGE_CITY:
3197 if (!context->city) {
3198 return TRI_MAYBE;
3199 }
3200 if (pterrain != nullptr) {
3202 city_tile(context->city), ptile) {
3203 if (tile_terrain(ptile) == pterrain) {
3204 return TRI_YES;
3205 }
3207 }
3208 return TRI_NO;
3210 if (!context->city) {
3211 return TRI_MAYBE;
3212 }
3213 if (pterrain != nullptr) {
3214 enum fc_tristate ret;
3215
3217 city_tile(context->city), ptile) {
3218 if (tile_terrain(ptile) == pterrain) {
3219 return TRI_YES;
3220 }
3222
3223 ret = TRI_NO;
3225 if (trade_partner == nullptr) {
3226 ret = TRI_MAYBE;
3227 } else {
3229 city_tile(trade_partner), ptile) {
3230 if (tile_terrain(ptile) == pterrain) {
3231 return TRI_YES;
3232 }
3234 }
3236
3237 return ret;
3238 }
3239
3240 return TRI_MAYBE;
3242 case REQ_RANGE_PLAYER:
3243 case REQ_RANGE_TEAM:
3244 case REQ_RANGE_ALLIANCE:
3245 case REQ_RANGE_WORLD:
3246 case REQ_RANGE_LOCAL:
3247 case REQ_RANGE_COUNT:
3248 break;
3249 }
3250
3251 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3252
3253 return TRI_MAYBE;
3254}
3255
3256/**********************************************************************/
3264static enum fc_tristate
3266 const struct req_context *context,
3267 const struct req_context *other_context,
3268 const struct requirement *req)
3269{
3270 enum terrain_class pclass;
3271 enum fc_tristate ret;
3272
3274
3276
3277 switch (req->range) {
3278 case REQ_RANGE_TILE:
3279 /* The requirement is filled if the tile has the terrain of correct class. */
3280 if (!context->tile) {
3281 return TRI_MAYBE;
3282 }
3285 if (!context->tile) {
3286 return TRI_MAYBE;
3287 }
3290 case REQ_RANGE_ADJACENT:
3291 if (!context->tile) {
3292 return TRI_MAYBE;
3293 }
3296 case REQ_RANGE_CITY:
3297 if (!context->city) {
3298 return TRI_MAYBE;
3299 }
3301 city_tile(context->city), ptile) {
3302 const struct terrain *pterrain = tile_terrain(ptile);
3303
3304 if (pterrain != T_UNKNOWN
3305 && terrain_type_terrain_class(pterrain) == pclass) {
3306 return TRI_YES;
3307 }
3309
3310 return TRI_NO;
3312 if (!context->city) {
3313 return TRI_MAYBE;
3314 }
3316 city_tile(context->city), ptile) {
3317 const struct terrain *pterrain = tile_terrain(ptile);
3318
3319 if (pterrain != T_UNKNOWN
3320 && terrain_type_terrain_class(pterrain) == pclass) {
3321 return TRI_YES;
3322 }
3324
3325 ret = TRI_NO;
3327 if (trade_partner == nullptr) {
3328 ret = TRI_MAYBE;
3329 } else {
3331 city_tile(trade_partner), ptile) {
3332 const struct terrain *pterrain = tile_terrain(ptile);
3333
3334 if (pterrain != T_UNKNOWN
3335 && terrain_type_terrain_class(pterrain) == pclass) {
3336 return TRI_YES;
3337 }
3339 }
3341
3342 return ret;
3344 case REQ_RANGE_PLAYER:
3345 case REQ_RANGE_TEAM:
3346 case REQ_RANGE_ALLIANCE:
3347 case REQ_RANGE_WORLD:
3348 case REQ_RANGE_LOCAL:
3349 case REQ_RANGE_COUNT:
3350 break;
3351 }
3352
3353 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3354
3355 return TRI_MAYBE;
3356}
3357
3358/**********************************************************************/
3366static enum fc_tristate
3368 const struct req_context *context,
3369 const struct req_context *other_context,
3370 const struct requirement *req)
3371{
3373 enum fc_tristate ret;
3374
3376
3378
3379 switch (req->range) {
3380 case REQ_RANGE_TILE:
3381 /* The requirement is fulfilled if the tile has a terrain with
3382 * correct flag. */
3383 if (!context->tile) {
3384 return TRI_MAYBE;
3385 }
3387 terrflag));
3389 if (!context->tile) {
3390 return TRI_MAYBE;
3391 }
3393 terrflag)
3395 terrflag));
3396 case REQ_RANGE_ADJACENT:
3397 if (!context->tile) {
3398 return TRI_MAYBE;
3399 }
3401 terrflag)
3403 terrflag));
3404 case REQ_RANGE_CITY:
3405 if (!context->city) {
3406 return TRI_MAYBE;
3407 }
3409 city_tile(context->city), ptile) {
3410 const struct terrain *pterrain = tile_terrain(ptile);
3411
3412 if (pterrain != T_UNKNOWN
3413 && terrain_has_flag(pterrain, terrflag)) {
3414 return TRI_YES;
3415 }
3417
3418 return TRI_NO;
3420 if (!context->city) {
3421 return TRI_MAYBE;
3422 }
3424 city_tile(context->city), ptile) {
3425 const struct terrain *pterrain = tile_terrain(ptile);
3426
3427 if (pterrain != T_UNKNOWN
3428 && terrain_has_flag(pterrain, terrflag)) {
3429 return TRI_YES;
3430 }
3432
3433 ret = TRI_NO;
3435 if (trade_partner == nullptr) {
3436 ret = TRI_MAYBE;
3437 } else {
3439 city_tile(trade_partner), ptile) {
3440 const struct terrain *pterrain = tile_terrain(ptile);
3441
3442 if (pterrain != T_UNKNOWN
3443 && terrain_has_flag(pterrain, terrflag)) {
3444 return TRI_YES;
3445 }
3447 }
3449
3450 return ret;
3452 case REQ_RANGE_PLAYER:
3453 case REQ_RANGE_TEAM:
3454 case REQ_RANGE_ALLIANCE:
3455 case REQ_RANGE_WORLD:
3456 case REQ_RANGE_LOCAL:
3457 case REQ_RANGE_COUNT:
3458 break;
3459 }
3460
3461 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3462
3463 return TRI_MAYBE;
3464}
3465
3466/**********************************************************************/
3474static enum fc_tristate
3476 const struct req_context *context,
3477 const struct req_context *other_context,
3478 const struct requirement *req)
3479{
3480 enum road_flag_id roadflag;
3481 enum fc_tristate ret;
3482
3484
3485 roadflag = req->source.value.roadflag;
3486
3487 switch (req->range) {
3488 case REQ_RANGE_LOCAL:
3489 {
3490 if (!context->extra) {
3491 return TRI_MAYBE;
3492 }
3493 struct road_type *r = extra_road_get(context->extra);
3494
3495 return BOOL_TO_TRISTATE(
3496 r && road_has_flag(r, roadflag)
3497 );
3498 }
3499 case REQ_RANGE_TILE:
3500 /* The requirement is filled if the tile has a road with correct flag. */
3501 if (!context->tile) {
3502 return TRI_MAYBE;
3503 }
3504 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3506 if (!context->tile) {
3507 return TRI_MAYBE;
3508 }
3509 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3511 roadflag));
3512 case REQ_RANGE_ADJACENT:
3513 if (!context->tile) {
3514 return TRI_MAYBE;
3515 }
3516 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3518 roadflag));
3519 case REQ_RANGE_CITY:
3520 if (!context->city) {
3521 return TRI_MAYBE;
3522 }
3524 city_tile(context->city), ptile) {
3525 if (tile_has_road_flag(ptile, roadflag)) {
3526 return TRI_YES;
3527 }
3529
3530 return TRI_NO;
3532 if (!context->city) {
3533 return TRI_MAYBE;
3534 }
3536 city_tile(context->city), ptile) {
3537 if (tile_has_road_flag(ptile, roadflag)) {
3538 return TRI_YES;
3539 }
3541
3542 ret = TRI_NO;
3544 if (trade_partner == nullptr) {
3545 ret = TRI_MAYBE;
3546 } else {
3548 city_tile(trade_partner), ptile) {
3549 if (tile_has_road_flag(ptile, roadflag)) {
3550 return TRI_YES;
3551 }
3553 }
3555
3556 return ret;
3558 case REQ_RANGE_PLAYER:
3559 case REQ_RANGE_TEAM:
3560 case REQ_RANGE_ALLIANCE:
3561 case REQ_RANGE_WORLD:
3562 case REQ_RANGE_COUNT:
3563 break;
3564 }
3565
3566 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3567
3568 return TRI_MAYBE;
3569}
3570
3571/**********************************************************************/
3579static enum fc_tristate
3581 const struct req_context *context,
3582 const struct req_context *other_context,
3583 const struct requirement *req)
3584{
3585 enum extra_flag_id extraflag;
3586 enum fc_tristate ret;
3587
3589
3590 extraflag = req->source.value.extraflag;
3591
3592 switch (req->range) {
3593 case REQ_RANGE_LOCAL:
3594 if (!context->extra) {
3595 return TRI_MAYBE;
3596 }
3597 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3598 case REQ_RANGE_TILE:
3599 /* The requirement is filled if the tile has an extra with correct flag. */
3600 if (!context->tile) {
3601 return TRI_MAYBE;
3602 }
3603 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3605 if (!context->tile) {
3606 return TRI_MAYBE;
3607 }
3608 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3609 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3610 case REQ_RANGE_ADJACENT:
3611 if (!context->tile) {
3612 return TRI_MAYBE;
3613 }
3614 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3615 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3616 case REQ_RANGE_CITY:
3617 if (!context->city) {
3618 return TRI_MAYBE;
3619 }
3621 city_tile(context->city), ptile) {
3622 if (tile_has_extra_flag(ptile, extraflag)) {
3623 return TRI_YES;
3624 }
3626
3627 return TRI_NO;
3629 if (!context->city) {
3630 return TRI_MAYBE;
3631 }
3633 city_tile(context->city), ptile) {
3634 if (tile_has_extra_flag(ptile, extraflag)) {
3635 return TRI_YES;
3636 }
3638
3639 ret = TRI_NO;
3641 if (trade_partner == nullptr) {
3642 ret = TRI_MAYBE;
3643 } else {
3645 city_tile(trade_partner), ptile) {
3646 if (tile_has_extra_flag(ptile, extraflag)) {
3647 return TRI_YES;
3648 }
3650 }
3652
3653 return ret;
3655 case REQ_RANGE_PLAYER:
3656 case REQ_RANGE_TEAM:
3657 case REQ_RANGE_ALLIANCE:
3658 case REQ_RANGE_WORLD:
3659 case REQ_RANGE_COUNT:
3660 break;
3661 }
3662
3663 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3664
3665 return TRI_MAYBE;
3666}
3667
3668/**********************************************************************/
3676static enum fc_tristate
3678 const struct req_context *context,
3679 const struct req_context *other_context,
3680 const struct requirement *req)
3681{
3683
3685
3687
3688 if (!context->tile) {
3689 return TRI_MAYBE;
3690 }
3691
3692 switch (req->range) {
3693 case REQ_RANGE_TILE:
3697 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
3698 case REQ_RANGE_CITY:
3701 case REQ_RANGE_PLAYER:
3702 case REQ_RANGE_TEAM:
3703 case REQ_RANGE_ALLIANCE:
3704 case REQ_RANGE_WORLD:
3705 case REQ_RANGE_LOCAL:
3706 case REQ_RANGE_COUNT:
3707 break;
3708 }
3709
3710 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3711
3712 return TRI_MAYBE;
3713}
3714
3715/**********************************************************************/
3723static enum fc_tristate
3725 const struct req_context *context,
3726 const struct req_context *other_context,
3727 const struct requirement *req)
3728{
3730
3731 if (context->player == nullptr) {
3732 return TRI_MAYBE;
3733 } else {
3735 == req->source.value.govern);
3736 }
3737}
3738
3739/**********************************************************************/
3747static enum fc_tristate
3749 const struct req_context *context,
3750 const struct req_context *other_context,
3751 const struct requirement *req)
3752{
3754
3755 if (context->player == nullptr) {
3756 return TRI_MAYBE;
3757 } else {
3758 return BOOL_TO_TRISTATE(context->player->style
3759 == req->source.value.style);
3760 }
3761}
3762
3763/**********************************************************************/
3771static enum fc_tristate
3773 const struct req_context *context,
3774 const struct req_context *other_context,
3775 const struct requirement *req)
3776{
3778
3779 switch (req->range) {
3780 case REQ_RANGE_WORLD:
3781 /* "None" does not count */
3782 return ((game.info.global_advance_count - 1)
3783 >= req->source.value.min_techs);
3784 case REQ_RANGE_PLAYER:
3785 if (context->player == nullptr) {
3786 return TRI_MAYBE;
3787 } else {
3788 /* "None" does not count */
3789 return BOOL_TO_TRISTATE(
3790 (research_get(context->player)->techs_researched - 1)
3791 >= req->source.value.min_techs
3792 );
3793 }
3794 default:
3795 return TRI_MAYBE;
3796 }
3797}
3798
3799/**********************************************************************/
3807static enum fc_tristate
3809 const struct req_context *context,
3810 const struct req_context *other_context,
3811 const struct requirement *req)
3812{
3814
3815 switch (req->range) {
3816 case REQ_RANGE_PLAYER:
3817 if (context->player == nullptr) {
3818 return TRI_MAYBE;
3819 } else {
3820 /* "None" does not count */
3821 return BOOL_TO_TRISTATE(
3822 city_list_size(context->player->cities)
3823 >= req->source.value.min_cities
3824 );
3825 }
3826 default:
3827 return TRI_MAYBE;
3828 }
3829}
3830
3831/**********************************************************************/
3839static enum fc_tristate
3841 const struct req_context *context,
3842 const struct req_context *other_context,
3843 const struct requirement *req)
3844{
3846
3847 if (context->player == nullptr) {
3848 return TRI_MAYBE;
3849 } else {
3850 return BOOL_TO_TRISTATE(is_ai(context->player)
3851 && context->player->ai_common.skill_level
3852 == req->source.value.ai_level);
3853 }
3854}
3855
3856/**********************************************************************/
3864static enum fc_tristate
3866 const struct req_context *context,
3867 const struct req_context *other_context,
3868 const struct requirement *req)
3869{
3870 const struct nation_type *nation;
3871
3873
3874 nation = req->source.value.nation;
3875
3876 switch (req->range) {
3877 case REQ_RANGE_PLAYER:
3878 if (context->player == nullptr) {
3879 return TRI_MAYBE;
3880 }
3881 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
3882 case REQ_RANGE_TEAM:
3883 case REQ_RANGE_ALLIANCE:
3884 if (context->player == nullptr) {
3885 return TRI_MAYBE;
3886 }
3887 players_iterate_alive(plr2) {
3888 if (players_in_same_range(context->player, plr2, req->range)) {
3889 if (nation_of_player(plr2) == nation) {
3890 return TRI_YES;
3891 }
3892 }
3894 return TRI_NO;
3895 case REQ_RANGE_WORLD:
3896 /* NB: if a player is ever removed outright from the game
3897 * (e.g. via /remove), rather than just dying, this 'survives'
3898 * requirement will stop being true for their nation.
3899 * create_command_newcomer() can also cause this to happen. */
3900 return BOOL_TO_TRISTATE(nation->player != nullptr
3901 && (req->survives || nation->player->is_alive));
3902 case REQ_RANGE_LOCAL:
3903 case REQ_RANGE_TILE:
3905 case REQ_RANGE_ADJACENT:
3906 case REQ_RANGE_CITY:
3909 case REQ_RANGE_COUNT:
3910 break;
3911 }
3912
3913 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3914
3915 return TRI_MAYBE;
3916}
3917
3918/**********************************************************************/
3926static enum fc_tristate
3928 const struct req_context *context,
3929 const struct req_context *other_context,
3930 const struct requirement *req)
3931{
3932 const struct nation_group *ngroup;
3933
3935
3937
3938 switch (req->range) {
3939 case REQ_RANGE_PLAYER:
3940 if (context->player == nullptr) {
3941 return TRI_MAYBE;
3942 }
3944 nation_of_player(context->player), ngroup));
3945 case REQ_RANGE_TEAM:
3946 case REQ_RANGE_ALLIANCE:
3947 case REQ_RANGE_WORLD:
3948 if (context->player == nullptr) {
3949 return TRI_MAYBE;
3950 }
3951 players_iterate_alive(plr2) {
3952 if (players_in_same_range(context->player, plr2, req->range)) {
3954 return TRI_YES;
3955 }
3956 }
3958 return TRI_NO;
3959 case REQ_RANGE_LOCAL:
3960 case REQ_RANGE_TILE:
3962 case REQ_RANGE_ADJACENT:
3963 case REQ_RANGE_CITY:
3966 case REQ_RANGE_COUNT:
3967 break;
3968 }
3969
3970 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3971
3972 return TRI_MAYBE;
3973}
3974
3975/**********************************************************************/
3983static enum fc_tristate
3985 const struct req_context *context,
3986 const struct req_context *other_context,
3987 const struct requirement *req)
3988{
3989 const struct nation_type *nationality;
3990 enum fc_tristate ret;
3991
3993
3994 nationality = req->source.value.nationality;
3995
3996 switch (req->range) {
3997 case REQ_RANGE_CITY:
3998 if (context->city == nullptr) {
3999 return TRI_MAYBE;
4000 }
4001 citizens_iterate(context->city, slot, count) {
4002 if (player_slot_get_player(slot)->nation == nationality) {
4003 return TRI_YES;
4004 }
4006
4007 return TRI_NO;
4009 if (context->city == nullptr) {
4010 return TRI_MAYBE;
4011 }
4012 citizens_iterate(context->city, slot, count) {
4013 if (player_slot_get_player(slot)->nation == nationality) {
4014 return TRI_YES;
4015 }
4017
4018 ret = TRI_NO;
4020 if (trade_partner == nullptr) {
4021 ret = TRI_MAYBE;
4022 } else {
4023 citizens_iterate(trade_partner, slot, count) {
4024 if (player_slot_get_player(slot)->nation == nationality) {
4025 return TRI_YES;
4026 }
4028 }
4030
4031 return ret;
4032 case REQ_RANGE_PLAYER:
4033 case REQ_RANGE_TEAM:
4034 case REQ_RANGE_ALLIANCE:
4035 case REQ_RANGE_WORLD:
4036 case REQ_RANGE_LOCAL:
4037 case REQ_RANGE_TILE:
4039 case REQ_RANGE_ADJACENT:
4041 case REQ_RANGE_COUNT:
4042 break;
4043 }
4044
4045 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4046
4047 return TRI_MAYBE;
4048}
4049
4050/**********************************************************************/
4058static enum fc_tristate
4060 const struct req_context *context,
4061 const struct req_context *other_context,
4062 const struct requirement *req)
4063{
4064 const struct nation_type *nation;
4065
4067
4068 nation = req->source.value.origowner;
4069
4070 switch (req->range) {
4071 case REQ_RANGE_CITY:
4072 if (context->city == nullptr || context->city->original == nullptr) {
4073 return TRI_MAYBE;
4074 }
4075 if (player_nation(context->city->original) == nation) {
4076 return TRI_YES;
4077 }
4078
4079 return TRI_NO;
4081 case REQ_RANGE_PLAYER:
4082 case REQ_RANGE_TEAM:
4083 case REQ_RANGE_ALLIANCE:
4084 case REQ_RANGE_WORLD:
4085 case REQ_RANGE_LOCAL:
4086 case REQ_RANGE_TILE:
4088 case REQ_RANGE_ADJACENT:
4090 case REQ_RANGE_COUNT:
4091 break;
4092 }
4093
4094 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4095
4096 return TRI_MAYBE;
4097}
4098
4099/**********************************************************************/
4103 const struct player *other_player,
4104 enum req_range range,
4105 int diplrel)
4106{
4107 switch (range) {
4108 case REQ_RANGE_PLAYER:
4109 if (target_player == nullptr) {
4110 return TRI_MAYBE;
4111 }
4113 case REQ_RANGE_TEAM:
4114 case REQ_RANGE_ALLIANCE:
4115 case REQ_RANGE_WORLD:
4116 if (target_player == nullptr) {
4117 return TRI_MAYBE;
4118 }
4119 players_iterate_alive(plr2) {
4121 if (is_diplrel_to_other(plr2, diplrel)) {
4122 return TRI_YES;
4123 }
4124 }
4126 return TRI_NO;
4127 case REQ_RANGE_LOCAL:
4128 if (target_player == nullptr || other_player == nullptr) {
4129 return TRI_MAYBE;
4130 }
4131 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
4132 case REQ_RANGE_TILE:
4134 case REQ_RANGE_ADJACENT:
4135 case REQ_RANGE_CITY:
4138 case REQ_RANGE_COUNT:
4139 break;
4140 }
4141
4142 fc_assert_msg(FALSE, "Invalid range %d.", range);
4143
4144 return TRI_MAYBE;
4145}
4146
4147/**********************************************************************/
4155static enum fc_tristate
4157 const struct req_context *context,
4158 const struct req_context *other_context,
4159 const struct requirement *req)
4160{
4162
4163 return is_diplrel_in_range(context->player, other_context->player,
4164 req->range, req->source.value.diplrel);
4165}
4166
4167/**********************************************************************/
4175static enum fc_tristate
4177 const struct req_context *context,
4178 const struct req_context *other_context,
4179 const struct requirement *req)
4180{
4182
4183 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4184 : nullptr,
4185 context->player,
4186 req->range,
4187 req->source.value.diplrel);
4188}
4189
4190/**********************************************************************/
4199static enum fc_tristate
4201 const struct req_context *context,
4202 const struct req_context *other_context,
4203 const struct requirement *req)
4204{
4206
4207 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4208 : nullptr,
4209 other_context->player,
4210 req->range,
4211 req->source.value.diplrel);
4212}
4213
4214/**********************************************************************/
4217static enum fc_tristate
4219 const struct player *other_player,
4220 enum req_range range,
4221 int diplrel)
4222{
4223 enum fc_tristate out = TRI_NO;
4224
4225 if (target_tile == nullptr) {
4226 return TRI_MAYBE;
4227 }
4228
4231 unit_owner(target_unit), other_player, range, diplrel);
4232
4235
4236 return out;
4237}
4238
4239/**********************************************************************/
4248static enum fc_tristate
4250 const struct req_context *context,
4251 const struct req_context *other_context,
4252 const struct requirement *req)
4253{
4255
4256 return is_diplrel_unitany_in_range(context->tile, context->player,
4257 req->range,
4258 req->source.value.diplrel);
4259}
4260
4261/**********************************************************************/
4270static enum fc_tristate
4272 const struct req_context *context,
4273 const struct req_context *other_context,
4274 const struct requirement *req)
4275{
4277
4279 req->range,
4280 req->source.value.diplrel);
4281}
4282
4283/**********************************************************************/
4291static enum fc_tristate
4293 const struct req_context *context,
4294 const struct req_context *other_context,
4295 const struct requirement *req)
4296{
4297 const struct unit_type *punittype;
4298
4300
4301 punittype = req->source.value.utype;
4302
4303 switch (req->range) {
4304 case REQ_RANGE_LOCAL:
4305 if (!context->unittype) {
4306 return TRI_MAYBE;
4307 }
4308 return BOOL_TO_TRISTATE(context->unittype == punittype);
4309 case REQ_RANGE_TILE:
4311 case REQ_RANGE_ADJACENT:
4312 if (context->tile == nullptr) {
4313 return TRI_MAYBE;
4314 }
4315
4316 unit_list_iterate(context->tile->units, punit) {
4317 if (punit->utype == punittype) {
4318 return TRI_YES;
4319 }
4321
4322 if (req->range == REQ_RANGE_TILE) {
4323 return TRI_NO;
4324 }
4325
4326 if (req->range == REQ_RANGE_CADJACENT) {
4329 if (punit->utype == punittype) {
4330 return TRI_YES;
4331 }
4334 } else {
4336
4339 if (punit->utype == punittype) {
4340 return TRI_YES;
4341 }
4344 }
4345
4346 return TRI_NO;
4347
4348 case REQ_RANGE_CITY:
4351 case REQ_RANGE_PLAYER:
4352 case REQ_RANGE_TEAM:
4353 case REQ_RANGE_ALLIANCE:
4354 case REQ_RANGE_WORLD:
4355 case REQ_RANGE_COUNT:
4357 break;
4358 }
4359
4360 return TRI_NO;
4361}
4362
4363/**********************************************************************/
4371static enum fc_tristate
4373 const struct req_context *context,
4374 const struct req_context *other_context,
4375 const struct requirement *req)
4376{
4377 enum unit_type_flag_id unitflag;
4378
4380
4381 unitflag = req->source.value.unitflag;
4382
4383 switch (req->range) {
4384 case REQ_RANGE_LOCAL:
4385 if (!context->unittype) {
4386 return TRI_MAYBE;
4387 }
4388 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4389 case REQ_RANGE_TILE:
4391 case REQ_RANGE_ADJACENT:
4392 if (context->tile == nullptr) {
4393 return TRI_MAYBE;
4394 }
4395
4396 unit_list_iterate(context->tile->units, punit) {
4397 if (unit_has_type_flag(punit, unitflag)) {
4398 return TRI_YES;
4399 }
4401
4402 if (req->range == REQ_RANGE_TILE) {
4403 return TRI_NO;
4404 }
4405
4406 if (req->range == REQ_RANGE_CADJACENT) {
4409 if (unit_has_type_flag(punit, unitflag)) {
4410 return TRI_YES;
4411 }
4414 } else {
4416
4419 if (unit_has_type_flag(punit, unitflag)) {
4420 return TRI_YES;
4421 }
4424 }
4425
4426 return TRI_NO;
4427
4428 case REQ_RANGE_CITY:
4431 case REQ_RANGE_PLAYER:
4432 case REQ_RANGE_TEAM:
4433 case REQ_RANGE_ALLIANCE:
4434 case REQ_RANGE_WORLD:
4435 case REQ_RANGE_COUNT:
4437 break;
4438 }
4439
4440 return TRI_NO;
4441}
4442
4443/**********************************************************************/
4451static enum fc_tristate
4453 const struct req_context *context,
4454 const struct req_context *other_context,
4455 const struct requirement *req)
4456{
4457 const struct unit_class *pclass;
4458
4460
4461 pclass = req->source.value.uclass;
4462
4463 switch (req->range) {
4464 case REQ_RANGE_LOCAL:
4465 if (!context->unittype) {
4466 return TRI_MAYBE;
4467 }
4468 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4469 case REQ_RANGE_TILE:
4471 case REQ_RANGE_ADJACENT:
4472 if (context->tile == nullptr) {
4473 return TRI_MAYBE;
4474 }
4475
4476 unit_list_iterate(context->tile->units, punit) {
4477 if (unit_class_get(punit) == pclass) {
4478 return TRI_YES;
4479 }
4481
4482 if (req->range == REQ_RANGE_TILE) {
4483 return TRI_NO;
4484 }
4485
4486 if (req->range == REQ_RANGE_CADJACENT) {
4489 if (unit_class_get(punit) == pclass) {
4490 return TRI_YES;
4491 }
4494 } else {
4496
4499 if (unit_class_get(punit) == pclass) {
4500 return TRI_YES;
4501 }
4504 }
4505
4506 return TRI_NO;
4507
4508 case REQ_RANGE_CITY:
4511 case REQ_RANGE_PLAYER:
4512 case REQ_RANGE_TEAM:
4513 case REQ_RANGE_ALLIANCE:
4514 case REQ_RANGE_WORLD:
4515 case REQ_RANGE_COUNT:
4517 break;
4518 }
4519
4520 return TRI_NO;
4521}
4522
4523/**********************************************************************/
4531static enum fc_tristate
4533 const struct req_context *context,
4534 const struct req_context *other_context,
4535 const struct requirement *req)
4536{
4538
4540
4542
4543 switch (req->range) {
4544 case REQ_RANGE_LOCAL:
4545 if (!context->unittype) {
4546 return TRI_MAYBE;
4547 }
4549 case REQ_RANGE_TILE:
4551 case REQ_RANGE_ADJACENT:
4552 if (context->tile == nullptr) {
4553 return TRI_MAYBE;
4554 }
4555
4556 unit_list_iterate(context->tile->units, punit) {
4558 return TRI_YES;
4559 }
4561
4562 if (req->range == REQ_RANGE_TILE) {
4563 return TRI_NO;
4564 }
4565
4566 if (req->range == REQ_RANGE_CADJACENT) {
4570 return TRI_YES;
4571 }
4574 } else {
4576
4580 return TRI_YES;
4581 }
4584 }
4585
4586 return TRI_NO;
4587
4588 case REQ_RANGE_CITY:
4591 case REQ_RANGE_PLAYER:
4592 case REQ_RANGE_TEAM:
4593 case REQ_RANGE_ALLIANCE:
4594 case REQ_RANGE_WORLD:
4595 case REQ_RANGE_COUNT:
4597 break;
4598 }
4599
4600 return TRI_NO;
4601}
4602
4603/**********************************************************************/
4611static enum fc_tristate
4613 const struct req_context *context,
4614 const struct req_context *other_context,
4615 const struct requirement *req)
4616{
4617 enum ustate_prop uprop;
4618
4620
4622
4624 "Unsupported range \"%s\"",
4625 req_range_name(req->range));
4626
4627 /* Could be asked with incomplete data.
4628 * is_req_active() will handle it based on prob_type. */
4629 if (context->unit == nullptr) {
4630 return TRI_MAYBE;
4631 }
4632
4633 switch (uprop) {
4634 case USP_TRANSPORTED:
4635 return BOOL_TO_TRISTATE(context->unit->transporter != nullptr);
4636 case USP_LIVABLE_TILE:
4637 return BOOL_TO_TRISTATE(
4639 unit_tile(context->unit)));
4640 break;
4641 case USP_TRANSPORTING:
4643 case USP_HAS_HOME_CITY:
4644 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
4645 case USP_NATIVE_TILE:
4646 return BOOL_TO_TRISTATE(
4648 unit_tile(context->unit)));
4649 break;
4650 case USP_NATIVE_EXTRA:
4651 return BOOL_TO_TRISTATE(
4653 unit_type_get(context->unit)));
4654 break;
4656 return BOOL_TO_TRISTATE(context->unit->moved);
4657 case USP_COUNT:
4658 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
4659 /* Invalid property is unknowable. */
4660 return TRI_NO;
4661 }
4662
4663 /* Should never be reached */
4664 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
4665
4666 return TRI_NO;
4667}
4668
4669/**********************************************************************/
4677static enum fc_tristate
4679 const struct req_context *context,
4680 const struct req_context *other_context,
4681 const struct requirement *req)
4682{
4683 enum unit_activity activity;
4684
4686
4687 activity = req->source.value.activity;
4688
4690 "Unsupported range \"%s\"",
4691 req_range_name(req->range));
4692
4693 if (context->unit == nullptr) {
4694 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
4695 * it's the zero value that context has by default - so many callers
4696 * who meant not to set specific activity actually have ACTIVITY_IDLE
4697 * instead of ACTIVITY_LAST */
4698 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
4699 return BOOL_TO_TRISTATE(activity == context->activity);
4700 }
4701
4702 /* Could be asked with incomplete data.
4703 * is_req_active() will handle it based on prob_type. */
4704 return TRI_MAYBE;
4705 }
4706
4707 switch (context->unit->activity) {
4708 case ACTIVITY_IDLE:
4709 case ACTIVITY_SENTRY:
4710 case ACTIVITY_GOTO:
4711 case ACTIVITY_EXPLORE:
4712 /* Seen as idle. */
4713 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
4714 default:
4715 /* Handled below. */
4716 break;
4717 }
4718
4719 return BOOL_TO_TRISTATE(context->unit->activity == activity);
4720}
4721
4722/**********************************************************************/
4730static enum fc_tristate
4732 const struct req_context *context,
4733 const struct req_context *other_context,
4734 const struct requirement *req)
4735{
4737
4738 if (context->unit == nullptr) {
4739 return TRI_MAYBE;
4740 } else {
4741 return BOOL_TO_TRISTATE(context->unit->veteran
4742 >= req->source.value.minveteran);
4743 }
4744}
4745
4746/**********************************************************************/
4754static enum fc_tristate
4756 const struct req_context *context,
4757 const struct req_context *other_context,
4758 const struct requirement *req)
4759{
4761
4762 if (context->unit == nullptr) {
4763 return TRI_MAYBE;
4764 } else {
4766 <= context->unit->moves_left);
4767 }
4768}
4769
4770/**********************************************************************/
4778static enum fc_tristate
4780 const struct req_context *context,
4781 const struct req_context *other_context,
4782 const struct requirement *req)
4783{
4785
4786 if (context->unit == nullptr) {
4787 return TRI_MAYBE;
4788 } else {
4790 <= context->unit->hp);
4791 }
4792}
4793
4794/**********************************************************************/
4802static enum fc_tristate
4804 const struct req_context *context,
4805 const struct req_context *other_context,
4806 const struct requirement *req)
4807{
4809
4810 switch (req->range) {
4811 case REQ_RANGE_LOCAL:
4812 if (context->unit == nullptr || !is_server()) {
4813 return TRI_MAYBE;
4814 } else {
4815 return BOOL_TO_TRISTATE(
4816 req->source.value.age <=
4817 game.info.turn - context->unit->birth_turn);
4818 }
4819 break;
4820 case REQ_RANGE_CITY:
4821 if (context->city == nullptr) {
4822 return TRI_MAYBE;
4823 } else {
4824 return BOOL_TO_TRISTATE(
4825 req->source.value.age <=
4826 game.info.turn - context->city->turn_founded);
4827 }
4828 break;
4829 case REQ_RANGE_PLAYER:
4830 if (context->player == nullptr) {
4831 return TRI_MAYBE;
4832 } else {
4833 return BOOL_TO_TRISTATE(req->source.value.age
4834 <= player_age(context->player));
4835 }
4836 break;
4837 default:
4838 return TRI_MAYBE;
4839 break;
4840 }
4841}
4842
4843/**********************************************************************/
4851static enum fc_tristate
4853 const struct req_context *context,
4854 const struct req_context *other_context,
4855 const struct requirement *req)
4856{
4858
4859 switch (req->range) {
4860 case REQ_RANGE_LOCAL:
4861 if (context->unit == nullptr || !is_server()) {
4862 return TRI_MAYBE;
4863 } else {
4864 return BOOL_TO_TRISTATE(
4865 req->source.value.form_age <=
4866 game.info.turn - context->unit->current_form_turn);
4867 }
4868 break;
4869 default:
4870 return TRI_MAYBE;
4871 break;
4872 }
4873}
4874
4875/**********************************************************************/
4879static inline enum fc_tristate
4881{
4883 bool whole_known;
4884
4885 if (cont > 0) {
4888
4889 if (actual_surrounder > 0) {
4890 return TRI_NO;
4891 }
4892 } else if (cont < 0) {
4895
4896 if (actual_surrounder < 0) {
4897 return TRI_NO;
4898 }
4899 } else {
4900 return TRI_MAYBE;
4901 }
4902
4903 if (actual_surrounder == 0 || surrounder == 0) {
4904 return TRI_MAYBE;
4905 } else if (actual_surrounder != surrounder) {
4906 return TRI_NO;
4907 } else if (!whole_known) {
4908 return TRI_MAYBE;
4909 } else {
4910 return TRI_YES;
4911 }
4912}
4913
4914/**********************************************************************/
4922static enum fc_tristate
4924 const struct req_context *context,
4925 const struct req_context *other_context,
4926 const struct requirement *req)
4927{
4929
4930 if (context->tile == nullptr || other_context->tile == nullptr) {
4931 /* Note: For some values, we might be able to give a definitive
4932 * TRI_NO answer even if one of the tiles is missing, but that's
4933 * probably not worth the added effort. */
4934 return TRI_MAYBE;
4935 }
4936
4937 switch (req->source.value.tilerel) {
4938 case TREL_SAME_TCLASS:
4939 if (tile_terrain(other_context->tile) == T_UNKNOWN) {
4940 return TRI_MAYBE;
4941 }
4943 || req->range == REQ_RANGE_CADJACENT
4944 || req->range == REQ_RANGE_ADJACENT),
4945 TRI_MAYBE,
4946 "Invalid range %d for tile relation \"%s\" req",
4948 {
4951 bool seen_unknown = FALSE;
4952 const struct terrain *terr;
4953
4954 if ((terr = tile_terrain(context->tile)) == T_UNKNOWN) {
4956 } else if (terrain_type_terrain_class(terr) == cls) {
4957 return TRUE;
4958 }
4959
4961 if ((terr = tile_terrain(adj_tile)) == T_UNKNOWN) {
4963 } else if (terrain_type_terrain_class(terr) == cls) {
4964 return TRUE;
4965 }
4967
4968 if (seen_unknown) {
4969 return TRI_MAYBE;
4970 } else {
4971 return TRI_NO;
4972 }
4973 }
4974 break;
4975 case TREL_SAME_REGION:
4976 if (tile_continent(other_context->tile) == 0) {
4977 return TRI_MAYBE;
4978 }
4980 || req->range == REQ_RANGE_CADJACENT
4981 || req->range == REQ_RANGE_ADJACENT),
4982 TRI_MAYBE,
4983 "Invalid range %d for tile relation \"%s\" req",
4985
4986 if (tile_continent(context->tile)
4987 == tile_continent(other_context->tile)) {
4988 return TRI_YES;
4989 } else {
4990 bool seen_unknown = (tile_continent(context->tile) == 0);
4992
4995
4996 if (adj_cont == cont) {
4997 return TRI_YES;
4998 } else if (adj_cont == 0) {
5000 }
5002
5003 if (seen_unknown) {
5004 return TRI_MAYBE;
5005 } else {
5006 return TRI_NO;
5007 }
5008 }
5009 break;
5011 if (tile_continent(context->tile) == 0
5012 || tile_continent(other_context->tile) == 0) {
5013 /* Note: We could still give a definitive TRI_NO answer if there are
5014 * too many different adjacent continents, but that's probably not
5015 * worth the added effort. */
5016 return TRI_MAYBE;
5017 }
5019 || req->range == REQ_RANGE_ADJACENT),
5020 TRI_MAYBE,
5021 "Invalid range %d for tile relation \"%s\" req",
5022 req->range,
5024
5025 {
5026 bool seen_unknown = FALSE;
5027 Continent_id cont = tile_continent(context->tile);
5029
5032
5033 if (adj_cont == 0) {
5035 } else if (adj_cont != cont && adj_cont != other_cont) {
5036 return TRI_NO;
5037 }
5039
5040 if (seen_unknown) {
5041 return TRI_MAYBE;
5042 } else {
5043 return TRI_YES;
5044 }
5045 }
5046 break;
5049 || req->range == REQ_RANGE_CADJACENT
5050 || req->range == REQ_RANGE_ADJACENT),
5051 TRI_MAYBE,
5052 "Invalid range %d for tile relation \"%s\" req",
5053 req->range,
5055
5056 {
5057 bool seen_maybe = FALSE;
5059
5061 wanted)) {
5062 case TRI_YES:
5063 return TRI_YES;
5064 case TRI_MAYBE:
5065 seen_maybe = TRUE;
5066 break;
5067 default:
5068 break;
5069 }
5070
5073 wanted)) {
5074 case TRI_YES:
5075 return TRI_YES;
5076 case TRI_MAYBE:
5077 seen_maybe = TRUE;
5078 break;
5079 default:
5080 break;
5081 }
5083
5084 if (seen_maybe) {
5085 return TRI_MAYBE;
5086 } else {
5087 return TRI_NO;
5088 }
5089 }
5090 break;
5091 default:
5092 break;
5093 }
5094
5096 "Illegal value %d for tile relationship requirement.",
5097 req->source.value.tilerel);
5098 return TRI_MAYBE;
5099}
5100
5101/**********************************************************************/
5104static bool is_city_in_tile(const struct tile *ptile,
5105 const struct city *pcity)
5106{
5107 if (pcity == nullptr) {
5108 return tile_city(ptile) != nullptr;
5109 } else {
5110 return is_city_center(pcity, ptile);
5111 }
5112}
5113
5114/**********************************************************************/
5122static enum fc_tristate
5124 const struct req_context *context,
5125 const struct req_context *other_context,
5126 const struct requirement *req)
5127{
5128 enum citytile_type citytile;
5129
5131
5132 citytile = req->source.value.citytile;
5133
5135 if (context->tile == nullptr) {
5136 return TRI_MAYBE;
5137 }
5138
5139 switch (citytile) {
5140 case CITYT_CENTER:
5141 switch (req->range) {
5142 case REQ_RANGE_TILE:
5144 context->city));
5146 if (is_city_in_tile(context->tile, context->city)) {
5147 return TRI_YES;
5148 }
5150 if (is_city_in_tile(adjc_tile, context->city)) {
5151 return TRI_YES;
5152 }
5154
5155 return TRI_NO;
5156 case REQ_RANGE_ADJACENT:
5157 if (is_city_in_tile(context->tile, context->city)) {
5158 return TRI_YES;
5159 }
5161 if (is_city_in_tile(adjc_tile, context->city)) {
5162 return TRI_YES;
5163 }
5165
5166 return TRI_NO;
5167 case REQ_RANGE_CITY:
5170 case REQ_RANGE_PLAYER:
5171 case REQ_RANGE_TEAM:
5172 case REQ_RANGE_ALLIANCE:
5173 case REQ_RANGE_WORLD:
5174 case REQ_RANGE_LOCAL:
5175 case REQ_RANGE_COUNT:
5176 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5177 break;
5178 }
5179
5180 return TRI_MAYBE;
5181 case CITYT_CLAIMED:
5182 switch (req->range) {
5183 case REQ_RANGE_TILE:
5184 return BOOL_TO_TRISTATE(context->tile->owner != nullptr);
5186 if (context->tile->owner != nullptr) {
5187 return TRI_YES;
5188 }
5190 if (adjc_tile->owner != nullptr) {
5191 return TRI_YES;
5192 }
5194
5195 return TRI_NO;
5196 case REQ_RANGE_ADJACENT:
5197 if (context->tile->owner != nullptr) {
5198 return TRI_YES;
5199 }
5201 if (adjc_tile->owner != nullptr) {
5202 return TRI_YES;
5203 }
5205
5206 return TRI_NO;
5207 case REQ_RANGE_CITY:
5210 case REQ_RANGE_PLAYER:
5211 case REQ_RANGE_TEAM:
5212 case REQ_RANGE_ALLIANCE:
5213 case REQ_RANGE_WORLD:
5214 case REQ_RANGE_LOCAL:
5215 case REQ_RANGE_COUNT:
5216 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5217 break;
5218 }
5219
5220 return TRI_MAYBE;
5221 case CITYT_EXTRAS_OWNED:
5222 switch (req->range) {
5223 case REQ_RANGE_TILE:
5224 return BOOL_TO_TRISTATE(context->tile->extras_owner != nullptr);
5226 if (context->tile->extras_owner != nullptr) {
5227 return TRI_YES;
5228 }
5230 if (adjc_tile->extras_owner != nullptr) {
5231 return TRI_YES;
5232 }
5234
5235 return TRI_NO;
5236 case REQ_RANGE_ADJACENT:
5237 if (context->tile->extras_owner != nullptr) {
5238 return TRI_YES;
5239 }
5241 if (adjc_tile->extras_owner != nullptr) {
5242 return TRI_YES;
5243 }
5245
5246 return TRI_NO;
5247 case REQ_RANGE_CITY:
5250 case REQ_RANGE_PLAYER:
5251 case REQ_RANGE_TEAM:
5252 case REQ_RANGE_ALLIANCE:
5253 case REQ_RANGE_WORLD:
5254 case REQ_RANGE_LOCAL:
5255 case REQ_RANGE_COUNT:
5256 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5257 break;
5258 }
5259
5260 return TRI_MAYBE;
5261 case CITYT_WORKED:
5262 switch (req->range) {
5263 case REQ_RANGE_TILE:
5264 return BOOL_TO_TRISTATE(context->tile->worked != nullptr);
5266 if (context->tile->worked != nullptr) {
5267 return TRI_YES;
5268 }
5270 if (adjc_tile->worked != nullptr) {
5271 return TRI_YES;
5272 }
5274
5275 return TRI_NO;
5276 case REQ_RANGE_ADJACENT:
5277 if (context->tile->worked != nullptr) {
5278 return TRI_YES;
5279 }
5281 if (adjc_tile->worked != nullptr) {
5282 return TRI_YES;
5283 }
5285
5286 return TRI_NO;
5287 case REQ_RANGE_CITY:
5290 case REQ_RANGE_PLAYER:
5291 case REQ_RANGE_TEAM:
5292 case REQ_RANGE_ALLIANCE:
5293 case REQ_RANGE_WORLD:
5294 case REQ_RANGE_LOCAL:
5295 case REQ_RANGE_COUNT:
5296 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5297 break;
5298 }
5299
5300 return TRI_MAYBE;
5302 {
5304 const struct tile *target_tile = context->tile, *cc_tile;
5305
5306 if (!context->city) {
5307 return TRI_MAYBE;
5308 }
5309 cc_tile = city_tile(context->city);
5310 if (!cc_tile) {
5311 /* Unplaced virtual city */
5312 return TRI_MAYBE;
5313 }
5315 /* Note: No special treatment of 0 == cc here*/
5316 switch (req->range) {
5317 case REQ_RANGE_TILE:
5320 if (tile_continent(target_tile) == cc) {
5321 return TRI_YES;
5322 }
5324 if (tile_continent(adjc_tile) == cc) {
5325 return TRI_YES;
5326 }
5328
5329 return TRI_NO;
5330 case REQ_RANGE_ADJACENT:
5331 if (tile_continent(target_tile) == cc) {
5332 return TRI_YES;
5333 }
5335 if (tile_continent(adjc_tile) == cc) {
5336 return TRI_YES;
5337 }
5339
5340 return TRI_NO;
5341 case REQ_RANGE_CITY:
5344 case REQ_RANGE_PLAYER:
5345 case REQ_RANGE_TEAM:
5346 case REQ_RANGE_ALLIANCE:
5347 case REQ_RANGE_WORLD:
5348 case REQ_RANGE_LOCAL:
5349 case REQ_RANGE_COUNT:
5350 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5351 break;
5352 }
5353 }
5354
5355 return TRI_MAYBE;
5357 {
5358 int n = 0;
5360 bool ukt = FALSE;
5361 const struct tile *target_tile = context->tile, *cc_tile;
5362
5363 if (!context->city) {
5364 return TRI_MAYBE;
5365 }
5366 cc_tile = city_tile(context->city);
5367 if (!cc_tile) {
5368 /* Unplaced virtual city */
5369 return TRI_MAYBE;
5370 }
5372 if (!cc) {
5373 /* Don't know the city center terrain class.
5374 * Maybe, the city floats? Even if the rules prohibit it... */
5375 return TRI_MAYBE;
5376 }
5379
5380 if (0 != tc) {
5381 bool seen = FALSE;
5382 int i = n;
5383
5384 if (tc == cc) {
5385 continue;
5386 }
5387 while (--i >= 0) {
5388 if (adjc_cont[i] == tc) {
5389 seen = TRUE;
5390 break;
5391 }
5392 }
5393 if (seen) {
5394 continue;
5395 }
5397 } else {
5398 /* Likely, it's a black tile in client and we don't know
5399 * We possibly can calculate, but keep it simple. */
5400 ukt = TRUE;
5401 }
5403 if (0 == n) {
5404 return ukt ? TRI_MAYBE : TRI_NO;
5405 }
5406
5407 switch (req->range) {
5408 case REQ_RANGE_TILE:
5409 {
5411
5412 if (cc == tc) {
5413 return TRI_NO;
5414 }
5415 if (0 == tc || ukt) {
5416 return TRI_MAYBE;
5417 }
5418 for (int i = 0; i < n; i++) {
5419 if (tc == adjc_cont[i]) {
5420 return TRI_YES;
5421 }
5422 }
5423 }
5424
5425 return TRI_NO;
5426 case REQ_RANGE_ADJACENT:
5427 if (ukt) {
5428 /* If ALL the tiles in range are on cc, we can say it's false */
5430 if (tile_continent(adjc_tile) != cc) {
5431 return TRI_MAYBE;
5432 }
5434
5435 return TRI_NO;
5436 } else {
5439
5440 if (0 == tc) {
5441 return TRI_MAYBE;
5442 }
5443 for (int i = 0; i < n; i++) {
5444 if (tc == adjc_cont[i]) {
5445 return TRI_YES;
5446 }
5447 }
5449 }
5450
5451 return TRI_NO;
5453 if (ukt) {
5454 /* If ALL the tiles in range are on cc, we can say it's false */
5456 if (tile_continent(cadjc_tile) != cc) {
5457 return TRI_MAYBE;
5458 }
5460 } else {
5463
5464 if (0 == tc) {
5465 return TRI_MAYBE;
5466 }
5467 for (int i = 0; i < n; i++) {
5468 if (tc == adjc_cont[i]) {
5469 return TRI_YES;
5470 }
5471 }
5473 }
5474
5475 return TRI_NO;
5476 case REQ_RANGE_CITY:
5479 case REQ_RANGE_PLAYER:
5480 case REQ_RANGE_TEAM:
5481 case REQ_RANGE_ALLIANCE:
5482 case REQ_RANGE_WORLD:
5483 case REQ_RANGE_LOCAL:
5484 case REQ_RANGE_COUNT:
5485 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5486 break;
5487 }
5488 }
5489
5490 return TRI_MAYBE;
5491 case CITYT_LAST:
5492 /* Handled below */
5493 break;
5494 }
5495
5496 /* Not implemented */
5497 log_error("is_req_active(): citytile %d not supported.",
5498 citytile);
5499 return TRI_MAYBE;
5500}
5501
5502/**********************************************************************/
5510static enum fc_tristate
5512 const struct req_context *context,
5513 const struct req_context *other_context,
5514 const struct requirement *req)
5515{
5516 enum citystatus_type citystatus;
5517
5519
5520 citystatus = req->source.value.citystatus;
5521
5522 if (context->city == nullptr) {
5523 return TRI_MAYBE;
5524 }
5525
5526 switch (citystatus) {
5528 switch (req->range) {
5529 case REQ_RANGE_CITY:
5530 if (context->city->original == nullptr) {
5531 return TRI_MAYBE;
5532 }
5533 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
5535 {
5536 enum fc_tristate ret;
5537
5538 if (city_owner(context->city) == context->city->original) {
5539 return TRI_YES;
5540 }
5541
5542 ret = TRI_NO;
5544 if (trade_partner == nullptr || trade_partner->original == nullptr) {
5545 ret = TRI_MAYBE;
5546 } else if (city_owner(trade_partner) == trade_partner->original) {
5547 return TRI_YES;
5548 }
5550
5551 return ret;
5552 }
5553 case REQ_RANGE_LOCAL:
5554 case REQ_RANGE_TILE:
5556 case REQ_RANGE_ADJACENT:
5558 case REQ_RANGE_PLAYER:
5559 case REQ_RANGE_TEAM:
5560 case REQ_RANGE_ALLIANCE:
5561 case REQ_RANGE_WORLD:
5562 case REQ_RANGE_COUNT:
5563 break;
5564 }
5565
5566 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
5567 req->range);
5568
5569 return TRI_MAYBE;
5570
5571 case CITYS_STARVED:
5572 switch (req->range) {
5573 case REQ_RANGE_CITY:
5574 return BOOL_TO_TRISTATE(context->city->had_famine);
5576 {
5577 enum fc_tristate ret;
5578
5579 if (context->city->had_famine) {
5580 return TRI_YES;
5581 }
5582
5583 ret = TRI_NO;
5585 if (trade_partner == nullptr) {
5586 ret = TRI_MAYBE;
5587 } else if (trade_partner->had_famine) {
5588 return TRI_YES;
5589 }
5591
5592 return ret;
5593 }
5594 case REQ_RANGE_LOCAL:
5595 case REQ_RANGE_TILE:
5597 case REQ_RANGE_ADJACENT:
5599 case REQ_RANGE_PLAYER:
5600 case REQ_RANGE_TEAM:
5601 case REQ_RANGE_ALLIANCE:
5602 case REQ_RANGE_WORLD:
5603 case REQ_RANGE_COUNT:
5604 break;
5605 }
5606
5607 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
5608 req->range);
5609
5610 return TRI_MAYBE;
5611
5612 case CITYS_DISORDER:
5613 switch (req->range) {
5614 case REQ_RANGE_CITY:
5615 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
5617 {
5618 enum fc_tristate ret;
5619
5620 if (context->city->anarchy > 0) {
5621 return TRI_YES;
5622 }
5623
5624 ret = TRI_NO;
5626 if (trade_partner == nullptr) {
5627 ret = TRI_MAYBE;
5628 } else if (trade_partner->anarchy > 0) {
5629 return TRI_YES;
5630 }
5632
5633 return ret;
5634 }
5635 case REQ_RANGE_LOCAL:
5636 case REQ_RANGE_TILE:
5638 case REQ_RANGE_ADJACENT:
5640 case REQ_RANGE_PLAYER:
5641 case REQ_RANGE_TEAM:
5642 case REQ_RANGE_ALLIANCE:
5643 case REQ_RANGE_WORLD:
5644 case REQ_RANGE_COUNT:
5645 break;
5646 }
5647
5648 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
5649 req->range);
5650
5651 return TRI_MAYBE;
5652
5653 case CITYS_CELEBRATION:
5654 switch (req->range) {
5655 case REQ_RANGE_CITY:
5656 return BOOL_TO_TRISTATE(context->city->rapture > 0);
5658 {
5659 enum fc_tristate ret;
5660
5661 if (context->city->rapture > 0) {
5662 return TRI_YES;
5663 }
5664
5665 ret = TRI_NO;
5667 if (trade_partner == nullptr) {
5668 ret = TRI_MAYBE;
5669 } else if (trade_partner->rapture > 0) {
5670 return TRI_YES;
5671 }
5673
5674 return ret;
5675 }
5676 case REQ_RANGE_LOCAL:
5677 case REQ_RANGE_TILE:
5679 case REQ_RANGE_ADJACENT:
5681 case REQ_RANGE_PLAYER:
5682 case REQ_RANGE_TEAM:
5683 case REQ_RANGE_ALLIANCE:
5684 case REQ_RANGE_WORLD:
5685 case REQ_RANGE_COUNT:
5686 break;
5687 }
5688
5689 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
5690 req->range);
5691
5692 return TRI_MAYBE;
5693
5694 case CITYS_TRANSFERRED:
5695 switch (req->range) {
5696 case REQ_RANGE_CITY:
5697 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
5699 {
5700 enum fc_tristate ret;
5701
5702 if (context->city->acquire_t != CACQ_FOUNDED) {
5703 return TRI_YES;
5704 }
5705
5706 ret = TRI_NO;
5708 if (trade_partner == nullptr) {
5709 ret = TRI_MAYBE;
5710 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
5711 return TRI_YES;
5712 }
5714
5715 return ret;
5716 }
5717 case REQ_RANGE_LOCAL:
5718 case REQ_RANGE_TILE:
5720 case REQ_RANGE_ADJACENT:
5722 case REQ_RANGE_PLAYER:
5723 case REQ_RANGE_TEAM:
5724 case REQ_RANGE_ALLIANCE:
5725 case REQ_RANGE_WORLD:
5726 case REQ_RANGE_COUNT:
5727 break;
5728 }
5729
5730 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
5731 req->range);
5732
5733 return TRI_MAYBE;
5734
5735 case CITYS_LAST:
5736 break;
5737 }
5738
5739 /* Not implemented */
5740 log_error("is_req_active(): citystatus %d not supported.",
5741 citystatus);
5742
5743 return TRI_MAYBE;
5744}
5745
5746/**********************************************************************/
5754static enum fc_tristate
5756 const struct req_context *context,
5757 const struct req_context *other_context,
5758 const struct requirement *req)
5759{
5761
5762 if (context->city == nullptr) {
5763 return TRI_MAYBE;
5764 } else {
5765 if (req->range == REQ_RANGE_TRADE_ROUTE) {
5766 enum fc_tristate ret;
5767
5768 if (city_size_get(context->city) >= req->source.value.minsize) {
5769 return TRI_YES;
5770 }
5771
5772 ret = TRI_NO;
5774 if (trade_partner == nullptr) {
5775 ret = TRI_MAYBE;
5776 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
5777 return TRI_YES;
5778 }
5780
5781 return ret;
5782 } else {
5784 >= req->source.value.minsize);
5785 }
5786 }
5787}
5788
5789/**********************************************************************/
5797static enum fc_tristate
5799 const struct req_context *context,
5800 const struct req_context *other_context,
5801 const struct requirement *req)
5802{
5803 const struct counter *count;
5804
5806
5807 count = req->source.value.counter;
5808
5809 if (context->city == nullptr) {
5810 return TRI_MAYBE;
5811 }
5812 return BOOL_TO_TRISTATE(count->checkpoint <=
5813 context->city->counter_values[
5814 counter_index(count)]);
5815}
5816
5817/**********************************************************************/
5825static enum fc_tristate
5827 const struct req_context *context,
5828 const struct req_context *other_context,
5829 const struct requirement *req)
5830{
5831 const struct achievement *achievement;
5832
5834
5836
5837 if (req->range == REQ_RANGE_WORLD) {
5839 } else if (context->player == nullptr) {
5840 return TRI_MAYBE;
5841 } else if (req->range == REQ_RANGE_ALLIANCE
5842 || req->range == REQ_RANGE_TEAM) {
5843 players_iterate_alive(plr2) {
5844 if (players_in_same_range(context->player, plr2, req->range)
5846 return TRI_YES;
5847 }
5849 return TRI_NO;
5850 } else if (req->range == REQ_RANGE_PLAYER) {
5852 return TRI_YES;
5853 } else {
5854 return TRI_NO;
5855 }
5856 }
5857
5858 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
5859
5860 return TRI_MAYBE;
5861}
5862
5863/**********************************************************************/
5871static enum fc_tristate
5873 const struct req_context *context,
5874 const struct req_context *other_context,
5875 const struct requirement *req)
5876{
5877 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
5878
5879 fc_assert_ret_val(req != nullptr, TRI_MAYBE);
5880 fc_assert(context != nullptr);
5881
5882 switch (req->source.kind) {
5883 case VUT_MINLATITUDE:
5884 min = req->source.value.latitude;
5885 break;
5886 case VUT_MAXLATITUDE:
5887 max = req->source.value.latitude;
5888 break;
5889 default:
5891 || req->source.kind == VUT_MAXLATITUDE);
5892 break;
5893 }
5894
5895 switch (req->range) {
5896 case REQ_RANGE_WORLD:
5898 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
5899
5900 case REQ_RANGE_TILE:
5901 if (context->tile == nullptr) {
5902 return TRI_MAYBE;
5903 } else {
5905
5907 }
5908
5910 if (context->tile == nullptr) {
5911 return TRI_MAYBE;
5912 }
5913
5916
5918 return TRI_YES;
5919 }
5921 return TRI_NO;
5922
5923 case REQ_RANGE_ADJACENT:
5924 if (!context->tile) {
5925 return TRI_MAYBE;
5926 }
5927
5930
5932 return TRI_YES;
5933 }
5935 return TRI_NO;
5936
5937 case REQ_RANGE_CITY:
5940 case REQ_RANGE_PLAYER:
5941 case REQ_RANGE_TEAM:
5942 case REQ_RANGE_ALLIANCE:
5943 case REQ_RANGE_LOCAL:
5944 case REQ_RANGE_COUNT:
5945 break;
5946 }
5947
5949 "Illegal range %d for latitude requirement.", req->range);
5950
5951 return TRI_MAYBE;
5952}
5953
5954/**********************************************************************/
5962static enum fc_tristate
5964 const struct req_context *context,
5965 const struct req_context *other_context,
5966 const struct requirement *req)
5967{
5969
5970 switch (req->range) {
5971 case REQ_RANGE_TILE:
5972 if (context->tile == nullptr || other_context->tile == nullptr) {
5973 return TRI_MAYBE;
5974 }
5975 return BOOL_TO_TRISTATE(
5977 <= req->source.value.distance_sq
5978 );
5979 default:
5980 break;
5981 }
5982
5984 "Illegal range %d for max squared distance requirement.",
5985 req->range);
5986
5987 return TRI_MAYBE;
5988}
5989
5990/**********************************************************************/
5998static enum fc_tristate
6000 const struct req_context *context,
6001 const struct req_context *other_context,
6002 const struct requirement *req)
6003{
6004 int max_tiles, min_tiles = 1;
6005
6007
6008 switch (req->range) {
6010 case REQ_RANGE_ADJACENT:
6011 if (context->tile == nullptr) {
6012 /* The tile itself is included in the range */
6013 max_tiles = 1 + ((req->range == REQ_RANGE_CADJACENT)
6014 ? nmap->num_cardinal_dirs
6015 : nmap->num_valid_dirs);
6016
6017 break;
6018 } else {
6019 Continent_id cont = tile_continent(context->tile);
6020
6021 /* Count how many adjacent tiles there actually are as we go along */
6022 max_tiles = 1;
6023
6026
6027 if (adj_cont == 0 || cont == 0) {
6028 max_tiles++;
6029 } else if (adj_cont == cont) {
6030 min_tiles++;
6031 max_tiles++;
6032 }
6034 }
6035 break;
6037 {
6038 Continent_id cont = context->tile ? tile_continent(context->tile) : 0;
6039
6042
6043 /* Note: We could come up with a better upper bound by subtracting
6044 * all other continent/ocean sizes, or all except the largest if we
6045 * don't know the tile.
6046 * We could even do a flood-fill count of the unknown area bordered
6047 * by known tiles of the continent.
6048 * Probably not worth the effort though. */
6049 max_tiles = nmap->xsize * nmap->ysize;
6050
6051 if (cont > 0) {
6052 min_tiles = nmap->continent_sizes[cont];
6053 if (is_whole_continent_known(cont)) {
6055 }
6056 } else if (cont < 0) {
6057 min_tiles = nmap->ocean_sizes[-cont];
6058 if (is_whole_ocean_known(-cont)) {
6060 }
6061 }
6062 }
6063 break;
6064 default:
6066 "Illegal range %d for max region tiles requirement.",
6067 req->range);
6068 return TRI_MAYBE;
6069 }
6070
6071 if (min_tiles > req->source.value.region_tiles) {
6072 return TRI_NO;
6073 } else if (max_tiles <= req->source.value.region_tiles) {
6074 return TRI_YES;
6075 }
6076 return TRI_MAYBE;
6077}
6078
6079/**********************************************************************/
6087static enum fc_tristate
6089 const struct req_context *context,
6090 const struct req_context *other_context,
6091 const struct requirement *req)
6092{
6094
6096}
6097
6098/**********************************************************************/
6106static enum fc_tristate
6108 const struct req_context *context,
6109 const struct req_context *other_context,
6110 const struct requirement *req)
6111{
6113
6115 >= req->source.value.mincalfrag);
6116}
6117
6118/**********************************************************************/
6126static enum fc_tristate
6128 const struct req_context *context,
6129 const struct req_context *other_context,
6130 const struct requirement *req)
6131{
6133
6134 return BOOL_TO_TRISTATE(
6136}
6137
6138/**********************************************************************/
6146static enum fc_tristate
6148 const struct req_context *context,
6149 const struct req_context *other_context,
6150 const struct requirement *req)
6151{
6153
6154 return BOOL_TO_TRISTATE(
6156}
6157
6158/**********************************************************************/
6166static enum fc_tristate
6168 const struct req_context *context,
6169 const struct req_context *other_context,
6170 const struct requirement *req)
6171{
6173
6175 req->source.value.ssetval));
6176}
6177
6178/* Not const for potential ruleset-related adjustment */
6181
6182 /* Alphabetical order of enum constant */
6245};
6246
6247/**********************************************************************/
6261 const struct req_context *other_context,
6262 const struct requirement *req,
6263 const enum req_problem_type prob_type)
6264{
6265 const struct civ_map *nmap = &(wld.map);
6267 req);
6268
6269 if (eval == TRI_MAYBE) {
6270 if (prob_type == RPT_POSSIBLE) {
6271 return TRUE;
6272 } else {
6273 return FALSE;
6274 }
6275 }
6276 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
6277}
6278
6279/**********************************************************************/
6288static
6290 const struct req_context *context,
6291 const struct req_context *other_context,
6292 const struct requirement *req)
6293{
6294 if (!context) {
6296 }
6297 if (!other_context) {
6299 }
6300
6301 if (req->source.kind >= VUT_COUNT) {
6302 log_error("tri_req_present(): invalid source kind %d.",
6303 req->source.kind);
6304 return TRI_NO;
6305 }
6306
6308
6309 return req_definitions[req->source.kind].cb(nmap, context,
6310 other_context, req);
6311}
6312
6313/**********************************************************************/
6323 const struct req_context *other_context,
6324 const struct requirement *req)
6325{
6326 const struct civ_map *nmap = &(wld.map);
6328
6329 if (!req->present) {
6330 if (TRI_NO == eval) {
6331 return TRI_YES;
6332 }
6333 if (TRI_YES == eval) {
6334 return TRI_NO;
6335 }
6336 }
6337
6338 return eval;
6339}
6340
6341/**********************************************************************/
6357 const struct req_context *other_context,
6358 const struct requirement_vector *reqs,
6359 const enum req_problem_type prob_type)
6360{
6363 return FALSE;
6364 }
6366
6367 return TRUE;
6368}
6369
6370/**********************************************************************/
6375 const enum req_range max_range,
6376 const struct req_context *context,
6377 const struct req_context *other_context,
6378 const struct requirement_vector *reqs,
6379 const enum req_problem_type prob_type)
6380{
6382 if (preq->range >= min_range && preq->range <= max_range) {
6384 return FALSE;
6385 }
6386 }
6388
6389 return TRUE;
6390}
6391
6392/**********************************************************************/
6398enum fc_tristate
6400 const struct req_context *context,
6401 const struct req_context *other_context,
6402 const struct requirement *req)
6403{
6404 /* FIXME: Doubles code from calendar.c */
6408 int fragment1 = fragment; /* If fragments don't advance */
6409 int year_inc, year_inc1;
6412 bool present, present1;
6413
6414 fc_assert(pass >= 0 && period >= 0);
6415 if (slowdown >= 3) {
6416 if (ypt > 1) {
6417 ypt = 1;
6418 }
6419 } else if (slowdown >= 2) {
6420 if (ypt > 2) {
6421 ypt = 2;
6422 }
6423 } else if (slowdown >= 1) {
6424 if (ypt > 5) {
6425 ypt = 5;
6426 }
6427 }
6428 year_inc = ypt * pass;
6431 int fragment_years;
6432
6433 fragment += fpt * pass;
6441 }
6443 if (year_inc + game.info.year >= 0) {
6444 year_inc++;
6445 year_inc1++;
6446 } else if (year_inc1 + game.info.year >= 0) {
6447 year_inc1++;
6448 }
6449 }
6450
6451 switch (req->source.kind) {
6452 case VUT_AGE:
6453 switch (req->range) {
6454 case REQ_RANGE_LOCAL:
6455 if (context->unit == nullptr || !is_server()) {
6456 return TRI_MAYBE;
6457 } else {
6458 int ua = game.info.turn + pass - context->unit->birth_turn;
6459
6460 present = req->source.value.age <= ua;
6461 present1 = req->source.value.age <= ua + period;
6462 }
6463 break;
6464 case REQ_RANGE_CITY:
6465 if (context->city == nullptr) {
6466 return TRI_MAYBE;
6467 } else {
6468 int ca = game.info.turn + pass - context->city->turn_founded;
6469
6470 present = req->source.value.age <= ca;
6471 present1 = req->source.value.age <= ca + period;
6472 }
6473 break;
6474 case REQ_RANGE_PLAYER:
6475 if (context->player == nullptr) {
6476 return TRI_MAYBE;
6477 } else {
6478 present = req->source.value.age
6479 <= player_age(context->player) + pass;
6480 present1 = req->source.value.age
6481 <= player_age(context->player) + pass + period;
6482 }
6483 break;
6484 default:
6485 return TRI_MAYBE;
6486 }
6487 break;
6488 case VUT_FORM_AGE:
6489 if (context->unit == nullptr || !is_server()) {
6490 return TRI_MAYBE;
6491 } else {
6492 int ua = game.info.turn + pass - context->unit->current_form_turn;
6493
6494 present = req->source.value.form_age <= ua;
6495 present1 = req->source.value.form_age <= ua + period;
6496 }
6497 break;
6498 case VUT_MINYEAR:
6499 present = game.info.year + year_inc >= req->source.value.minyear;
6501 break;
6502 case VUT_MINCALFRAG:
6504 /* Hope that the requirement is valid and fragments advance fine */
6505 return TRI_YES;
6506 }
6507 present = fragment >= req->source.value.mincalfrag;
6509 break;
6510 default:
6511 /* No special handling invented */
6512 return tri_req_active(context, other_context, req);
6513 }
6514 return BOOL_TO_TRISTATE(req->present
6515 ? present || present1 : !(present && present1));
6516}
6517
6518/**********************************************************************/
6524 (const struct req_context *context,
6525 const struct req_context *other_context,
6526 const struct requirement *req,
6527 void *data, int n_data)
6528{
6529 int i;
6530
6531 fc_assert_ret_val(data || n_data == 0, TRI_NO);
6532
6533 for (i = 0; i < n_data; i++) {
6534 if (are_requirements_contradictions(&((struct requirement *) data)[i],
6535 req)) {
6536 return TRI_NO;
6537 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
6538 return TRI_YES;
6539 }
6540 }
6541
6542 return tri_req_active(context, other_context, req);
6543}
6544
6545/**********************************************************************/
6551enum fc_tristate
6553 const struct req_context *other_context,
6554 const struct requirement_vector *reqs,
6557 void *data, int n_data)
6558{
6559 bool active = TRUE;
6560 bool certain = TRUE;
6561
6562 fc_assert_ret_val(tester != nullptr, TRI_NO);
6563
6566 data, n_data)) {
6567 case TRI_NO:
6568 active = FALSE;
6569 certain = TRUE;
6570 break;
6571 case TRI_YES:
6572 break;
6573 case TRI_MAYBE:
6574 certain = FALSE;
6575 if (maybe_reqs) {
6577 }
6578 break;
6579 default:
6581 active = FALSE;
6582 }
6583 if (!active) {
6584 break;
6585 }
6587
6588 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
6589}
6590
6591/**********************************************************************/
6601 const struct requirement *req)
6602{
6603 enum req_unchanging_status s;
6604 const struct civ_map *nmap = &(wld.map);
6605
6608 "Invalid source kind %d.", req->source.kind);
6610
6611 if (req->survives) {
6612 /* Special case for surviving requirements */
6613 /* Buildings may obsolete even here */
6614 if (VUT_IMPROVEMENT == req->source.kind) {
6615 const struct impr_type *b = req->source.value.building;
6616
6618 if (improvement_obsolete(context->player, b, context->city)) {
6619 /* FIXME: Sometimes can unobsolete, but considering it
6620 * may sometimes put the function on endless recursion */
6621 return REQUCH_ACT; /* Mostly about techs */
6622 } else {
6623 /* NOTE: May obsoletion reqs be unchanging? Hardly but why not. */
6624 return REQUCH_NO;
6625 }
6626 }
6627 }
6628 s = unchanging_present(nmap, s, context, req);
6629 if (s != REQUCH_NO) {
6630 return unchanging_noally(nmap, s, context, req);
6631 }
6632 } else {
6635
6636 if (cond) {
6637 return cond(nmap, s, context, req);
6638 }
6639 }
6640
6641 return s;
6642}
6643
6644/**********************************************************************/
6649 const struct req_context *other_context,
6650 const struct requirement *req,
6652{
6654
6655 if (REQUCH_NO != u) {
6656 /* Presence is precalculated */
6657 bool auto_present = (req->survives
6658 && !(VUT_IMPROVEMENT == req->source.kind
6662
6663 if (auto_present ? req->present
6665 /* Unchanging but does not block */
6666 return REQUCH_NO;
6667 }
6668 }
6669
6670 return u;
6671}
6672
6673/**********************************************************************/
6677bool is_req_in_vec(const struct requirement *req,
6678 const struct requirement_vector *vec)
6679{
6681 if (are_requirements_equal(req, preq)) {
6682 return TRUE;
6683 }
6685
6686 return FALSE;
6687}
6688
6689/**********************************************************************/
6697 enum universals_n kind)
6698{
6700 if (preq->present && preq->source.kind == kind) {
6701 return TRUE;
6702 }
6704 return FALSE;
6705}
6706
6707/**********************************************************************/
6716{
6717 switch (source->kind) {
6718 case VUT_ACTION:
6719 return !action_is_in_use(source->value.action);
6720 case VUT_UTFLAG:
6721 return !utype_flag_is_in_use(source->value.unitflag);
6722 case VUT_UCFLAG:
6723 return !uclass_flag_is_in_use(source->value.unitclassflag);
6724 case VUT_EXTRAFLAG:
6725 return !extra_flag_is_in_use(source->value.extraflag);
6726 case VUT_MINLATITUDE:
6727 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
6728 case VUT_MAXLATITUDE:
6729 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
6730 case VUT_COUNTER:
6731 case VUT_OTYPE:
6732 case VUT_SPECIALIST:
6733 case VUT_AI_LEVEL:
6734 case VUT_CITYTILE:
6735 case VUT_CITYSTATUS:
6736 case VUT_STYLE:
6737 case VUT_TOPO:
6738 case VUT_WRAP:
6739 case VUT_SERVERSETTING:
6740 case VUT_NATION:
6741 case VUT_NATIONGROUP:
6742 case VUT_ADVANCE:
6743 case VUT_TECHFLAG:
6744 case VUT_GOVERNMENT:
6745 case VUT_ACHIEVEMENT:
6746 case VUT_IMPROVEMENT:
6747 case VUT_SITE:
6748 case VUT_IMPR_GENUS:
6749 case VUT_IMPR_FLAG:
6750 case VUT_PLAYER_FLAG:
6751 case VUT_PLAYER_STATE:
6752 case VUT_MINSIZE:
6753 case VUT_MINCULTURE:
6754 case VUT_MINFOREIGNPCT:
6755 case VUT_MINTECHS:
6756 case VUT_MINCITIES:
6757 case VUT_NATIONALITY:
6758 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
6759 case VUT_DIPLREL:
6760 case VUT_DIPLREL_TILE:
6761 case VUT_DIPLREL_TILE_O:
6764 case VUT_MAXTILEUNITS:
6765 case VUT_UTYPE:
6766 case VUT_UCLASS:
6767 case VUT_MINVETERAN:
6768 case VUT_UNITSTATE:
6769 case VUT_ACTIVITY:
6770 case VUT_MINMOVES:
6771 case VUT_MINHP:
6772 case VUT_AGE:
6773 case VUT_FORM_AGE:
6774 case VUT_ROADFLAG:
6775 case VUT_MINCALFRAG:
6776 case VUT_TERRAIN:
6777 case VUT_EXTRA:
6778 case VUT_GOOD:
6779 case VUT_TERRAINCLASS:
6780 case VUT_TERRFLAG:
6781 case VUT_TERRAINALTER:
6782 case VUT_MINYEAR:
6785 case VUT_TILE_REL:
6786 case VUT_NONE:
6787 case VUT_COUNT:
6788 /* Not implemented. */
6789 break;
6790 }
6791
6792 return FALSE;
6793}
6794
6795/**********************************************************************/
6804{
6805 /* Not known to be impossible to fulfill */
6806 return req->present && universal_never_there(&req->source);
6807}
6808
6809/**********************************************************************/
6818{
6821 return TRUE;
6822 }
6824
6825 /* Not known to be impossible to fulfill */
6826 return FALSE;
6827}
6828
6829/**********************************************************************/
6839 const struct requirement_vector *vec)
6840{
6841 if (vec) {
6842 return 0;
6843 } else {
6844 return -1;
6845 }
6846}
6847
6848/********************************************************************/
6857struct requirement_vector *
6859{
6860 fc_assert_ret_val(number == 0, nullptr);
6861
6862 return (struct requirement_vector *)parent_item;
6863}
6864
6865/**********************************************************************/
6876const char *req_vec_change_translation(const struct req_vec_change *change,
6878{
6879 const char *req_vec_description;
6880 static char buf[MAX_LEN_NAME * 3];
6881 struct astring astr;
6882
6883 fc_assert_ret_val(change, nullptr);
6885 nullptr);
6886
6887 /* Get rid of the previous. */
6888 buf[0] = '\0';
6889
6890 if (namer == nullptr) {
6891 /* TRANS: default description of a requirement vector
6892 * (used in ruledit) */
6893 req_vec_description = _("the requirement vector");
6894 } else {
6896 }
6897
6898 switch (change->operation) {
6899 case RVCO_REMOVE:
6900 fc_snprintf(buf, sizeof(buf),
6901 /* TRANS: remove a requirement from a requirement vector
6902 * (in ruledit).
6903 * The first %s is the operation.
6904 * The second %s is the requirement.
6905 * The third %s is a description of the requirement vector,
6906 * like "actor_reqs" */
6907 _("%s %s from %s"),
6909 req_to_fstring(&change->req, &astr),
6911 astr_free(&astr);
6912 break;
6913 case RVCO_APPEND:
6914 fc_snprintf(buf, sizeof(buf),
6915 /* TRANS: append a requirement to a requirement vector
6916 * (in ruledit).
6917 * The first %s is the operation.
6918 * The second %s is the requirement.
6919 * The third %s is a description of the requirement vector,
6920 * like "actor_reqs" */
6921 _("%s %s to %s"),
6923 req_to_fstring(&change->req, &astr),
6925 astr_free(&astr);
6926 break;
6927 case RVCO_NOOP:
6928 fc_snprintf(buf, sizeof(buf),
6929 /* TRANS: do nothing to a requirement vector (in ruledit).
6930 * The first %s is a description of the requirement vector,
6931 * like "actor_reqs" */
6932 _("Do nothing to %s"), req_vec_description);
6933 break;
6934 }
6935
6936 return buf;
6937}
6938
6939/**********************************************************************/
6952 const void *parent_item)
6953{
6954 struct requirement_vector *target
6955 = getter(parent_item, modification->vector_number);
6956 int i = 0;
6957
6958 switch (modification->operation) {
6959 case RVCO_APPEND:
6961 return TRUE;
6962 case RVCO_REMOVE:
6966 return TRUE;
6967 }
6968 i++;
6970 return FALSE;
6971 case RVCO_NOOP:
6972 return FALSE;
6973 }
6974
6975 return FALSE;
6976}
6977
6978/**********************************************************************/
6988struct req_vec_problem *
6990 const char *description,
6991 const char *description_translated)
6992{
6993 struct req_vec_problem *out;
6994 int i;
6995
6996 out = fc_malloc(sizeof(*out));
6997
6998 fc_strlcpy(out->description, description, sizeof(out->description));
6999 fc_strlcpy(out->description_translated, _(description_translated),
7000 sizeof(out->description_translated));
7001
7002 out->num_suggested_solutions = num_suggested_solutions;
7003 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
7004 * sizeof(struct req_vec_change));
7005 for (i = 0; i < out->num_suggested_solutions; i++) {
7006 /* No suggestions are ready yet. */
7007 out->suggested_solutions[i].operation = RVCO_NOOP;
7008 out->suggested_solutions[i].vector_number = -1;
7009 out->suggested_solutions[i].req.source.kind = VUT_NONE;
7010 }
7011
7012 return out;
7013}
7014
7015/**********************************************************************/
7025 const char *descr, ...)
7026{
7027 char description[500];
7028 char description_translated[500];
7029 va_list ap;
7030
7031 va_start(ap, descr);
7032 fc_vsnprintf(description, sizeof(description), descr, ap);
7033 va_end(ap);
7034
7035 va_start(ap, descr);
7037 _(descr), ap);
7038 va_end(ap);
7039
7042}
7043
7044/**********************************************************************/
7051{
7052 FC_FREE(issue->suggested_solutions);
7053 issue->num_suggested_solutions = 0;
7054
7055 FC_FREE(issue);
7056}
7057
7058/**********************************************************************/
7070struct req_vec_problem *
7073 const void *parent_item)
7074{
7075 int i, j;
7077
7078 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7079 /* No vector. */
7080 return nullptr;
7081 }
7082
7083 if (get_num == nullptr || parent_item == nullptr) {
7084 vec_num = 0;
7085 } else {
7086 vec_num = get_num(parent_item, vec);
7087 }
7088
7089 /* Look for contradictions */
7090 for (i = 0; i < requirement_vector_size(vec); i++) {
7091 struct requirement *preq = requirement_vector_get(vec, i);
7092 for (j = 0; j < requirement_vector_size(vec); j++) {
7093 struct requirement *nreq = requirement_vector_get(vec, j);
7094
7096 struct req_vec_problem *problem;
7097 struct astring astr;
7098 struct astring nastr;
7099
7101 N_("Requirements {%s} and {%s} contradict each other."),
7103
7104 astr_free(&astr);
7105 astr_free(&nastr);
7106
7107 /* The solution is to remove one of the contradictions. */
7108 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7109 problem->suggested_solutions[0].vector_number = vec_num;
7110 problem->suggested_solutions[0].req = *preq;
7111
7112 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7113 problem->suggested_solutions[1].vector_number = vec_num;
7114 problem->suggested_solutions[1].req = *nreq;
7115
7116 /* Only the first contradiction is reported. */
7117 return problem;
7118 }
7119 }
7120 }
7121
7122 return nullptr;
7123}
7124
7125/**********************************************************************/
7136struct req_vec_problem *
7139 const void *parent_item)
7140{
7141 /* Check for self contradictins. */
7143}
7144
7145/**********************************************************************/
7158struct req_vec_problem *
7161 const void *parent_item)
7162{
7163 int i;
7165 struct req_vec_problem *problem = nullptr;
7166
7167 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7168 /* No vector. */
7169 return nullptr;
7170 }
7171
7172 if (get_num == nullptr || parent_item == nullptr) {
7173 vec_num = 0;
7174 } else {
7175 vec_num = get_num(parent_item, vec);
7176 }
7177
7178 /* Look for contradictions */
7179 for (i = 0; i < requirement_vector_size(vec); i++) {
7180 struct requirement *preq = requirement_vector_get(vec, i);
7181
7182 if (universal_never_there(&preq->source)) {
7183 struct astring astr;
7184
7185 if (preq->present) {
7186 /* The requirement vector can never be fulfilled. Removing the
7187 * requirement makes it possible to fulfill it. This is a rule
7188 * change and shouldn't be "fixed" without thinking. Don't offer any
7189 * automatic solution to prevent mindless "fixes". */
7190 /* TRANS: Ruledit warns a user about an unused requirement vector
7191 * that never can be fulfilled because it asks for something that
7192 * never will be there. */
7193 if (problem == nullptr) {
7195 N_("Requirement {%s} requires %s but it will never be"
7196 " there."),
7198 astr_free(&astr);
7199 }
7200
7201 /* Continue to check if other problems have a solution proposal,
7202 * and prefer to return those. */
7203 continue;
7204 }
7205
7206 if (problem != nullptr) {
7207 /* Free previous one (one with no solution proposals) */
7209 }
7210
7212 N_("Requirement {%s} mentions %s but it will never be there."),
7214
7215 astr_free(&astr);
7216
7217 /* The solution is to remove the reference to the missing
7218 * universal. */
7219 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7220 problem->suggested_solutions[0].vector_number = vec_num;
7221 problem->suggested_solutions[0].req = *preq;
7222
7223 /* Only the first missing universal is reported. */
7224 return problem;
7225 }
7226 }
7227
7228 return problem;
7229}
7230
7231/**********************************************************************/
7244struct req_vec_problem *
7247 const void *parent_item)
7248{
7249 int i, j;
7251
7252 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7253 /* No vector. */
7254 return nullptr;
7255 }
7256
7257 if (get_num == nullptr || parent_item == nullptr) {
7258 vec_num = 0;
7259 } else {
7260 vec_num = get_num(parent_item, vec);
7261 }
7262
7263 /* Look for repeated requirements */
7264 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
7265 struct requirement *preq = requirement_vector_get(vec, i);
7266 for (j = i + 1; j < requirement_vector_size(vec); j++) {
7267 struct requirement *nreq = requirement_vector_get(vec, j);
7268
7270 struct req_vec_problem *problem;
7271 struct astring astr;
7272 struct astring nastr;
7273
7275 N_("Requirements {%s} and {%s} are the same."),
7277
7278 astr_free(&astr);
7279 astr_free(&nastr);
7280
7281 /* The solution is to remove one of the redundant requirements. */
7282 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7283 problem->suggested_solutions[0].vector_number = vec_num;
7284 problem->suggested_solutions[0].req = *preq;
7285
7286 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7287 problem->suggested_solutions[1].vector_number = vec_num;
7288 problem->suggested_solutions[1].req = *nreq;
7289
7290 /* Only the first redundancy is reported. */
7291 return problem;
7292 }
7293 }
7294 }
7295
7296 return nullptr;
7297}
7298
7299/**********************************************************************/
7311struct req_vec_problem *
7314 const void *parent_item)
7315{
7316 struct req_vec_problem *out;
7317
7319 if (out != nullptr) {
7320 /* A bug, not just a potential improvement */
7321 return out;
7322 }
7323
7324 /* Check if a universal that never will appear in the game is checked. */
7326 if (out != nullptr) {
7327 return out;
7328 }
7329
7330 /* Check if a requirement is redundant. */
7332 return out;
7333}
7334
7335/**********************************************************************/
7340 const struct universal *psource2)
7341{
7342 if (psource1->kind != psource2->kind) {
7343 return FALSE;
7344 }
7345 switch (psource1->kind) {
7346 case VUT_NONE:
7347 return TRUE;
7348 case VUT_COUNTER:
7349 return psource1->value.counter == psource2->value.counter;
7350 case VUT_ADVANCE:
7351 return psource1->value.advance == psource2->value.advance;
7352 case VUT_TECHFLAG:
7353 return psource1->value.techflag == psource2->value.techflag;
7354 case VUT_GOVERNMENT:
7355 return psource1->value.govern == psource2->value.govern;
7356 case VUT_ACHIEVEMENT:
7357 return psource1->value.achievement == psource2->value.achievement;
7358 case VUT_STYLE:
7359 return psource1->value.style == psource2->value.style;
7360 case VUT_IMPROVEMENT:
7361 case VUT_SITE:
7362 return psource1->value.building == psource2->value.building;
7363 case VUT_IMPR_GENUS:
7364 return psource1->value.impr_genus == psource2->value.impr_genus;
7365 case VUT_IMPR_FLAG:
7366 return psource1->value.impr_flag == psource2->value.impr_flag;
7367 case VUT_PLAYER_FLAG:
7368 return psource1->value.plr_flag == psource2->value.plr_flag;
7369 case VUT_PLAYER_STATE:
7370 return psource1->value.plrstate == psource2->value.plrstate;
7371 case VUT_EXTRA:
7372 return psource1->value.extra == psource2->value.extra;
7373 case VUT_GOOD:
7374 return psource1->value.good == psource2->value.good;
7375 case VUT_TERRAIN:
7376 return psource1->value.terrain == psource2->value.terrain;
7377 case VUT_TERRFLAG:
7378 return psource1->value.terrainflag == psource2->value.terrainflag;
7379 case VUT_NATION:
7380 return psource1->value.nation == psource2->value.nation;
7381 case VUT_NATIONGROUP:
7382 return psource1->value.nationgroup == psource2->value.nationgroup;
7383 case VUT_NATIONALITY:
7384 return psource1->value.nationality == psource2->value.nationality;
7385 case VUT_ORIGINAL_OWNER:
7386 return psource1->value.origowner == psource2->value.origowner;
7387 case VUT_DIPLREL:
7388 case VUT_DIPLREL_TILE:
7389 case VUT_DIPLREL_TILE_O:
7392 return psource1->value.diplrel == psource2->value.diplrel;
7393 case VUT_UTYPE:
7394 return psource1->value.utype == psource2->value.utype;
7395 case VUT_UTFLAG:
7396 return psource1->value.unitflag == psource2->value.unitflag;
7397 case VUT_UCLASS:
7398 return psource1->value.uclass == psource2->value.uclass;
7399 case VUT_UCFLAG:
7400 return psource1->value.unitclassflag == psource2->value.unitclassflag;
7401 case VUT_MINVETERAN:
7402 return psource1->value.minveteran == psource2->value.minveteran;
7403 case VUT_UNITSTATE:
7404 return psource1->value.unit_state == psource2->value.unit_state;
7405 case VUT_ACTIVITY:
7406 return psource1->value.activity == psource2->value.activity;
7407 case VUT_MINMOVES:
7408 return psource1->value.minmoves == psource2->value.minmoves;
7409 case VUT_MINHP:
7410 return psource1->value.min_hit_points == psource2->value.min_hit_points;
7411 case VUT_AGE:
7412 return psource1->value.age == psource2->value.age;
7413 case VUT_FORM_AGE:
7414 return psource1->value.form_age == psource2->value.form_age;
7415 case VUT_MINTECHS:
7416 return psource1->value.min_techs == psource2->value.min_techs;
7417 case VUT_MINCITIES:
7418 return psource1->value.min_cities == psource2->value.min_cities;
7419 case VUT_ACTION:
7420 return (action_number(psource1->value.action)
7421 == action_number(psource2->value.action));
7422 case VUT_OTYPE:
7423 return psource1->value.outputtype == psource2->value.outputtype;
7424 case VUT_SPECIALIST:
7425 return psource1->value.specialist == psource2->value.specialist;
7426 case VUT_MINSIZE:
7427 return psource1->value.minsize == psource2->value.minsize;
7428 case VUT_MINCULTURE:
7429 return psource1->value.minculture == psource2->value.minculture;
7430 case VUT_MINFOREIGNPCT:
7431 return psource1->value.minforeignpct == psource2->value.minforeignpct;
7432 case VUT_AI_LEVEL:
7433 return psource1->value.ai_level == psource2->value.ai_level;
7434 case VUT_MAXTILEUNITS:
7435 return psource1->value.max_tile_units == psource2->value.max_tile_units;
7436 case VUT_TERRAINCLASS:
7437 return psource1->value.terrainclass == psource2->value.terrainclass;
7438 case VUT_ROADFLAG:
7439 return psource1->value.roadflag == psource2->value.roadflag;
7440 case VUT_EXTRAFLAG:
7441 return psource1->value.extraflag == psource2->value.extraflag;
7442 case VUT_MINYEAR:
7443 return psource1->value.minyear == psource2->value.minyear;
7444 case VUT_MINCALFRAG:
7445 return psource1->value.mincalfrag == psource2->value.mincalfrag;
7446 case VUT_TOPO:
7447 return psource1->value.topo_property == psource2->value.topo_property;
7448 case VUT_WRAP:
7449 return psource1->value.wrap_property == psource2->value.wrap_property;
7450 case VUT_SERVERSETTING:
7451 return psource1->value.ssetval == psource2->value.ssetval;
7452 case VUT_TERRAINALTER:
7453 return psource1->value.terrainalter == psource2->value.terrainalter;
7454 case VUT_CITYTILE:
7455 return psource1->value.citytile == psource2->value.citytile;
7456 case VUT_CITYSTATUS:
7457 return psource1->value.citystatus == psource2->value.citystatus;
7458 case VUT_TILE_REL:
7459 return psource1->value.tilerel == psource2->value.tilerel;
7460 case VUT_MINLATITUDE:
7461 case VUT_MAXLATITUDE:
7462 return psource1->value.latitude == psource2->value.latitude;
7464 return psource1->value.distance_sq == psource2->value.distance_sq;
7466 return psource1->value.region_tiles == psource2->value.region_tiles;
7467 case VUT_COUNT:
7468 break;
7469 }
7470
7471 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
7472 return FALSE;
7473}
7474
7475/**********************************************************************/
7479const char *universal_rule_name(const struct universal *psource)
7480{
7481 static char buffer[10];
7482
7483 switch (psource->kind) {
7484 case VUT_NONE:
7485 return "(none)";
7486 case VUT_COUNTER:
7487 return counter_rule_name(psource->value.counter);
7488 case VUT_CITYTILE:
7489 return citytile_type_name(psource->value.citytile);
7490 case VUT_CITYSTATUS:
7491 return citystatus_type_name(psource->value.citystatus);
7492 case VUT_TILE_REL:
7493 return tilerel_type_name(psource->value.tilerel);
7494 case VUT_MINYEAR:
7495 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
7496
7497 return buffer;
7498 case VUT_MINCALFRAG:
7499 /* Rule name is 0-based number, not pretty name from ruleset */
7500 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
7501
7502 return buffer;
7503 case VUT_TOPO:
7504 return topo_flag_name(psource->value.topo_property);
7505 case VUT_WRAP:
7506 return wrap_flag_name(psource->value.wrap_property);
7507 case VUT_SERVERSETTING:
7508 return ssetv_rule_name(psource->value.ssetval);
7509 case VUT_ADVANCE:
7510 return advance_rule_name(psource->value.advance);
7511 case VUT_TECHFLAG:
7512 return tech_flag_id_name(psource->value.techflag);
7513 case VUT_GOVERNMENT:
7514 return government_rule_name(psource->value.govern);
7515 case VUT_ACHIEVEMENT:
7516 return achievement_rule_name(psource->value.achievement);
7517 case VUT_STYLE:
7518 return style_rule_name(psource->value.style);
7519 case VUT_IMPROVEMENT:
7520 case VUT_SITE:
7521 return improvement_rule_name(psource->value.building);
7522 case VUT_IMPR_GENUS:
7523 return impr_genus_id_name(psource->value.impr_genus);
7524 case VUT_IMPR_FLAG:
7525 return impr_flag_id_name(psource->value.impr_flag);
7526 case VUT_PLAYER_FLAG:
7527 return plr_flag_id_name(psource->value.plr_flag);
7528 case VUT_PLAYER_STATE:
7529 return plrstate_type_name(psource->value.plrstate);
7530 case VUT_EXTRA:
7531 return extra_rule_name(psource->value.extra);
7532 case VUT_GOOD:
7533 return goods_rule_name(psource->value.good);
7534 case VUT_TERRAIN:
7535 return terrain_rule_name(psource->value.terrain);
7536 case VUT_TERRFLAG:
7537 return terrain_flag_id_name(psource->value.terrainflag);
7538 case VUT_NATION:
7539 return nation_rule_name(psource->value.nation);
7540 case VUT_NATIONGROUP:
7541 return nation_group_rule_name(psource->value.nationgroup);
7542 case VUT_DIPLREL:
7543 case VUT_DIPLREL_TILE:
7544 case VUT_DIPLREL_TILE_O:
7547 return diplrel_rule_name(psource->value.diplrel);
7548 case VUT_NATIONALITY:
7549 return nation_rule_name(psource->value.nationality);
7550 case VUT_ORIGINAL_OWNER:
7551 return nation_rule_name(psource->value.origowner);
7552 case VUT_UTYPE:
7553 return utype_rule_name(psource->value.utype);
7554 case VUT_UTFLAG:
7555 return unit_type_flag_id_name(psource->value.unitflag);
7556 case VUT_UCLASS:
7557 return uclass_rule_name(psource->value.uclass);
7558 case VUT_UCFLAG:
7559 return unit_class_flag_id_name(psource->value.unitclassflag);
7560 case VUT_MINVETERAN:
7561 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
7562
7563 return buffer;
7564 case VUT_UNITSTATE:
7565 return ustate_prop_name(psource->value.unit_state);
7566 case VUT_ACTIVITY:
7567 return unit_activity_name(psource->value.activity);
7568 case VUT_MINMOVES:
7569 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
7570
7571 return buffer;
7572 case VUT_MINHP:
7573 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
7574
7575 return buffer;
7576 case VUT_AGE:
7577 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
7578
7579 return buffer;
7580 case VUT_FORM_AGE:
7581 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
7582
7583 return buffer;
7584 case VUT_MINTECHS:
7585 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
7586
7587 return buffer;
7588 case VUT_MINCITIES:
7589 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_cities);
7590
7591 return buffer;
7592 case VUT_ACTION:
7593 return action_rule_name(psource->value.action);
7594 case VUT_OTYPE:
7595 return get_output_identifier(psource->value.outputtype);
7596 case VUT_SPECIALIST:
7597 return specialist_rule_name(psource->value.specialist);
7598 case VUT_MINSIZE:
7599 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
7600
7601 return buffer;
7602 case VUT_MINCULTURE:
7603 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
7604
7605 return buffer;
7606 case VUT_MINFOREIGNPCT:
7607 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
7608
7609 return buffer;
7610 case VUT_AI_LEVEL:
7611 return ai_level_name(psource->value.ai_level);
7612 case VUT_MAXTILEUNITS:
7613 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_units);
7614 return buffer;
7615 case VUT_TERRAINCLASS:
7616 return terrain_class_name(psource->value.terrainclass);
7617 case VUT_ROADFLAG:
7618 return road_flag_id_name(psource->value.roadflag);
7619 case VUT_EXTRAFLAG:
7620 return extra_flag_id_name(psource->value.extraflag);
7621 case VUT_TERRAINALTER:
7622 return terrain_alteration_name(psource->value.terrainalter);
7623 case VUT_MINLATITUDE:
7624 case VUT_MAXLATITUDE:
7625 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
7626
7627 return buffer;
7629 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.distance_sq);
7630
7631 return buffer;
7633 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.region_tiles);
7634
7635 return buffer;
7636 case VUT_COUNT:
7637 break;
7638 }
7639
7640 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
7641
7642 return nullptr;
7643}
7644
7645/**********************************************************************/
7654 char *buf, size_t bufsz)
7655{
7656 buf[0] = '\0'; /* to be safe. */
7657 switch (psource->kind) {
7658 case VUT_NONE:
7659 /* TRANS: missing value */
7660 fc_strlcat(buf, _("(none)"), bufsz);
7661 return buf;
7662 case VUT_ADVANCE:
7664 return buf;
7665 case VUT_COUNTER:
7667 return buf;
7668 case VUT_TECHFLAG:
7669 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
7670 tech_flag_id_translated_name(psource->value.techflag));
7671 return buf;
7672 case VUT_GOVERNMENT:
7674 bufsz);
7675 return buf;
7676 case VUT_ACHIEVEMENT:
7678 bufsz);
7679 return buf;
7680 case VUT_STYLE:
7682 bufsz);
7683 return buf;
7684 case VUT_IMPROVEMENT:
7686 bufsz);
7687 return buf;
7688 case VUT_SITE:
7689 {
7690 char local_buf[1024];
7691
7692 fc_snprintf(local_buf, sizeof(local_buf), _("%s site"),
7693 improvement_name_translation(psource->value.building));
7695 }
7696
7697 return buf;
7698 case VUT_IMPR_GENUS:
7700 impr_genus_id_translated_name(psource->value.impr_genus),
7701 bufsz);
7702 return buf;
7703 case VUT_IMPR_FLAG:
7705 impr_flag_id_translated_name(psource->value.impr_flag),
7706 bufsz);
7707 return buf;
7708 case VUT_PLAYER_FLAG:
7710 plr_flag_id_translated_name(psource->value.plr_flag),
7711 bufsz);
7712 return buf;
7713 case VUT_PLAYER_STATE:
7715 plrstate_type_translated_name(psource->value.plrstate),
7716 bufsz);
7717 return buf;
7718 case VUT_EXTRA:
7720 return buf;
7721 case VUT_GOOD:
7723 return buf;
7724 case VUT_TERRAIN:
7726 return buf;
7727 case VUT_NATION:
7729 bufsz);
7730 return buf;
7731 case VUT_NATIONGROUP:
7733 bufsz);
7734 return buf;
7735 case VUT_NATIONALITY:
7736 cat_snprintf(buf, bufsz, _("%s citizens"),
7737 nation_adjective_translation(psource->value.nationality));
7738 return buf;
7739 case VUT_ORIGINAL_OWNER:
7740 /* TRANS: Keep short. City founding nation. */
7741 cat_snprintf(buf, bufsz, _("%s original owner"),
7742 nation_adjective_translation(psource->value.origowner));
7743 return buf;
7744 case VUT_DIPLREL:
7745 case VUT_DIPLREL_TILE:
7746 case VUT_DIPLREL_TILE_O:
7750 bufsz);
7751 return buf;
7752 case VUT_UTYPE:
7754 return buf;
7755 case VUT_UTFLAG:
7757 /* TRANS: Unit type flag */
7758 Q_("?utflag:\"%s\" units"),
7760 psource->value.unitflag));
7761 return buf;
7762 case VUT_UCLASS:
7764 /* TRANS: Unit class */
7765 _("%s units"),
7766 uclass_name_translation(psource->value.uclass));
7767 return buf;
7768 case VUT_UCFLAG:
7770 /* TRANS: Unit class flag */
7771 Q_("?ucflag:\"%s\" units"),
7773 psource->value.unitclassflag));
7774 return buf;
7775 case VUT_MINVETERAN:
7776 /* FIXME */
7777 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
7778 psource->value.minveteran);
7779 return buf;
7780 case VUT_UNITSTATE:
7781 switch (psource->value.unit_state) {
7782 case USP_TRANSPORTED:
7783 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7784 cat_snprintf(buf, bufsz, _("Transported"));
7785 break;
7786 case USP_LIVABLE_TILE:
7788 /* TRANS: unit state. (appears in strings like
7789 * "Missile+On livable tile") */
7790 _("On livable tile"));
7791 break;
7792 case USP_TRANSPORTING:
7793 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7794 cat_snprintf(buf, bufsz, _("Transporting"));
7795 break;
7796 case USP_HAS_HOME_CITY:
7797 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
7798 cat_snprintf(buf, bufsz, _("Has a home city"));
7799 break;
7800 case USP_NATIVE_TILE:
7802 /* TRANS: unit state. (appears in strings like
7803 * "Missile+On native tile") */
7804 _("On native tile"));
7805 break;
7806 case USP_NATIVE_EXTRA:
7808 /* TRANS: unit state. (appears in strings like
7809 * "Missile+In native extra") */
7810 _("In native extra"));
7811 break;
7813 /* TRANS: unit state. (appears in strings like
7814 * "Missile+Has moved this turn") */
7815 cat_snprintf(buf, bufsz, _("Has moved this turn"));
7816 break;
7817 case USP_COUNT:
7818 fc_assert_msg(psource->value.unit_state != USP_COUNT,
7819 "Invalid unit state property.");
7820 break;
7821 }
7822 return buf;
7823 case VUT_ACTIVITY:
7824 cat_snprintf(buf, bufsz, _("%s activity"),
7825 Q_(unit_activity_name(psource->value.activity)));
7826 return buf;
7827 case VUT_MINMOVES:
7828 /* TRANS: Minimum unit movement points left for requirement to be met
7829 * (%s is a string like "1" or "2 1/3") */
7830 cat_snprintf(buf, bufsz, _("%s MP"),
7831 move_points_text(psource->value.minmoves, TRUE));
7832 return buf;
7833 case VUT_MINHP:
7834 /* TRANS: HP = hit points */
7835 cat_snprintf(buf, bufsz, _("%d HP"),
7836 psource->value.min_hit_points);
7837 return buf;
7838 case VUT_AGE:
7839 cat_snprintf(buf, bufsz, _("Age %d"),
7840 psource->value.age);
7841 return buf;
7842 case VUT_FORM_AGE:
7843 cat_snprintf(buf, bufsz, _("Form age %d"),
7844 psource->value.form_age);
7845 return buf;
7846 case VUT_MINTECHS:
7847 cat_snprintf(buf, bufsz, _("%d Techs"),
7848 psource->value.min_techs);
7849 return buf;
7850 case VUT_MINCITIES:
7851 cat_snprintf(buf, bufsz, _("%d Cities"),
7852 psource->value.min_cities);
7853 return buf;
7854 case VUT_ACTION:
7856 bufsz);
7857 return buf;
7858 case VUT_OTYPE:
7859 /* FIXME */
7860 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
7861 return buf;
7862 case VUT_SPECIALIST:
7864 bufsz);
7865 return buf;
7866 case VUT_MINSIZE:
7867 cat_snprintf(buf, bufsz, _("Size %d"),
7868 psource->value.minsize);
7869 return buf;
7870 case VUT_MINCULTURE:
7871 cat_snprintf(buf, bufsz, _("Culture %d"),
7872 psource->value.minculture);
7873 return buf;
7874 case VUT_MINFOREIGNPCT:
7875 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
7876 psource->value.minforeignpct);
7877 return buf;
7878 case VUT_AI_LEVEL:
7879 /* TRANS: "Hard AI" */
7880 cat_snprintf(buf, bufsz, _("%s AI"),
7881 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
7882 return buf;
7883 case VUT_MAXTILEUNITS:
7884 /* TRANS: here <= means 'less than or equal' */
7885 cat_snprintf(buf, bufsz, PL_("<=%d unit",
7886 "<=%d units", psource->value.max_tile_units),
7887 psource->value.max_tile_units);
7888 return buf;
7889 case VUT_TERRAINCLASS:
7890 /* TRANS: Terrain class: "Land terrain" */
7891 cat_snprintf(buf, bufsz, _("%s terrain"),
7892 terrain_class_name_translation(psource->value.terrainclass));
7893 return buf;
7894 case VUT_TERRFLAG:
7896 /* TRANS: Terrain flag */
7897 Q_("?terrflag:\"%s\" terrain"),
7899 psource->value.terrainflag));
7900 return buf;
7901 case VUT_ROADFLAG:
7903 /* TRANS: Road flag */
7904 Q_("?roadflag:\"%s\" road"),
7905 road_flag_id_translated_name(psource->value.roadflag));
7906 return buf;
7907 case VUT_EXTRAFLAG:
7909 /* TRANS: Extra flag */
7910 Q_("?extraflag:\"%s\" extra"),
7911 extra_flag_id_translated_name(psource->value.extraflag));
7912 return buf;
7913 case VUT_MINYEAR:
7914 cat_snprintf(buf, bufsz, _("After %s"),
7915 textyear(psource->value.minyear));
7916 return buf;
7917 case VUT_MINCALFRAG:
7918 /* TRANS: here >= means 'greater than or equal'.
7919 * %s identifies a calendar fragment (may be bare number). */
7920 cat_snprintf(buf, bufsz, _(">=%s"),
7921 textcalfrag(psource->value.mincalfrag));
7922 return buf;
7923 case VUT_TOPO:
7924 /* TRANS: topology flag name ("Hex", "ISO") */
7925 cat_snprintf(buf, bufsz, _("%s map"),
7926 _(topo_flag_name(psource->value.topo_property)));
7927 return buf;
7928 case VUT_WRAP:
7929 /* TRANS: wrap flag name ("WrapX", "WrapY") */
7930 cat_snprintf(buf, bufsz, _("%s map"),
7931 _(wrap_flag_name(psource->value.wrap_property)));
7932 return buf;
7933 case VUT_SERVERSETTING:
7935 bufsz);
7936 return buf;
7937 case VUT_TERRAINALTER:
7938 /* TRANS: "Irrigation possible" */
7939 cat_snprintf(buf, bufsz, _("%s possible"),
7940 Q_(terrain_alteration_name(psource->value.terrainalter)));
7941 return buf;
7942 case VUT_CITYTILE:
7943 switch (psource->value.citytile) {
7944 case CITYT_CENTER:
7945 fc_strlcat(buf, _("City center"), bufsz);
7946 break;
7947 case CITYT_CLAIMED:
7948 fc_strlcat(buf, _("Tile claimed"), bufsz);
7949 break;
7950 case CITYT_EXTRAS_OWNED:
7951 fc_strlcat(buf, _("Extras owned"), bufsz);
7952 break;
7953 case CITYT_WORKED:
7954 fc_strlcat(buf, _("Worked tile"), bufsz);
7955 break;
7957 fc_strlcat(buf, _("Same continent tile"), bufsz);
7958 break;
7960 /* TRANS: Short for "a tile of other terrain class mass near city" */
7961 fc_strlcat(buf, _("Port reachable tile"), bufsz);
7962 break;
7963 case CITYT_LAST:
7964 fc_assert(psource->value.citytile != CITYT_LAST);
7965 fc_strlcat(buf, "error", bufsz);
7966 break;
7967 }
7968 return buf;
7969 case VUT_CITYSTATUS:
7970 switch (psource->value.citystatus) {
7972 fc_strlcat(buf, _("Owned by original"), bufsz);
7973 break;
7974 case CITYS_STARVED:
7975 fc_strlcat(buf, _("Starved"), bufsz);
7976 break;
7977 case CITYS_DISORDER:
7978 fc_strlcat(buf, _("Disorder"), bufsz);
7979 break;
7980 case CITYS_CELEBRATION:
7981 fc_strlcat(buf, _("Celebration"), bufsz);
7982 break;
7983 case CITYS_TRANSFERRED:
7984 /* TRANS: CityStatus value - city has changed hands */
7985 fc_strlcat(buf, _("Transferred"), bufsz);
7986 break;
7987 case CITYS_LAST:
7988 fc_assert(psource->value.citystatus != CITYS_LAST);
7989 fc_strlcat(buf, "error", bufsz);
7990 break;
7991 }
7992 return buf;
7993 case VUT_TILE_REL:
7994 switch (psource->value.tilerel) {
7995 case TREL_SAME_TCLASS:
7996 fc_strlcat(buf, _("Same terrain class"), bufsz);
7997 break;
7998 case TREL_SAME_REGION:
7999 fc_strlcat(buf, _("Same continent/ocean"), bufsz);
8000 break;
8002 fc_strlcat(buf, _("Only other continent/ocean"), bufsz);
8003 break;
8005 fc_strlcat(buf, _("Lake/island surrounded"), bufsz);
8006 break;
8007 case TREL_COUNT:
8008 fc_assert(psource->value.tilerel != TREL_COUNT);
8009 fc_strlcat(buf, "error", bufsz);
8010 break;
8011 }
8012 return buf;
8013 case VUT_MINLATITUDE:
8014 /* TRANS: here >= means 'greater than or equal'. */
8015 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
8016 psource->value.latitude);
8017 return buf;
8018 case VUT_MAXLATITUDE:
8019 /* TRANS: here <= means 'less than or equal'. */
8020 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
8021 psource->value.latitude);
8022 return buf;
8024 /* TRANS: here <= means 'less than or equal'. */
8025 cat_snprintf(buf, bufsz, _("Squared distance <= %d"),
8026 psource->value.distance_sq);
8027 return buf;
8029 cat_snprintf(buf, bufsz, _("%d or fewer region tiles"),
8030 psource->value.region_tiles);
8031 return buf;
8032 case VUT_COUNT:
8033 break;
8034 }
8035
8036 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8037 return buf;
8038}
8039
8040/**********************************************************************/
8044{
8045 return universals_n_name(psource->kind);
8046}
8047
8048/**********************************************************************/
8052 const struct universal *target)
8053{
8054 switch (target->kind) {
8055 case VUT_IMPROVEMENT:
8056 case VUT_SITE:
8057 return impr_build_shield_cost(pcity, target->value.building);
8058 case VUT_UTYPE:
8059 return utype_build_shield_cost(pcity, nullptr, target->value.utype);
8060 default:
8061 break;
8062 }
8063 return FC_INFINITY;
8064}
8065
8066/**********************************************************************/
8072 const struct universal *to_replace,
8073 const struct universal *replacement)
8074{
8075 bool changed = FALSE;
8076
8079 preq->source = *replacement;
8080 changed = TRUE;
8081 }
8083
8084 return changed;
8085}
8086
8087/**********************************************************************/
8092 const struct requirement_vector *reqs,
8093 const struct universal *psource)
8094{
8097 return TRUE;
8098 }
8100
8101 return FALSE;
8102}
8103
8104/**********************************************************************/
8115 struct universal *unis,
8116 size_t n_unis)
8117{
8118 int i;
8119
8120 for (i = 0; i < n_unis; i++) {
8122 /* This universal makes it impossible to fulfill the specified
8123 * requirement vector */
8124 return TRUE;
8125 }
8126 }
8127
8128 /* No specified universal is known to guarantee that the requirement
8129 * vector never will be fulfilled. */
8130 return FALSE;
8131}
8132
8133/**********************************************************************/
8149 struct universal *unis,
8150 size_t n_unis)
8151{
8153 int i;
8155
8156 for (i = 0; i < n_unis; i++) {
8157 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
8158 case ITF_NO:
8159 case ITF_YES:
8160 /* this req matched this source */
8162 break;
8163 case ITF_NOT_APPLICABLE:
8164 /* Not a mention. */
8165 break;
8166 }
8167 }
8168
8170 /* A requirement not relevant to any of the specified universals was
8171 * found in the requirement vector. */
8172 return FALSE;
8173 }
8175
8176 /* No requirement not relevant to any of the specified universals was
8177 * found in the requirement vector. */
8178 return TRUE;
8179}
8180
8181/**********************************************************************/
8184enum req_item_found
8186 const struct universal *source)
8187{
8190 "No req item found function for %s",
8192
8193 return (*universal_found_function[source->kind])(preq, source);
8194}
8195
8196/**********************************************************************/
8207 const struct requirement_vector *reqs,
8208 const struct universal *source)
8209{
8210 bool necessary = FALSE;
8211
8214 "No req item found function for %s",
8216
8218 switch ((*universal_found_function[source->kind])(preq, source)) {
8219 case ITF_NOT_APPLICABLE:
8220 continue;
8221 case ITF_NO:
8222 if (preq->present) {
8223 return FALSE;
8224 }
8225 break;
8226 case ITF_YES:
8227 if (preq->present) {
8228 necessary = TRUE;
8229 } else {
8230 return FALSE;
8231 }
8232 break;
8233 }
8235
8236 return (!check_necessary || necessary);
8237}
8238
8239/**********************************************************************/
8244 const struct universal *source)
8245{
8246 switch (universal_fulfills_requirement(req, source)) {
8247 case ITF_NOT_APPLICABLE:
8248 return FALSE;
8249 case ITF_NO:
8250 case ITF_YES:
8251 return TRUE;
8252 }
8253
8254 log_error("Unhandled item_found value");
8255 return FALSE;
8256}
8257
8258/**********************************************************************/
8262 const struct universal *source)
8263{
8264 fc_assert(source->value.nation);
8265
8266 switch (preq->source.kind) {
8267 case VUT_NATION:
8268 return preq->source.value.nation == source->value.nation ? ITF_YES
8269 : ITF_NO;
8270 case VUT_NATIONGROUP:
8271 return nation_is_in_group(source->value.nation,
8272 preq->source.value.nationgroup) ? ITF_YES
8273 : ITF_NO;
8274 default:
8275 break;
8276 }
8277
8278 return ITF_NOT_APPLICABLE;
8279}
8280
8281/**********************************************************************/
8285 const struct universal *source)
8286{
8287 fc_assert(source->value.govern);
8288
8289 if (preq->source.kind == VUT_GOVERNMENT) {
8290 return preq->source.value.govern == source->value.govern ? ITF_YES
8291 : ITF_NO;
8292 }
8293
8294 return ITF_NOT_APPLICABLE;
8295}
8296
8297/**********************************************************************/
8301 const struct universal *source)
8302{
8303 fc_assert(source->value.min_cities);
8304
8305 if (preq->source.kind == VUT_MINCITIES) {
8306 return preq->source.value.min_cities <= source->value.min_cities ? ITF_YES
8307 : ITF_NO;
8308 }
8309
8310 return ITF_NOT_APPLICABLE;
8311}
8312
8313/**********************************************************************/
8317 const struct universal *source)
8318{
8319 fc_assert(source->value.building);
8320
8321 /* We only ever return ITF_YES, because requiring a different
8322 * improvement does not mean that the improvement under consideration
8323 * cannot fulfill the requirements. This is necessary to allow
8324 * requirement vectors to specify multiple required improvements. */
8325
8326 switch (preq->source.kind) {
8327 case VUT_IMPROVEMENT:
8328 case VUT_SITE:
8329 if (source->value.building == preq->source.value.building) {
8330 return ITF_YES;
8331 }
8332 break;
8333 case VUT_IMPR_GENUS:
8334 if (source->value.building->genus == preq->source.value.impr_genus) {
8335 return ITF_YES;
8336 }
8337 break;
8338 case VUT_IMPR_FLAG:
8339 if (improvement_has_flag(source->value.building,
8340 preq->source.value.impr_flag)) {
8341 return ITF_YES;
8342 }
8343 break;
8344 default:
8345 break;
8346 }
8347
8348 return ITF_NOT_APPLICABLE;
8349}
8350
8351/**********************************************************************/
8355 const struct universal *source)
8356{
8357 fc_assert(source->value.uclass);
8358
8359 switch (preq->source.kind) {
8360 case VUT_UCLASS:
8361 return source->value.uclass == preq->source.value.uclass ? ITF_YES
8362 : ITF_NO;
8363 case VUT_UCFLAG:
8364 return uclass_has_flag(source->value.uclass,
8365 preq->source.value.unitclassflag) ? ITF_YES
8366 : ITF_NO;
8367
8368 default:
8369 /* Not found and not relevant. */
8370 return ITF_NOT_APPLICABLE;
8371 };
8372}
8373
8374/**********************************************************************/
8378 const struct universal *source)
8379{
8380 fc_assert(source->value.utype);
8381
8382 switch (preq->source.kind) {
8383 case VUT_UTYPE:
8384 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
8385 case VUT_UCLASS:
8386 return utype_class(source->value.utype) == preq->source.value.uclass
8387 ? ITF_YES : ITF_NO;
8388 case VUT_UTFLAG:
8389 return utype_has_flag(source->value.utype,
8390 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
8391 case VUT_UCFLAG:
8392 return uclass_has_flag(utype_class(source->value.utype),
8393 preq->source.value.unitclassflag) ? ITF_YES
8394 : ITF_NO;
8395 default:
8396 /* Not found and not relevant. */
8397 return ITF_NOT_APPLICABLE;
8398 };
8399}
8400
8401/**********************************************************************/
8404static enum req_item_found
8406 const struct universal *source)
8407{
8410
8411 switch (preq->source.kind) {
8412 case VUT_ACTIVITY:
8413 return source->value.activity == preq->source.value.activity ? ITF_YES
8414 : ITF_NO;
8415 default:
8416 /* Not found and not relevant. */
8417 return ITF_NOT_APPLICABLE;
8418 };
8419}
8420
8421/**********************************************************************/
8425 const struct universal *source)
8426{
8427 fc_assert(source->value.terrain);
8428
8429 switch (preq->source.kind) {
8430 case VUT_TERRAIN:
8431 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
8432 case VUT_TERRAINCLASS:
8433 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
8434 ? ITF_YES : ITF_NO;
8435 case VUT_TERRFLAG:
8436 return terrain_has_flag(source->value.terrain,
8437 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
8438 case VUT_TERRAINALTER:
8439 return (terrain_can_support_alteration(source->value.terrain,
8440 preq->source.value.terrainalter)
8441 ? ITF_YES : ITF_NO);
8442 default:
8443 /* Not found and not relevant. */
8444 return ITF_NOT_APPLICABLE;
8445 };
8446}
8447
8448/**********************************************************************/
8452 const struct universal *source)
8453{
8456
8457 switch (preq->source.kind) {
8458 case VUT_CITYTILE:
8459 return (source->value.citytile == preq->source.value.citytile
8460 ? ITF_YES
8461 /* The presence of one tile state doesn't block another */
8463 default:
8464 /* Not found and not relevant. */
8465 return ITF_NOT_APPLICABLE;
8466 };
8467}
8468
8469/**********************************************************************/
8473 const struct universal *source)
8474{
8475 fc_assert(source->value.extra);
8476
8477 switch (preq->source.kind) {
8478 case VUT_EXTRA:
8479 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
8480 case VUT_EXTRAFLAG:
8481 return extra_has_flag(source->value.extra,
8482 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
8483 case VUT_ROADFLAG:
8484 {
8485 struct road_type *r = extra_road_get(source->value.extra);
8486 return r && road_has_flag(r, preq->source.value.roadflag)
8487 ? ITF_YES : ITF_NO;
8488 }
8489 default:
8490 /* Not found and not relevant. */
8491 return ITF_NOT_APPLICABLE;
8492 }
8493}
8494
8495/**********************************************************************/
8499 const struct universal *source)
8500{
8501 fc_assert(source->value.action);
8502
8503 if (preq->source.kind == VUT_ACTION) {
8504 return preq->source.value.action == source->value.action ? ITF_YES
8505 : ITF_NO;
8506 }
8507
8508 return ITF_NOT_APPLICABLE;
8509}
8510
8511/**********************************************************************/
8515 const struct universal *source)
8516{
8518 || source->kind == VUT_DIPLREL_TILE
8519 || source->kind == VUT_DIPLREL_TILE_O
8520 || source->kind == VUT_DIPLREL_UNITANY
8521 || source->kind == VUT_DIPLREL_UNITANY_O),
8523
8524 if (preq->source.kind == source->kind) {
8525 if (preq->source.value.diplrel == source->value.diplrel) {
8526 /* The diplrel itself. */
8527 return ITF_YES;
8528 }
8529 if (preq->source.value.diplrel == DRO_FOREIGN
8530 && source->value.diplrel < DS_LAST) {
8531 /* All diplstate_type values are to foreigners. */
8532 return ITF_YES;
8533 }
8534 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
8535 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
8536 /* A real embassy is an embassy. */
8537 return ITF_YES;
8538 }
8539 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
8540 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
8541 /* A real embassy is an embassy. */
8542 return ITF_YES;
8543 }
8544 if (preq->source.value.diplrel < DS_LAST
8545 && source->value.diplrel < DS_LAST
8546 && preq->range == REQ_RANGE_LOCAL) {
8547 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
8548 ITF_YES);
8549 /* Can only have one diplstate_type to a specific player. */
8550 return ITF_NO;
8551 }
8552 /* Can't say this diplrel blocks the other diplrel. */
8553 return ITF_NOT_APPLICABLE;
8554 }
8555
8556 /* Not relevant. */
8557 return ITF_NOT_APPLICABLE;
8558}
8559
8560/**********************************************************************/
8564 const struct universal *source)
8565{
8566 switch (preq->source.kind) {
8567 case VUT_OTYPE:
8568 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
8569 : ITF_NO;
8570 default:
8571 /* Not found and not relevant. */
8572 return ITF_NOT_APPLICABLE;
8573 }
8574}
8575
8576/**********************************************************************/
8580 const struct universal *source)
8581{
8582 if (preq->range != REQ_RANGE_LOCAL) {
8583 return ITF_NOT_APPLICABLE;
8584 }
8585
8586 if (preq->source.kind == VUT_UNITSTATE) {
8587 switch (source->value.unit_state) {
8588 case USP_TRANSPORTED:
8589 case USP_TRANSPORTING:
8590 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
8591 case USP_LIVABLE_TILE:
8592 case USP_NATIVE_TILE:
8593 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
8594 * UTYF_COAST_STRICT. */
8595 case USP_HAS_HOME_CITY:
8596 case USP_NATIVE_EXTRA:
8598 if (source->value.unit_state == preq->source.value.unit_state) {
8599 /* The other unit states doesn't contradict */
8600 return ITF_YES;
8601 }
8602 break;
8603 case USP_COUNT:
8604 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
8606 }
8607 }
8608
8609 /* Not found and not relevant. */
8610 return ITF_NOT_APPLICABLE;
8611}
8612
8613/**********************************************************************/
8638
8639/**********************************************************************/
8647int requirement_kind_ereq(const int value,
8648 const enum req_range range,
8649 const bool present,
8650 const int max_value)
8651{
8652 /* The enumerators in each range starts with present for every possible
8653 * value followed by !present for every possible value. */
8654 const int pres_start = (present ? 0 : max_value);
8655
8656 /* The enumerators for every range follows all the positions of the
8657 * previous range(s). */
8658 const int range_start = ((max_value - 1) * 2) * range;
8659
8660 return range_start + pres_start + value;
8661}
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:5676
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:396
#define ACTION_NONE
Definition actions.h:55
@ BODYGUARD_NONE
Definition aiguard.c:37
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
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:236
req_problem_type
Definition fc_types.h:531
@ RPT_POSSIBLE
Definition fc_types.h:532
#define MAX_LEN_NAME
Definition fc_types.h:66
@ VC_SPACERACE
Definition fc_types.h:979
@ O_LAST
Definition fc_types.h:101
signed short Continent_id
Definition fc_types.h:231
#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
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:498
#define MAP_MAX_LATITUDE
Definition map.h:602
#define adjc_iterate_end
Definition map.h:430
#define MAP_MAX_REAL_LATITUDE(_nmap)
Definition map.h:614
#define range_adjc_iterate_end
Definition map.h:501
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:388
#define cardinal_adjc_iterate_end
Definition map.h:456
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:425
#define is_whole_continent_known(cont)
Definition map.h:78
#define square_iterate_end
Definition map.h:391
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:452
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:398
#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:616
#define circle_iterate_end
Definition map.h:401
#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:1016
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:318
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:330
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)
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)
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)
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)
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)
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 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)
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
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:608
universals_u value
Definition fc_types.h:607
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:186
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:612
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:591
const char * terrain_class_name_translation(enum terrain_class tclass)
Definition terrain.c:661
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:238
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:156
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Definition terrain.c:673
bool is_terrain_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:327
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:582
bool is_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:458
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:147
bool is_terrain_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:438
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:348
#define T_UNKNOWN
Definition terrain.h:62
#define terrain_has_flag(terr, flag)
Definition terrain.h:176
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:111
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
#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:553
int region_tiles
Definition fc_types.h:597
struct nation_style * style
Definition fc_types.h:557
enum ai_level ai_level
Definition fc_types.h:561
struct specialist * specialist
Definition fc_types.h:550
enum impr_genus_id impr_genus
Definition fc_types.h:584
enum citytile_type citytile
Definition fc_types.h:562
struct nation_group * nationgroup
Definition fc_types.h:556
struct extra_type * extra
Definition fc_types.h:554
enum wrap_flag wrap_property
Definition fc_types.h:600
enum plrstate_type plrstate
Definition fc_types.h:564
enum tilerel_type tilerel
Definition fc_types.h:565
struct nation_type * nation
Definition fc_types.h:547
int terrainclass
Definition fc_types.h:572
int unitclassflag
Definition fc_types.h:574
struct government * govern
Definition fc_types.h:545
struct nation_type * origowner
Definition fc_types.h:549
enum impr_flag_id impr_flag
Definition fc_types.h:585
int max_tile_units
Definition fc_types.h:588
int terrainalter
Definition fc_types.h:573
enum citystatus_type citystatus
Definition fc_types.h:563
int minforeignpct
Definition fc_types.h:568
const struct impr_type * building
Definition fc_types.h:546
struct achievement * achievement
Definition fc_types.h:555
ssetv ssetval
Definition fc_types.h:601
struct advance * advance
Definition fc_types.h:543
enum unit_activity activity
Definition fc_types.h:583
struct goods_type * good
Definition fc_types.h:559
struct terrain * terrain
Definition fc_types.h:551
int terrainflag
Definition fc_types.h:576
enum ustate_prop unit_state
Definition fc_types.h:582
Output_type_id outputtype
Definition fc_types.h:571
int distance_sq
Definition fc_types.h:596
enum topo_flag topo_property
Definition fc_types.h:599
struct counter * counter
Definition fc_types.h:544
int min_hit_points
Definition fc_types.h:590
struct unit_class * uclass
Definition fc_types.h:552
struct nation_type * nationality
Definition fc_types.h:548
struct action * action
Definition fc_types.h:558
enum plr_flag_id plr_flag
Definition fc_types.h:586
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1820
#define unit_tile(_pu)
Definition unit.h:404
#define unit_owner(_pu)
Definition unit.h:403
#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