Freeciv-3.3
Loading...
Searching...
No Matches
requirements.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2004 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17#include <stdarg.h>
18
19/* utility */
20#include "astring.h"
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "achievements.h"
27#include "calendar.h"
28#include "citizens.h"
29#include "counters.h"
30#include "culture.h"
31#include "game.h"
32#include "government.h"
33#include "improvement.h"
34#include "movement.h"
35#include "nation.h"
36#include "player.h"
37#include "map.h"
38#include "research.h"
39#include "road.h"
40#include "server_settings.h"
41#include "specialist.h"
42#include "style.h"
43#include "victory.h" /* victory_enabled() */
44
45#include "requirements.h"
46
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 uninitialized 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 uninitialized 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/**********************************************************************/
2053struct requirement *
2055 const struct requirement_vector *vec)
2056{
2057 /* If the requirement is contradicted by any requirement in the vector it
2058 * contradicts the entire requirement vector. */
2061 return preq;
2062 }
2064
2065 /* Not a single requirement in the requirement vector is contradicted to be
2066 * the specified requirement. */
2067 return nullptr;
2068}
2069
2070/**********************************************************************/
2075 const struct requirement_vector *vec)
2076{
2077 return req_vec_first_contradiction_in_vec(req, vec) != nullptr;
2078}
2079
2080/**********************************************************************/
2083static inline bool are_tiles_in_range(const struct tile *tile1,
2084 const struct tile *tile2,
2085 enum req_range range)
2086{
2087 switch (range) {
2088 case REQ_RANGE_ADJACENT:
2090 return TRUE;
2091 }
2093 case REQ_RANGE_TILE:
2094 return same_pos(tile1, tile2);
2096 return map_distance(tile1, tile2) <= 1;
2097 case REQ_RANGE_CITY:
2099 case REQ_RANGE_LOCAL:
2101 case REQ_RANGE_PLAYER:
2102 case REQ_RANGE_TEAM:
2103 case REQ_RANGE_ALLIANCE:
2104 case REQ_RANGE_WORLD:
2105 case REQ_RANGE_COUNT:
2106 /* Invalid */
2108 }
2109 return FALSE;
2110}
2111
2112/**********************************************************************/
2115static inline bool players_in_same_range(const struct player *pplayer1,
2116 const struct player *pplayer2,
2117 enum req_range range)
2118{
2119 switch (range) {
2120 case REQ_RANGE_WORLD:
2121 return TRUE;
2122 case REQ_RANGE_ALLIANCE:
2124 case REQ_RANGE_TEAM:
2126 case REQ_RANGE_PLAYER:
2127 return pplayer1 == pplayer2;
2130 case REQ_RANGE_CITY:
2131 case REQ_RANGE_ADJACENT:
2133 case REQ_RANGE_TILE:
2134 case REQ_RANGE_LOCAL:
2135 case REQ_RANGE_COUNT:
2136 break;
2137 }
2138
2139 fc_assert_msg(FALSE, "Invalid range %d.", range);
2140 return FALSE;
2141}
2142
2143#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
2144{ \
2145 fc_assert_ret_val(req != nullptr, TRI_MAYBE); \
2146 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
2147 fc_assert(context != nullptr); \
2148 fc_assert(other_context != nullptr); \
2149}
2150
2151/**********************************************************************/
2159static enum fc_tristate
2161 const struct req_context *context,
2162 const struct req_context *other_context,
2163 const struct requirement *req)
2164{
2166
2167 return TRI_YES;
2168}
2169
2170/**********************************************************************/
2174static int num_world_buildings_total(const struct impr_type *building)
2175{
2176 if (is_great_wonder(building)) {
2177 return (great_wonder_is_built(building)
2178 || great_wonder_is_destroyed(building) ? 1 : 0);
2179 } else {
2180 log_error("World-ranged requirements are only supported for wonders.");
2181 return 0;
2182 }
2183}
2184
2185/**********************************************************************/
2188static int num_world_buildings(const struct impr_type *building)
2189{
2190 if (is_great_wonder(building)) {
2191 return (great_wonder_is_built(building) ? 1 : 0);
2192 } else {
2193 log_error("World-ranged requirements are only supported for wonders.");
2194 return 0;
2195 }
2196}
2197
2198/**********************************************************************/
2209static bool player_has_ever_built(const struct player *pplayer,
2210 const struct impr_type *building)
2211{
2212 if (is_wonder(building)) {
2213 return (wonder_is_built(pplayer, building)
2214 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2215 } else {
2216 log_error("Player-ranged requirements are only supported for wonders.");
2217 return FALSE;
2218 }
2219}
2220
2221/**********************************************************************/
2224static int num_player_buildings(const struct player *pplayer,
2225 const struct impr_type *building)
2226{
2227 if (is_wonder(building)) {
2228 return (wonder_is_built(pplayer, building) ? 1 : 0);
2229 } else {
2230 log_error("Player-ranged requirements are only supported for wonders.");
2231 return 0;
2232 }
2233}
2234
2235/**********************************************************************/
2238static int num_continent_buildings(const struct player *pplayer,
2239 int continent,
2240 const struct impr_type *building)
2241{
2242 if (is_wonder(building)) {
2243 const struct city *pcity;
2244
2245 pcity = city_from_wonder(pplayer, building);
2246 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2247 return 1;
2248 }
2249 } else {
2250 log_error("Island-ranged requirements are only supported for wonders.");
2251 }
2252 return 0;
2253}
2254
2255/**********************************************************************/
2263static enum fc_tristate
2265 const struct req_context *context,
2266 const struct req_context *other_context,
2267 const struct requirement *req)
2268{
2269 const struct impr_type *building;
2270
2271 /* Can't use this assertion, as both VUT_IMPROVEMENT and VUT_SITE
2272 * are handled here. */
2273 /* IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT); */
2274
2275 building = req->source.value.building;
2276
2277 /* Check if it's certain that the building is obsolete given the
2278 * specification we have */
2279 if (req->source.kind == VUT_IMPROVEMENT
2280 && improvement_obsolete(context->player, building, context->city)) {
2281 return TRI_NO;
2282 }
2283
2284 if (req->survives) {
2285
2286 /* Check whether condition has ever held, using cached information. */
2287 switch (req->range) {
2288 case REQ_RANGE_WORLD:
2289 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2290 case REQ_RANGE_ALLIANCE:
2291 case REQ_RANGE_TEAM:
2292 if (context->player == nullptr) {
2293 return TRI_MAYBE;
2294 }
2295 players_iterate_alive(plr2) {
2296 if (players_in_same_range(context->player, plr2, req->range)
2297 && player_has_ever_built(plr2, building)) {
2298 return TRI_YES;
2299 }
2301 return TRI_NO;
2302 case REQ_RANGE_PLAYER:
2303 if (context->player == nullptr) {
2304 return TRI_MAYBE;
2305 }
2307 building));
2310 case REQ_RANGE_CITY:
2311 case REQ_RANGE_LOCAL:
2312 case REQ_RANGE_TILE:
2314 case REQ_RANGE_ADJACENT:
2315 /* There is no sources cache for this. */
2316 log_error("Surviving requirements are only supported at "
2317 "World/Alliance/Team/Player ranges.");
2318 return TRI_NO;
2319 case REQ_RANGE_COUNT:
2320 break;
2321 }
2322
2323 } else {
2324
2325 /* Non-surviving requirement. */
2326 switch (req->range) {
2327 case REQ_RANGE_WORLD:
2328 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2329 case REQ_RANGE_ALLIANCE:
2330 case REQ_RANGE_TEAM:
2331 if (context->player == nullptr) {
2332 return TRI_MAYBE;
2333 }
2334 players_iterate_alive(plr2) {
2335 if (players_in_same_range(context->player, plr2, req->range)
2336 && num_player_buildings(plr2, building) > 0) {
2337 return TRI_YES;
2338 }
2340 return TRI_NO;
2341 case REQ_RANGE_PLAYER:
2342 if (context->player == nullptr) {
2343 return TRI_MAYBE;
2344 }
2346 building)
2347 > 0);
2349 /* At present, "Continent" effects can affect only
2350 * cities and units in cities. */
2351 if (context->player && context->city) {
2352 int continent = tile_continent(context->city->tile);
2354 continent, building)
2355 > 0);
2356 } else {
2357 return TRI_MAYBE;
2358 }
2360 if (context->city) {
2361 if (city_has_building(context->city, building)) {
2362 return TRI_YES;
2363 } else {
2364 enum fc_tristate ret = TRI_NO;
2365
2367 if (trade_partner == nullptr) {
2368 ret = TRI_MAYBE;
2369 } else if (city_has_building(trade_partner, building)) {
2370 return TRI_YES;
2371 }
2373
2374 return ret;
2375 }
2376 } else {
2377 return TRI_MAYBE;
2378 }
2379 case REQ_RANGE_CITY:
2380 if (context->city) {
2381 return BOOL_TO_TRISTATE(city_has_building(context->city, building));
2382 } else {
2383 return TRI_MAYBE;
2384 }
2385 case REQ_RANGE_LOCAL:
2386 if (context->building) {
2387 if (context->building == building) {
2388 return TRI_YES;
2389 } else {
2390 return TRI_NO;
2391 }
2392 } else {
2393 /* TODO: Other local targets */
2394 return TRI_MAYBE;
2395 }
2396 case REQ_RANGE_TILE:
2397 if (context->tile) {
2398 const struct city *pcity = tile_city(context->tile);
2399
2400 if (pcity) {
2401 return BOOL_TO_TRISTATE(city_has_building(pcity, building));
2402 } else {
2403 return TRI_NO;
2404 }
2405 } else {
2406 return TRI_MAYBE;
2407 }
2409 case REQ_RANGE_ADJACENT:
2410 case REQ_RANGE_COUNT:
2411 break;
2412 }
2413
2414 }
2415
2416 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2417 return TRI_NO;
2418}
2419
2420/**********************************************************************/
2428static enum fc_tristate
2430 const struct req_context *context,
2431 const struct req_context *other_context,
2432 const struct requirement *req)
2433{
2435
2436 return (context->building ? BOOL_TO_TRISTATE(
2437 context->building->genus
2438 == req->source.value.impr_genus)
2439 : TRI_MAYBE);
2440}
2441
2442/**********************************************************************/
2446 enum impr_flag_id flag)
2447{
2448 struct player *owner;
2449
2450 if (pcity == nullptr) {
2451 return TRI_MAYBE;
2452 }
2453
2455 city_built_iterate(pcity, impr) {
2456 if (improvement_has_flag(impr, flag)
2457 && !improvement_obsolete(owner, impr, pcity)) {
2458 return TRI_YES;
2459 }
2461
2462 return TRI_NO;
2463}
2464
2465/**********************************************************************/
2473static enum fc_tristate
2475 const struct req_context *context,
2476 const struct req_context *other_context,
2477 const struct requirement *req)
2478{
2480
2481 switch (req->range) {
2482 case REQ_RANGE_LOCAL:
2483 return (context->building
2485 req->source.value.impr_flag))
2486 : TRI_MAYBE);
2487 case REQ_RANGE_CITY:
2489 case REQ_RANGE_TILE:
2490 if (context->tile == nullptr) {
2491 return TRI_MAYBE;
2492 }
2494 req->source.value.impr_flag);
2496 case REQ_RANGE_ADJACENT:
2499 case REQ_RANGE_PLAYER:
2500 case REQ_RANGE_ALLIANCE:
2501 case REQ_RANGE_TEAM:
2502 case REQ_RANGE_WORLD:
2503 case REQ_RANGE_COUNT:
2504 break;
2505 }
2506
2507 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2508
2509 return TRI_MAYBE;
2510}
2511
2512/**********************************************************************/
2520static enum fc_tristate
2522 const struct req_context *context,
2523 const struct req_context *other_context,
2524 const struct requirement *req)
2525{
2527
2528 switch (req->range) {
2529 case REQ_RANGE_PLAYER:
2530 return (context->player != nullptr
2532 req->source.value.plr_flag))
2533 : TRI_MAYBE);
2534 case REQ_RANGE_LOCAL:
2535 case REQ_RANGE_CITY:
2536 case REQ_RANGE_TILE:
2538 case REQ_RANGE_ADJACENT:
2541 case REQ_RANGE_ALLIANCE:
2542 case REQ_RANGE_TEAM:
2543 case REQ_RANGE_WORLD:
2544 case REQ_RANGE_COUNT:
2545 break;
2546 }
2547
2548 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2549
2550 return TRI_MAYBE;
2551}
2552
2553/**********************************************************************/
2561static enum fc_tristate
2563 const struct req_context *context,
2564 const struct req_context *other_context,
2565 const struct requirement *req)
2566{
2568
2569 switch (req->range) {
2570 case REQ_RANGE_PLAYER:
2571 return (context->player != nullptr
2573 req->source.value.plrstate))
2574 : TRI_MAYBE);
2575 case REQ_RANGE_LOCAL:
2576 case REQ_RANGE_CITY:
2577 case REQ_RANGE_TILE:
2579 case REQ_RANGE_ADJACENT:
2582 case REQ_RANGE_ALLIANCE:
2583 case REQ_RANGE_TEAM:
2584 case REQ_RANGE_WORLD:
2585 case REQ_RANGE_COUNT:
2586 break;
2587 }
2588
2589 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2590
2591 return TRI_MAYBE;
2592}
2593
2594/**********************************************************************/
2602static enum fc_tristate
2604 const struct req_context *context,
2605 const struct req_context *other_context,
2606 const struct requirement *req)
2607{
2608 Tech_type_id tech;
2609
2611
2612 tech = advance_number(req->source.value.advance);
2613
2614 if (req->survives) {
2617 }
2618
2619 /* Not a 'surviving' requirement. */
2620 switch (req->range) {
2621 case REQ_RANGE_PLAYER:
2622 if (context->player != nullptr) {
2624 (research_get(context->player), tech));
2625 } else {
2626 return TRI_MAYBE;
2627 }
2628 case REQ_RANGE_TEAM:
2629 case REQ_RANGE_ALLIANCE:
2630 case REQ_RANGE_WORLD:
2631 if (context->player == nullptr) {
2632 return TRI_MAYBE;
2633 }
2634 players_iterate_alive(plr2) {
2635 if (players_in_same_range(context->player, plr2, req->range)) {
2636 if (research_invention_state(research_get(plr2), tech)
2637 == TECH_KNOWN) {
2638 return TRI_YES;
2639 }
2640 }
2642
2643 return TRI_NO;
2644 case REQ_RANGE_LOCAL:
2645 if (context->player == nullptr) {
2646 return TRI_MAYBE;
2647 }
2648 if (research_get(context->player)->researching == tech) {
2649 return TRI_YES;
2650 }
2651 return TRI_NO;
2652 case REQ_RANGE_TILE:
2654 case REQ_RANGE_ADJACENT:
2655 case REQ_RANGE_CITY:
2658 case REQ_RANGE_COUNT:
2659 break;
2660 }
2661
2662 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2663
2664 return TRI_MAYBE;
2665}
2666
2667/**********************************************************************/
2675static enum fc_tristate
2677 const struct req_context *context,
2678 const struct req_context *other_context,
2679 const struct requirement *req)
2680{
2681 enum tech_flag_id techflag;
2682
2684
2685 techflag = req->source.value.techflag;
2686
2687 switch (req->range) {
2688 case REQ_RANGE_PLAYER:
2689 if (context->player != nullptr) {
2691 techflag));
2692 } else {
2693 return TRI_MAYBE;
2694 }
2695 break;
2696 case REQ_RANGE_TEAM:
2697 case REQ_RANGE_ALLIANCE:
2698 if (context->player == nullptr) {
2699 return TRI_MAYBE;
2700 }
2701 players_iterate_alive(plr2) {
2702 if (players_in_same_range(context->player, plr2, req->range)
2703 && player_knows_techs_with_flag(plr2, techflag)) {
2704 return TRI_YES;
2705 }
2707 return TRI_NO;
2708 case REQ_RANGE_WORLD:
2709 players_iterate(pplayer) {
2710 if (player_knows_techs_with_flag(pplayer, techflag)) {
2711 return TRI_YES;
2712 }
2714
2715 return TRI_NO;
2716 case REQ_RANGE_LOCAL:
2717 if (context->player == nullptr) {
2718 return TRI_MAYBE;
2719 }
2720 if (advance_has_flag(research_get(context->player)->researching, techflag)) {
2721 return TRI_YES;
2722 }
2723 return TRI_NO;
2724 case REQ_RANGE_TILE:
2726 case REQ_RANGE_ADJACENT:
2727 case REQ_RANGE_CITY:
2730 case REQ_RANGE_COUNT:
2731 break;
2732 }
2733
2734 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2735
2736 return TRI_MAYBE;
2737}
2738
2739/**********************************************************************/
2747static enum fc_tristate
2749 const struct req_context *context,
2750 const struct req_context *other_context,
2751 const struct requirement *req)
2752{
2753 int minculture;
2754
2756
2757 minculture = req->source.value.minculture;
2758
2759 switch (req->range) {
2760 case REQ_RANGE_CITY:
2761 if (!context->city) {
2762 return TRI_MAYBE;
2763 }
2764 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2766 if (!context->city) {
2767 return TRI_MAYBE;
2768 }
2769 if (city_culture(context->city) >= minculture) {
2770 return TRI_YES;
2771 } else {
2772 enum fc_tristate ret = TRI_NO;
2773
2775 if (trade_partner == nullptr) {
2776 ret = TRI_MAYBE;
2777 } else if (city_culture(trade_partner) >= minculture) {
2778 return TRI_YES;
2779 }
2781
2782 return ret;
2783 }
2784 case REQ_RANGE_PLAYER:
2785 case REQ_RANGE_TEAM:
2786 case REQ_RANGE_ALLIANCE:
2787 case REQ_RANGE_WORLD:
2788 if (context->player == nullptr) {
2789 return TRI_MAYBE;
2790 }
2791 players_iterate_alive(plr2) {
2792 if (players_in_same_range(context->player, plr2, req->range)) {
2793 if (player_culture(plr2) >= minculture) {
2794 return TRI_YES;
2795 }
2796 }
2798 return TRI_NO;
2799 case REQ_RANGE_LOCAL:
2800 case REQ_RANGE_TILE:
2802 case REQ_RANGE_ADJACENT:
2804 case REQ_RANGE_COUNT:
2805 break;
2806 }
2807
2808 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2809
2810 return TRI_MAYBE;
2811}
2812
2813/**********************************************************************/
2821static enum fc_tristate
2823 const struct req_context *context,
2824 const struct req_context *other_context,
2825 const struct requirement *req)
2826{
2828
2830
2832
2833 switch (req->range) {
2834 case REQ_RANGE_CITY:
2835 if (!context->city) {
2836 return TRI_MAYBE;
2837 }
2839 / city_size_get(context->city);
2842 if (!context->city) {
2843 return TRI_MAYBE;
2844 }
2846 / city_size_get(context->city);
2848 return TRI_YES;
2849 } else {
2850 enum fc_tristate ret = TRI_NO;
2851
2853 if (trade_partner == nullptr) {
2854 ret = TRI_MAYBE;
2855 } else {
2859 return TRI_YES;
2860 }
2861 }
2863
2864 return ret;
2865 }
2866 case REQ_RANGE_PLAYER:
2867 case REQ_RANGE_TEAM:
2868 case REQ_RANGE_ALLIANCE:
2869 case REQ_RANGE_WORLD:
2870 case REQ_RANGE_LOCAL:
2871 case REQ_RANGE_TILE:
2873 case REQ_RANGE_ADJACENT:
2875 case REQ_RANGE_COUNT:
2876 break;
2877 }
2878
2879 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2880
2881 return TRI_MAYBE;
2882}
2883
2884/**********************************************************************/
2892static enum fc_tristate
2894 const struct req_context *context,
2895 const struct req_context *other_context,
2896 const struct requirement *req)
2897{
2898 int max_units;
2899
2901
2903
2904 /* TODO: If can't see V_INVIS -> TRI_MAYBE */
2905 switch (req->range) {
2906 case REQ_RANGE_TILE:
2907 if (!context->tile) {
2908 return TRI_MAYBE;
2909 }
2910 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
2912 if (!context->tile) {
2913 return TRI_MAYBE;
2914 }
2915 if (unit_list_size(context->tile->units) <= max_units) {
2916 return TRI_YES;
2917 }
2919 if (unit_list_size(adjc_tile->units) <= max_units) {
2920 return TRI_YES;
2921 }
2923 return TRI_NO;
2924 case REQ_RANGE_ADJACENT:
2925 if (!context->tile) {
2926 return TRI_MAYBE;
2927 }
2928 if (unit_list_size(context->tile->units) <= max_units) {
2929 return TRI_YES;
2930 }
2932 if (unit_list_size(adjc_tile->units) <= max_units) {
2933 return TRI_YES;
2934 }
2936 return TRI_NO;
2937 case REQ_RANGE_CITY:
2940 case REQ_RANGE_PLAYER:
2941 case REQ_RANGE_TEAM:
2942 case REQ_RANGE_ALLIANCE:
2943 case REQ_RANGE_WORLD:
2944 case REQ_RANGE_LOCAL:
2945 case REQ_RANGE_COUNT:
2946 break;
2947 }
2948
2949 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2950
2951 return TRI_MAYBE;
2952}
2953
2954/**********************************************************************/
2962static enum fc_tristate
2964 const struct req_context *context,
2965 const struct req_context *other_context,
2966 const struct requirement *req)
2967{
2968 const struct extra_type *pextra;
2969 enum fc_tristate ret;
2970
2972
2973 pextra = req->source.value.extra;
2974
2975 switch (req->range) {
2976 case REQ_RANGE_LOCAL:
2977 if (!context->extra) {
2978 return TRI_MAYBE;
2979 }
2980 return BOOL_TO_TRISTATE(context->extra == pextra);
2981 case REQ_RANGE_TILE:
2982 /* The requirement is filled if the tile has extra of requested type. */
2983 if (!context->tile) {
2984 return TRI_MAYBE;
2985 }
2986 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
2988 if (!context->tile) {
2989 return TRI_MAYBE;
2990 }
2991 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2992 || is_extra_card_near(nmap, context->tile, pextra));
2993 case REQ_RANGE_ADJACENT:
2994 if (!context->tile) {
2995 return TRI_MAYBE;
2996 }
2997 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2998 || is_extra_near_tile(nmap, context->tile, pextra));
2999 case REQ_RANGE_CITY:
3000 if (!context->city) {
3001 return TRI_MAYBE;
3002 }
3004 city_tile(context->city), ptile) {
3005 if (tile_has_extra(ptile, pextra)) {
3006 return TRI_YES;
3007 }
3009
3010 return TRI_NO;
3011
3013 if (!context->city) {
3014 return TRI_MAYBE;
3015 }
3017 city_tile(context->city), ptile) {
3018 if (tile_has_extra(ptile, pextra)) {
3019 return TRI_YES;
3020 }
3022
3023 ret = TRI_NO;
3025 if (trade_partner == nullptr) {
3026 ret = TRI_MAYBE;
3027 } else {
3029 city_tile(trade_partner), ptile) {
3030 if (tile_has_extra(ptile, pextra)) {
3031 return TRI_YES;
3032 }
3034 }
3036
3037 return ret;
3038
3040 case REQ_RANGE_PLAYER:
3041 case REQ_RANGE_TEAM:
3042 case REQ_RANGE_ALLIANCE:
3043 case REQ_RANGE_WORLD:
3044 case REQ_RANGE_COUNT:
3045 break;
3046 }
3047
3048 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3049
3050 return TRI_MAYBE;
3051}
3052
3053/**********************************************************************/
3061static enum fc_tristate
3063 const struct req_context *context,
3064 const struct req_context *other_context,
3065 const struct requirement *req)
3066{
3067 const struct goods_type *pgood;
3068
3070
3071 pgood = req->source.value.good;
3072
3073 switch (req->range) {
3074 case REQ_RANGE_LOCAL:
3075 case REQ_RANGE_CITY:
3076 /* The requirement is filled if the city imports good of requested type. */
3077 if (!context->city) {
3078 return TRI_MAYBE;
3079 }
3083 nullptr)));
3084 case REQ_RANGE_TILE:
3086 case REQ_RANGE_ADJACENT:
3089 case REQ_RANGE_PLAYER:
3090 case REQ_RANGE_TEAM:
3091 case REQ_RANGE_ALLIANCE:
3092 case REQ_RANGE_WORLD:
3093 case REQ_RANGE_COUNT:
3094 break;
3095 }
3096
3097 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3098
3099 return TRI_MAYBE;
3100}
3101
3102/**********************************************************************/
3110static enum fc_tristate
3112 const struct req_context *context,
3113 const struct req_context *other_context,
3114 const struct requirement *req)
3115{
3117
3118 if (context->action) {
3119 return BOOL_TO_TRISTATE(action_number(context->action)
3120 == action_number(req->source.value.action));
3121 }
3122
3123 if (context->unit != nullptr && context->unit->action != ACTION_NONE) {
3124 log_normal("Unit action %s", action_id_rule_name(context->unit->action));
3125 return BOOL_TO_TRISTATE(context->unit->action
3126 == action_number(req->source.value.action));
3127 }
3128
3129 return TRI_NO;
3130}
3131
3132/**********************************************************************/
3140static enum fc_tristate
3142 const struct req_context *context,
3143 const struct req_context *other_context,
3144 const struct requirement *req)
3145{
3147
3148 return BOOL_TO_TRISTATE(context->output
3149 && context->output->index
3150 == req->source.value.outputtype);
3151}
3152
3153/**********************************************************************/
3161static enum fc_tristate
3163 const struct req_context *context,
3164 const struct req_context *other_context,
3165 const struct requirement *req)
3166{
3168
3169 return BOOL_TO_TRISTATE(context->specialist
3170 && context->specialist
3171 == req->source.value.specialist);
3172}
3173
3174/**********************************************************************/
3182static enum fc_tristate
3184 const struct req_context *context,
3185 const struct req_context *other_context,
3186 const struct requirement *req)
3187{
3188 const struct terrain *pterrain;
3189
3191
3192 pterrain = req->source.value.terrain;
3193
3194 switch (req->range) {
3195 case REQ_RANGE_TILE:
3196 /* The requirement is filled if the tile has the terrain. */
3197 if (!context->tile) {
3198 return TRI_MAYBE;
3199 }
3200 return pterrain && tile_terrain(context->tile) == pterrain;
3202 if (!context->tile) {
3203 return TRI_MAYBE;
3204 }
3205 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
3206 case REQ_RANGE_ADJACENT:
3207 if (!context->tile) {
3208 return TRI_MAYBE;
3209 }
3210 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
3211 case REQ_RANGE_CITY:
3212 if (!context->city) {
3213 return TRI_MAYBE;
3214 }
3215 if (pterrain != nullptr) {
3217 city_tile(context->city), ptile) {
3218 if (tile_terrain(ptile) == pterrain) {
3219 return TRI_YES;
3220 }
3222 }
3223 return TRI_NO;
3225 if (!context->city) {
3226 return TRI_MAYBE;
3227 }
3228 if (pterrain != nullptr) {
3229 enum fc_tristate ret;
3230
3232 city_tile(context->city), ptile) {
3233 if (tile_terrain(ptile) == pterrain) {
3234 return TRI_YES;
3235 }
3237
3238 ret = TRI_NO;
3240 if (trade_partner == nullptr) {
3241 ret = TRI_MAYBE;
3242 } else {
3244 city_tile(trade_partner), ptile) {
3245 if (tile_terrain(ptile) == pterrain) {
3246 return TRI_YES;
3247 }
3249 }
3251
3252 return ret;
3253 }
3254
3255 return TRI_MAYBE;
3257 case REQ_RANGE_PLAYER:
3258 case REQ_RANGE_TEAM:
3259 case REQ_RANGE_ALLIANCE:
3260 case REQ_RANGE_WORLD:
3261 case REQ_RANGE_LOCAL:
3262 case REQ_RANGE_COUNT:
3263 break;
3264 }
3265
3266 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3267
3268 return TRI_MAYBE;
3269}
3270
3271/**********************************************************************/
3279static enum fc_tristate
3281 const struct req_context *context,
3282 const struct req_context *other_context,
3283 const struct requirement *req)
3284{
3285 enum terrain_class pclass;
3286 enum fc_tristate ret;
3287
3289
3291
3292 switch (req->range) {
3293 case REQ_RANGE_TILE:
3294 /* The requirement is filled if the tile has the terrain of correct class. */
3295 if (!context->tile) {
3296 return TRI_MAYBE;
3297 }
3300 if (!context->tile) {
3301 return TRI_MAYBE;
3302 }
3305 case REQ_RANGE_ADJACENT:
3306 if (!context->tile) {
3307 return TRI_MAYBE;
3308 }
3311 case REQ_RANGE_CITY:
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 return TRI_NO;
3327 if (!context->city) {
3328 return TRI_MAYBE;
3329 }
3331 city_tile(context->city), 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
3340 ret = TRI_NO;
3342 if (trade_partner == nullptr) {
3343 ret = TRI_MAYBE;
3344 } else {
3346 city_tile(trade_partner), ptile) {
3347 const struct terrain *pterrain = tile_terrain(ptile);
3348
3349 if (pterrain != T_UNKNOWN
3350 && terrain_type_terrain_class(pterrain) == pclass) {
3351 return TRI_YES;
3352 }
3354 }
3356
3357 return ret;
3359 case REQ_RANGE_PLAYER:
3360 case REQ_RANGE_TEAM:
3361 case REQ_RANGE_ALLIANCE:
3362 case REQ_RANGE_WORLD:
3363 case REQ_RANGE_LOCAL:
3364 case REQ_RANGE_COUNT:
3365 break;
3366 }
3367
3368 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3369
3370 return TRI_MAYBE;
3371}
3372
3373/**********************************************************************/
3381static enum fc_tristate
3383 const struct req_context *context,
3384 const struct req_context *other_context,
3385 const struct requirement *req)
3386{
3388 enum fc_tristate ret;
3389
3391
3393
3394 switch (req->range) {
3395 case REQ_RANGE_TILE:
3396 /* The requirement is fulfilled if the tile has a terrain with
3397 * correct flag. */
3398 if (!context->tile) {
3399 return TRI_MAYBE;
3400 }
3402 terrflag));
3404 if (!context->tile) {
3405 return TRI_MAYBE;
3406 }
3408 terrflag)
3410 terrflag));
3411 case REQ_RANGE_ADJACENT:
3412 if (!context->tile) {
3413 return TRI_MAYBE;
3414 }
3416 terrflag)
3418 terrflag));
3419 case REQ_RANGE_CITY:
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 return TRI_NO;
3435 if (!context->city) {
3436 return TRI_MAYBE;
3437 }
3439 city_tile(context->city), 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
3448 ret = TRI_NO;
3450 if (trade_partner == nullptr) {
3451 ret = TRI_MAYBE;
3452 } else {
3454 city_tile(trade_partner), ptile) {
3455 const struct terrain *pterrain = tile_terrain(ptile);
3456
3457 if (pterrain != T_UNKNOWN
3458 && terrain_has_flag(pterrain, terrflag)) {
3459 return TRI_YES;
3460 }
3462 }
3464
3465 return ret;
3467 case REQ_RANGE_PLAYER:
3468 case REQ_RANGE_TEAM:
3469 case REQ_RANGE_ALLIANCE:
3470 case REQ_RANGE_WORLD:
3471 case REQ_RANGE_LOCAL:
3472 case REQ_RANGE_COUNT:
3473 break;
3474 }
3475
3476 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3477
3478 return TRI_MAYBE;
3479}
3480
3481/**********************************************************************/
3489static enum fc_tristate
3491 const struct req_context *context,
3492 const struct req_context *other_context,
3493 const struct requirement *req)
3494{
3495 enum road_flag_id roadflag;
3496 enum fc_tristate ret;
3497
3499
3500 roadflag = req->source.value.roadflag;
3501
3502 switch (req->range) {
3503 case REQ_RANGE_LOCAL:
3504 {
3505 if (!context->extra) {
3506 return TRI_MAYBE;
3507 }
3508 struct road_type *r = extra_road_get(context->extra);
3509
3510 return BOOL_TO_TRISTATE(
3511 r && road_has_flag(r, roadflag)
3512 );
3513 }
3514 case REQ_RANGE_TILE:
3515 /* The requirement is filled if the tile has a road with correct flag. */
3516 if (!context->tile) {
3517 return TRI_MAYBE;
3518 }
3519 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3521 if (!context->tile) {
3522 return TRI_MAYBE;
3523 }
3524 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3526 roadflag));
3527 case REQ_RANGE_ADJACENT:
3528 if (!context->tile) {
3529 return TRI_MAYBE;
3530 }
3531 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3533 roadflag));
3534 case REQ_RANGE_CITY:
3535 if (!context->city) {
3536 return TRI_MAYBE;
3537 }
3539 city_tile(context->city), ptile) {
3540 if (tile_has_road_flag(ptile, roadflag)) {
3541 return TRI_YES;
3542 }
3544
3545 return TRI_NO;
3547 if (!context->city) {
3548 return TRI_MAYBE;
3549 }
3551 city_tile(context->city), ptile) {
3552 if (tile_has_road_flag(ptile, roadflag)) {
3553 return TRI_YES;
3554 }
3556
3557 ret = TRI_NO;
3559 if (trade_partner == nullptr) {
3560 ret = TRI_MAYBE;
3561 } else {
3563 city_tile(trade_partner), ptile) {
3564 if (tile_has_road_flag(ptile, roadflag)) {
3565 return TRI_YES;
3566 }
3568 }
3570
3571 return ret;
3573 case REQ_RANGE_PLAYER:
3574 case REQ_RANGE_TEAM:
3575 case REQ_RANGE_ALLIANCE:
3576 case REQ_RANGE_WORLD:
3577 case REQ_RANGE_COUNT:
3578 break;
3579 }
3580
3581 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3582
3583 return TRI_MAYBE;
3584}
3585
3586/**********************************************************************/
3594static enum fc_tristate
3596 const struct req_context *context,
3597 const struct req_context *other_context,
3598 const struct requirement *req)
3599{
3600 enum extra_flag_id extraflag;
3601 enum fc_tristate ret;
3602
3604
3605 extraflag = req->source.value.extraflag;
3606
3607 switch (req->range) {
3608 case REQ_RANGE_LOCAL:
3609 if (!context->extra) {
3610 return TRI_MAYBE;
3611 }
3612 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3613 case REQ_RANGE_TILE:
3614 /* The requirement is filled if the tile has an extra with correct flag. */
3615 if (!context->tile) {
3616 return TRI_MAYBE;
3617 }
3618 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3620 if (!context->tile) {
3621 return TRI_MAYBE;
3622 }
3623 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3624 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3625 case REQ_RANGE_ADJACENT:
3626 if (!context->tile) {
3627 return TRI_MAYBE;
3628 }
3629 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3630 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3631 case REQ_RANGE_CITY:
3632 if (!context->city) {
3633 return TRI_MAYBE;
3634 }
3636 city_tile(context->city), ptile) {
3637 if (tile_has_extra_flag(ptile, extraflag)) {
3638 return TRI_YES;
3639 }
3641
3642 return TRI_NO;
3644 if (!context->city) {
3645 return TRI_MAYBE;
3646 }
3648 city_tile(context->city), ptile) {
3649 if (tile_has_extra_flag(ptile, extraflag)) {
3650 return TRI_YES;
3651 }
3653
3654 ret = TRI_NO;
3656 if (trade_partner == nullptr) {
3657 ret = TRI_MAYBE;
3658 } else {
3660 city_tile(trade_partner), ptile) {
3661 if (tile_has_extra_flag(ptile, extraflag)) {
3662 return TRI_YES;
3663 }
3665 }
3667
3668 return ret;
3670 case REQ_RANGE_PLAYER:
3671 case REQ_RANGE_TEAM:
3672 case REQ_RANGE_ALLIANCE:
3673 case REQ_RANGE_WORLD:
3674 case REQ_RANGE_COUNT:
3675 break;
3676 }
3677
3678 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3679
3680 return TRI_MAYBE;
3681}
3682
3683/**********************************************************************/
3691static enum fc_tristate
3693 const struct req_context *context,
3694 const struct req_context *other_context,
3695 const struct requirement *req)
3696{
3698
3700
3702
3703 if (!context->tile) {
3704 return TRI_MAYBE;
3705 }
3706
3707 switch (req->range) {
3708 case REQ_RANGE_TILE:
3712 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
3713 case REQ_RANGE_CITY:
3716 case REQ_RANGE_PLAYER:
3717 case REQ_RANGE_TEAM:
3718 case REQ_RANGE_ALLIANCE:
3719 case REQ_RANGE_WORLD:
3720 case REQ_RANGE_LOCAL:
3721 case REQ_RANGE_COUNT:
3722 break;
3723 }
3724
3725 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3726
3727 return TRI_MAYBE;
3728}
3729
3730/**********************************************************************/
3738static enum fc_tristate
3740 const struct req_context *context,
3741 const struct req_context *other_context,
3742 const struct requirement *req)
3743{
3745
3746 if (context->player == nullptr) {
3747 return TRI_MAYBE;
3748 } else {
3750 == req->source.value.govern);
3751 }
3752}
3753
3754/**********************************************************************/
3762static enum fc_tristate
3764 const struct req_context *context,
3765 const struct req_context *other_context,
3766 const struct requirement *req)
3767{
3769
3770 if (context->player == nullptr) {
3771 return TRI_MAYBE;
3772 } else {
3773 return BOOL_TO_TRISTATE(context->player->style
3774 == req->source.value.style);
3775 }
3776}
3777
3778/**********************************************************************/
3786static enum fc_tristate
3788 const struct req_context *context,
3789 const struct req_context *other_context,
3790 const struct requirement *req)
3791{
3793
3794 switch (req->range) {
3795 case REQ_RANGE_WORLD:
3796 /* "None" does not count */
3797 return ((game.info.global_advance_count - 1)
3798 >= req->source.value.min_techs);
3799 case REQ_RANGE_PLAYER:
3800 if (context->player == nullptr) {
3801 return TRI_MAYBE;
3802 } else {
3803 /* "None" does not count */
3804 return BOOL_TO_TRISTATE(
3805 (research_get(context->player)->techs_researched - 1)
3806 >= req->source.value.min_techs
3807 );
3808 }
3809 default:
3810 return TRI_MAYBE;
3811 }
3812}
3813
3814/**********************************************************************/
3822static enum fc_tristate
3824 const struct req_context *context,
3825 const struct req_context *other_context,
3826 const struct requirement *req)
3827{
3829
3830 switch (req->range) {
3831 case REQ_RANGE_PLAYER:
3832 if (context->player == nullptr) {
3833 return TRI_MAYBE;
3834 } else {
3835 /* "None" does not count */
3836 return BOOL_TO_TRISTATE(
3837 city_list_size(context->player->cities)
3838 >= req->source.value.min_cities
3839 );
3840 }
3841 default:
3842 return TRI_MAYBE;
3843 }
3844}
3845
3846/**********************************************************************/
3854static enum fc_tristate
3856 const struct req_context *context,
3857 const struct req_context *other_context,
3858 const struct requirement *req)
3859{
3861
3862 if (context->player == nullptr) {
3863 return TRI_MAYBE;
3864 } else {
3865 return BOOL_TO_TRISTATE(is_ai(context->player)
3866 && context->player->ai_common.skill_level
3867 == req->source.value.ai_level);
3868 }
3869}
3870
3871/**********************************************************************/
3879static enum fc_tristate
3881 const struct req_context *context,
3882 const struct req_context *other_context,
3883 const struct requirement *req)
3884{
3885 const struct nation_type *nation;
3886
3888
3889 nation = req->source.value.nation;
3890
3891 switch (req->range) {
3892 case REQ_RANGE_PLAYER:
3893 if (context->player == nullptr) {
3894 return TRI_MAYBE;
3895 }
3896 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
3897 case REQ_RANGE_TEAM:
3898 case REQ_RANGE_ALLIANCE:
3899 if (context->player == nullptr) {
3900 return TRI_MAYBE;
3901 }
3902 players_iterate_alive(plr2) {
3903 if (players_in_same_range(context->player, plr2, req->range)) {
3904 if (nation_of_player(plr2) == nation) {
3905 return TRI_YES;
3906 }
3907 }
3909 return TRI_NO;
3910 case REQ_RANGE_WORLD:
3911 /* NB: if a player is ever removed outright from the game
3912 * (e.g. via /remove), rather than just dying, this 'survives'
3913 * requirement will stop being true for their nation.
3914 * create_command_newcomer() can also cause this to happen. */
3915 return BOOL_TO_TRISTATE(nation->player != nullptr
3916 && (req->survives || nation->player->is_alive));
3917 case REQ_RANGE_LOCAL:
3918 case REQ_RANGE_TILE:
3920 case REQ_RANGE_ADJACENT:
3921 case REQ_RANGE_CITY:
3924 case REQ_RANGE_COUNT:
3925 break;
3926 }
3927
3928 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3929
3930 return TRI_MAYBE;
3931}
3932
3933/**********************************************************************/
3941static enum fc_tristate
3943 const struct req_context *context,
3944 const struct req_context *other_context,
3945 const struct requirement *req)
3946{
3947 const struct nation_group *ngroup;
3948
3950
3952
3953 switch (req->range) {
3954 case REQ_RANGE_PLAYER:
3955 if (context->player == nullptr) {
3956 return TRI_MAYBE;
3957 }
3959 nation_of_player(context->player), ngroup));
3960 case REQ_RANGE_TEAM:
3961 case REQ_RANGE_ALLIANCE:
3962 case REQ_RANGE_WORLD:
3963 if (context->player == nullptr) {
3964 return TRI_MAYBE;
3965 }
3966 players_iterate_alive(plr2) {
3967 if (players_in_same_range(context->player, plr2, req->range)) {
3969 return TRI_YES;
3970 }
3971 }
3973 return TRI_NO;
3974 case REQ_RANGE_LOCAL:
3975 case REQ_RANGE_TILE:
3977 case REQ_RANGE_ADJACENT:
3978 case REQ_RANGE_CITY:
3981 case REQ_RANGE_COUNT:
3982 break;
3983 }
3984
3985 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3986
3987 return TRI_MAYBE;
3988}
3989
3990/**********************************************************************/
3998static enum fc_tristate
4000 const struct req_context *context,
4001 const struct req_context *other_context,
4002 const struct requirement *req)
4003{
4004 const struct nation_type *nationality;
4005 enum fc_tristate ret;
4006
4008
4009 nationality = req->source.value.nationality;
4010
4011 switch (req->range) {
4012 case REQ_RANGE_CITY:
4013 if (context->city == nullptr) {
4014 return TRI_MAYBE;
4015 }
4016 citizens_iterate(context->city, slot, count) {
4017 if (player_slot_get_player(slot)->nation == nationality) {
4018 return TRI_YES;
4019 }
4021
4022 return TRI_NO;
4024 if (context->city == nullptr) {
4025 return TRI_MAYBE;
4026 }
4027 citizens_iterate(context->city, slot, count) {
4028 if (player_slot_get_player(slot)->nation == nationality) {
4029 return TRI_YES;
4030 }
4032
4033 ret = TRI_NO;
4035 if (trade_partner == nullptr) {
4036 ret = TRI_MAYBE;
4037 } else {
4038 citizens_iterate(trade_partner, slot, count) {
4039 if (player_slot_get_player(slot)->nation == nationality) {
4040 return TRI_YES;
4041 }
4043 }
4045
4046 return ret;
4047 case REQ_RANGE_PLAYER:
4048 case REQ_RANGE_TEAM:
4049 case REQ_RANGE_ALLIANCE:
4050 case REQ_RANGE_WORLD:
4051 case REQ_RANGE_LOCAL:
4052 case REQ_RANGE_TILE:
4054 case REQ_RANGE_ADJACENT:
4056 case REQ_RANGE_COUNT:
4057 break;
4058 }
4059
4060 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4061
4062 return TRI_MAYBE;
4063}
4064
4065/**********************************************************************/
4073static enum fc_tristate
4075 const struct req_context *context,
4076 const struct req_context *other_context,
4077 const struct requirement *req)
4078{
4079 const struct nation_type *nation;
4080
4082
4083 nation = req->source.value.origowner;
4084
4085 switch (req->range) {
4086 case REQ_RANGE_CITY:
4087 if (context->city == nullptr || context->city->original == nullptr) {
4088 return TRI_MAYBE;
4089 }
4090 if (player_nation(context->city->original) == nation) {
4091 return TRI_YES;
4092 }
4093
4094 return TRI_NO;
4096 case REQ_RANGE_PLAYER:
4097 case REQ_RANGE_TEAM:
4098 case REQ_RANGE_ALLIANCE:
4099 case REQ_RANGE_WORLD:
4100 case REQ_RANGE_LOCAL:
4101 case REQ_RANGE_TILE:
4103 case REQ_RANGE_ADJACENT:
4105 case REQ_RANGE_COUNT:
4106 break;
4107 }
4108
4109 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4110
4111 return TRI_MAYBE;
4112}
4113
4114/**********************************************************************/
4118 const struct player *other_player,
4119 enum req_range range,
4120 int diplrel)
4121{
4122 switch (range) {
4123 case REQ_RANGE_PLAYER:
4124 if (target_player == nullptr) {
4125 return TRI_MAYBE;
4126 }
4128 case REQ_RANGE_TEAM:
4129 case REQ_RANGE_ALLIANCE:
4130 case REQ_RANGE_WORLD:
4131 if (target_player == nullptr) {
4132 return TRI_MAYBE;
4133 }
4134 players_iterate_alive(plr2) {
4136 if (is_diplrel_to_other(plr2, diplrel)) {
4137 return TRI_YES;
4138 }
4139 }
4141 return TRI_NO;
4142 case REQ_RANGE_LOCAL:
4143 if (target_player == nullptr || other_player == nullptr) {
4144 return TRI_MAYBE;
4145 }
4146 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
4147 case REQ_RANGE_TILE:
4149 case REQ_RANGE_ADJACENT:
4150 case REQ_RANGE_CITY:
4153 case REQ_RANGE_COUNT:
4154 break;
4155 }
4156
4157 fc_assert_msg(FALSE, "Invalid range %d.", range);
4158
4159 return TRI_MAYBE;
4160}
4161
4162/**********************************************************************/
4170static enum fc_tristate
4172 const struct req_context *context,
4173 const struct req_context *other_context,
4174 const struct requirement *req)
4175{
4177
4178 return is_diplrel_in_range(context->player, other_context->player,
4179 req->range, req->source.value.diplrel);
4180}
4181
4182/**********************************************************************/
4190static enum fc_tristate
4192 const struct req_context *context,
4193 const struct req_context *other_context,
4194 const struct requirement *req)
4195{
4197
4198 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4199 : nullptr,
4200 context->player,
4201 req->range,
4202 req->source.value.diplrel);
4203}
4204
4205/**********************************************************************/
4214static enum fc_tristate
4216 const struct req_context *context,
4217 const struct req_context *other_context,
4218 const struct requirement *req)
4219{
4221
4222 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4223 : nullptr,
4224 other_context->player,
4225 req->range,
4226 req->source.value.diplrel);
4227}
4228
4229/**********************************************************************/
4232static enum fc_tristate
4234 const struct player *other_player,
4235 enum req_range range,
4236 int diplrel)
4237{
4238 enum fc_tristate out = TRI_NO;
4239
4240 if (target_tile == nullptr) {
4241 return TRI_MAYBE;
4242 }
4243
4246 unit_owner(target_unit), other_player, range, diplrel);
4247
4250
4251 return out;
4252}
4253
4254/**********************************************************************/
4263static enum fc_tristate
4265 const struct req_context *context,
4266 const struct req_context *other_context,
4267 const struct requirement *req)
4268{
4270
4271 return is_diplrel_unitany_in_range(context->tile, context->player,
4272 req->range,
4273 req->source.value.diplrel);
4274}
4275
4276/**********************************************************************/
4285static enum fc_tristate
4287 const struct req_context *context,
4288 const struct req_context *other_context,
4289 const struct requirement *req)
4290{
4292
4294 req->range,
4295 req->source.value.diplrel);
4296}
4297
4298/**********************************************************************/
4306static enum fc_tristate
4308 const struct req_context *context,
4309 const struct req_context *other_context,
4310 const struct requirement *req)
4311{
4312 const struct unit_type *punittype;
4313
4315
4316 punittype = req->source.value.utype;
4317
4318 switch (req->range) {
4319 case REQ_RANGE_LOCAL:
4320 if (!context->unittype) {
4321 return TRI_MAYBE;
4322 }
4323 return BOOL_TO_TRISTATE(context->unittype == punittype);
4324 case REQ_RANGE_TILE:
4326 case REQ_RANGE_ADJACENT:
4327 if (context->tile == nullptr) {
4328 return TRI_MAYBE;
4329 }
4330
4331 unit_list_iterate(context->tile->units, punit) {
4332 if (punit->utype == punittype) {
4333 return TRI_YES;
4334 }
4336
4337 if (req->range == REQ_RANGE_TILE) {
4338 return TRI_NO;
4339 }
4340
4341 if (req->range == REQ_RANGE_CADJACENT) {
4344 if (punit->utype == punittype) {
4345 return TRI_YES;
4346 }
4349 } else {
4351
4354 if (punit->utype == punittype) {
4355 return TRI_YES;
4356 }
4359 }
4360
4361 return TRI_NO;
4362
4363 case REQ_RANGE_CITY:
4366 case REQ_RANGE_PLAYER:
4367 case REQ_RANGE_TEAM:
4368 case REQ_RANGE_ALLIANCE:
4369 case REQ_RANGE_WORLD:
4370 case REQ_RANGE_COUNT:
4372 break;
4373 }
4374
4375 return TRI_NO;
4376}
4377
4378/**********************************************************************/
4386static enum fc_tristate
4388 const struct req_context *context,
4389 const struct req_context *other_context,
4390 const struct requirement *req)
4391{
4392 enum unit_type_flag_id unitflag;
4393
4395
4396 unitflag = req->source.value.unitflag;
4397
4398 switch (req->range) {
4399 case REQ_RANGE_LOCAL:
4400 if (!context->unittype) {
4401 return TRI_MAYBE;
4402 }
4403 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4404 case REQ_RANGE_TILE:
4406 case REQ_RANGE_ADJACENT:
4407 if (context->tile == nullptr) {
4408 return TRI_MAYBE;
4409 }
4410
4411 unit_list_iterate(context->tile->units, punit) {
4412 if (unit_has_type_flag(punit, unitflag)) {
4413 return TRI_YES;
4414 }
4416
4417 if (req->range == REQ_RANGE_TILE) {
4418 return TRI_NO;
4419 }
4420
4421 if (req->range == REQ_RANGE_CADJACENT) {
4424 if (unit_has_type_flag(punit, unitflag)) {
4425 return TRI_YES;
4426 }
4429 } else {
4431
4434 if (unit_has_type_flag(punit, unitflag)) {
4435 return TRI_YES;
4436 }
4439 }
4440
4441 return TRI_NO;
4442
4443 case REQ_RANGE_CITY:
4446 case REQ_RANGE_PLAYER:
4447 case REQ_RANGE_TEAM:
4448 case REQ_RANGE_ALLIANCE:
4449 case REQ_RANGE_WORLD:
4450 case REQ_RANGE_COUNT:
4452 break;
4453 }
4454
4455 return TRI_NO;
4456}
4457
4458/**********************************************************************/
4466static enum fc_tristate
4468 const struct req_context *context,
4469 const struct req_context *other_context,
4470 const struct requirement *req)
4471{
4472 const struct unit_class *pclass;
4473
4475
4476 pclass = req->source.value.uclass;
4477
4478 switch (req->range) {
4479 case REQ_RANGE_LOCAL:
4480 if (!context->unittype) {
4481 return TRI_MAYBE;
4482 }
4483 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4484 case REQ_RANGE_TILE:
4486 case REQ_RANGE_ADJACENT:
4487 if (context->tile == nullptr) {
4488 return TRI_MAYBE;
4489 }
4490
4491 unit_list_iterate(context->tile->units, punit) {
4492 if (unit_class_get(punit) == pclass) {
4493 return TRI_YES;
4494 }
4496
4497 if (req->range == REQ_RANGE_TILE) {
4498 return TRI_NO;
4499 }
4500
4501 if (req->range == REQ_RANGE_CADJACENT) {
4504 if (unit_class_get(punit) == pclass) {
4505 return TRI_YES;
4506 }
4509 } else {
4511
4514 if (unit_class_get(punit) == pclass) {
4515 return TRI_YES;
4516 }
4519 }
4520
4521 return TRI_NO;
4522
4523 case REQ_RANGE_CITY:
4526 case REQ_RANGE_PLAYER:
4527 case REQ_RANGE_TEAM:
4528 case REQ_RANGE_ALLIANCE:
4529 case REQ_RANGE_WORLD:
4530 case REQ_RANGE_COUNT:
4532 break;
4533 }
4534
4535 return TRI_NO;
4536}
4537
4538/**********************************************************************/
4546static enum fc_tristate
4548 const struct req_context *context,
4549 const struct req_context *other_context,
4550 const struct requirement *req)
4551{
4553
4555
4557
4558 switch (req->range) {
4559 case REQ_RANGE_LOCAL:
4560 if (!context->unittype) {
4561 return TRI_MAYBE;
4562 }
4564 case REQ_RANGE_TILE:
4566 case REQ_RANGE_ADJACENT:
4567 if (context->tile == nullptr) {
4568 return TRI_MAYBE;
4569 }
4570
4571 unit_list_iterate(context->tile->units, punit) {
4573 return TRI_YES;
4574 }
4576
4577 if (req->range == REQ_RANGE_TILE) {
4578 return TRI_NO;
4579 }
4580
4581 if (req->range == REQ_RANGE_CADJACENT) {
4585 return TRI_YES;
4586 }
4589 } else {
4591
4595 return TRI_YES;
4596 }
4599 }
4600
4601 return TRI_NO;
4602
4603 case REQ_RANGE_CITY:
4606 case REQ_RANGE_PLAYER:
4607 case REQ_RANGE_TEAM:
4608 case REQ_RANGE_ALLIANCE:
4609 case REQ_RANGE_WORLD:
4610 case REQ_RANGE_COUNT:
4612 break;
4613 }
4614
4615 return TRI_NO;
4616}
4617
4618/**********************************************************************/
4626static enum fc_tristate
4628 const struct req_context *context,
4629 const struct req_context *other_context,
4630 const struct requirement *req)
4631{
4632 enum ustate_prop uprop;
4633
4635
4637
4639 "Unsupported range \"%s\"",
4640 req_range_name(req->range));
4641
4642 /* Could be asked with incomplete data.
4643 * is_req_active() will handle it based on prob_type. */
4644 if (context->unit == nullptr) {
4645 return TRI_MAYBE;
4646 }
4647
4648 switch (uprop) {
4649 case USP_TRANSPORTED:
4650 return BOOL_TO_TRISTATE(context->unit->transporter != nullptr);
4651 case USP_LIVABLE_TILE:
4652 return BOOL_TO_TRISTATE(
4654 unit_tile(context->unit)));
4655 break;
4656 case USP_TRANSPORTING:
4658 case USP_HAS_HOME_CITY:
4659 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
4660 case USP_NATIVE_TILE:
4661 return BOOL_TO_TRISTATE(
4663 unit_tile(context->unit)));
4664 break;
4665 case USP_NATIVE_EXTRA:
4666 return BOOL_TO_TRISTATE(
4668 unit_type_get(context->unit)));
4669 break;
4671 return BOOL_TO_TRISTATE(context->unit->moved);
4672 case USP_COUNT:
4673 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
4674 /* Invalid property is unknowable. */
4675 return TRI_NO;
4676 }
4677
4678 /* Should never be reached */
4679 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
4680
4681 return TRI_NO;
4682}
4683
4684/**********************************************************************/
4692static enum fc_tristate
4694 const struct req_context *context,
4695 const struct req_context *other_context,
4696 const struct requirement *req)
4697{
4698 enum unit_activity activity;
4699
4701
4702 activity = req->source.value.activity;
4703
4705 "Unsupported range \"%s\"",
4706 req_range_name(req->range));
4707
4708 if (context->unit == nullptr) {
4709 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
4710 * it's the zero value that context has by default - so many callers
4711 * who meant not to set specific activity actually have ACTIVITY_IDLE
4712 * instead of ACTIVITY_LAST */
4713 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
4714 return BOOL_TO_TRISTATE(activity == context->activity);
4715 }
4716
4717 /* Could be asked with incomplete data.
4718 * is_req_active() will handle it based on prob_type. */
4719 return TRI_MAYBE;
4720 }
4721
4722 switch (context->unit->activity) {
4723 case ACTIVITY_IDLE:
4724 case ACTIVITY_SENTRY:
4725 case ACTIVITY_GOTO:
4726 case ACTIVITY_EXPLORE:
4727 /* Seen as idle. */
4728 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
4729 default:
4730 /* Handled below. */
4731 break;
4732 }
4733
4734 return BOOL_TO_TRISTATE(context->unit->activity == activity);
4735}
4736
4737/**********************************************************************/
4745static enum fc_tristate
4747 const struct req_context *context,
4748 const struct req_context *other_context,
4749 const struct requirement *req)
4750{
4752
4753 if (context->unit == nullptr) {
4754 return TRI_MAYBE;
4755 } else {
4756 return BOOL_TO_TRISTATE(context->unit->veteran
4757 >= req->source.value.minveteran);
4758 }
4759}
4760
4761/**********************************************************************/
4769static enum fc_tristate
4771 const struct req_context *context,
4772 const struct req_context *other_context,
4773 const struct requirement *req)
4774{
4776
4777 if (context->unit == nullptr) {
4778 return TRI_MAYBE;
4779 } else {
4781 <= context->unit->moves_left);
4782 }
4783}
4784
4785/**********************************************************************/
4793static enum fc_tristate
4795 const struct req_context *context,
4796 const struct req_context *other_context,
4797 const struct requirement *req)
4798{
4800
4801 if (context->unit == nullptr) {
4802 return TRI_MAYBE;
4803 } else {
4805 <= context->unit->hp);
4806 }
4807}
4808
4809/**********************************************************************/
4817static enum fc_tristate
4819 const struct req_context *context,
4820 const struct req_context *other_context,
4821 const struct requirement *req)
4822{
4824
4825 switch (req->range) {
4826 case REQ_RANGE_LOCAL:
4827 if (context->unit == nullptr || !is_server()) {
4828 return TRI_MAYBE;
4829 } else {
4830 return BOOL_TO_TRISTATE(
4831 req->source.value.age <=
4832 game.info.turn - context->unit->birth_turn);
4833 }
4834 break;
4835 case REQ_RANGE_CITY:
4836 if (context->city == nullptr) {
4837 return TRI_MAYBE;
4838 } else {
4839 return BOOL_TO_TRISTATE(
4840 req->source.value.age <=
4841 game.info.turn - context->city->turn_founded);
4842 }
4843 break;
4844 case REQ_RANGE_PLAYER:
4845 if (context->player == nullptr) {
4846 return TRI_MAYBE;
4847 } else {
4848 return BOOL_TO_TRISTATE(req->source.value.age
4849 <= player_age(context->player));
4850 }
4851 break;
4852 default:
4853 return TRI_MAYBE;
4854 break;
4855 }
4856}
4857
4858/**********************************************************************/
4866static enum fc_tristate
4868 const struct req_context *context,
4869 const struct req_context *other_context,
4870 const struct requirement *req)
4871{
4873
4874 switch (req->range) {
4875 case REQ_RANGE_LOCAL:
4876 if (context->unit == nullptr || !is_server()) {
4877 return TRI_MAYBE;
4878 } else {
4879 return BOOL_TO_TRISTATE(
4880 req->source.value.form_age <=
4881 game.info.turn - context->unit->current_form_turn);
4882 }
4883 break;
4884 default:
4885 return TRI_MAYBE;
4886 break;
4887 }
4888}
4889
4890/**********************************************************************/
4894static inline enum fc_tristate
4896{
4898 bool whole_known;
4899
4900 if (cont > 0) {
4903
4904 if (actual_surrounder > 0) {
4905 return TRI_NO;
4906 }
4907 } else if (cont < 0) {
4910
4911 if (actual_surrounder < 0) {
4912 return TRI_NO;
4913 }
4914 } else {
4915 return TRI_MAYBE;
4916 }
4917
4918 if (actual_surrounder == 0 || surrounder == 0) {
4919 return TRI_MAYBE;
4920 } else if (actual_surrounder != surrounder) {
4921 return TRI_NO;
4922 } else if (!whole_known) {
4923 return TRI_MAYBE;
4924 } else {
4925 return TRI_YES;
4926 }
4927}
4928
4929/**********************************************************************/
4937static enum fc_tristate
4939 const struct req_context *context,
4940 const struct req_context *other_context,
4941 const struct requirement *req)
4942{
4944
4945 if (context->tile == nullptr || other_context->tile == nullptr) {
4946 /* Note: For some values, we might be able to give a definitive
4947 * TRI_NO answer even if one of the tiles is missing, but that's
4948 * probably not worth the added effort. */
4949 return TRI_MAYBE;
4950 }
4951
4952 switch (req->source.value.tilerel) {
4953 case TREL_SAME_TCLASS:
4954 if (tile_terrain(other_context->tile) == T_UNKNOWN) {
4955 return TRI_MAYBE;
4956 }
4958 || req->range == REQ_RANGE_CADJACENT
4959 || req->range == REQ_RANGE_ADJACENT),
4960 TRI_MAYBE,
4961 "Invalid range %d for tile relation \"%s\" req",
4963 {
4966 bool seen_unknown = FALSE;
4967 const struct terrain *terr;
4968
4969 if ((terr = tile_terrain(context->tile)) == T_UNKNOWN) {
4971 } else if (terrain_type_terrain_class(terr) == cls) {
4972 return TRUE;
4973 }
4974
4976 if ((terr = tile_terrain(adj_tile)) == T_UNKNOWN) {
4978 } else if (terrain_type_terrain_class(terr) == cls) {
4979 return TRUE;
4980 }
4982
4983 if (seen_unknown) {
4984 return TRI_MAYBE;
4985 } else {
4986 return TRI_NO;
4987 }
4988 }
4989 break;
4990 case TREL_SAME_REGION:
4991 if (tile_continent(other_context->tile) == 0) {
4992 return TRI_MAYBE;
4993 }
4995 || req->range == REQ_RANGE_CADJACENT
4996 || req->range == REQ_RANGE_ADJACENT),
4997 TRI_MAYBE,
4998 "Invalid range %d for tile relation \"%s\" req",
5000
5001 if (tile_continent(context->tile)
5002 == tile_continent(other_context->tile)) {
5003 return TRI_YES;
5004 } else {
5005 bool seen_unknown = (tile_continent(context->tile) == 0);
5007
5010
5011 if (adj_cont == cont) {
5012 return TRI_YES;
5013 } else if (adj_cont == 0) {
5015 }
5017
5018 if (seen_unknown) {
5019 return TRI_MAYBE;
5020 } else {
5021 return TRI_NO;
5022 }
5023 }
5024 break;
5026 if (tile_continent(context->tile) == 0
5027 || tile_continent(other_context->tile) == 0) {
5028 /* Note: We could still give a definitive TRI_NO answer if there are
5029 * too many different adjacent continents, but that's probably not
5030 * worth the added effort. */
5031 return TRI_MAYBE;
5032 }
5034 || req->range == REQ_RANGE_ADJACENT),
5035 TRI_MAYBE,
5036 "Invalid range %d for tile relation \"%s\" req",
5037 req->range,
5039
5040 {
5041 bool seen_unknown = FALSE;
5042 Continent_id cont = tile_continent(context->tile);
5044
5047
5048 if (adj_cont == 0) {
5050 } else if (adj_cont != cont && adj_cont != other_cont) {
5051 return TRI_NO;
5052 }
5054
5055 if (seen_unknown) {
5056 return TRI_MAYBE;
5057 } else {
5058 return TRI_YES;
5059 }
5060 }
5061 break;
5064 || req->range == REQ_RANGE_CADJACENT
5065 || req->range == REQ_RANGE_ADJACENT),
5066 TRI_MAYBE,
5067 "Invalid range %d for tile relation \"%s\" req",
5068 req->range,
5070
5071 {
5072 bool seen_maybe = FALSE;
5074
5076 wanted)) {
5077 case TRI_YES:
5078 return TRI_YES;
5079 case TRI_MAYBE:
5080 seen_maybe = TRUE;
5081 break;
5082 default:
5083 break;
5084 }
5085
5088 wanted)) {
5089 case TRI_YES:
5090 return TRI_YES;
5091 case TRI_MAYBE:
5092 seen_maybe = TRUE;
5093 break;
5094 default:
5095 break;
5096 }
5098
5099 if (seen_maybe) {
5100 return TRI_MAYBE;
5101 } else {
5102 return TRI_NO;
5103 }
5104 }
5105 break;
5106 default:
5107 break;
5108 }
5109
5111 "Illegal value %d for tile relationship requirement.",
5112 req->source.value.tilerel);
5113 return TRI_MAYBE;
5114}
5115
5116/**********************************************************************/
5119static bool is_city_in_tile(const struct tile *ptile,
5120 const struct city *pcity)
5121{
5122 if (pcity == nullptr) {
5123 return tile_city(ptile) != nullptr;
5124 } else {
5125 return is_city_center(pcity, ptile);
5126 }
5127}
5128
5129/**********************************************************************/
5137static enum fc_tristate
5139 const struct req_context *context,
5140 const struct req_context *other_context,
5141 const struct requirement *req)
5142{
5143 enum citytile_type citytile;
5144
5146
5147 citytile = req->source.value.citytile;
5148
5150 if (context->tile == nullptr) {
5151 return TRI_MAYBE;
5152 }
5153
5154 switch (citytile) {
5155 case CITYT_CENTER:
5156 switch (req->range) {
5157 case REQ_RANGE_TILE:
5159 context->city));
5161 if (is_city_in_tile(context->tile, context->city)) {
5162 return TRI_YES;
5163 }
5165 if (is_city_in_tile(adjc_tile, context->city)) {
5166 return TRI_YES;
5167 }
5169
5170 return TRI_NO;
5171 case REQ_RANGE_ADJACENT:
5172 if (is_city_in_tile(context->tile, context->city)) {
5173 return TRI_YES;
5174 }
5176 if (is_city_in_tile(adjc_tile, context->city)) {
5177 return TRI_YES;
5178 }
5180
5181 return TRI_NO;
5182 case REQ_RANGE_CITY:
5185 case REQ_RANGE_PLAYER:
5186 case REQ_RANGE_TEAM:
5187 case REQ_RANGE_ALLIANCE:
5188 case REQ_RANGE_WORLD:
5189 case REQ_RANGE_LOCAL:
5190 case REQ_RANGE_COUNT:
5191 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5192 break;
5193 }
5194
5195 return TRI_MAYBE;
5196 case CITYT_CLAIMED:
5197 switch (req->range) {
5198 case REQ_RANGE_TILE:
5199 return BOOL_TO_TRISTATE(context->tile->owner != nullptr);
5201 if (context->tile->owner != nullptr) {
5202 return TRI_YES;
5203 }
5205 if (adjc_tile->owner != nullptr) {
5206 return TRI_YES;
5207 }
5209
5210 return TRI_NO;
5211 case REQ_RANGE_ADJACENT:
5212 if (context->tile->owner != nullptr) {
5213 return TRI_YES;
5214 }
5216 if (adjc_tile->owner != nullptr) {
5217 return TRI_YES;
5218 }
5220
5221 return TRI_NO;
5222 case REQ_RANGE_CITY:
5225 case REQ_RANGE_PLAYER:
5226 case REQ_RANGE_TEAM:
5227 case REQ_RANGE_ALLIANCE:
5228 case REQ_RANGE_WORLD:
5229 case REQ_RANGE_LOCAL:
5230 case REQ_RANGE_COUNT:
5231 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5232 break;
5233 }
5234
5235 return TRI_MAYBE;
5236 case CITYT_EXTRAS_OWNED:
5237 switch (req->range) {
5238 case REQ_RANGE_TILE:
5239 return BOOL_TO_TRISTATE(context->tile->extras_owner != nullptr);
5241 if (context->tile->extras_owner != nullptr) {
5242 return TRI_YES;
5243 }
5245 if (adjc_tile->extras_owner != nullptr) {
5246 return TRI_YES;
5247 }
5249
5250 return TRI_NO;
5251 case REQ_RANGE_ADJACENT:
5252 if (context->tile->extras_owner != nullptr) {
5253 return TRI_YES;
5254 }
5256 if (adjc_tile->extras_owner != nullptr) {
5257 return TRI_YES;
5258 }
5260
5261 return TRI_NO;
5262 case REQ_RANGE_CITY:
5265 case REQ_RANGE_PLAYER:
5266 case REQ_RANGE_TEAM:
5267 case REQ_RANGE_ALLIANCE:
5268 case REQ_RANGE_WORLD:
5269 case REQ_RANGE_LOCAL:
5270 case REQ_RANGE_COUNT:
5271 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5272 break;
5273 }
5274
5275 return TRI_MAYBE;
5276 case CITYT_WORKED:
5277 switch (req->range) {
5278 case REQ_RANGE_TILE:
5279 return BOOL_TO_TRISTATE(context->tile->worked != nullptr);
5281 if (context->tile->worked != nullptr) {
5282 return TRI_YES;
5283 }
5285 if (adjc_tile->worked != nullptr) {
5286 return TRI_YES;
5287 }
5289
5290 return TRI_NO;
5291 case REQ_RANGE_ADJACENT:
5292 if (context->tile->worked != nullptr) {
5293 return TRI_YES;
5294 }
5296 if (adjc_tile->worked != nullptr) {
5297 return TRI_YES;
5298 }
5300
5301 return TRI_NO;
5302 case REQ_RANGE_CITY:
5305 case REQ_RANGE_PLAYER:
5306 case REQ_RANGE_TEAM:
5307 case REQ_RANGE_ALLIANCE:
5308 case REQ_RANGE_WORLD:
5309 case REQ_RANGE_LOCAL:
5310 case REQ_RANGE_COUNT:
5311 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5312 break;
5313 }
5314
5315 return TRI_MAYBE;
5317 {
5319 const struct tile *target_tile = context->tile, *cc_tile;
5320
5321 if (!context->city) {
5322 return TRI_MAYBE;
5323 }
5324 cc_tile = city_tile(context->city);
5325 if (!cc_tile) {
5326 /* Unplaced virtual city */
5327 return TRI_MAYBE;
5328 }
5330 /* Note: No special treatment of 0 == cc here*/
5331 switch (req->range) {
5332 case REQ_RANGE_TILE:
5335 if (tile_continent(target_tile) == cc) {
5336 return TRI_YES;
5337 }
5339 if (tile_continent(adjc_tile) == cc) {
5340 return TRI_YES;
5341 }
5343
5344 return TRI_NO;
5345 case REQ_RANGE_ADJACENT:
5346 if (tile_continent(target_tile) == cc) {
5347 return TRI_YES;
5348 }
5350 if (tile_continent(adjc_tile) == cc) {
5351 return TRI_YES;
5352 }
5354
5355 return TRI_NO;
5356 case REQ_RANGE_CITY:
5359 case REQ_RANGE_PLAYER:
5360 case REQ_RANGE_TEAM:
5361 case REQ_RANGE_ALLIANCE:
5362 case REQ_RANGE_WORLD:
5363 case REQ_RANGE_LOCAL:
5364 case REQ_RANGE_COUNT:
5365 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5366 break;
5367 }
5368 }
5369
5370 return TRI_MAYBE;
5372 {
5373 int n = 0;
5375 bool ukt = FALSE;
5376 const struct tile *target_tile = context->tile, *cc_tile;
5377
5378 if (!context->city) {
5379 return TRI_MAYBE;
5380 }
5381 cc_tile = city_tile(context->city);
5382 if (!cc_tile) {
5383 /* Unplaced virtual city */
5384 return TRI_MAYBE;
5385 }
5387 if (!cc) {
5388 /* Don't know the city center terrain class.
5389 * Maybe, the city floats? Even if the rules prohibit it... */
5390 return TRI_MAYBE;
5391 }
5394
5395 if (0 != tc) {
5396 bool seen = FALSE;
5397 int i = n;
5398
5399 if (tc == cc) {
5400 continue;
5401 }
5402 while (--i >= 0) {
5403 if (adjc_cont[i] == tc) {
5404 seen = TRUE;
5405 break;
5406 }
5407 }
5408 if (seen) {
5409 continue;
5410 }
5412 } else {
5413 /* Likely, it's a black tile in client and we don't know
5414 * We possibly can calculate, but keep it simple. */
5415 ukt = TRUE;
5416 }
5418 if (0 == n) {
5419 return ukt ? TRI_MAYBE : TRI_NO;
5420 }
5421
5422 switch (req->range) {
5423 case REQ_RANGE_TILE:
5424 {
5426
5427 if (cc == tc) {
5428 return TRI_NO;
5429 }
5430 if (0 == tc || ukt) {
5431 return TRI_MAYBE;
5432 }
5433 for (int i = 0; i < n; i++) {
5434 if (tc == adjc_cont[i]) {
5435 return TRI_YES;
5436 }
5437 }
5438 }
5439
5440 return TRI_NO;
5441 case REQ_RANGE_ADJACENT:
5442 if (ukt) {
5443 /* If ALL the tiles in range are on cc, we can say it's false */
5445 if (tile_continent(adjc_tile) != cc) {
5446 return TRI_MAYBE;
5447 }
5449
5450 return TRI_NO;
5451 } else {
5454
5455 if (0 == tc) {
5456 return TRI_MAYBE;
5457 }
5458 for (int i = 0; i < n; i++) {
5459 if (tc == adjc_cont[i]) {
5460 return TRI_YES;
5461 }
5462 }
5464 }
5465
5466 return TRI_NO;
5468 if (ukt) {
5469 /* If ALL the tiles in range are on cc, we can say it's false */
5471 if (tile_continent(cadjc_tile) != cc) {
5472 return TRI_MAYBE;
5473 }
5475 } else {
5478
5479 if (0 == tc) {
5480 return TRI_MAYBE;
5481 }
5482 for (int i = 0; i < n; i++) {
5483 if (tc == adjc_cont[i]) {
5484 return TRI_YES;
5485 }
5486 }
5488 }
5489
5490 return TRI_NO;
5491 case REQ_RANGE_CITY:
5494 case REQ_RANGE_PLAYER:
5495 case REQ_RANGE_TEAM:
5496 case REQ_RANGE_ALLIANCE:
5497 case REQ_RANGE_WORLD:
5498 case REQ_RANGE_LOCAL:
5499 case REQ_RANGE_COUNT:
5500 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5501 break;
5502 }
5503 }
5504
5505 return TRI_MAYBE;
5506 case CITYT_LAST:
5507 /* Handled below */
5508 break;
5509 }
5510
5511 /* Not implemented */
5512 log_error("is_req_active(): citytile %d not supported.",
5513 citytile);
5514 return TRI_MAYBE;
5515}
5516
5517/**********************************************************************/
5525static enum fc_tristate
5527 const struct req_context *context,
5528 const struct req_context *other_context,
5529 const struct requirement *req)
5530{
5531 enum citystatus_type citystatus;
5532
5534
5535 citystatus = req->source.value.citystatus;
5536
5537 if (context->city == nullptr) {
5538 return TRI_MAYBE;
5539 }
5540
5541 switch (citystatus) {
5543 switch (req->range) {
5544 case REQ_RANGE_CITY:
5545 if (context->city->original == nullptr) {
5546 return TRI_MAYBE;
5547 }
5548 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
5550 {
5551 enum fc_tristate ret;
5552
5553 if (city_owner(context->city) == context->city->original) {
5554 return TRI_YES;
5555 }
5556
5557 ret = TRI_NO;
5559 if (trade_partner == nullptr || trade_partner->original == nullptr) {
5560 ret = TRI_MAYBE;
5561 } else if (city_owner(trade_partner) == trade_partner->original) {
5562 return TRI_YES;
5563 }
5565
5566 return ret;
5567 }
5568 case REQ_RANGE_LOCAL:
5569 case REQ_RANGE_TILE:
5571 case REQ_RANGE_ADJACENT:
5573 case REQ_RANGE_PLAYER:
5574 case REQ_RANGE_TEAM:
5575 case REQ_RANGE_ALLIANCE:
5576 case REQ_RANGE_WORLD:
5577 case REQ_RANGE_COUNT:
5578 break;
5579 }
5580
5581 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
5582 req->range);
5583
5584 return TRI_MAYBE;
5585
5586 case CITYS_STARVED:
5587 switch (req->range) {
5588 case REQ_RANGE_CITY:
5589 return BOOL_TO_TRISTATE(context->city->had_famine);
5591 {
5592 enum fc_tristate ret;
5593
5594 if (context->city->had_famine) {
5595 return TRI_YES;
5596 }
5597
5598 ret = TRI_NO;
5600 if (trade_partner == nullptr) {
5601 ret = TRI_MAYBE;
5602 } else if (trade_partner->had_famine) {
5603 return TRI_YES;
5604 }
5606
5607 return ret;
5608 }
5609 case REQ_RANGE_LOCAL:
5610 case REQ_RANGE_TILE:
5612 case REQ_RANGE_ADJACENT:
5614 case REQ_RANGE_PLAYER:
5615 case REQ_RANGE_TEAM:
5616 case REQ_RANGE_ALLIANCE:
5617 case REQ_RANGE_WORLD:
5618 case REQ_RANGE_COUNT:
5619 break;
5620 }
5621
5622 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
5623 req->range);
5624
5625 return TRI_MAYBE;
5626
5627 case CITYS_DISORDER:
5628 switch (req->range) {
5629 case REQ_RANGE_CITY:
5630 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
5632 {
5633 enum fc_tristate ret;
5634
5635 if (context->city->anarchy > 0) {
5636 return TRI_YES;
5637 }
5638
5639 ret = TRI_NO;
5641 if (trade_partner == nullptr) {
5642 ret = TRI_MAYBE;
5643 } else if (trade_partner->anarchy > 0) {
5644 return TRI_YES;
5645 }
5647
5648 return ret;
5649 }
5650 case REQ_RANGE_LOCAL:
5651 case REQ_RANGE_TILE:
5653 case REQ_RANGE_ADJACENT:
5655 case REQ_RANGE_PLAYER:
5656 case REQ_RANGE_TEAM:
5657 case REQ_RANGE_ALLIANCE:
5658 case REQ_RANGE_WORLD:
5659 case REQ_RANGE_COUNT:
5660 break;
5661 }
5662
5663 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
5664 req->range);
5665
5666 return TRI_MAYBE;
5667
5668 case CITYS_CELEBRATION:
5669 switch (req->range) {
5670 case REQ_RANGE_CITY:
5671 return BOOL_TO_TRISTATE(context->city->rapture > 0);
5673 {
5674 enum fc_tristate ret;
5675
5676 if (context->city->rapture > 0) {
5677 return TRI_YES;
5678 }
5679
5680 ret = TRI_NO;
5682 if (trade_partner == nullptr) {
5683 ret = TRI_MAYBE;
5684 } else if (trade_partner->rapture > 0) {
5685 return TRI_YES;
5686 }
5688
5689 return ret;
5690 }
5691 case REQ_RANGE_LOCAL:
5692 case REQ_RANGE_TILE:
5694 case REQ_RANGE_ADJACENT:
5696 case REQ_RANGE_PLAYER:
5697 case REQ_RANGE_TEAM:
5698 case REQ_RANGE_ALLIANCE:
5699 case REQ_RANGE_WORLD:
5700 case REQ_RANGE_COUNT:
5701 break;
5702 }
5703
5704 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
5705 req->range);
5706
5707 return TRI_MAYBE;
5708
5709 case CITYS_TRANSFERRED:
5710 switch (req->range) {
5711 case REQ_RANGE_CITY:
5712 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
5714 {
5715 enum fc_tristate ret;
5716
5717 if (context->city->acquire_t != CACQ_FOUNDED) {
5718 return TRI_YES;
5719 }
5720
5721 ret = TRI_NO;
5723 if (trade_partner == nullptr) {
5724 ret = TRI_MAYBE;
5725 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
5726 return TRI_YES;
5727 }
5729
5730 return ret;
5731 }
5732 case REQ_RANGE_LOCAL:
5733 case REQ_RANGE_TILE:
5735 case REQ_RANGE_ADJACENT:
5737 case REQ_RANGE_PLAYER:
5738 case REQ_RANGE_TEAM:
5739 case REQ_RANGE_ALLIANCE:
5740 case REQ_RANGE_WORLD:
5741 case REQ_RANGE_COUNT:
5742 break;
5743 }
5744
5745 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
5746 req->range);
5747
5748 return TRI_MAYBE;
5749
5750 case CITYS_LAST:
5751 break;
5752 }
5753
5754 /* Not implemented */
5755 log_error("is_req_active(): citystatus %d not supported.",
5756 citystatus);
5757
5758 return TRI_MAYBE;
5759}
5760
5761/**********************************************************************/
5769static enum fc_tristate
5771 const struct req_context *context,
5772 const struct req_context *other_context,
5773 const struct requirement *req)
5774{
5776
5777 if (context->city == nullptr) {
5778 return TRI_MAYBE;
5779 } else {
5780 if (req->range == REQ_RANGE_TRADE_ROUTE) {
5781 enum fc_tristate ret;
5782
5783 if (city_size_get(context->city) >= req->source.value.minsize) {
5784 return TRI_YES;
5785 }
5786
5787 ret = TRI_NO;
5789 if (trade_partner == nullptr) {
5790 ret = TRI_MAYBE;
5791 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
5792 return TRI_YES;
5793 }
5795
5796 return ret;
5797 } else {
5799 >= req->source.value.minsize);
5800 }
5801 }
5802}
5803
5804/**********************************************************************/
5812static enum fc_tristate
5814 const struct req_context *context,
5815 const struct req_context *other_context,
5816 const struct requirement *req)
5817{
5818 const struct counter *count;
5819
5821
5822 count = req->source.value.counter;
5823
5824 if (context->city == nullptr) {
5825 return TRI_MAYBE;
5826 }
5827 return BOOL_TO_TRISTATE(count->checkpoint <=
5828 context->city->counter_values[
5829 counter_index(count)]);
5830}
5831
5832/**********************************************************************/
5840static enum fc_tristate
5842 const struct req_context *context,
5843 const struct req_context *other_context,
5844 const struct requirement *req)
5845{
5846 const struct achievement *achievement;
5847
5849
5851
5852 if (req->range == REQ_RANGE_WORLD) {
5854 } else if (context->player == nullptr) {
5855 return TRI_MAYBE;
5856 } else if (req->range == REQ_RANGE_ALLIANCE
5857 || req->range == REQ_RANGE_TEAM) {
5858 players_iterate_alive(plr2) {
5859 if (players_in_same_range(context->player, plr2, req->range)
5861 return TRI_YES;
5862 }
5864 return TRI_NO;
5865 } else if (req->range == REQ_RANGE_PLAYER) {
5867 return TRI_YES;
5868 } else {
5869 return TRI_NO;
5870 }
5871 }
5872
5873 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
5874
5875 return TRI_MAYBE;
5876}
5877
5878/**********************************************************************/
5886static enum fc_tristate
5888 const struct req_context *context,
5889 const struct req_context *other_context,
5890 const struct requirement *req)
5891{
5892 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
5893
5894 fc_assert_ret_val(req != nullptr, TRI_MAYBE);
5895 fc_assert(context != nullptr);
5896
5897 switch (req->source.kind) {
5898 case VUT_MINLATITUDE:
5899 min = req->source.value.latitude;
5900 break;
5901 case VUT_MAXLATITUDE:
5902 max = req->source.value.latitude;
5903 break;
5904 default:
5906 || req->source.kind == VUT_MAXLATITUDE);
5907 break;
5908 }
5909
5910 switch (req->range) {
5911 case REQ_RANGE_WORLD:
5913 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
5914
5915 case REQ_RANGE_TILE:
5916 if (context->tile == nullptr) {
5917 return TRI_MAYBE;
5918 } else {
5920
5922 }
5923
5925 if (context->tile == nullptr) {
5926 return TRI_MAYBE;
5927 }
5928
5931
5933 return TRI_YES;
5934 }
5936 return TRI_NO;
5937
5938 case REQ_RANGE_ADJACENT:
5939 if (!context->tile) {
5940 return TRI_MAYBE;
5941 }
5942
5945
5947 return TRI_YES;
5948 }
5950 return TRI_NO;
5951
5952 case REQ_RANGE_CITY:
5955 case REQ_RANGE_PLAYER:
5956 case REQ_RANGE_TEAM:
5957 case REQ_RANGE_ALLIANCE:
5958 case REQ_RANGE_LOCAL:
5959 case REQ_RANGE_COUNT:
5960 break;
5961 }
5962
5964 "Illegal range %d for latitude requirement.", req->range);
5965
5966 return TRI_MAYBE;
5967}
5968
5969/**********************************************************************/
5977static enum fc_tristate
5979 const struct req_context *context,
5980 const struct req_context *other_context,
5981 const struct requirement *req)
5982{
5984
5985 switch (req->range) {
5986 case REQ_RANGE_TILE:
5987 if (context->tile == nullptr || other_context->tile == nullptr) {
5988 return TRI_MAYBE;
5989 }
5990 return BOOL_TO_TRISTATE(
5992 <= req->source.value.distance_sq
5993 );
5994 default:
5995 break;
5996 }
5997
5999 "Illegal range %d for max squared distance requirement.",
6000 req->range);
6001
6002 return TRI_MAYBE;
6003}
6004
6005/**********************************************************************/
6013static enum fc_tristate
6015 const struct req_context *context,
6016 const struct req_context *other_context,
6017 const struct requirement *req)
6018{
6019 int max_tiles, min_tiles = 1;
6020
6022
6023 switch (req->range) {
6025 case REQ_RANGE_ADJACENT:
6026 if (context->tile == nullptr) {
6027 /* The tile itself is included in the range */
6028 max_tiles = 1 + ((req->range == REQ_RANGE_CADJACENT)
6029 ? nmap->num_cardinal_dirs
6030 : nmap->num_valid_dirs);
6031
6032 break;
6033 } else {
6034 Continent_id cont = tile_continent(context->tile);
6035
6036 /* Count how many adjacent tiles there actually are as we go along */
6037 max_tiles = 1;
6038
6041
6042 if (adj_cont == 0 || cont == 0) {
6043 max_tiles++;
6044 } else if (adj_cont == cont) {
6045 min_tiles++;
6046 max_tiles++;
6047 }
6049 }
6050 break;
6052 {
6053 Continent_id cont = context->tile ? tile_continent(context->tile) : 0;
6054
6057
6058 /* Note: We could come up with a better upper bound by subtracting
6059 * all other continent/ocean sizes, or all except the largest if we
6060 * don't know the tile.
6061 * We could even do a flood-fill count of the unknown area bordered
6062 * by known tiles of the continent.
6063 * Probably not worth the effort though. */
6064 max_tiles = nmap->xsize * nmap->ysize;
6065
6066 if (cont > 0) {
6067 min_tiles = nmap->continent_sizes[cont];
6068 if (is_whole_continent_known(cont)) {
6070 }
6071 } else if (cont < 0) {
6072 min_tiles = nmap->ocean_sizes[-cont];
6073 if (is_whole_ocean_known(-cont)) {
6075 }
6076 }
6077 }
6078 break;
6079 default:
6081 "Illegal range %d for max region tiles requirement.",
6082 req->range);
6083 return TRI_MAYBE;
6084 }
6085
6086 if (min_tiles > req->source.value.region_tiles) {
6087 return TRI_NO;
6088 } else if (max_tiles <= req->source.value.region_tiles) {
6089 return TRI_YES;
6090 }
6091 return TRI_MAYBE;
6092}
6093
6094/**********************************************************************/
6102static enum fc_tristate
6104 const struct req_context *context,
6105 const struct req_context *other_context,
6106 const struct requirement *req)
6107{
6109
6111}
6112
6113/**********************************************************************/
6121static enum fc_tristate
6123 const struct req_context *context,
6124 const struct req_context *other_context,
6125 const struct requirement *req)
6126{
6128
6130 >= req->source.value.mincalfrag);
6131}
6132
6133/**********************************************************************/
6141static enum fc_tristate
6143 const struct req_context *context,
6144 const struct req_context *other_context,
6145 const struct requirement *req)
6146{
6148
6149 return BOOL_TO_TRISTATE(
6151}
6152
6153/**********************************************************************/
6161static enum fc_tristate
6163 const struct req_context *context,
6164 const struct req_context *other_context,
6165 const struct requirement *req)
6166{
6168
6169 return BOOL_TO_TRISTATE(
6171}
6172
6173/**********************************************************************/
6181static enum fc_tristate
6183 const struct req_context *context,
6184 const struct req_context *other_context,
6185 const struct requirement *req)
6186{
6188
6190 req->source.value.ssetval));
6191}
6192
6193/* Not const for potential ruleset-related adjustment */
6196
6197 /* Alphabetical order of enum constant */
6260};
6261
6262/**********************************************************************/
6276 const struct req_context *other_context,
6277 const struct requirement *req,
6278 const enum req_problem_type prob_type)
6279{
6280 const struct civ_map *nmap = &(wld.map);
6282 req);
6283
6284 if (eval == TRI_MAYBE) {
6285 if (prob_type == RPT_POSSIBLE) {
6286 return TRUE;
6287 } else {
6288 return FALSE;
6289 }
6290 }
6291 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
6292}
6293
6294/**********************************************************************/
6303static
6305 const struct req_context *context,
6306 const struct req_context *other_context,
6307 const struct requirement *req)
6308{
6309 if (!context) {
6311 }
6312 if (!other_context) {
6314 }
6315
6316 if (req->source.kind >= VUT_COUNT) {
6317 log_error("tri_req_present(): invalid source kind %d.",
6318 req->source.kind);
6319 return TRI_NO;
6320 }
6321
6323
6324 return req_definitions[req->source.kind].cb(nmap, context,
6325 other_context, req);
6326}
6327
6328/**********************************************************************/
6338 const struct req_context *other_context,
6339 const struct requirement *req)
6340{
6341 const struct civ_map *nmap = &(wld.map);
6343
6344 if (!req->present) {
6345 if (TRI_NO == eval) {
6346 return TRI_YES;
6347 }
6348 if (TRI_YES == eval) {
6349 return TRI_NO;
6350 }
6351 }
6352
6353 return eval;
6354}
6355
6356/**********************************************************************/
6372 const struct req_context *other_context,
6373 const struct requirement_vector *reqs,
6374 const enum req_problem_type prob_type)
6375{
6378 return FALSE;
6379 }
6381
6382 return TRUE;
6383}
6384
6385/**********************************************************************/
6390 const enum req_range max_range,
6391 const struct req_context *context,
6392 const struct req_context *other_context,
6393 const struct requirement_vector *reqs,
6394 const enum req_problem_type prob_type)
6395{
6397 if (preq->range >= min_range && preq->range <= max_range) {
6399 return FALSE;
6400 }
6401 }
6403
6404 return TRUE;
6405}
6406
6407/**********************************************************************/
6413enum fc_tristate
6415 const struct req_context *context,
6416 const struct req_context *other_context,
6417 const struct requirement *req)
6418{
6419 /* FIXME: Doubles code from calendar.c */
6423 int fragment1 = fragment; /* If fragments don't advance */
6424 int year_inc, year_inc1;
6427 bool present, present1;
6428
6429 fc_assert(pass >= 0 && period >= 0);
6430 if (slowdown >= 3) {
6431 if (ypt > 1) {
6432 ypt = 1;
6433 }
6434 } else if (slowdown >= 2) {
6435 if (ypt > 2) {
6436 ypt = 2;
6437 }
6438 } else if (slowdown >= 1) {
6439 if (ypt > 5) {
6440 ypt = 5;
6441 }
6442 }
6443 year_inc = ypt * pass;
6446 int fragment_years;
6447
6448 fragment += fpt * pass;
6456 }
6458 if (year_inc + game.info.year >= 0) {
6459 year_inc++;
6460 year_inc1++;
6461 } else if (year_inc1 + game.info.year >= 0) {
6462 year_inc1++;
6463 }
6464 }
6465
6466 switch (req->source.kind) {
6467 case VUT_AGE:
6468 switch (req->range) {
6469 case REQ_RANGE_LOCAL:
6470 if (context->unit == nullptr || !is_server()) {
6471 return TRI_MAYBE;
6472 } else {
6473 int ua = game.info.turn + pass - context->unit->birth_turn;
6474
6475 present = req->source.value.age <= ua;
6476 present1 = req->source.value.age <= ua + period;
6477 }
6478 break;
6479 case REQ_RANGE_CITY:
6480 if (context->city == nullptr) {
6481 return TRI_MAYBE;
6482 } else {
6483 int ca = game.info.turn + pass - context->city->turn_founded;
6484
6485 present = req->source.value.age <= ca;
6486 present1 = req->source.value.age <= ca + period;
6487 }
6488 break;
6489 case REQ_RANGE_PLAYER:
6490 if (context->player == nullptr) {
6491 return TRI_MAYBE;
6492 } else {
6493 present = req->source.value.age
6494 <= player_age(context->player) + pass;
6495 present1 = req->source.value.age
6496 <= player_age(context->player) + pass + period;
6497 }
6498 break;
6499 default:
6500 return TRI_MAYBE;
6501 }
6502 break;
6503 case VUT_FORM_AGE:
6504 if (context->unit == nullptr || !is_server()) {
6505 return TRI_MAYBE;
6506 } else {
6507 int ua = game.info.turn + pass - context->unit->current_form_turn;
6508
6509 present = req->source.value.form_age <= ua;
6510 present1 = req->source.value.form_age <= ua + period;
6511 }
6512 break;
6513 case VUT_MINYEAR:
6514 present = game.info.year + year_inc >= req->source.value.minyear;
6516 break;
6517 case VUT_MINCALFRAG:
6519 /* Hope that the requirement is valid and fragments advance fine */
6520 return TRI_YES;
6521 }
6522 present = fragment >= req->source.value.mincalfrag;
6524 break;
6525 default:
6526 /* No special handling invented */
6527 return tri_req_active(context, other_context, req);
6528 }
6529 return BOOL_TO_TRISTATE(req->present
6530 ? present || present1 : !(present && present1));
6531}
6532
6533/**********************************************************************/
6539 (const struct req_context *context,
6540 const struct req_context *other_context,
6541 const struct requirement *req,
6542 void *data, int n_data)
6543{
6544 int i;
6545
6546 fc_assert_ret_val(data || n_data == 0, TRI_NO);
6547
6548 for (i = 0; i < n_data; i++) {
6549 if (are_requirements_contradictions(&((struct requirement *) data)[i],
6550 req)) {
6551 return TRI_NO;
6552 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
6553 return TRI_YES;
6554 }
6555 }
6556
6557 return tri_req_active(context, other_context, req);
6558}
6559
6560/**********************************************************************/
6566enum fc_tristate
6568 const struct req_context *other_context,
6569 const struct requirement_vector *reqs,
6572 void *data, int n_data)
6573{
6574 bool active = TRUE;
6575 bool certain = TRUE;
6576
6577 fc_assert_ret_val(tester != nullptr, TRI_NO);
6578
6581 data, n_data)) {
6582 case TRI_NO:
6583 active = FALSE;
6584 certain = TRUE;
6585 break;
6586 case TRI_YES:
6587 break;
6588 case TRI_MAYBE:
6589 certain = FALSE;
6590 if (maybe_reqs) {
6592 }
6593 break;
6594 default:
6596 active = FALSE;
6597 }
6598 if (!active) {
6599 break;
6600 }
6602
6603 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
6604}
6605
6606/**********************************************************************/
6616 const struct requirement *req)
6617{
6618 enum req_unchanging_status s;
6619 const struct civ_map *nmap = &(wld.map);
6620
6623 "Invalid source kind %d.", req->source.kind);
6625
6626 if (req->survives) {
6627 /* Special case for surviving requirements */
6628 /* Buildings may obsolete even here */
6629 if (VUT_IMPROVEMENT == req->source.kind) {
6630 const struct impr_type *b = req->source.value.building;
6631
6633 if (improvement_obsolete(context->player, b, context->city)) {
6634 /* FIXME: Sometimes can unobsolete, but considering it
6635 * may sometimes put the function on endless recursion */
6636 return REQUCH_ACT; /* Mostly about techs */
6637 } else {
6638 /* NOTE: May obsoletion reqs be unchanging? Hardly but why not. */
6639 return REQUCH_NO;
6640 }
6641 }
6642 }
6643 s = unchanging_present(nmap, s, context, req);
6644 if (s != REQUCH_NO) {
6645 return unchanging_noally(nmap, s, context, req);
6646 }
6647 } else {
6650
6651 if (cond) {
6652 return cond(nmap, s, context, req);
6653 }
6654 }
6655
6656 return s;
6657}
6658
6659/**********************************************************************/
6664 const struct req_context *other_context,
6665 const struct requirement *req,
6667{
6669
6670 if (REQUCH_NO != u) {
6671 /* Presence is precalculated */
6672 bool auto_present = (req->survives
6673 && !(VUT_IMPROVEMENT == req->source.kind
6677
6678 if (auto_present ? req->present
6680 /* Unchanging but does not block */
6681 return REQUCH_NO;
6682 }
6683 }
6684
6685 return u;
6686}
6687
6688/**********************************************************************/
6692bool is_req_in_vec(const struct requirement *req,
6693 const struct requirement_vector *vec)
6694{
6696 if (are_requirements_equal(req, preq)) {
6697 return TRUE;
6698 }
6700
6701 return FALSE;
6702}
6703
6704/**********************************************************************/
6712 enum universals_n kind)
6713{
6715 if (preq->present && preq->source.kind == kind) {
6716 return TRUE;
6717 }
6719 return FALSE;
6720}
6721
6722/**********************************************************************/
6731{
6732 switch (source->kind) {
6733 case VUT_ACTION:
6734 return !action_is_in_use(source->value.action);
6735 case VUT_UTFLAG:
6736 return !utype_flag_is_in_use(source->value.unitflag);
6737 case VUT_UCFLAG:
6738 return !uclass_flag_is_in_use(source->value.unitclassflag);
6739 case VUT_EXTRAFLAG:
6740 return !extra_flag_is_in_use(source->value.extraflag);
6741 case VUT_MINLATITUDE:
6742 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
6743 case VUT_MAXLATITUDE:
6744 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
6745 case VUT_COUNTER:
6746 case VUT_OTYPE:
6747 case VUT_SPECIALIST:
6748 case VUT_AI_LEVEL:
6749 case VUT_CITYTILE:
6750 case VUT_CITYSTATUS:
6751 case VUT_STYLE:
6752 case VUT_TOPO:
6753 case VUT_WRAP:
6754 case VUT_SERVERSETTING:
6755 case VUT_NATION:
6756 case VUT_NATIONGROUP:
6757 case VUT_ADVANCE:
6758 case VUT_TECHFLAG:
6759 case VUT_GOVERNMENT:
6760 case VUT_ACHIEVEMENT:
6761 case VUT_IMPROVEMENT:
6762 case VUT_SITE:
6763 case VUT_IMPR_GENUS:
6764 case VUT_IMPR_FLAG:
6765 case VUT_PLAYER_FLAG:
6766 case VUT_PLAYER_STATE:
6767 case VUT_MINSIZE:
6768 case VUT_MINCULTURE:
6769 case VUT_MINFOREIGNPCT:
6770 case VUT_MINTECHS:
6771 case VUT_MINCITIES:
6772 case VUT_NATIONALITY:
6773 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
6774 case VUT_DIPLREL:
6775 case VUT_DIPLREL_TILE:
6776 case VUT_DIPLREL_TILE_O:
6779 case VUT_MAXTILEUNITS:
6780 case VUT_UTYPE:
6781 case VUT_UCLASS:
6782 case VUT_MINVETERAN:
6783 case VUT_UNITSTATE:
6784 case VUT_ACTIVITY:
6785 case VUT_MINMOVES:
6786 case VUT_MINHP:
6787 case VUT_AGE:
6788 case VUT_FORM_AGE:
6789 case VUT_ROADFLAG:
6790 case VUT_MINCALFRAG:
6791 case VUT_TERRAIN:
6792 case VUT_EXTRA:
6793 case VUT_GOOD:
6794 case VUT_TERRAINCLASS:
6795 case VUT_TERRFLAG:
6796 case VUT_TERRAINALTER:
6797 case VUT_MINYEAR:
6800 case VUT_TILE_REL:
6801 case VUT_NONE:
6802 case VUT_COUNT:
6803 /* Not implemented. */
6804 break;
6805 }
6806
6807 return FALSE;
6808}
6809
6810/**********************************************************************/
6819{
6820 /* Not known to be impossible to fulfill */
6821 return req->present && universal_never_there(&req->source);
6822}
6823
6824/**********************************************************************/
6833{
6836 return TRUE;
6837 }
6839
6840 /* Not known to be impossible to fulfill */
6841 return FALSE;
6842}
6843
6844/**********************************************************************/
6854 const struct requirement_vector *vec)
6855{
6856 if (vec) {
6857 return 0;
6858 } else {
6859 return -1;
6860 }
6861}
6862
6863/********************************************************************/
6872struct requirement_vector *
6874{
6875 fc_assert_ret_val(number == 0, nullptr);
6876
6877 return (struct requirement_vector *)parent_item;
6878}
6879
6880/**********************************************************************/
6891const char *req_vec_change_translation(const struct req_vec_change *change,
6893{
6894 const char *req_vec_description;
6895 static char buf[MAX_LEN_NAME * 3];
6896 struct astring astr;
6897
6898 fc_assert_ret_val(change, nullptr);
6900 nullptr);
6901
6902 /* Get rid of the previous. */
6903 buf[0] = '\0';
6904
6905 if (namer == nullptr) {
6906 /* TRANS: default description of a requirement vector
6907 * (used in ruledit) */
6908 req_vec_description = _("the requirement vector");
6909 } else {
6911 }
6912
6913 switch (change->operation) {
6914 case RVCO_REMOVE:
6915 fc_snprintf(buf, sizeof(buf),
6916 /* TRANS: remove a requirement from a requirement vector
6917 * (in ruledit).
6918 * The first %s is the operation.
6919 * The second %s is the requirement.
6920 * The third %s is a description of the requirement vector,
6921 * like "actor_reqs" */
6922 _("%s %s from %s"),
6924 req_to_fstring(&change->req, &astr),
6926 astr_free(&astr);
6927 break;
6928 case RVCO_APPEND:
6929 fc_snprintf(buf, sizeof(buf),
6930 /* TRANS: append a requirement to a requirement vector
6931 * (in ruledit).
6932 * The first %s is the operation.
6933 * The second %s is the requirement.
6934 * The third %s is a description of the requirement vector,
6935 * like "actor_reqs" */
6936 _("%s %s to %s"),
6938 req_to_fstring(&change->req, &astr),
6940 astr_free(&astr);
6941 break;
6942 case RVCO_NOOP:
6943 fc_snprintf(buf, sizeof(buf),
6944 /* TRANS: do nothing to a requirement vector (in ruledit).
6945 * The first %s is a description of the requirement vector,
6946 * like "actor_reqs" */
6947 _("Do nothing to %s"), req_vec_description);
6948 break;
6949 }
6950
6951 return buf;
6952}
6953
6954/**********************************************************************/
6967 const void *parent_item)
6968{
6969 struct requirement_vector *target
6970 = getter(parent_item, modification->vector_number);
6971 int i = 0;
6972
6973 switch (modification->operation) {
6974 case RVCO_APPEND:
6976 return TRUE;
6977 case RVCO_REMOVE:
6981 return TRUE;
6982 }
6983 i++;
6985 return FALSE;
6986 case RVCO_NOOP:
6987 return FALSE;
6988 }
6989
6990 return FALSE;
6991}
6992
6993/**********************************************************************/
7003struct req_vec_problem *
7005 const char *description,
7006 const char *description_translated)
7007{
7008 struct req_vec_problem *out;
7009 int i;
7010
7011 out = fc_malloc(sizeof(*out));
7012
7013 fc_strlcpy(out->description, description, sizeof(out->description));
7014 fc_strlcpy(out->description_translated, _(description_translated),
7015 sizeof(out->description_translated));
7016
7017 out->num_suggested_solutions = num_suggested_solutions;
7018 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
7019 * sizeof(struct req_vec_change));
7020 for (i = 0; i < out->num_suggested_solutions; i++) {
7021 /* No suggestions are ready yet. */
7022 out->suggested_solutions[i].operation = RVCO_NOOP;
7023 out->suggested_solutions[i].vector_number = -1;
7024 out->suggested_solutions[i].req.source.kind = VUT_NONE;
7025 }
7026
7027 return out;
7028}
7029
7030/**********************************************************************/
7040 const char *descr, ...)
7041{
7042 char description[500];
7043 char description_translated[500];
7044 va_list ap;
7045
7046 va_start(ap, descr);
7047 fc_vsnprintf(description, sizeof(description), descr, ap);
7048 va_end(ap);
7049
7050 va_start(ap, descr);
7052 _(descr), ap);
7053 va_end(ap);
7054
7057}
7058
7059/**********************************************************************/
7066{
7067 FC_FREE(issue->suggested_solutions);
7068 issue->num_suggested_solutions = 0;
7069
7070 FC_FREE(issue);
7071}
7072
7073/**********************************************************************/
7085struct req_vec_problem *
7088 const void *parent_item)
7089{
7090 int i, j;
7092
7093 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7094 /* No vector. */
7095 return nullptr;
7096 }
7097
7098 if (get_num == nullptr || parent_item == nullptr) {
7099 vec_num = 0;
7100 } else {
7101 vec_num = get_num(parent_item, vec);
7102 }
7103
7104 /* Look for contradictions */
7105 for (i = 0; i < requirement_vector_size(vec); i++) {
7106 struct requirement *preq = requirement_vector_get(vec, i);
7107 for (j = 0; j < requirement_vector_size(vec); j++) {
7108 struct requirement *nreq = requirement_vector_get(vec, j);
7109
7111 struct req_vec_problem *problem;
7112 struct astring astr;
7113 struct astring nastr;
7114
7116 N_("Requirements {%s} and {%s} contradict each other."),
7118
7119 astr_free(&astr);
7120 astr_free(&nastr);
7121
7122 /* The solution is to remove one of the contradictions. */
7123 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7124 problem->suggested_solutions[0].vector_number = vec_num;
7125 problem->suggested_solutions[0].req = *preq;
7126
7127 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7128 problem->suggested_solutions[1].vector_number = vec_num;
7129 problem->suggested_solutions[1].req = *nreq;
7130
7131 /* Only the first contradiction is reported. */
7132 return problem;
7133 }
7134 }
7135 }
7136
7137 return nullptr;
7138}
7139
7140/**********************************************************************/
7151struct req_vec_problem *
7154 const void *parent_item)
7155{
7156 /* Check for self contradictins. */
7158}
7159
7160/**********************************************************************/
7173struct req_vec_problem *
7176 const void *parent_item)
7177{
7178 int i;
7180 struct req_vec_problem *problem = nullptr;
7181
7182 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7183 /* No vector. */
7184 return nullptr;
7185 }
7186
7187 if (get_num == nullptr || parent_item == nullptr) {
7188 vec_num = 0;
7189 } else {
7190 vec_num = get_num(parent_item, vec);
7191 }
7192
7193 /* Look for contradictions */
7194 for (i = 0; i < requirement_vector_size(vec); i++) {
7195 struct requirement *preq = requirement_vector_get(vec, i);
7196
7197 if (universal_never_there(&preq->source)) {
7198 struct astring astr;
7199
7200 if (preq->present) {
7201 /* The requirement vector can never be fulfilled. Removing the
7202 * requirement makes it possible to fulfill it. This is a rule
7203 * change and shouldn't be "fixed" without thinking. Don't offer any
7204 * automatic solution to prevent mindless "fixes". */
7205 /* TRANS: Ruledit warns a user about an unused requirement vector
7206 * that never can be fulfilled because it asks for something that
7207 * never will be there. */
7208 if (problem == nullptr) {
7210 N_("Requirement {%s} requires %s but it will never be"
7211 " there."),
7213 astr_free(&astr);
7214 }
7215
7216 /* Continue to check if other problems have a solution proposal,
7217 * and prefer to return those. */
7218 continue;
7219 }
7220
7221 if (problem != nullptr) {
7222 /* Free previous one (one with no solution proposals) */
7224 }
7225
7227 N_("Requirement {%s} mentions %s but it will never be there."),
7229
7230 astr_free(&astr);
7231
7232 /* The solution is to remove the reference to the missing
7233 * universal. */
7234 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7235 problem->suggested_solutions[0].vector_number = vec_num;
7236 problem->suggested_solutions[0].req = *preq;
7237
7238 /* Only the first missing universal is reported. */
7239 return problem;
7240 }
7241 }
7242
7243 return problem;
7244}
7245
7246/**********************************************************************/
7259struct req_vec_problem *
7262 const void *parent_item)
7263{
7264 int i, j;
7266
7267 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7268 /* No vector. */
7269 return nullptr;
7270 }
7271
7272 if (get_num == nullptr || parent_item == nullptr) {
7273 vec_num = 0;
7274 } else {
7275 vec_num = get_num(parent_item, vec);
7276 }
7277
7278 /* Look for repeated requirements */
7279 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
7280 struct requirement *preq = requirement_vector_get(vec, i);
7281 for (j = i + 1; j < requirement_vector_size(vec); j++) {
7282 struct requirement *nreq = requirement_vector_get(vec, j);
7283
7285 struct req_vec_problem *problem;
7286 struct astring astr;
7287 struct astring nastr;
7288
7290 N_("Requirements {%s} and {%s} are the same."),
7292
7293 astr_free(&astr);
7294 astr_free(&nastr);
7295
7296 /* The solution is to remove one of the redundant requirements. */
7297 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7298 problem->suggested_solutions[0].vector_number = vec_num;
7299 problem->suggested_solutions[0].req = *preq;
7300
7301 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7302 problem->suggested_solutions[1].vector_number = vec_num;
7303 problem->suggested_solutions[1].req = *nreq;
7304
7305 /* Only the first redundancy is reported. */
7306 return problem;
7307 }
7308 }
7309 }
7310
7311 return nullptr;
7312}
7313
7314/**********************************************************************/
7326struct req_vec_problem *
7329 const void *parent_item)
7330{
7331 struct req_vec_problem *out;
7332
7334 if (out != nullptr) {
7335 /* A bug, not just a potential improvement */
7336 return out;
7337 }
7338
7339 /* Check if a universal that never will appear in the game is checked. */
7341 if (out != nullptr) {
7342 return out;
7343 }
7344
7345 /* Check if a requirement is redundant. */
7347 return out;
7348}
7349
7350/**********************************************************************/
7355 const struct universal *psource2)
7356{
7357 if (psource1->kind != psource2->kind) {
7358 return FALSE;
7359 }
7360 switch (psource1->kind) {
7361 case VUT_NONE:
7362 return TRUE;
7363 case VUT_COUNTER:
7364 return psource1->value.counter == psource2->value.counter;
7365 case VUT_ADVANCE:
7366 return psource1->value.advance == psource2->value.advance;
7367 case VUT_TECHFLAG:
7368 return psource1->value.techflag == psource2->value.techflag;
7369 case VUT_GOVERNMENT:
7370 return psource1->value.govern == psource2->value.govern;
7371 case VUT_ACHIEVEMENT:
7372 return psource1->value.achievement == psource2->value.achievement;
7373 case VUT_STYLE:
7374 return psource1->value.style == psource2->value.style;
7375 case VUT_IMPROVEMENT:
7376 case VUT_SITE:
7377 return psource1->value.building == psource2->value.building;
7378 case VUT_IMPR_GENUS:
7379 return psource1->value.impr_genus == psource2->value.impr_genus;
7380 case VUT_IMPR_FLAG:
7381 return psource1->value.impr_flag == psource2->value.impr_flag;
7382 case VUT_PLAYER_FLAG:
7383 return psource1->value.plr_flag == psource2->value.plr_flag;
7384 case VUT_PLAYER_STATE:
7385 return psource1->value.plrstate == psource2->value.plrstate;
7386 case VUT_EXTRA:
7387 return psource1->value.extra == psource2->value.extra;
7388 case VUT_GOOD:
7389 return psource1->value.good == psource2->value.good;
7390 case VUT_TERRAIN:
7391 return psource1->value.terrain == psource2->value.terrain;
7392 case VUT_TERRFLAG:
7393 return psource1->value.terrainflag == psource2->value.terrainflag;
7394 case VUT_NATION:
7395 return psource1->value.nation == psource2->value.nation;
7396 case VUT_NATIONGROUP:
7397 return psource1->value.nationgroup == psource2->value.nationgroup;
7398 case VUT_NATIONALITY:
7399 return psource1->value.nationality == psource2->value.nationality;
7400 case VUT_ORIGINAL_OWNER:
7401 return psource1->value.origowner == psource2->value.origowner;
7402 case VUT_DIPLREL:
7403 case VUT_DIPLREL_TILE:
7404 case VUT_DIPLREL_TILE_O:
7407 return psource1->value.diplrel == psource2->value.diplrel;
7408 case VUT_UTYPE:
7409 return psource1->value.utype == psource2->value.utype;
7410 case VUT_UTFLAG:
7411 return psource1->value.unitflag == psource2->value.unitflag;
7412 case VUT_UCLASS:
7413 return psource1->value.uclass == psource2->value.uclass;
7414 case VUT_UCFLAG:
7415 return psource1->value.unitclassflag == psource2->value.unitclassflag;
7416 case VUT_MINVETERAN:
7417 return psource1->value.minveteran == psource2->value.minveteran;
7418 case VUT_UNITSTATE:
7419 return psource1->value.unit_state == psource2->value.unit_state;
7420 case VUT_ACTIVITY:
7421 return psource1->value.activity == psource2->value.activity;
7422 case VUT_MINMOVES:
7423 return psource1->value.minmoves == psource2->value.minmoves;
7424 case VUT_MINHP:
7425 return psource1->value.min_hit_points == psource2->value.min_hit_points;
7426 case VUT_AGE:
7427 return psource1->value.age == psource2->value.age;
7428 case VUT_FORM_AGE:
7429 return psource1->value.form_age == psource2->value.form_age;
7430 case VUT_MINTECHS:
7431 return psource1->value.min_techs == psource2->value.min_techs;
7432 case VUT_MINCITIES:
7433 return psource1->value.min_cities == psource2->value.min_cities;
7434 case VUT_ACTION:
7435 return (action_number(psource1->value.action)
7436 == action_number(psource2->value.action));
7437 case VUT_OTYPE:
7438 return psource1->value.outputtype == psource2->value.outputtype;
7439 case VUT_SPECIALIST:
7440 return psource1->value.specialist == psource2->value.specialist;
7441 case VUT_MINSIZE:
7442 return psource1->value.minsize == psource2->value.minsize;
7443 case VUT_MINCULTURE:
7444 return psource1->value.minculture == psource2->value.minculture;
7445 case VUT_MINFOREIGNPCT:
7446 return psource1->value.minforeignpct == psource2->value.minforeignpct;
7447 case VUT_AI_LEVEL:
7448 return psource1->value.ai_level == psource2->value.ai_level;
7449 case VUT_MAXTILEUNITS:
7450 return psource1->value.max_tile_units == psource2->value.max_tile_units;
7451 case VUT_TERRAINCLASS:
7452 return psource1->value.terrainclass == psource2->value.terrainclass;
7453 case VUT_ROADFLAG:
7454 return psource1->value.roadflag == psource2->value.roadflag;
7455 case VUT_EXTRAFLAG:
7456 return psource1->value.extraflag == psource2->value.extraflag;
7457 case VUT_MINYEAR:
7458 return psource1->value.minyear == psource2->value.minyear;
7459 case VUT_MINCALFRAG:
7460 return psource1->value.mincalfrag == psource2->value.mincalfrag;
7461 case VUT_TOPO:
7462 return psource1->value.topo_property == psource2->value.topo_property;
7463 case VUT_WRAP:
7464 return psource1->value.wrap_property == psource2->value.wrap_property;
7465 case VUT_SERVERSETTING:
7466 return psource1->value.ssetval == psource2->value.ssetval;
7467 case VUT_TERRAINALTER:
7468 return psource1->value.terrainalter == psource2->value.terrainalter;
7469 case VUT_CITYTILE:
7470 return psource1->value.citytile == psource2->value.citytile;
7471 case VUT_CITYSTATUS:
7472 return psource1->value.citystatus == psource2->value.citystatus;
7473 case VUT_TILE_REL:
7474 return psource1->value.tilerel == psource2->value.tilerel;
7475 case VUT_MINLATITUDE:
7476 case VUT_MAXLATITUDE:
7477 return psource1->value.latitude == psource2->value.latitude;
7479 return psource1->value.distance_sq == psource2->value.distance_sq;
7481 return psource1->value.region_tiles == psource2->value.region_tiles;
7482 case VUT_COUNT:
7483 break;
7484 }
7485
7486 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
7487 return FALSE;
7488}
7489
7490/**********************************************************************/
7494const char *universal_rule_name(const struct universal *psource)
7495{
7496 static char buffer[10];
7497
7498 switch (psource->kind) {
7499 case VUT_NONE:
7500 return "(none)";
7501 case VUT_COUNTER:
7502 return counter_rule_name(psource->value.counter);
7503 case VUT_CITYTILE:
7504 return citytile_type_name(psource->value.citytile);
7505 case VUT_CITYSTATUS:
7506 return citystatus_type_name(psource->value.citystatus);
7507 case VUT_TILE_REL:
7508 return tilerel_type_name(psource->value.tilerel);
7509 case VUT_MINYEAR:
7510 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
7511
7512 return buffer;
7513 case VUT_MINCALFRAG:
7514 /* Rule name is 0-based number, not pretty name from ruleset */
7515 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
7516
7517 return buffer;
7518 case VUT_TOPO:
7519 return topo_flag_name(psource->value.topo_property);
7520 case VUT_WRAP:
7521 return wrap_flag_name(psource->value.wrap_property);
7522 case VUT_SERVERSETTING:
7523 return ssetv_rule_name(psource->value.ssetval);
7524 case VUT_ADVANCE:
7525 return advance_rule_name(psource->value.advance);
7526 case VUT_TECHFLAG:
7527 return tech_flag_id_name(psource->value.techflag);
7528 case VUT_GOVERNMENT:
7529 return government_rule_name(psource->value.govern);
7530 case VUT_ACHIEVEMENT:
7531 return achievement_rule_name(psource->value.achievement);
7532 case VUT_STYLE:
7533 return style_rule_name(psource->value.style);
7534 case VUT_IMPROVEMENT:
7535 case VUT_SITE:
7536 return improvement_rule_name(psource->value.building);
7537 case VUT_IMPR_GENUS:
7538 return impr_genus_id_name(psource->value.impr_genus);
7539 case VUT_IMPR_FLAG:
7540 return impr_flag_id_name(psource->value.impr_flag);
7541 case VUT_PLAYER_FLAG:
7542 return plr_flag_id_name(psource->value.plr_flag);
7543 case VUT_PLAYER_STATE:
7544 return plrstate_type_name(psource->value.plrstate);
7545 case VUT_EXTRA:
7546 return extra_rule_name(psource->value.extra);
7547 case VUT_GOOD:
7548 return goods_rule_name(psource->value.good);
7549 case VUT_TERRAIN:
7550 return terrain_rule_name(psource->value.terrain);
7551 case VUT_TERRFLAG:
7552 return terrain_flag_id_name(psource->value.terrainflag);
7553 case VUT_NATION:
7554 return nation_rule_name(psource->value.nation);
7555 case VUT_NATIONGROUP:
7556 return nation_group_rule_name(psource->value.nationgroup);
7557 case VUT_DIPLREL:
7558 case VUT_DIPLREL_TILE:
7559 case VUT_DIPLREL_TILE_O:
7562 return diplrel_rule_name(psource->value.diplrel);
7563 case VUT_NATIONALITY:
7564 return nation_rule_name(psource->value.nationality);
7565 case VUT_ORIGINAL_OWNER:
7566 return nation_rule_name(psource->value.origowner);
7567 case VUT_UTYPE:
7568 return utype_rule_name(psource->value.utype);
7569 case VUT_UTFLAG:
7570 return unit_type_flag_id_name(psource->value.unitflag);
7571 case VUT_UCLASS:
7572 return uclass_rule_name(psource->value.uclass);
7573 case VUT_UCFLAG:
7574 return unit_class_flag_id_name(psource->value.unitclassflag);
7575 case VUT_MINVETERAN:
7576 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
7577
7578 return buffer;
7579 case VUT_UNITSTATE:
7580 return ustate_prop_name(psource->value.unit_state);
7581 case VUT_ACTIVITY:
7582 return unit_activity_name(psource->value.activity);
7583 case VUT_MINMOVES:
7584 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
7585
7586 return buffer;
7587 case VUT_MINHP:
7588 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
7589
7590 return buffer;
7591 case VUT_AGE:
7592 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
7593
7594 return buffer;
7595 case VUT_FORM_AGE:
7596 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
7597
7598 return buffer;
7599 case VUT_MINTECHS:
7600 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
7601
7602 return buffer;
7603 case VUT_MINCITIES:
7604 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_cities);
7605
7606 return buffer;
7607 case VUT_ACTION:
7608 return action_rule_name(psource->value.action);
7609 case VUT_OTYPE:
7610 return get_output_identifier(psource->value.outputtype);
7611 case VUT_SPECIALIST:
7612 return specialist_rule_name(psource->value.specialist);
7613 case VUT_MINSIZE:
7614 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
7615
7616 return buffer;
7617 case VUT_MINCULTURE:
7618 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
7619
7620 return buffer;
7621 case VUT_MINFOREIGNPCT:
7622 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
7623
7624 return buffer;
7625 case VUT_AI_LEVEL:
7626 return ai_level_name(psource->value.ai_level);
7627 case VUT_MAXTILEUNITS:
7628 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_units);
7629 return buffer;
7630 case VUT_TERRAINCLASS:
7631 return terrain_class_name(psource->value.terrainclass);
7632 case VUT_ROADFLAG:
7633 return road_flag_id_name(psource->value.roadflag);
7634 case VUT_EXTRAFLAG:
7635 return extra_flag_id_name(psource->value.extraflag);
7636 case VUT_TERRAINALTER:
7637 return terrain_alteration_name(psource->value.terrainalter);
7638 case VUT_MINLATITUDE:
7639 case VUT_MAXLATITUDE:
7640 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
7641
7642 return buffer;
7644 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.distance_sq);
7645
7646 return buffer;
7648 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.region_tiles);
7649
7650 return buffer;
7651 case VUT_COUNT:
7652 break;
7653 }
7654
7655 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
7656
7657 return nullptr;
7658}
7659
7660/**********************************************************************/
7669 char *buf, size_t bufsz)
7670{
7671 buf[0] = '\0'; /* to be safe. */
7672 switch (psource->kind) {
7673 case VUT_NONE:
7674 /* TRANS: missing value */
7675 fc_strlcat(buf, _("(none)"), bufsz);
7676 return buf;
7677 case VUT_ADVANCE:
7679 return buf;
7680 case VUT_COUNTER:
7682 return buf;
7683 case VUT_TECHFLAG:
7684 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
7685 tech_flag_id_translated_name(psource->value.techflag));
7686 return buf;
7687 case VUT_GOVERNMENT:
7689 bufsz);
7690 return buf;
7691 case VUT_ACHIEVEMENT:
7693 bufsz);
7694 return buf;
7695 case VUT_STYLE:
7697 bufsz);
7698 return buf;
7699 case VUT_IMPROVEMENT:
7701 bufsz);
7702 return buf;
7703 case VUT_SITE:
7704 {
7705 char local_buf[1024];
7706
7707 fc_snprintf(local_buf, sizeof(local_buf), _("%s site"),
7708 improvement_name_translation(psource->value.building));
7710 }
7711
7712 return buf;
7713 case VUT_IMPR_GENUS:
7715 impr_genus_id_translated_name(psource->value.impr_genus),
7716 bufsz);
7717 return buf;
7718 case VUT_IMPR_FLAG:
7720 impr_flag_id_translated_name(psource->value.impr_flag),
7721 bufsz);
7722 return buf;
7723 case VUT_PLAYER_FLAG:
7725 plr_flag_id_translated_name(psource->value.plr_flag),
7726 bufsz);
7727 return buf;
7728 case VUT_PLAYER_STATE:
7730 plrstate_type_translated_name(psource->value.plrstate),
7731 bufsz);
7732 return buf;
7733 case VUT_EXTRA:
7735 return buf;
7736 case VUT_GOOD:
7738 return buf;
7739 case VUT_TERRAIN:
7741 return buf;
7742 case VUT_NATION:
7744 bufsz);
7745 return buf;
7746 case VUT_NATIONGROUP:
7748 bufsz);
7749 return buf;
7750 case VUT_NATIONALITY:
7751 cat_snprintf(buf, bufsz, _("%s citizens"),
7752 nation_adjective_translation(psource->value.nationality));
7753 return buf;
7754 case VUT_ORIGINAL_OWNER:
7755 /* TRANS: Keep short. City founding nation. */
7756 cat_snprintf(buf, bufsz, _("%s original owner"),
7757 nation_adjective_translation(psource->value.origowner));
7758 return buf;
7759 case VUT_DIPLREL:
7760 case VUT_DIPLREL_TILE:
7761 case VUT_DIPLREL_TILE_O:
7765 bufsz);
7766 return buf;
7767 case VUT_UTYPE:
7769 return buf;
7770 case VUT_UTFLAG:
7772 /* TRANS: Unit type flag */
7773 Q_("?utflag:\"%s\" units"),
7775 psource->value.unitflag));
7776 return buf;
7777 case VUT_UCLASS:
7779 /* TRANS: Unit class */
7780 _("%s units"),
7781 uclass_name_translation(psource->value.uclass));
7782 return buf;
7783 case VUT_UCFLAG:
7785 /* TRANS: Unit class flag */
7786 Q_("?ucflag:\"%s\" units"),
7788 psource->value.unitclassflag));
7789 return buf;
7790 case VUT_MINVETERAN:
7791 /* FIXME */
7792 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
7793 psource->value.minveteran);
7794 return buf;
7795 case VUT_UNITSTATE:
7796 switch (psource->value.unit_state) {
7797 case USP_TRANSPORTED:
7798 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7799 cat_snprintf(buf, bufsz, _("Transported"));
7800 break;
7801 case USP_LIVABLE_TILE:
7803 /* TRANS: unit state. (appears in strings like
7804 * "Missile+On livable tile") */
7805 _("On livable tile"));
7806 break;
7807 case USP_TRANSPORTING:
7808 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7809 cat_snprintf(buf, bufsz, _("Transporting"));
7810 break;
7811 case USP_HAS_HOME_CITY:
7812 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
7813 cat_snprintf(buf, bufsz, _("Has a home city"));
7814 break;
7815 case USP_NATIVE_TILE:
7817 /* TRANS: unit state. (appears in strings like
7818 * "Missile+On native tile") */
7819 _("On native tile"));
7820 break;
7821 case USP_NATIVE_EXTRA:
7823 /* TRANS: unit state. (appears in strings like
7824 * "Missile+In native extra") */
7825 _("In native extra"));
7826 break;
7828 /* TRANS: unit state. (appears in strings like
7829 * "Missile+Has moved this turn") */
7830 cat_snprintf(buf, bufsz, _("Has moved this turn"));
7831 break;
7832 case USP_COUNT:
7833 fc_assert_msg(psource->value.unit_state != USP_COUNT,
7834 "Invalid unit state property.");
7835 break;
7836 }
7837 return buf;
7838 case VUT_ACTIVITY:
7839 cat_snprintf(buf, bufsz, _("%s activity"),
7840 Q_(unit_activity_name(psource->value.activity)));
7841 return buf;
7842 case VUT_MINMOVES:
7843 /* TRANS: Minimum unit movement points left for requirement to be met
7844 * (%s is a string like "1" or "2 1/3") */
7845 cat_snprintf(buf, bufsz, _("%s MP"),
7846 move_points_text(psource->value.minmoves, TRUE));
7847 return buf;
7848 case VUT_MINHP:
7849 /* TRANS: HP = hit points */
7850 cat_snprintf(buf, bufsz, _("%d HP"),
7851 psource->value.min_hit_points);
7852 return buf;
7853 case VUT_AGE:
7854 cat_snprintf(buf, bufsz, _("Age %d"),
7855 psource->value.age);
7856 return buf;
7857 case VUT_FORM_AGE:
7858 cat_snprintf(buf, bufsz, _("Form age %d"),
7859 psource->value.form_age);
7860 return buf;
7861 case VUT_MINTECHS:
7862 cat_snprintf(buf, bufsz, _("%d Techs"),
7863 psource->value.min_techs);
7864 return buf;
7865 case VUT_MINCITIES:
7866 cat_snprintf(buf, bufsz, _("%d Cities"),
7867 psource->value.min_cities);
7868 return buf;
7869 case VUT_ACTION:
7871 bufsz);
7872 return buf;
7873 case VUT_OTYPE:
7874 /* FIXME */
7875 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
7876 return buf;
7877 case VUT_SPECIALIST:
7879 bufsz);
7880 return buf;
7881 case VUT_MINSIZE:
7882 cat_snprintf(buf, bufsz, _("Size %d"),
7883 psource->value.minsize);
7884 return buf;
7885 case VUT_MINCULTURE:
7886 cat_snprintf(buf, bufsz, _("Culture %d"),
7887 psource->value.minculture);
7888 return buf;
7889 case VUT_MINFOREIGNPCT:
7890 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
7891 psource->value.minforeignpct);
7892 return buf;
7893 case VUT_AI_LEVEL:
7894 /* TRANS: "Hard AI" */
7895 cat_snprintf(buf, bufsz, _("%s AI"),
7896 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
7897 return buf;
7898 case VUT_MAXTILEUNITS:
7899 /* TRANS: here <= means 'less than or equal' */
7900 cat_snprintf(buf, bufsz, PL_("<=%d unit",
7901 "<=%d units", psource->value.max_tile_units),
7902 psource->value.max_tile_units);
7903 return buf;
7904 case VUT_TERRAINCLASS:
7905 /* TRANS: Terrain class: "Land terrain" */
7906 cat_snprintf(buf, bufsz, _("%s terrain"),
7907 terrain_class_name_translation(psource->value.terrainclass));
7908 return buf;
7909 case VUT_TERRFLAG:
7911 /* TRANS: Terrain flag */
7912 Q_("?terrflag:\"%s\" terrain"),
7914 psource->value.terrainflag));
7915 return buf;
7916 case VUT_ROADFLAG:
7918 /* TRANS: Road flag */
7919 Q_("?roadflag:\"%s\" road"),
7920 road_flag_id_translated_name(psource->value.roadflag));
7921 return buf;
7922 case VUT_EXTRAFLAG:
7924 /* TRANS: Extra flag */
7925 Q_("?extraflag:\"%s\" extra"),
7926 extra_flag_id_translated_name(psource->value.extraflag));
7927 return buf;
7928 case VUT_MINYEAR:
7929 cat_snprintf(buf, bufsz, _("After %s"),
7930 textyear(psource->value.minyear));
7931 return buf;
7932 case VUT_MINCALFRAG:
7933 /* TRANS: here >= means 'greater than or equal'.
7934 * %s identifies a calendar fragment (may be bare number). */
7935 cat_snprintf(buf, bufsz, _(">=%s"),
7936 textcalfrag(psource->value.mincalfrag));
7937 return buf;
7938 case VUT_TOPO:
7939 /* TRANS: topology flag name ("Hex", "ISO") */
7940 cat_snprintf(buf, bufsz, _("%s map"),
7941 _(topo_flag_name(psource->value.topo_property)));
7942 return buf;
7943 case VUT_WRAP:
7944 /* TRANS: wrap flag name ("WrapX", "WrapY") */
7945 cat_snprintf(buf, bufsz, _("%s map"),
7946 _(wrap_flag_name(psource->value.wrap_property)));
7947 return buf;
7948 case VUT_SERVERSETTING:
7950 bufsz);
7951 return buf;
7952 case VUT_TERRAINALTER:
7953 /* TRANS: "Irrigation possible" */
7954 cat_snprintf(buf, bufsz, _("%s possible"),
7955 Q_(terrain_alteration_name(psource->value.terrainalter)));
7956 return buf;
7957 case VUT_CITYTILE:
7958 switch (psource->value.citytile) {
7959 case CITYT_CENTER:
7960 fc_strlcat(buf, _("City center"), bufsz);
7961 break;
7962 case CITYT_CLAIMED:
7963 fc_strlcat(buf, _("Tile claimed"), bufsz);
7964 break;
7965 case CITYT_EXTRAS_OWNED:
7966 fc_strlcat(buf, _("Extras owned"), bufsz);
7967 break;
7968 case CITYT_WORKED:
7969 fc_strlcat(buf, _("Worked tile"), bufsz);
7970 break;
7972 fc_strlcat(buf, _("Same continent tile"), bufsz);
7973 break;
7975 /* TRANS: Short for "a tile of other terrain class mass near city" */
7976 fc_strlcat(buf, _("Port reachable tile"), bufsz);
7977 break;
7978 case CITYT_LAST:
7979 fc_assert(psource->value.citytile != CITYT_LAST);
7980 fc_strlcat(buf, "error", bufsz);
7981 break;
7982 }
7983 return buf;
7984 case VUT_CITYSTATUS:
7985 switch (psource->value.citystatus) {
7987 fc_strlcat(buf, _("Owned by original"), bufsz);
7988 break;
7989 case CITYS_STARVED:
7990 fc_strlcat(buf, _("Starved"), bufsz);
7991 break;
7992 case CITYS_DISORDER:
7993 fc_strlcat(buf, _("Disorder"), bufsz);
7994 break;
7995 case CITYS_CELEBRATION:
7996 fc_strlcat(buf, _("Celebration"), bufsz);
7997 break;
7998 case CITYS_TRANSFERRED:
7999 /* TRANS: CityStatus value - city has changed hands */
8000 fc_strlcat(buf, _("Transferred"), bufsz);
8001 break;
8002 case CITYS_LAST:
8003 fc_assert(psource->value.citystatus != CITYS_LAST);
8004 fc_strlcat(buf, "error", bufsz);
8005 break;
8006 }
8007 return buf;
8008 case VUT_TILE_REL:
8009 switch (psource->value.tilerel) {
8010 case TREL_SAME_TCLASS:
8011 fc_strlcat(buf, _("Same terrain class"), bufsz);
8012 break;
8013 case TREL_SAME_REGION:
8014 fc_strlcat(buf, _("Same continent/ocean"), bufsz);
8015 break;
8017 fc_strlcat(buf, _("Only other continent/ocean"), bufsz);
8018 break;
8020 fc_strlcat(buf, _("Lake/island surrounded"), bufsz);
8021 break;
8022 case TREL_COUNT:
8023 fc_assert(psource->value.tilerel != TREL_COUNT);
8024 fc_strlcat(buf, "error", bufsz);
8025 break;
8026 }
8027 return buf;
8028 case VUT_MINLATITUDE:
8029 /* TRANS: here >= means 'greater than or equal'. */
8030 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
8031 psource->value.latitude);
8032 return buf;
8033 case VUT_MAXLATITUDE:
8034 /* TRANS: here <= means 'less than or equal'. */
8035 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
8036 psource->value.latitude);
8037 return buf;
8039 /* TRANS: here <= means 'less than or equal'. */
8040 cat_snprintf(buf, bufsz, _("Squared distance <= %d"),
8041 psource->value.distance_sq);
8042 return buf;
8044 cat_snprintf(buf, bufsz, _("%d or fewer region tiles"),
8045 psource->value.region_tiles);
8046 return buf;
8047 case VUT_COUNT:
8048 break;
8049 }
8050
8051 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8052 return buf;
8053}
8054
8055/**********************************************************************/
8059{
8060 return universals_n_name(psource->kind);
8061}
8062
8063/**********************************************************************/
8067 const struct universal *target)
8068{
8069 switch (target->kind) {
8070 case VUT_IMPROVEMENT:
8071 case VUT_SITE:
8072 return impr_build_shield_cost(pcity, target->value.building);
8073 case VUT_UTYPE:
8074 return utype_build_shield_cost(pcity, nullptr, target->value.utype);
8075 default:
8076 break;
8077 }
8078 return FC_INFINITY;
8079}
8080
8081/**********************************************************************/
8087 const struct universal *to_replace,
8088 const struct universal *replacement)
8089{
8090 bool changed = FALSE;
8091
8094 preq->source = *replacement;
8095 changed = TRUE;
8096 }
8098
8099 return changed;
8100}
8101
8102/**********************************************************************/
8107 const struct requirement_vector *reqs,
8108 const struct universal *psource)
8109{
8112 return TRUE;
8113 }
8115
8116 return FALSE;
8117}
8118
8119/**********************************************************************/
8130 struct universal *unis,
8131 size_t n_unis)
8132{
8133 int i;
8134
8135 for (i = 0; i < n_unis; i++) {
8137 /* This universal makes it impossible to fulfill the specified
8138 * requirement vector */
8139 return TRUE;
8140 }
8141 }
8142
8143 /* No specified universal is known to guarantee that the requirement
8144 * vector never will be fulfilled. */
8145 return FALSE;
8146}
8147
8148/**********************************************************************/
8164 struct universal *unis,
8165 size_t n_unis)
8166{
8168 int i;
8170
8171 for (i = 0; i < n_unis; i++) {
8172 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
8173 case ITF_NO:
8174 case ITF_YES:
8175 /* this req matched this source */
8177 break;
8178 case ITF_NOT_APPLICABLE:
8179 /* Not a mention. */
8180 break;
8181 }
8182 }
8183
8185 /* A requirement not relevant to any of the specified universals was
8186 * found in the requirement vector. */
8187 return FALSE;
8188 }
8190
8191 /* No requirement not relevant to any of the specified universals was
8192 * found in the requirement vector. */
8193 return TRUE;
8194}
8195
8196/**********************************************************************/
8199enum req_item_found
8201 const struct universal *source)
8202{
8205 "No req item found function for %s",
8207
8208 return (*universal_found_function[source->kind])(preq, source);
8209}
8210
8211/**********************************************************************/
8222 const struct requirement_vector *reqs,
8223 const struct universal *source)
8224{
8225 bool necessary = FALSE;
8226
8229 "No req item found function for %s",
8231
8233 switch ((*universal_found_function[source->kind])(preq, source)) {
8234 case ITF_NOT_APPLICABLE:
8235 continue;
8236 case ITF_NO:
8237 if (preq->present) {
8238 return FALSE;
8239 }
8240 break;
8241 case ITF_YES:
8242 if (preq->present) {
8243 necessary = TRUE;
8244 } else {
8245 return FALSE;
8246 }
8247 break;
8248 }
8250
8251 return (!check_necessary || necessary);
8252}
8253
8254/**********************************************************************/
8259 const struct universal *source)
8260{
8261 switch (universal_fulfills_requirement(req, source)) {
8262 case ITF_NOT_APPLICABLE:
8263 return FALSE;
8264 case ITF_NO:
8265 case ITF_YES:
8266 return TRUE;
8267 }
8268
8269 log_error("Unhandled item_found value");
8270 return FALSE;
8271}
8272
8273/**********************************************************************/
8277 const struct universal *source)
8278{
8279 fc_assert(source->value.nation);
8280
8281 switch (preq->source.kind) {
8282 case VUT_NATION:
8283 return preq->source.value.nation == source->value.nation ? ITF_YES
8284 : ITF_NO;
8285 case VUT_NATIONGROUP:
8286 return nation_is_in_group(source->value.nation,
8287 preq->source.value.nationgroup) ? ITF_YES
8288 : ITF_NO;
8289 default:
8290 break;
8291 }
8292
8293 return ITF_NOT_APPLICABLE;
8294}
8295
8296/**********************************************************************/
8300 const struct universal *source)
8301{
8302 fc_assert(source->value.govern);
8303
8304 if (preq->source.kind == VUT_GOVERNMENT) {
8305 return preq->source.value.govern == source->value.govern ? ITF_YES
8306 : ITF_NO;
8307 }
8308
8309 return ITF_NOT_APPLICABLE;
8310}
8311
8312/**********************************************************************/
8316 const struct universal *source)
8317{
8318 fc_assert(source->value.min_cities);
8319
8320 if (preq->source.kind == VUT_MINCITIES) {
8321 return preq->source.value.min_cities <= source->value.min_cities ? ITF_YES
8322 : ITF_NO;
8323 }
8324
8325 return ITF_NOT_APPLICABLE;
8326}
8327
8328/**********************************************************************/
8332 const struct universal *source)
8333{
8334 fc_assert(source->value.building);
8335
8336 /* We only ever return ITF_YES, because requiring a different
8337 * improvement does not mean that the improvement under consideration
8338 * cannot fulfill the requirements. This is necessary to allow
8339 * requirement vectors to specify multiple required improvements. */
8340
8341 switch (preq->source.kind) {
8342 case VUT_IMPROVEMENT:
8343 case VUT_SITE:
8344 if (source->value.building == preq->source.value.building) {
8345 return ITF_YES;
8346 }
8347 break;
8348 case VUT_IMPR_GENUS:
8349 if (source->value.building->genus == preq->source.value.impr_genus) {
8350 return ITF_YES;
8351 }
8352 break;
8353 case VUT_IMPR_FLAG:
8354 if (improvement_has_flag(source->value.building,
8355 preq->source.value.impr_flag)) {
8356 return ITF_YES;
8357 }
8358 break;
8359 default:
8360 break;
8361 }
8362
8363 return ITF_NOT_APPLICABLE;
8364}
8365
8366/**********************************************************************/
8370 const struct universal *source)
8371{
8372 fc_assert(source->value.uclass);
8373
8374 switch (preq->source.kind) {
8375 case VUT_UCLASS:
8376 return source->value.uclass == preq->source.value.uclass ? ITF_YES
8377 : ITF_NO;
8378 case VUT_UCFLAG:
8379 return uclass_has_flag(source->value.uclass,
8380 preq->source.value.unitclassflag) ? ITF_YES
8381 : ITF_NO;
8382
8383 default:
8384 /* Not found and not relevant. */
8385 return ITF_NOT_APPLICABLE;
8386 };
8387}
8388
8389/**********************************************************************/
8393 const struct universal *source)
8394{
8395 fc_assert(source->value.utype);
8396
8397 switch (preq->source.kind) {
8398 case VUT_UTYPE:
8399 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
8400 case VUT_UCLASS:
8401 return utype_class(source->value.utype) == preq->source.value.uclass
8402 ? ITF_YES : ITF_NO;
8403 case VUT_UTFLAG:
8404 return utype_has_flag(source->value.utype,
8405 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
8406 case VUT_UCFLAG:
8407 return uclass_has_flag(utype_class(source->value.utype),
8408 preq->source.value.unitclassflag) ? ITF_YES
8409 : ITF_NO;
8410 default:
8411 /* Not found and not relevant. */
8412 return ITF_NOT_APPLICABLE;
8413 };
8414}
8415
8416/**********************************************************************/
8419static enum req_item_found
8421 const struct universal *source)
8422{
8425
8426 switch (preq->source.kind) {
8427 case VUT_ACTIVITY:
8428 return source->value.activity == preq->source.value.activity ? ITF_YES
8429 : ITF_NO;
8430 default:
8431 /* Not found and not relevant. */
8432 return ITF_NOT_APPLICABLE;
8433 };
8434}
8435
8436/**********************************************************************/
8440 const struct universal *source)
8441{
8442 fc_assert(source->value.terrain);
8443
8444 switch (preq->source.kind) {
8445 case VUT_TERRAIN:
8446 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
8447 case VUT_TERRAINCLASS:
8448 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
8449 ? ITF_YES : ITF_NO;
8450 case VUT_TERRFLAG:
8451 return terrain_has_flag(source->value.terrain,
8452 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
8453 case VUT_TERRAINALTER:
8454 return (terrain_can_support_alteration(source->value.terrain,
8455 preq->source.value.terrainalter)
8456 ? ITF_YES : ITF_NO);
8457 default:
8458 /* Not found and not relevant. */
8459 return ITF_NOT_APPLICABLE;
8460 };
8461}
8462
8463/**********************************************************************/
8467 const struct universal *source)
8468{
8471
8472 switch (preq->source.kind) {
8473 case VUT_CITYTILE:
8474 return (source->value.citytile == preq->source.value.citytile
8475 ? ITF_YES
8476 /* The presence of one tile state doesn't block another */
8478 default:
8479 /* Not found and not relevant. */
8480 return ITF_NOT_APPLICABLE;
8481 };
8482}
8483
8484/**********************************************************************/
8488 const struct universal *source)
8489{
8490 fc_assert(source->value.extra);
8491
8492 switch (preq->source.kind) {
8493 case VUT_EXTRA:
8494 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
8495 case VUT_EXTRAFLAG:
8496 return extra_has_flag(source->value.extra,
8497 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
8498 case VUT_ROADFLAG:
8499 {
8500 struct road_type *r = extra_road_get(source->value.extra);
8501 return r && road_has_flag(r, preq->source.value.roadflag)
8502 ? ITF_YES : ITF_NO;
8503 }
8504 default:
8505 /* Not found and not relevant. */
8506 return ITF_NOT_APPLICABLE;
8507 }
8508}
8509
8510/**********************************************************************/
8514 const struct universal *source)
8515{
8516 fc_assert(source->value.action);
8517
8518 if (preq->source.kind == VUT_ACTION) {
8519 return preq->source.value.action == source->value.action ? ITF_YES
8520 : ITF_NO;
8521 }
8522
8523 return ITF_NOT_APPLICABLE;
8524}
8525
8526/**********************************************************************/
8530 const struct universal *source)
8531{
8533 || source->kind == VUT_DIPLREL_TILE
8534 || source->kind == VUT_DIPLREL_TILE_O
8535 || source->kind == VUT_DIPLREL_UNITANY
8536 || source->kind == VUT_DIPLREL_UNITANY_O),
8538
8539 if (preq->source.kind == source->kind) {
8540 if (preq->source.value.diplrel == source->value.diplrel) {
8541 /* The diplrel itself. */
8542 return ITF_YES;
8543 }
8544 if (preq->source.value.diplrel == DRO_FOREIGN
8545 && source->value.diplrel < DS_LAST) {
8546 /* All diplstate_type values are to foreigners. */
8547 return ITF_YES;
8548 }
8549 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
8550 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
8551 /* A real embassy is an embassy. */
8552 return ITF_YES;
8553 }
8554 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
8555 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
8556 /* A real embassy is an embassy. */
8557 return ITF_YES;
8558 }
8559 if (preq->source.value.diplrel < DS_LAST
8560 && source->value.diplrel < DS_LAST
8561 && preq->range == REQ_RANGE_LOCAL) {
8562 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
8563 ITF_YES);
8564 /* Can only have one diplstate_type to a specific player. */
8565 return ITF_NO;
8566 }
8567 /* Can't say this diplrel blocks the other diplrel. */
8568 return ITF_NOT_APPLICABLE;
8569 }
8570
8571 /* Not relevant. */
8572 return ITF_NOT_APPLICABLE;
8573}
8574
8575/**********************************************************************/
8579 const struct universal *source)
8580{
8581 switch (preq->source.kind) {
8582 case VUT_OTYPE:
8583 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
8584 : ITF_NO;
8585 default:
8586 /* Not found and not relevant. */
8587 return ITF_NOT_APPLICABLE;
8588 }
8589}
8590
8591/**********************************************************************/
8595 const struct universal *source)
8596{
8597 if (preq->range != REQ_RANGE_LOCAL) {
8598 return ITF_NOT_APPLICABLE;
8599 }
8600
8601 if (preq->source.kind == VUT_UNITSTATE) {
8602 switch (source->value.unit_state) {
8603 case USP_TRANSPORTED:
8604 case USP_TRANSPORTING:
8605 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
8606 case USP_LIVABLE_TILE:
8607 case USP_NATIVE_TILE:
8608 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
8609 * UTYF_COAST_STRICT. */
8610 case USP_HAS_HOME_CITY:
8611 case USP_NATIVE_EXTRA:
8613 if (source->value.unit_state == preq->source.value.unit_state) {
8614 /* The other unit states doesn't contradict */
8615 return ITF_YES;
8616 }
8617 break;
8618 case USP_COUNT:
8619 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
8621 }
8622 }
8623
8624 /* Not found and not relevant. */
8625 return ITF_NOT_APPLICABLE;
8626}
8627
8628/**********************************************************************/
8653
8654/**********************************************************************/
8662int requirement_kind_ereq(const int value,
8663 const enum req_range range,
8664 const bool present,
8665 const int max_value)
8666{
8667 /* The enumerators in each range starts with present for every possible
8668 * value followed by !present for every possible value. */
8669 const int pres_start = (present ? 0 : max_value);
8670
8671 /* The enumerators for every range follows all the positions of the
8672 * previous range(s). */
8673 const int range_start = ((max_value - 1) * 2) * range;
8674
8675 return range_start + pres_start + value;
8676}
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:5661
struct action * action_by_rule_name(const char *name)
Definition actions.c:1079
const char * action_rule_name(const struct action *action)
Definition actions.c:1216
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1239
int action_number(const struct action *action)
Definition actions.c:1208
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define ACTION_NONE
Definition actions.h:59
void astr_free(struct astring *astr)
Definition astring.c:148
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:251
void astr_init(struct astring *astr)
Definition astring.c:139
#define n
Definition astring.c:77
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
const char * textcalfrag(int frag)
Definition calendar.c:101
const char * textyear(int year)
Definition calendar.c:121
citizens citizens_nation_foreign(const struct city *pcity)
Definition citizens.c:91
#define citizens_iterate_end
Definition citizens.h:54
#define citizens_iterate(_pcity, _pslot, _nationality)
Definition citizens.h:48
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:1240
Output_type_id output_type_by_identifier(const char *id)
Definition city.c:647
const char * get_output_identifier(Output_type_id output)
Definition city.c:619
const char * get_output_name(Output_type_id output)
Definition city.c:629
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
#define city_tile(_pcity_)
Definition city.h:561
static citizens city_size_get(const struct city *pcity)
Definition city.h:566
#define city_owner(_pcity_)
Definition city.h:560
static bool is_city_center(const struct city *pcity, const struct tile *ptile)
Definition city.h:865
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:227
#define city_tile_iterate_end
Definition city.h:235
#define city_built_iterate(_pcity, _p)
Definition city.h:831
#define city_built_iterate_end
Definition city.h:837
char * incite_cost
Definition comments.c:76
int counter_index(const struct counter *pcount)
Definition counters.c:174
const char * counter_name_translation(const struct counter *counter)
Definition counters.c:157
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:115
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:165
struct counter * counter_by_id(int id)
Definition counters.c:82
int counter_id(struct counter *pcount)
Definition counters.c:105
int city_culture(const struct city *pcity)
Definition culture.c:29
int player_culture(const struct player *plr)
Definition culture.c:49
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:56
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:57
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
struct @22::@23 reqs
int get_world_bonus(enum effect_type effect_type)
Definition effects.c:812
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
bool extra_flag_is_in_use(enum extra_flag_id id)
Definition extras.c:1001
bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:904
bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:884
bool is_extra_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:379
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:875
bool is_extra_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:363
struct extra_type * extra_by_number(int id)
Definition extras.c:183
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:194
#define extra_road_get(_e_)
Definition extras.h:191
static bool is_server(void)
int Tech_type_id
Definition fc_types.h: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:1048
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:350
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:362
struct nation_group * nation_group_by_rule_name(const char *name)
Definition nation.c:1021
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:486
const char * nation_adjective_translation(const struct nation_type *pnation)
Definition nation.c:149
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:475
const char * nation_group_rule_name(const struct nation_group *pgroup)
Definition nation.c:1079
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
bool nation_is_in_group(const struct nation_type *pnation, const struct nation_group *pgroup)
Definition nation.c:1099
const char * nation_group_name_translation(const struct nation_group *pgroup)
Definition nation.c:1090
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
struct nation_group * nation_group_by_number(int id)
Definition nation.c:1004
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:952
#define NO_NATION_SELECTED
Definition nation.h:30
bool player_knows_techs_with_flag(const struct player *pplayer, enum tech_flag_id flag)
Definition player.c:1328
bool player_has_state(const struct player *pplayer, enum plrstate_type state)
Definition player.c:2004
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Definition player.c:1829
int diplrel_by_rule_name(const char *value)
Definition player.c:1585
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1480
bool is_diplrel_to_other(const struct player *pplayer, int diplrel)
Definition player.c:1566
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1996
const char * diplrel_name_translation(int value)
Definition player.c:1631
bool is_diplrel_between(const struct player *player1, const struct player *player2, int diplrel)
Definition player.c:1516
int player_age(const struct player *pplayer)
Definition player.c:954
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1409
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:437
const char * diplrel_rule_name(int value)
Definition player.c:1619
#define players_iterate_end
Definition player.h:542
#define players_iterate(_pplayer)
Definition player.h:537
#define player_nation(_plr_)
Definition player.h:408
#define is_ai(plr)
Definition player.h:232
#define players_iterate_alive_end
Definition player.h:552
#define players_iterate_alive(_pplayer)
Definition player.h:547
static enum req_item_found terrain_type_found(const struct requirement *preq, const struct universal *source)
bool universal_never_there(const struct universal *source)
static enum fc_tristate is_unitclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unitflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_relevant_to_requirement(const struct requirement *req, const struct universal *source)
#define EXTRACT_INFO(req)
bool is_req_in_vec(const struct requirement *req, const struct requirement_vector *vec)
int universal_build_shield_cost(const struct city *pcity, const struct universal *target)
static enum fc_tristate is_terrainflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found city_tile_found(const struct requirement *preq, const struct universal *source)
struct req_vec_problem * req_vec_get_first_contradiction(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static universal_found universal_found_function[VUT_COUNT]
static enum req_unchanging_status unchanging_local(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
#define REQUC_CITYSTATUS
const struct req_context * req_context_empty(void)
static enum fc_tristate is_action_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found unit_type_found(const struct requirement *preq, const struct universal *source)
void universal_extraction(const struct universal *source, int *kind, int *value)
static int num_player_buildings(const struct player *pplayer, const struct impr_type *building)
static enum fc_tristate is_tech_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_none_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static int num_continent_buildings(const struct player *pplayer, int continent, const struct impr_type *building)
static enum fc_tristate is_minveteran_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * req_to_fstring(const struct requirement *req, struct astring *astr)
static enum fc_tristate is_counter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
req_vec_num_in_item req_vec_vector_number(const void *parent_item, const struct requirement_vector *vec)
static bool present_implies_not_present(const struct requirement *req1, const struct requirement *req2)
enum fc_tristate tri_req_active(const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct requirement_vector * req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
bool universal_fulfills_requirements(bool check_necessary, const struct requirement_vector *reqs, const struct universal *source)
static bool activity_is_valid_in_requirement(enum unit_activity act)
enum fc_tristate tri_reqs_cb_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, struct requirement_vector *maybe_reqs, req_tester_cb tester, void *data, int n_data)
static enum fc_tristate is_minsize_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_ai_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_noally(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_max_distance_sq_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_vec_change_apply(const struct req_vec_change *modification, requirement_vector_by_number getter, const void *parent_item)
void universal_copy(struct universal *dst, const struct universal *src)
static enum fc_tristate is_minculture_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_building(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_terrain_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_requirements_equal(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_minforeignpct_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_minyear_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found extra_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_buildingflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_in_range(const struct tile *target_tile, const struct player *other_player, enum req_range range, int diplrel)
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
struct requirement req_from_str(const char *type, const char *range, bool survives, bool present, bool quiet, const char *value)
struct req_vec_problem * req_vec_suggest_repair(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum fc_tristate is_wrap_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void universal_value_from_str(struct universal *source, const char *value)
static enum fc_tristate is_buildingflag_in_city(const struct city *pcity, enum impr_flag_id flag)
static enum fc_tristate is_latitude_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_get_values(const struct requirement *req, int *type, int *range, bool *survives, bool *present, bool *quiet, int *value)
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
static enum fc_tristate is_nationality_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * universal_rule_name(const struct universal *psource)
static enum req_unchanging_status unchanging_present(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
bool universal_replace_in_req_vec(struct requirement_vector *reqs, const struct universal *to_replace, const struct universal *replacement)
static enum req_item_found action_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_minmovefrags_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_requirements_contradictions(const struct requirement *req1, const struct requirement *req2)
#define REQUC_IMPR
static enum fc_tristate is_maxunitsontile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct req_vec_problem * req_vec_problem_new(int num_suggested_solutions, const char *descr,...)
static enum fc_tristate is_buildinggenus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_in_range(const struct player *target_player, const struct player *other_player, enum req_range range, int diplrel)
static enum fc_tristate is_mintechs_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool is_req_active(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, const enum req_problem_type prob_type)
static enum fc_tristate is_originalowner_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool are_bounds_contradictions(int bound1, bool is_upper1, int bound2, bool is_upper2)
static enum fc_tristate is_diplrel_tile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_legal_in_requirement(const struct universal *univ)
enum fc_tristate default_tester_cb(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, void *data, int n_data)
static enum fc_tristate tri_req_present(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
int requirement_kind_ereq(const int value, const enum req_range range, const bool present, const int max_value)
static enum fc_tristate is_achievement_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_vec_problem_free(struct req_vec_problem *issue)
static struct req_def req_definitions[VUT_COUNT]
static bool impr_contra_flag(const struct requirement *impr_req, const struct requirement *flag_req)
bool are_reqs_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
static enum req_item_found improvement_found(const struct requirement *preq, const struct universal *source)
struct req_vec_problem * req_vec_get_first_missing_univ(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum req_item_found mincities_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_extraflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum req_unchanging_status is_req_preventing(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, enum req_problem_type prob_type)
static enum fc_tristate is_plr_state_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool players_in_same_range(const struct player *pplayer1, const struct player *pplayer2, enum req_range range)
struct requirement * req_vec_first_contradiction_in_vec(const struct requirement *req, const struct requirement_vector *vec)
enum req_item_found(* universal_found)(const struct requirement *, const struct universal *)
static enum fc_tristate is_terrainclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct universal universal_by_number(const enum universals_n kind, const int value)
static enum fc_tristate is_roadflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum req_item_found universal_fulfills_requirement(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_building_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
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:115
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#define tile_owner(_tile)
Definition tile.h:97
bool goods_can_be_provided(const struct city *pcity, const struct goods_type *pgood, const struct unit *punit)
Goods_type_id goods_number(const struct goods_type *pgood)
bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
const char * goods_name_translation(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
#define trade_partners_iterate_end
#define trade_partners_iterate(c, p)
const struct unit_type * utype
Definition fc_types.h: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:1846
#define unit_tile(_pu)
Definition unit.h:407
#define unit_owner(_pu)
Definition unit.h:406
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const char * uclass_name_translation(const struct unit_class *pclass)
Definition unittype.c:1636
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
bool unit_has_class_flag(const struct unit *punit, enum unit_class_flag_id flag)
Definition unittype.c:1653
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1771
bool uclass_flag_is_in_use(enum unit_class_flag_id ucflag)
Definition unittype.c:2985
struct unit_class * uclass_by_number(const Unit_Class_id id)
Definition unittype.c:2481
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1582
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2503
struct unit_type * utype_by_number(const Unit_type_id id)
Definition unittype.c:112
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:194
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1645
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:100
struct unit_class * unit_class_by_rule_name(const char *s)
Definition unittype.c:1788
bool utype_flag_is_in_use(enum unit_type_flag_id uflag)
Definition unittype.c:3004
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1442
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2472
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1564
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:771
#define utype_class(_t_)
Definition unittype.h:754
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:622
bool victory_enabled(enum victory_condition_type victory)
Definition victory.c:26