Freeciv-3.4
Loading...
Searching...
No Matches
requirements.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2004 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17#include <stdarg.h>
18
19/* utility */
20#include "astring.h"
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "achievements.h"
27#include "calendar.h"
28#include "citizens.h"
29#include "counters.h"
30#include "culture.h"
31#include "game.h"
32#include "government.h"
33#include "improvement.h"
34#include "movement.h"
35#include "nation.h"
36#include "player.h"
37#include "map.h"
38#include "research.h"
39#include "road.h"
40#include "server_settings.h"
41#include "specialist.h"
42#include "style.h"
43#include "tiledef.h"
44#include "victory.h" /* victory_enabled() */
45
46#include "requirements.h"
47
48/************************************************************************
49 Container for req_item_found functions
50************************************************************************/
51typedef enum req_item_found (*universal_found)(const struct requirement *,
52 const struct universal *);
54
55static
57 const struct req_context *context,
58 const struct req_context *other_context,
59 const struct requirement *req);
60
61/* Function pointer for requirement-type-specific is_req_active handlers */
62typedef enum fc_tristate
63(*is_req_active_cb)(const struct civ_map *nmap,
64 const struct req_context *context,
65 const struct req_context *other_context,
66 const struct requirement *req);
67
68static inline bool are_tiles_in_range(const struct tile *tile1,
69 const struct tile *tile2,
70 enum req_range range);
71
72/**********************************************************************/
77static enum req_unchanging_status
79 enum req_unchanging_status def,
80 const struct req_context *context,
81 const struct requirement *req)
82{
83 return req->range == REQ_RANGE_LOCAL ? REQUCH_YES : def;
84}
85#define REQUC_LOCAL unchanging_local
86
87/**********************************************************************/
90static enum req_unchanging_status
92 enum req_unchanging_status def,
93 const struct req_context *context,
94 const struct requirement *req)
95{
96 if (TRI_YES != tri_req_present(nmap, context, nullptr, req)) {
97 return REQUCH_NO;
98 }
99 return def;
100}
101#define REQUC_PRESENT unchanging_present
102
103/**********************************************************************/
106static enum req_unchanging_status
108 enum req_unchanging_status def,
109 const struct req_context *context,
110 const struct requirement *req)
111{
112 return
114 context, req);
115}
116#define REQUC_WORLD unchanging_world
117
118/**********************************************************************/
122static enum req_unchanging_status
124 enum req_unchanging_status def,
125 const struct req_context *context,
126 const struct requirement *req)
127{
128 if (REQ_RANGE_ALLIANCE == req->range
129 || REQ_RANGE_TEAM == req->range) {
130 struct requirement preq;
131
132 req_copy(&preq, req);
133 preq.range = REQ_RANGE_PLAYER;
134 if (TRI_YES != tri_req_present(nmap, context, nullptr, &preq)) {
135 return REQ_RANGE_TEAM == req->range ? REQUCH_ACT : REQUCH_NO;
136 }
137 }
138 return def;
139}
140#define REQUC_NALLY unchanging_noally
141
142/**********************************************************************/
145static enum req_unchanging_status
147 enum req_unchanging_status def,
148 const struct req_context *context,
149 const struct requirement *req)
150{
154 && context->city != nullptr && context->tile != nullptr
155 && city_tile(context->city) != nullptr
157 req->range))){
158 /* Cities don't move, and most reqs are present on city center */
159 return REQUCH_YES;
160 }
161 return def;
162}
163#define REQUC_CITYTILE unchanging_citytile
164
165/**********************************************************************/
168static enum req_unchanging_status
170 enum req_unchanging_status def,
171 const struct req_context *context,
172 const struct requirement *req)
173{
175
176 if (REQ_RANGE_CITY == req->range
179 return REQUCH_CTRL;
180 }
181
182 return def;
183}
184#define REQUC_CITYSTATUS unchanging_citystatus
185
186/**********************************************************************/
191static enum req_unchanging_status
193 enum req_unchanging_status def,
194 const struct req_context *context,
195 const struct requirement *req)
196{
197 const struct impr_type *b = req->source.value.building;
198
200 || VUT_SITE == req->source.kind, REQUCH_NO);
201 if (REQ_RANGE_LOCAL == req->range) {
202 /* Likely, won't be questioned for an obsolete building */
203 return REQUCH_YES;
204 }
205
206 if (req->source.kind == VUT_IMPROVEMENT
207 && improvement_obsolete(context->player, b, context->city)) {
208 /* FIXME: Sometimes can unobsolete, but considering it
209 * may sometimes put the function on endless recursion */
210 return REQUCH_ACT; /* Mostly about techs */
211 }
212 if (is_great_wonder(b)) {
215 && (req->range <= REQ_RANGE_CITY && TRI_YES
216 == tri_req_present(nmap, context, nullptr, req)))) {
217 /* If the wonder stays somewhere, it may either remain there
218 * or be destroyed. If it is destroyed, it is nowhere. */
219 return REQUCH_SCRIPTS;
220 }
221 }
222 return def;
223}
224#define REQUC_IMPR unchanging_building
225
231
232/**********************************************************************/
240 const char *value)
241{
242 struct universal source;
243
245 if (!universals_n_is_valid(source.kind)) {
246 return source;
247 }
248
250
251 return source;
252}
253
254/**********************************************************************/
259{
260 return unit_activity_is_valid(act)
261 && act != ACTIVITY_SENTRY
262 && act != ACTIVITY_GOTO
263 && act != ACTIVITY_EXPLORE;
264}
265
266/**********************************************************************/
271{
272 if (univ->kind == VUT_ACTIVITY) {
274 }
275
276 return TRUE;
277}
278
279/**********************************************************************/
284{
285 /* Finally scan the value string based on the type of the source. */
286 switch (source->kind) {
287 case VUT_NONE:
288 return;
289 case VUT_ADVANCE:
290 source->value.advance = advance_by_rule_name(value);
291 if (source->value.advance != nullptr) {
292 return;
293 }
294 break;
295 case VUT_TECHFLAG:
296 source->value.techflag
298 if (tech_flag_id_is_valid(source->value.techflag)) {
299 return;
300 }
301 break;
302 case VUT_GOVERNMENT:
303 source->value.govern = government_by_rule_name(value);
304 if (source->value.govern != nullptr) {
305 return;
306 }
307 break;
308 case VUT_GOVFLAG:
310 if (gov_flag_id_is_valid(source->value.govflag)) {
311 return;
312 }
313 break;
314 case VUT_ACHIEVEMENT:
315 source->value.achievement = achievement_by_rule_name(value);
316 if (source->value.achievement != nullptr) {
317 return;
318 }
319 break;
320 case VUT_STYLE:
321 source->value.style = style_by_rule_name(value);
322 if (source->value.style != nullptr) {
323 return;
324 }
325 break;
326 case VUT_IMPROVEMENT:
327 case VUT_SITE:
328 source->value.building = improvement_by_rule_name(value);
329 if (source->value.building != nullptr) {
330 return;
331 }
332 break;
333 case VUT_IMPR_GENUS:
334 source->value.impr_genus = impr_genus_id_by_name(value, fc_strcasecmp);
335 if (impr_genus_id_is_valid(source->value.impr_genus)) {
336 return;
337 }
338 break;
339 case VUT_IMPR_FLAG:
340 source->value.impr_flag = impr_flag_id_by_name(value, fc_strcasecmp);
341 if (impr_flag_id_is_valid(source->value.impr_flag)) {
342 return;
343 }
344 break;
345 case VUT_PLAYER_FLAG:
346 source->value.plr_flag = plr_flag_id_by_name(value, fc_strcasecmp);
347 if (plr_flag_id_is_valid(source->value.plr_flag)) {
348 return;
349 }
350 break;
351 case VUT_EXTRA:
352 source->value.extra = extra_type_by_rule_name(value);
353 if (source->value.extra != nullptr) {
354 return;
355 }
356 break;
357 case VUT_TILEDEF:
358 source->value.tiledef = tiledef_by_rule_name(value);
359 if (source->value.tiledef != nullptr) {
360 return;
361 }
362 break;
363 case VUT_GOOD:
364 source->value.good = goods_by_rule_name(value);
365 if (source->value.good != nullptr) {
366 return;
367 }
368 break;
369 case VUT_TERRAIN:
370 source->value.terrain = terrain_by_rule_name(value);
371 if (source->value.terrain != T_UNKNOWN) {
372 return;
373 }
374 break;
375 case VUT_TERRFLAG:
376 source->value.terrainflag
378 if (terrain_flag_id_is_valid(source->value.terrainflag)) {
379 return;
380 }
381 break;
382 case VUT_NATION:
383 source->value.nation = nation_by_rule_name(value);
384 if (source->value.nation != NO_NATION_SELECTED) {
385 return;
386 }
387 break;
388 case VUT_NATIONGROUP:
389 source->value.nationgroup = nation_group_by_rule_name(value);
390 if (source->value.nationgroup != nullptr) {
391 return;
392 }
393 break;
394 case VUT_NATIONALITY:
395 source->value.nationality = nation_by_rule_name(value);
396 if (source->value.nationality != NO_NATION_SELECTED) {
397 return;
398 }
399 break;
401 source->value.origowner = nation_by_rule_name(value);
402 if (source->value.origowner != NO_NATION_SELECTED) {
403 return;
404 }
405 break;
406 case VUT_DIPLREL:
407 case VUT_DIPLREL_TILE:
411 source->value.diplrel = diplrel_by_rule_name(value);
412 if (source->value.diplrel != diplrel_other_invalid()) {
413 return;
414 }
415 break;
416 case VUT_UTYPE:
417 source->value.utype = unit_type_by_rule_name(value);
418 if (source->value.utype) {
419 return;
420 }
421 break;
422 case VUT_UTFLAG:
424 if (unit_type_flag_id_is_valid(source->value.unitflag)) {
425 return;
426 }
427 break;
428 case VUT_UCLASS:
429 source->value.uclass = unit_class_by_rule_name(value);
430 if (source->value.uclass) {
431 return;
432 }
433 break;
434 case VUT_UCFLAG:
435 source->value.unitclassflag
437 if (unit_class_flag_id_is_valid(source->value.unitclassflag)) {
438 return;
439 }
440 break;
441 case VUT_MINVETERAN:
442 source->value.minveteran = atoi(value);
443 if (source->value.minveteran > 0) {
444 return;
445 }
446 break;
447 case VUT_UNITSTATE:
448 source->value.unit_state = ustate_prop_by_name(value, fc_strcasecmp);
449 if (ustate_prop_is_valid(source->value.unit_state)) {
450 return;
451 }
452 break;
453 case VUT_ACTIVITY:
455 if (activity_is_valid_in_requirement(source->value.activity)) {
456 return;
457 }
458 break;
459 case VUT_MINMOVES:
460 source->value.minmoves = atoi(value);
461 if (source->value.minmoves > 0) {
462 return;
463 }
464 break;
465 case VUT_MINHP:
466 source->value.min_hit_points = atoi(value);
467 if (source->value.min_hit_points > 0) {
468 return;
469 }
470 break;
471 case VUT_AGE:
472 source->value.age = atoi(value);
473 if (source->value.age > 0) {
474 return;
475 }
476 break;
477 case VUT_FORM_AGE:
478 source->value.form_age = atoi(value);
479 if (source->value.form_age > 0) {
480 return;
481 }
482 break;
483 case VUT_MINTECHS:
484 source->value.min_techs = atoi(value);
485 if (source->value.min_techs > 0) {
486 return;
487 }
488 break;
489 case VUT_FUTURETECHS:
490 source->value.future_techs = atoi(value);
491 if (source->value.future_techs > 0) {
492 return;
493 }
494 break;
495 case VUT_MINCITIES:
496 source->value.min_cities = atoi(value);
497 if (source->value.min_cities > 0) {
498 return;
499 }
500 break;
501 case VUT_ACTION:
502 source->value.action = action_by_rule_name(value);
503 if (source->value.action != nullptr) {
504 return;
505 }
506 break;
507 case VUT_OTYPE:
508 source->value.outputtype = output_type_by_identifier(value);
509 if (source->value.outputtype != O_LAST) {
510 return;
511 }
512 break;
513 case VUT_SPECIALIST:
514 source->value.specialist = specialist_by_rule_name(value);
515 if (source->value.specialist) {
516 return;
517 }
518 break;
519 case VUT_MINSIZE:
520 source->value.minsize = atoi(value);
521 if (source->value.minsize > 0) {
522 return;
523 }
524 break;
525 case VUT_MINCULTURE:
526 source->value.minculture = atoi(value);
527 if (source->value.minculture > 0) {
528 return;
529 }
530 break;
532 source->value.minforeignpct = atoi(value);
533 if (source->value.minforeignpct > 0) {
534 return;
535 }
536 break;
537 case VUT_AI_LEVEL:
538 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
539 if (ai_level_is_valid(source->value.ai_level)) {
540 return;
541 }
542 break;
544 source->value.max_tile_total_units = atoi(value);
545 if (0 <= source->value.max_tile_total_units) {
546 return;
547 }
548 break;
550 source->value.max_tile_top_units = atoi(value);
551 if (0 <= source->value.max_tile_top_units) {
552 return;
553 }
554 break;
555 case VUT_TERRAINCLASS:
556 source->value.terrainclass
558 if (terrain_class_is_valid(source->value.terrainclass)) {
559 return;
560 }
561 break;
562 case VUT_ROADFLAG:
564 if (road_flag_id_is_valid(source->value.roadflag)) {
565 return;
566 }
567 break;
568 case VUT_EXTRAFLAG:
569 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
570 if (extra_flag_id_is_valid(source->value.extraflag)) {
571 return;
572 }
573 break;
574 case VUT_MINYEAR:
575 source->value.minyear = atoi(value);
576 return;
577 case VUT_MINCALFRAG:
578 /* Rule names are 0-based numbers, not pretty names from ruleset */
579 source->value.mincalfrag = atoi(value);
580 if (source->value.mincalfrag >= 0) {
581 /* More range checking done later, in sanity_check_req_individual() */
582 return;
583 }
584 break;
585 case VUT_TOPO:
586 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
587 if (topo_flag_is_valid(source->value.topo_property)) {
588 return;
589 }
590 break;
591 case VUT_WRAP:
592 source->value.wrap_property = wrap_flag_by_name(value, fc_strcasecmp);
593 if (wrap_flag_is_valid(source->value.wrap_property)) {
594 return;
595 }
596 break;
598 source->value.ssetval = ssetv_by_rule_name(value);
599 if (source->value.ssetval != SSETV_NONE) {
600 return;
601 }
602 break;
603 case VUT_TERRAINALTER:
604 source->value.terrainalter
606 if (terrain_alteration_is_valid(source->value.terrainalter)) {
607 return;
608 }
609 break;
610 case VUT_CITYTILE:
612 if (source->value.citytile != CITYT_LAST) {
613 return;
614 }
615 break;
616 case VUT_CITYSTATUS:
618 if (source->value.citystatus != CITYS_LAST) {
619 return;
620 }
621 break;
622 case VUT_PLAYER_STATE:
624 if (source->value.plrstate != PLRS_LAST) {
625 return;
626 }
627 break;
628 case VUT_MINLATITUDE:
629 case VUT_MAXLATITUDE:
630 source->value.latitude = atoi(value);
631 if (source->value.latitude >= -MAP_MAX_LATITUDE
632 && source->value.latitude <= MAP_MAX_LATITUDE) {
633 return;
634 }
635 break;
636 case VUT_COUNTER:
637 source->value.counter = counter_by_rule_name(value);
638 if (source->value.counter != nullptr) {
639 return;
640 }
641 break;
643 source->value.distance_sq = atoi(value);
644 if (0 <= source->value.distance_sq) {
645 return;
646 }
647 break;
649 source->value.region_tiles = atoi(value);
650 if (0 < source->value.region_tiles) {
651 return;
652 }
653 break;
654 case VUT_TILE_REL:
656 if (source->value.tilerel != TREL_COUNT) {
657 return;
658 }
659 break;
660 case VUT_COUNT:
661 break;
662 }
663
664 /* If we reach here there's been an error. */
666}
667
668/**********************************************************************/
675{
676 struct universal source;
677
678 source.kind = kind;
679
680 switch (source.kind) {
681 case VUT_NONE:
682 /* Avoid compiler warning about uninitialized source.value */
683 source.value.advance = nullptr;
684
685 return source;
686 case VUT_ADVANCE:
687 source.value.advance = advance_by_number(value);
688 if (source.value.advance != nullptr) {
689 return source;
690 }
691 break;
692 case VUT_TECHFLAG:
693 source.value.techflag = value;
694 return source;
695 case VUT_GOVERNMENT:
697 if (source.value.govern != nullptr) {
698 return source;
699 }
700 break;
701 case VUT_GOVFLAG:
702 source.value.govflag = value;
703 return source;
704 case VUT_ACHIEVEMENT:
706 if (source.value.achievement != nullptr) {
707 return source;
708 }
709 break;
710 case VUT_STYLE:
711 source.value.style = style_by_number(value);
712 if (source.value.style != nullptr) {
713 return source;
714 }
715 break;
716 case VUT_IMPROVEMENT:
717 case VUT_SITE:
718 source.value.building = improvement_by_number(value);
719 if (source.value.building != nullptr) {
720 return source;
721 }
722 break;
723 case VUT_IMPR_GENUS:
724 source.value.impr_genus = value;
725 return source;
726 case VUT_IMPR_FLAG:
727 source.value.impr_flag = value;
728 return source;
729 case VUT_PLAYER_FLAG:
730 source.value.plr_flag = value;
731 return source;
732 case VUT_EXTRA:
734 return source;
735 case VUT_TILEDEF:
736 source.value.tiledef = tiledef_by_number(value);
737 return source;
738 case VUT_GOOD:
739 source.value.good = goods_by_number(value);
740 return source;
741 case VUT_TERRAIN:
742 source.value.terrain = terrain_by_number(value);
743 if (source.value.terrain != nullptr) {
744 return source;
745 }
746 break;
747 case VUT_TERRFLAG:
748 source.value.terrainflag = value;
749 return source;
750 case VUT_NATION:
752 if (source.value.nation != nullptr) {
753 return source;
754 }
755 break;
756 case VUT_NATIONGROUP:
757 source.value.nationgroup = nation_group_by_number(value);
758 if (source.value.nationgroup != nullptr) {
759 return source;
760 }
761 break;
762 case VUT_DIPLREL:
763 case VUT_DIPLREL_TILE:
767 source.value.diplrel = value;
768 if (source.value.diplrel != diplrel_other_invalid()) {
769 return source;
770 }
771 break;
772 case VUT_NATIONALITY:
774 if (source.value.nationality != nullptr) {
775 return source;
776 }
777 break;
779 source.value.origowner = nation_by_number(value);
780 if (source.value.origowner != nullptr) {
781 return source;
782 }
783 break;
784 case VUT_UTYPE:
785 source.value.utype = utype_by_number(value);
786 if (source.value.utype != nullptr) {
787 return source;
788 }
789 break;
790 case VUT_UTFLAG:
791 source.value.unitflag = value;
792 return source;
793 case VUT_UCLASS:
795 if (source.value.uclass != nullptr) {
796 return source;
797 }
798 break;
799 case VUT_UCFLAG:
800 source.value.unitclassflag = value;
801 return source;
802 case VUT_MINVETERAN:
803 source.value.minveteran = value;
804 return source;
805 case VUT_UNITSTATE:
806 source.value.unit_state = value;
807 return source;
808 case VUT_ACTIVITY:
809 source.value.activity = value;
810 return source;
811 case VUT_MINMOVES:
812 source.value.minmoves = value;
813 return source;
814 case VUT_MINHP:
816 return source;
817 case VUT_AGE:
818 source.value.age = value;
819 return source;
820 case VUT_FORM_AGE:
821 source.value.form_age = value;
822 return source;
823 case VUT_MINTECHS:
824 source.value.min_techs = value;
825 return source;
826 case VUT_FUTURETECHS:
827 source.value.future_techs = value;
828 return source;
829 case VUT_MINCITIES:
830 source.value.min_cities = value;
831 return source;
832 case VUT_ACTION:
834 if (source.value.action != nullptr) {
835 return source;
836 }
837 break;
838 case VUT_OTYPE:
839 source.value.outputtype = value;
840 return source;
841 case VUT_SPECIALIST:
843 return source;
844 case VUT_MINSIZE:
845 source.value.minsize = value;
846 return source;
847 case VUT_MINCULTURE:
848 source.value.minculture = value;
849 return source;
851 source.value.minforeignpct = value;
852 return source;
853 case VUT_AI_LEVEL:
854 source.value.ai_level = value;
855 return source;
858 return source;
861 return source;
862 case VUT_TERRAINCLASS:
863 source.value.terrainclass = value;
864 return source;
865 case VUT_ROADFLAG:
866 source.value.roadflag = value;
867 return source;
868 case VUT_EXTRAFLAG:
869 source.value.extraflag = value;
870 return source;
871 case VUT_MINYEAR:
872 source.value.minyear = value;
873 return source;
874 case VUT_MINCALFRAG:
875 source.value.mincalfrag = value;
876 return source;
877 case VUT_TOPO:
878 source.value.topo_property = value;
879 return source;
880 case VUT_WRAP:
881 source.value.wrap_property = value;
882 return source;
884 source.value.ssetval = value;
885 return source;
886 case VUT_TERRAINALTER:
887 source.value.terrainalter = value;
888 return source;
889 case VUT_CITYTILE:
890 source.value.citytile = value;
891 return source;
892 case VUT_CITYSTATUS:
893 source.value.citystatus = value;
894 return source;
895 case VUT_PLAYER_STATE:
896 source.value.plrstate = value;
897 return source;
898 case VUT_COUNTER:
900 return source;
901 case VUT_MINLATITUDE:
902 case VUT_MAXLATITUDE:
903 source.value.latitude = value;
904 return source;
906 source.value.distance_sq = value;
907 return source;
909 source.value.region_tiles = value;
910 return source;
911 case VUT_TILE_REL:
912 source.value.tilerel = value;
913 return source;
914 case VUT_COUNT:
915 break;
916 }
917
918 /* If we reach here there's been an error. */
920 /* Avoid compiler warning about uninitialized source.value */
921 source.value.advance = nullptr;
922
923 return source;
924}
925
926/**********************************************************************/
929void universal_copy(struct universal *dst, const struct universal *src)
930{
931 dst->value = src->value;
932 dst->kind = src->kind;
933}
934
935/**********************************************************************/
940 int *kind, int *value)
941{
942 *kind = source->kind;
944}
945
946/**********************************************************************/
950{
951 switch (source->kind) {
952 case VUT_NONE:
953 return 0;
954 case VUT_ADVANCE:
955 return advance_number(source->value.advance);
956 case VUT_TECHFLAG:
957 return source->value.techflag;
958 case VUT_GOVERNMENT:
959 return government_number(source->value.govern);
960 case VUT_GOVFLAG:
961 return source->value.govflag;
962 case VUT_ACHIEVEMENT:
963 return achievement_number(source->value.achievement);
964 case VUT_STYLE:
965 return style_number(source->value.style);
966 case VUT_IMPROVEMENT:
967 case VUT_SITE:
968 return improvement_number(source->value.building);
969 case VUT_IMPR_GENUS:
970 return source->value.impr_genus;
971 case VUT_IMPR_FLAG:
972 return source->value.impr_flag;
973 case VUT_PLAYER_FLAG:
974 return source->value.plr_flag;
975 case VUT_EXTRA:
976 return extra_number(source->value.extra);
977 case VUT_TILEDEF:
978 return tiledef_number(source->value.tiledef);
979 case VUT_GOOD:
980 return goods_number(source->value.good);
981 case VUT_TERRAIN:
982 return terrain_number(source->value.terrain);
983 case VUT_TERRFLAG:
984 return source->value.terrainflag;
985 case VUT_NATION:
986 return nation_number(source->value.nation);
987 case VUT_NATIONGROUP:
988 return nation_group_number(source->value.nationgroup);
989 case VUT_NATIONALITY:
990 return nation_number(source->value.nationality);
992 return nation_number(source->value.origowner);
993 case VUT_DIPLREL:
994 case VUT_DIPLREL_TILE:
998 return source->value.diplrel;
999 case VUT_UTYPE:
1000 return utype_number(source->value.utype);
1001 case VUT_UTFLAG:
1002 return source->value.unitflag;
1003 case VUT_UCLASS:
1004 return uclass_number(source->value.uclass);
1005 case VUT_UCFLAG:
1006 return source->value.unitclassflag;
1007 case VUT_MINVETERAN:
1008 return source->value.minveteran;
1009 case VUT_UNITSTATE:
1010 return source->value.unit_state;
1011 case VUT_ACTIVITY:
1012 return source->value.activity;
1013 case VUT_MINMOVES:
1014 return source->value.minmoves;
1015 case VUT_MINHP:
1016 return source->value.min_hit_points;
1017 case VUT_AGE:
1018 return source->value.age;
1019 case VUT_FORM_AGE:
1020 return source->value.form_age;
1021 case VUT_MINTECHS:
1022 return source->value.min_techs;
1023 case VUT_FUTURETECHS:
1024 return source->value.future_techs;
1025 case VUT_MINCITIES:
1026 return source->value.min_cities;
1027 case VUT_ACTION:
1028 return action_number(source->value.action);
1029 case VUT_OTYPE:
1030 return source->value.outputtype;
1031 case VUT_SPECIALIST:
1032 return specialist_number(source->value.specialist);
1033 case VUT_MINSIZE:
1034 return source->value.minsize;
1035 case VUT_MINCULTURE:
1036 return source->value.minculture;
1037 case VUT_MINFOREIGNPCT:
1038 return source->value.minforeignpct;
1039 case VUT_AI_LEVEL:
1040 return source->value.ai_level;
1042 return source->value.max_tile_total_units;
1044 return source->value.max_tile_top_units;
1045 case VUT_TERRAINCLASS:
1046 return source->value.terrainclass;
1047 case VUT_ROADFLAG:
1048 return source->value.roadflag;
1049 case VUT_EXTRAFLAG:
1050 return source->value.extraflag;
1051 case VUT_MINYEAR:
1052 return source->value.minyear;
1053 case VUT_MINCALFRAG:
1054 return source->value.mincalfrag;
1055 case VUT_TOPO:
1056 return source->value.topo_property;
1057 case VUT_WRAP:
1058 return source->value.wrap_property;
1059 case VUT_SERVERSETTING:
1060 return source->value.ssetval;
1061 case VUT_TERRAINALTER:
1062 return source->value.terrainalter;
1063 case VUT_CITYTILE:
1064 return source->value.citytile;
1065 case VUT_CITYSTATUS:
1066 return source->value.citystatus;
1067 case VUT_PLAYER_STATE:
1068 return source->value.plrstate;
1069 case VUT_COUNTER:
1070 return counter_id(source->value.counter);
1071 case VUT_MINLATITUDE:
1072 case VUT_MAXLATITUDE:
1073 return source->value.latitude;
1075 return source->value.distance_sq;
1077 return source->value.region_tiles;
1078 case VUT_TILE_REL:
1079 return source->value.tilerel;
1080 case VUT_COUNT:
1081 break;
1082 }
1083
1084 /* If we reach here there's been an error. */
1085 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
1086 source->kind);
1087 return 0;
1088}
1089
1090
1091/**********************************************************************/
1095{
1096 static const struct req_context empty = {};
1097 return &empty;
1098}
1099
1100
1101/**********************************************************************/
1109const char *req_to_fstring(const struct requirement *req,
1110 struct astring *astr)
1111{
1112 astr_init(astr);
1113
1114 astr_set(astr, "%s%s %s %s%s",
1115 req->survives ? "surviving " : "",
1116 req_range_name(req->range),
1118 req->present ? "" : "!",
1120
1121 return astr_str(astr);
1122}
1123
1124/**********************************************************************/
1132 bool survives, bool present, bool quiet,
1133 const char *value)
1134{
1135 struct requirement req;
1136 bool invalid;
1137 const char *error = nullptr;
1138
1139 req.source = universal_by_rule_name(type, value);
1140
1142 if (invalid) {
1143 error = "bad type or name";
1144 } else {
1145 /* Scan the range string to find the range. If no range is given a
1146 * default fallback is used rather than giving an error. */
1147 if (range != nullptr) {
1149 if (!req_range_is_valid(req.range)) {
1150 invalid = TRUE;
1151 }
1152 } else {
1153 switch (req.source.kind) {
1154 case VUT_NONE:
1155 case VUT_COUNT:
1156 break;
1157 case VUT_IMPROVEMENT:
1158 case VUT_SITE:
1159 case VUT_IMPR_GENUS:
1160 case VUT_IMPR_FLAG:
1161 case VUT_UTYPE:
1162 case VUT_UTFLAG:
1163 case VUT_UCLASS:
1164 case VUT_UCFLAG:
1165 case VUT_MINVETERAN:
1166 case VUT_UNITSTATE:
1167 case VUT_ACTIVITY:
1168 case VUT_MINMOVES:
1169 case VUT_MINHP:
1170 case VUT_AGE:
1171 case VUT_FORM_AGE:
1172 case VUT_ACTION:
1173 case VUT_OTYPE:
1174 case VUT_SPECIALIST:
1175 case VUT_DIPLREL_TILE_O:
1177 req.range = REQ_RANGE_LOCAL;
1178 break;
1179 case VUT_EXTRA:
1180 case VUT_TILEDEF:
1181 case VUT_ROADFLAG:
1182 case VUT_EXTRAFLAG:
1183 /* Keep old behavior */
1184 req.range = REQ_RANGE_TILE;
1185 break;
1186 case VUT_TERRAIN:
1187 case VUT_TERRFLAG:
1188 case VUT_TERRAINCLASS:
1189 case VUT_TERRAINALTER:
1190 case VUT_CITYTILE:
1193 case VUT_MINLATITUDE:
1194 case VUT_MAXLATITUDE:
1196 req.range = REQ_RANGE_TILE;
1197 break;
1198 case VUT_COUNTER:
1199 case VUT_MINSIZE:
1200 case VUT_MINCULTURE:
1201 case VUT_MINFOREIGNPCT:
1202 case VUT_NATIONALITY:
1203 case VUT_ORIGINAL_OWNER:
1204 case VUT_CITYSTATUS:
1205 case VUT_GOOD:
1206 req.range = REQ_RANGE_CITY;
1207 break;
1208 case VUT_GOVERNMENT:
1209 case VUT_GOVFLAG:
1210 case VUT_ACHIEVEMENT:
1211 case VUT_STYLE:
1212 case VUT_ADVANCE:
1213 case VUT_TECHFLAG:
1214 case VUT_NATION:
1215 case VUT_NATIONGROUP:
1216 case VUT_DIPLREL:
1217 case VUT_DIPLREL_TILE:
1219 case VUT_AI_LEVEL:
1220 case VUT_PLAYER_FLAG:
1221 case VUT_PLAYER_STATE:
1222 case VUT_MINCITIES:
1223 case VUT_FUTURETECHS:
1224 req.range = REQ_RANGE_PLAYER;
1225 break;
1226 case VUT_MINYEAR:
1227 case VUT_MINCALFRAG:
1228 case VUT_TOPO:
1229 case VUT_WRAP:
1230 case VUT_MINTECHS:
1231 case VUT_SERVERSETTING:
1232 req.range = REQ_RANGE_WORLD;
1233 break;
1236 break;
1237 case VUT_TILE_REL:
1238 req.range = REQ_RANGE_TILE;
1240 /* Not available at Tile range */
1242 }
1243 break;
1244 }
1245 }
1246
1247 req.survives = survives;
1248 req.present = present;
1249 req.quiet = quiet;
1250
1251 /* These checks match what combinations are supported inside
1252 * is_req_active(). However, it's only possible to do basic checks,
1253 * not anything that might depend on the rest of the ruleset which
1254 * might not have been loaded yet. */
1255 switch (req.source.kind) {
1256 case VUT_TERRAIN:
1257 case VUT_TERRAINCLASS:
1258 case VUT_TERRFLAG:
1259 invalid = (req.range != REQ_RANGE_TILE
1260 && req.range != REQ_RANGE_CADJACENT
1261 && req.range != REQ_RANGE_ADJACENT
1262 && req.range != REQ_RANGE_CITY
1263 && req.range != REQ_RANGE_TRADE_ROUTE);
1264 break;
1265 case VUT_EXTRA:
1266 case VUT_ROADFLAG:
1267 case VUT_EXTRAFLAG:
1269 break;
1270 case VUT_TILEDEF:
1272 || req.range == REQ_RANGE_LOCAL);
1273 break;
1274 case VUT_ACHIEVEMENT:
1275 case VUT_MINTECHS:
1276 case VUT_FUTURETECHS:
1277 invalid = (req.range < REQ_RANGE_PLAYER);
1278 break;
1279 case VUT_ADVANCE:
1280 case VUT_TECHFLAG:
1282 && req.range != REQ_RANGE_LOCAL);
1283 break;
1284 case VUT_GOVERNMENT:
1285 case VUT_GOVFLAG:
1286 case VUT_AI_LEVEL:
1287 case VUT_STYLE:
1288 case VUT_MINCITIES:
1289 invalid = (req.range != REQ_RANGE_PLAYER);
1290 break;
1291 case VUT_MINSIZE:
1292 case VUT_MINFOREIGNPCT:
1293 case VUT_NATIONALITY:
1294 case VUT_CITYSTATUS:
1295 invalid = (req.range != REQ_RANGE_CITY
1296 && req.range != REQ_RANGE_TRADE_ROUTE);
1297 break;
1298 case VUT_GOOD:
1299 case VUT_ORIGINAL_OWNER:
1300 invalid = (req.range != REQ_RANGE_CITY);
1301 break;
1302 case VUT_MINCULTURE:
1303 invalid = (req.range != REQ_RANGE_CITY
1305 && req.range != REQ_RANGE_PLAYER
1306 && req.range != REQ_RANGE_TEAM
1307 && req.range != REQ_RANGE_ALLIANCE
1308 && req.range != REQ_RANGE_WORLD);
1309 break;
1310 case VUT_DIPLREL:
1311 invalid = (req.range != REQ_RANGE_LOCAL
1312 && req.range != REQ_RANGE_PLAYER
1313 && req.range != REQ_RANGE_TEAM
1314 && req.range != REQ_RANGE_ALLIANCE
1315 && req.range != REQ_RANGE_WORLD)
1316 /* Non local foreign makes no sense. */
1317 || (req.source.value.diplrel == DRO_FOREIGN
1318 && req.range != REQ_RANGE_LOCAL);
1319 break;
1320 case VUT_DIPLREL_TILE:
1321 invalid = (req.range != REQ_RANGE_LOCAL
1322 && req.range != REQ_RANGE_PLAYER
1323 && req.range != REQ_RANGE_TEAM
1324 && req.range != REQ_RANGE_ALLIANCE)
1325 /* Non local foreign makes no sense. */
1326 || (req.source.value.diplrel == DRO_FOREIGN
1327 && req.range != REQ_RANGE_LOCAL);
1328 break;
1329 case VUT_DIPLREL_TILE_O:
1330 invalid = (req.range != REQ_RANGE_LOCAL);
1331 break;
1333 invalid = (req.range != REQ_RANGE_LOCAL
1334 && req.range != REQ_RANGE_PLAYER
1335 && req.range != REQ_RANGE_TEAM
1336 && req.range != REQ_RANGE_ALLIANCE)
1337 /* Non local foreign makes no sense. */
1338 || (req.source.value.diplrel == DRO_FOREIGN
1339 && req.range != REQ_RANGE_LOCAL);
1340 break;
1342 invalid = (req.range != REQ_RANGE_LOCAL);
1343 break;
1344 case VUT_NATION:
1345 case VUT_NATIONGROUP:
1347 && req.range != REQ_RANGE_TEAM
1348 && req.range != REQ_RANGE_ALLIANCE
1349 && req.range != REQ_RANGE_WORLD);
1350 break;
1351 case VUT_MINVETERAN:
1352 case VUT_UNITSTATE:
1353 case VUT_ACTIVITY:
1354 case VUT_MINMOVES:
1355 case VUT_MINHP:
1356 case VUT_ACTION:
1357 case VUT_OTYPE:
1358 case VUT_SPECIALIST:
1359 invalid = (req.range != REQ_RANGE_LOCAL);
1360 break;
1361 case VUT_UTYPE:
1362 case VUT_UTFLAG:
1363 case VUT_UCLASS:
1364 case VUT_UCFLAG:
1365 invalid = (req.range != REQ_RANGE_LOCAL
1366 && req.range != REQ_RANGE_TILE
1367 && req.range != REQ_RANGE_CADJACENT
1368 && req.range != REQ_RANGE_ADJACENT);
1369 break;
1370 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1372 invalid = (req.range != REQ_RANGE_TILE);
1373 break;
1374 case VUT_CITYTILE:
1377 invalid = (req.range != REQ_RANGE_TILE
1378 && req.range != REQ_RANGE_CADJACENT
1379 && req.range != REQ_RANGE_ADJACENT);
1380 break;
1381 case VUT_MINLATITUDE:
1382 case VUT_MAXLATITUDE:
1383 invalid = (req.range != REQ_RANGE_TILE
1384 && req.range != REQ_RANGE_CADJACENT
1385 && req.range != REQ_RANGE_ADJACENT
1386 && req.range != REQ_RANGE_WORLD)
1387 /* Avoid redundancy at tile range: no negated requirements
1388 * that could be emulated by a present requirement of the
1389 * other type */
1390 || (req.range == REQ_RANGE_TILE && !req.present);
1391 break;
1392 case VUT_MINYEAR:
1393 case VUT_MINCALFRAG:
1394 case VUT_TOPO:
1395 case VUT_WRAP:
1396 case VUT_SERVERSETTING:
1397 invalid = (req.range != REQ_RANGE_WORLD);
1398 break;
1399 case VUT_AGE:
1400 /* FIXME: Could support TRADE_ROUTE, TEAM, etc */
1401 invalid = (req.range != REQ_RANGE_LOCAL
1402 && req.range != REQ_RANGE_CITY
1403 && req.range != REQ_RANGE_PLAYER);
1404 break;
1405 case VUT_FORM_AGE:
1406 invalid = (req.range != REQ_RANGE_LOCAL);
1407 break;
1408 case VUT_IMPR_GENUS:
1409 /* TODO: Support other ranges too. */
1410 invalid = (req.range != REQ_RANGE_LOCAL);
1411 break;
1412 case VUT_IMPR_FLAG:
1413 invalid = (req.range != REQ_RANGE_LOCAL
1414 && req.range != REQ_RANGE_TILE
1415 && req.range != REQ_RANGE_CITY);
1416 break;
1417 case VUT_COUNTER:
1418 invalid = req.range != REQ_RANGE_CITY;
1419 break;
1420 case VUT_PLAYER_FLAG:
1421 case VUT_PLAYER_STATE:
1422 invalid = (req.range != REQ_RANGE_PLAYER);
1423 break;
1426 && req.range != REQ_RANGE_CADJACENT
1427 && req.range != REQ_RANGE_ADJACENT);
1428 break;
1429 case VUT_TILE_REL:
1431 && req.range != REQ_RANGE_CADJACENT
1432 && req.range != REQ_RANGE_TILE)
1433 /* TREL_ONLY_OTHER_REGION not supported at Tile range */
1435 && req.range == REQ_RANGE_TILE);
1436 break;
1437 case VUT_IMPROVEMENT:
1438 case VUT_SITE:
1439 /* Valid ranges depend on the building genus (wonder/improvement),
1440 * which might not have been loaded from the ruleset yet.
1441 * So we allow anything here, and do a proper check once ruleset
1442 * loading is complete, in sanity_check_req_individual(). */
1443 case VUT_NONE:
1444 invalid = FALSE;
1445 break;
1446 case VUT_COUNT:
1447 break;
1448 }
1449 if (invalid) {
1450 error = "bad range";
1451 }
1452 }
1453
1454 if (!invalid) {
1455 /* Check 'survives'. */
1456 switch (req.source.kind) {
1457 case VUT_IMPROVEMENT:
1458 case VUT_SITE:
1459 /* See buildings_in_range(). */
1461 break;
1462 case VUT_NATION:
1463 case VUT_ADVANCE:
1465 break;
1466 case VUT_COUNTER:
1467 case VUT_IMPR_GENUS:
1468 case VUT_IMPR_FLAG:
1469 case VUT_PLAYER_FLAG:
1470 case VUT_PLAYER_STATE:
1471 case VUT_GOVERNMENT:
1472 case VUT_GOVFLAG:
1473 case VUT_TERRAIN:
1474 case VUT_UTYPE:
1475 case VUT_UTFLAG:
1476 case VUT_UCLASS:
1477 case VUT_UCFLAG:
1478 case VUT_MINVETERAN:
1479 case VUT_UNITSTATE:
1480 case VUT_ACTIVITY:
1481 case VUT_MINMOVES:
1482 case VUT_MINHP:
1483 case VUT_AGE:
1484 case VUT_FORM_AGE:
1485 case VUT_ACTION:
1486 case VUT_OTYPE:
1487 case VUT_SPECIALIST:
1488 case VUT_MINSIZE:
1489 case VUT_MINCULTURE:
1490 case VUT_MINFOREIGNPCT:
1491 case VUT_AI_LEVEL:
1492 case VUT_TERRAINCLASS:
1493 case VUT_MINYEAR:
1494 case VUT_MINCALFRAG:
1495 case VUT_TOPO:
1496 case VUT_WRAP:
1497 case VUT_SERVERSETTING:
1498 case VUT_TERRAINALTER:
1499 case VUT_CITYTILE:
1500 case VUT_CITYSTATUS:
1501 case VUT_TERRFLAG:
1502 case VUT_NATIONALITY:
1503 case VUT_ORIGINAL_OWNER:
1504 case VUT_ROADFLAG:
1505 case VUT_EXTRAFLAG:
1506 case VUT_EXTRA:
1507 case VUT_TILEDEF:
1508 case VUT_GOOD:
1509 case VUT_TECHFLAG:
1510 case VUT_ACHIEVEMENT:
1511 case VUT_NATIONGROUP:
1512 case VUT_STYLE:
1513 case VUT_DIPLREL:
1514 case VUT_DIPLREL_TILE:
1515 case VUT_DIPLREL_TILE_O:
1520 case VUT_MINTECHS:
1521 case VUT_FUTURETECHS:
1522 case VUT_MINCITIES:
1523 case VUT_MINLATITUDE:
1524 case VUT_MAXLATITUDE:
1527 case VUT_TILE_REL:
1528 /* Most requirements don't support 'survives'. */
1529 invalid = survives;
1530 break;
1531 case VUT_NONE:
1532 case VUT_COUNT:
1533 break;
1534 }
1535 if (invalid) {
1536 error = "bad 'survives'";
1537 }
1538 }
1539
1540 if (invalid) {
1541 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1542 type, range, survives ? "survives" : "",
1543 present ? "present" : "", value, error);
1545 }
1546
1547 return req;
1548}
1549
1550/**********************************************************************/
1556 int value)
1557{
1558 struct requirement req;
1559
1560 req.source = universal_by_number(type, value);
1561 req.range = range;
1562 req.survives = survives;
1563 req.present = present;
1564 req.quiet = quiet;
1565
1566 return req;
1567}
1568
1569/**********************************************************************/
1573void req_get_values(const struct requirement *req,
1574 int *type, int *range,
1575 bool *survives, bool *present, bool *quiet,
1576 int *value)
1577{
1578 universal_extraction(&req->source, type, value);
1579 *range = req->range;
1580 *survives = req->survives;
1581 *present = req->present;
1582 *quiet = req->quiet;
1583}
1584
1585/**********************************************************************/
1588void req_copy(struct requirement *dst, const struct requirement *src)
1589{
1590 universal_copy(&(dst->source), &(src->source));
1591 dst->range = src->range;
1592 dst->survives = src->survives;
1593 dst->present = src->present;
1594 dst->quiet = src->quiet;
1595}
1596
1597/**********************************************************************/
1601bool are_requirements_equal(const struct requirement *req1,
1602 const struct requirement *req2)
1603{
1604 return (are_universals_equal(&req1->source, &req2->source)
1605 && req1->range == req2->range
1606 && req1->survives == req2->survives
1607 && req1->present == req2->present);
1608}
1609
1610/**********************************************************************/
1613static bool are_requirements_opposites(const struct requirement *req1,
1614 const struct requirement *req2)
1615{
1616 return (are_universals_equal(&req1->source, &req2->source)
1617 && req1->range == req2->range
1618 && req1->survives == req2->survives
1619 && req1->present != req2->present);
1620}
1621
1622/**********************************************************************/
1626static bool impr_contra_genus(const struct requirement *impr_req,
1627 const struct requirement *genus_req)
1628{
1629 /* The input is sane. */
1631 || impr_req->source.kind == VUT_SITE, FALSE);
1633
1634 if (impr_req->range == REQ_RANGE_LOCAL
1635 && genus_req->range == REQ_RANGE_LOCAL) {
1636 /* Applies to the same target building. */
1637
1638 if (impr_req->present && !genus_req->present) {
1639 /* The target building can't not have the genus it has. */
1640 return (impr_req->source.value.building->genus
1641 == genus_req->source.value.impr_genus);
1642 }
1643
1644 if (impr_req->present && genus_req->present) {
1645 /* The target building can't have another genus than it has. */
1646 return (impr_req->source.value.building->genus
1647 != genus_req->source.value.impr_genus);
1648 }
1649 }
1650
1651 /* No special knowledge. */
1652 return FALSE;
1653}
1654
1655/**********************************************************************/
1659static bool impr_contra_flag(const struct requirement *impr_req,
1660 const struct requirement *flag_req)
1661{
1662 /* The input is sane. */
1664 || impr_req->source.kind == VUT_SITE, FALSE);
1666
1667 if (impr_req->range == REQ_RANGE_LOCAL
1668 && flag_req->range == REQ_RANGE_LOCAL) {
1669 /* Applies to the same target building. */
1670
1671 if (impr_req->present && !flag_req->present) {
1672 /* The target building can't not have the flag it has. */
1673 return improvement_has_flag(impr_req->source.value.building,
1674 flag_req->source.value.impr_flag);
1675 }
1676
1677 if (impr_req->present && flag_req->present) {
1678 /* The target building can't have another flag than it has. */
1679 return !improvement_has_flag(impr_req->source.value.building,
1680 flag_req->source.value.impr_flag);
1681 }
1682 }
1683
1684 /* No special knowledge. */
1685 return FALSE;
1686}
1687
1688/**********************************************************************/
1693 const struct requirement *group_req)
1694{
1695 /* The input is sane. */
1696 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1698
1699 if (nation_req->range == REQ_RANGE_PLAYER
1700 && group_req->range == REQ_RANGE_PLAYER) {
1701 /* Applies to the same target building. */
1702
1703 if (nation_req->present && !group_req->present) {
1704 /* The target nation can't be in the group. */
1705 return nation_is_in_group(nation_req->source.value.nation,
1706 group_req->source.value.nationgroup);
1707 }
1708 }
1709
1710 /* No special knowledge. */
1711 return FALSE;
1712}
1713
1714/**********************************************************************/
1718static bool city_center_contra(const struct requirement *cc_req,
1719 const struct requirement *ct_req)
1720{
1721 /* The input is sane. */
1722 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1723 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1724
1725 if (cc_req->source.value.citytile == CITYT_CENTER
1726 && cc_req->present && cc_req->range <= ct_req->range) {
1727 switch (ct_req->source.value.citytile) {
1728 case CITYT_CENTER:
1729 case CITYT_CLAIMED:
1730 case CITYT_EXTRAS_OWNED:
1731 case CITYT_WORKED:
1733 /* Should be always on city center */
1734 return !ct_req->present;
1736 /* Handled later */
1737 break;
1738 case CITYT_LAST:
1739 /* Error */
1740 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1741 }
1742 }
1743 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1744 || cc_req->source.value.citytile == CITYT_CENTER)
1745 && ct_req->source.value.citytile
1747 && REQ_RANGE_TILE == cc_req->range
1748 && REQ_RANGE_TILE == ct_req->range) {
1749 /* Can't coexist */
1750 return cc_req->present ? ct_req->present : !ct_req->present;
1751 }
1752
1753 return FALSE;
1754}
1755
1756/**********************************************************************/
1761static bool present_implies_not_present(const struct requirement *req1,
1762 const struct requirement *req2)
1763{
1764 const struct requirement *absent, *present;
1765
1766 if (req1->present == req2->present) {
1767 /* Can't use the knowledge in universal_found_function when both are
1768 * required to be absent or when both are required to be present.
1769 * It is no contradiction to require !Spy unit and !Missile unit class.
1770 * It is no contradiction to require River and Irrigation at the same
1771 * tile. */
1772 return FALSE;
1773 }
1774
1775 if (req1->present) {
1776 absent = req2;
1777 present = req1;
1778 } else {
1779 absent = req1;
1780 present = req2;
1781 }
1782
1783 if (!universal_found_function[present->source.kind]) {
1784 /* No knowledge to exploit. */
1785 return FALSE;
1786 }
1787
1788 if (present->range != absent->range) {
1789 /* Larger ranges are not always strict supersets of smaller ranges.
1790 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1791 * but not in Trade Route. */
1792 return FALSE;
1793 }
1794
1796 &present->source);
1797}
1798
1799/**********************************************************************/
1802bool req_implies_req(const struct requirement *req1,
1803 const struct requirement *req2)
1804{
1805 struct requirement nreq2;
1806
1807 req_copy(&nreq2, req2);
1808 nreq2.present = !nreq2.present;
1810}
1811
1812/**********************************************************************/
1817static inline bool are_bounds_contradictions(int bound1, bool is_upper1,
1818 int bound2, bool is_upper2)
1819{
1820 /* If the bounds are on opposite sides, and one is inclusive, the other
1821 * exclusive, the number of values that satisfy both bounds is exactly
1822 * their difference, (upper bound) - (lower bound).
1823 * The bounds contradict each other iff this difference is 0 or less,
1824 * i.e. iff (upper bound) <= (lower bound) */
1825 if (is_upper1 && !is_upper2) {
1826 return bound1 <= bound2;
1827 } else if (!is_upper1 && is_upper2) {
1828 return bound1 >= bound2;
1829 }
1830 /* Both are upper or both are lower ~> no contradiction possible */
1831 return FALSE;
1832}
1833
1834/**********************************************************************/
1842 const struct requirement *req2)
1843{
1844 if (are_requirements_opposites(req1, req2)) {
1845 /* The exact opposite. */
1846 return TRUE;
1847 }
1848
1849 if (present_implies_not_present(req1, req2)) {
1850 return TRUE;
1851 }
1852
1853 switch (req1->source.kind) {
1854 case VUT_IMPROVEMENT:
1855 case VUT_SITE:
1856 if (req2->source.kind == VUT_IMPR_GENUS) {
1857 return impr_contra_genus(req1, req2);
1858 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1859 return impr_contra_flag(req1, req2);
1860 } else if (req2->source.kind == VUT_CITYTILE
1861 && req2->source.value.citytile == CITYT_CENTER
1862 && REQ_RANGE_TILE == req2->range
1863 && REQ_RANGE_TILE == req1->range
1864 && req1->present) {
1865 /* A building must be in a city */
1866 return !req2->present;
1867 }
1868
1869 /* No special knowledge. */
1870 return FALSE;
1871 case VUT_IMPR_GENUS:
1872 if (req2->source.kind == VUT_IMPROVEMENT
1873 || req2->source.kind == VUT_SITE) {
1874 return impr_contra_genus(req2, req1);
1875 }
1876
1877 /* No special knowledge. */
1878 return FALSE;
1879 case VUT_IMPR_FLAG:
1880 if (req2->source.kind == VUT_IMPROVEMENT
1881 || req2->source.kind == VUT_SITE) {
1882 return impr_contra_flag(req2, req1);
1883 }
1884
1885 /* No special knowledge. */
1886 return FALSE;
1887 case VUT_DIPLREL:
1888 case VUT_DIPLREL_TILE:
1889 case VUT_DIPLREL_TILE_O:
1892 if (req2->source.kind != req1->source.kind) {
1893 /* Finding contradictions across requirement kinds aren't supported
1894 * for DiplRel requirements. */
1895 return FALSE;
1896 } else {
1897 /* Use the special knowledge about DiplRel requirements to find
1898 * contradictions. */
1899
1901 int req2_pos;
1902
1905 req2->range,
1906 req2->present);
1907
1908 return BV_ISSET(req1_contra, req2_pos);
1909 }
1910 break;
1911 case VUT_MINMOVES:
1912 if (req2->source.kind != VUT_MINMOVES) {
1913 /* Finding contradictions across requirement kinds aren't supported
1914 * for MinMoveFrags requirements. */
1915 return FALSE;
1916 }
1918 req1->source.value.minmoves, !req1->present,
1919 req2->source.value.minmoves, !req2->present);
1920 case VUT_MINLATITUDE:
1921 case VUT_MAXLATITUDE:
1922 if (req2->source.kind != VUT_MINLATITUDE
1923 && req2->source.kind != VUT_MAXLATITUDE) {
1924 /* Finding contradictions across requirement kinds other than each
1925 * other is not supported for MinLatitude and MaxLatitude. */
1926 return FALSE;
1927 } else {
1928 /* For a contradiction, we need
1929 * - a minimum (present MinLatitude or negated MaxLatitude)
1930 * - a maximum (negated MinLatitude or present MaxLatitude)
1931 * - the maximum to be less than the minimum
1932 * - a requirement at the larger range that applies to the entire
1933 * range (i.e. a negated requirement, unless the range is Tile)
1934 * Otherwise, the two requirements could still be fulfilled
1935 * simultaneously by different tiles in the range */
1936
1937 /* Initial values beyond the boundaries to avoid edge cases */
1938 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
1940
1941#define EXTRACT_INFO(req) \
1942 if (req->present) { \
1943 if (req->source.kind == VUT_MINLATITUDE) { \
1944 /* present MinLatitude */ \
1945 minimum = MAX(minimum, req->source.value.latitude); \
1946 } else { \
1947 /* present MaxLatitude */ \
1948 maximum = MIN(maximum, req->source.value.latitude); \
1949 } \
1950 } else { \
1951 covered_range = MAX(covered_range, req->range); \
1952 if (req->source.kind == VUT_MINLATITUDE) { \
1953 /* negated MinLatitude */ \
1954 maximum = MIN(maximum, req->source.value.latitude - 1); \
1955 } else { \
1956 /* negated MaxLatitude */ \
1957 minimum = MAX(minimum, req->source.value.latitude + 1); \
1958 } \
1959 }
1960
1961 EXTRACT_INFO(req1);
1962 EXTRACT_INFO(req2);
1963
1964#undef EXTRACT_INFO
1965
1966 return (maximum < minimum
1967 && covered_range >= req1->range
1968 && covered_range >= req2->range);
1969 }
1970 break;
1971 case VUT_NATION:
1972 if (req2->source.kind == VUT_NATIONGROUP) {
1973 return nation_contra_group(req1, req2);
1974 }
1975
1976 /* No special knowledge. */
1977 return FALSE;
1978 break;
1979 case VUT_NATIONGROUP:
1980 if (req2->source.kind == VUT_NATION) {
1981 return nation_contra_group(req2, req1);
1982 }
1983
1984 /* No special knowledge. */
1985 return FALSE;
1986 break;
1987 case VUT_CITYTILE:
1988 if (req2->source.kind == VUT_CITYTILE) {
1989 return city_center_contra(req1, req2)
1990 || city_center_contra(req2, req1);
1991 } else if (req1->source.value.citytile == CITYT_CENTER
1992 && (req2->source.kind == VUT_IMPROVEMENT
1993 || req2->source.kind == VUT_SITE)
1994 && REQ_RANGE_TILE == req2->range
1995 && REQ_RANGE_TILE == req1->range
1996 && req2->present) {
1997 /* A building must be in a city */
1998 return !req1->present;
1999 }
2000
2001 return FALSE;
2003 if (req2->source.kind != VUT_MAX_DISTANCE_SQ) {
2004 /* Finding contradictions across requirement kinds isn't supported
2005 * for MaxDistanceSq requirements. */
2006 return FALSE;
2007 }
2009 req1->source.value.distance_sq, req1->present,
2010 req2->source.value.distance_sq, req2->present);
2012 if (req2->source.kind != VUT_MAX_REGION_TILES) {
2013 /* Finding contradictions across requirement kinds isn't supported
2014 * for MaxRegionTiles requirements. */
2015 return FALSE;
2016 } else if (req1->range != req2->range) {
2017 /* FIXME: Finding contradictions across ranges not yet supported.
2018 * In particular, a max at a small range and a min at a larger range
2019 * needs extra work to figure out. */
2020 return FALSE;
2021 }
2023 req1->source.value.region_tiles, req1->present,
2024 req2->source.value.region_tiles, req2->present);
2025 case VUT_TILE_REL:
2026 if (req2->source.kind != VUT_TILE_REL) {
2027 /* Finding contradictions across requirement kinds isn't supported
2028 * for TileRel requirements. */
2029 return FALSE;
2030 }
2031 if (req1->source.value.tilerel == req2->source.value.tilerel) {
2032 /* Same requirement at different ranges. Note that same range is
2033 * already covered by are_requirements_opposites() above. */
2034 switch (req1->source.value.tilerel) {
2035 case TREL_SAME_TCLASS:
2036 case TREL_SAME_REGION:
2038 /* Negated req at larger range contradicts present req at
2039 * smaller range. */
2040 if (req1->range > req2->range) {
2041 return !req1->present && req2->present;
2042 } else {
2043 return req1->present && !req2->present;
2044 }
2045 break;
2047 /* Present req at larger range contradicts negated req at
2048 * smaller range */
2049 if (req1->range > req2->range) {
2050 return req1->present && !req2->present;
2051 } else {
2052 return !req1->present && req2->present;
2053 }
2054 break;
2055 default:
2056 return FALSE;
2057 }
2058 }
2060 && req2->source.value.tilerel == TREL_SAME_REGION) {
2061 /* Same region at any range implies same terrain class at that range
2062 * and any larger range ~> contradicts negated */
2063 return (!req1->present && req2->present
2064 && (req1->range >= req2->range));
2065 } else if (req2->source.value.tilerel == TREL_SAME_TCLASS
2066 && req1->source.value.tilerel == TREL_SAME_REGION) {
2067 /* Same as above */
2068 return (req1->present && !req2->present
2069 && (req1->range <= req2->range));
2070 } else if (req1->source.value.tilerel == TREL_REGION_SURROUNDED
2072 const struct requirement *surr, *other;
2074 surr = req1;
2075 other = req2;
2076 } else {
2077 surr = req2;
2078 other = req1;
2079 }
2080 if (surr->present && surr->range == REQ_RANGE_TILE) {
2081 /* Target tile must be part of a surrounded region
2082 * ~> not the same terrain class
2083 * ~> not the same region
2084 * ~> not touched by a third region */
2085 switch (other->source.value.tilerel) {
2086 case TREL_SAME_TCLASS:
2087 case TREL_SAME_REGION:
2088 return (other->present && other->range == REQ_RANGE_TILE);
2090 return (!other->present);
2091 default:
2092 break;
2093 }
2094 }
2095 }
2096 /* No further contradictions we can detect */
2097 return FALSE;
2098 default:
2099 /* No special knowledge exists. The requirements aren't the exact
2100 * opposite of each other per the initial check. */
2101 return FALSE;
2102 }
2103}
2104
2105/**********************************************************************/
2113struct requirement *
2115 const struct requirement_vector *vec)
2116{
2117 /* If the requirement is contradicted by any requirement in the vector it
2118 * contradicts the entire requirement vector. */
2121 return preq;
2122 }
2124
2125 /* Not a single requirement in the requirement vector is contradicted to be
2126 * the specified requirement. */
2127 return nullptr;
2128}
2129
2130/**********************************************************************/
2135 const struct requirement_vector *vec)
2136{
2137 return req_vec_first_contradiction_in_vec(req, vec) != nullptr;
2138}
2139
2140/**********************************************************************/
2143static inline bool are_tiles_in_range(const struct tile *tile1,
2144 const struct tile *tile2,
2145 enum req_range range)
2146{
2147 switch (range) {
2148 case REQ_RANGE_ADJACENT:
2150 return TRUE;
2151 }
2153 case REQ_RANGE_TILE:
2154 return same_pos(tile1, tile2);
2156 return map_distance(tile1, tile2) <= 1;
2157 case REQ_RANGE_CITY:
2159 case REQ_RANGE_LOCAL:
2161 case REQ_RANGE_PLAYER:
2162 case REQ_RANGE_TEAM:
2163 case REQ_RANGE_ALLIANCE:
2164 case REQ_RANGE_WORLD:
2165 case REQ_RANGE_COUNT:
2166 /* Invalid */
2168 }
2169 return FALSE;
2170}
2171
2172/**********************************************************************/
2175static inline bool players_in_same_range(const struct player *pplayer1,
2176 const struct player *pplayer2,
2177 enum req_range range)
2178{
2179 switch (range) {
2180 case REQ_RANGE_WORLD:
2181 return TRUE;
2182 case REQ_RANGE_ALLIANCE:
2184 case REQ_RANGE_TEAM:
2186 case REQ_RANGE_PLAYER:
2187 return pplayer1 == pplayer2;
2190 case REQ_RANGE_CITY:
2191 case REQ_RANGE_ADJACENT:
2193 case REQ_RANGE_TILE:
2194 case REQ_RANGE_LOCAL:
2195 case REQ_RANGE_COUNT:
2196 break;
2197 }
2198
2199 fc_assert_msg(FALSE, "Invalid range %d.", range);
2200 return FALSE;
2201}
2202
2203#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
2204{ \
2205 fc_assert_ret_val(req != nullptr, TRI_MAYBE); \
2206 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
2207 fc_assert(context != nullptr); \
2208 fc_assert(other_context != nullptr); \
2209}
2210
2211/**********************************************************************/
2219static enum fc_tristate
2221 const struct req_context *context,
2222 const struct req_context *other_context,
2223 const struct requirement *req)
2224{
2226
2227 return TRI_YES;
2228}
2229
2230/**********************************************************************/
2234static int num_world_buildings_total(const struct impr_type *building)
2235{
2236 if (is_great_wonder(building)) {
2237 return (great_wonder_is_built(building)
2238 || great_wonder_is_destroyed(building) ? 1 : 0);
2239 } else {
2240 log_error("World-ranged requirements are only supported for wonders.");
2241 return 0;
2242 }
2243}
2244
2245/**********************************************************************/
2248static int num_world_buildings(const struct impr_type *building)
2249{
2250 if (is_great_wonder(building)) {
2251 return (great_wonder_is_built(building) ? 1 : 0);
2252 } else {
2253 log_error("World-ranged requirements are only supported for wonders.");
2254 return 0;
2255 }
2256}
2257
2258/**********************************************************************/
2269static bool player_has_ever_built(const struct player *pplayer,
2270 const struct impr_type *building)
2271{
2272 if (is_wonder(building)) {
2273 return (wonder_is_built(pplayer, building)
2274 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2275 } else {
2276 log_error("Player-ranged requirements are only supported for wonders.");
2277 return FALSE;
2278 }
2279}
2280
2281/**********************************************************************/
2284static int num_player_buildings(const struct player *pplayer,
2285 const struct impr_type *building)
2286{
2287 if (is_wonder(building)) {
2288 return (wonder_is_built(pplayer, building) ? 1 : 0);
2289 } else {
2290 log_error("Player-ranged requirements are only supported for wonders.");
2291 return 0;
2292 }
2293}
2294
2295/**********************************************************************/
2298static int num_continent_buildings(const struct player *pplayer,
2299 int continent,
2300 const struct impr_type *building)
2301{
2302 if (is_wonder(building)) {
2303 const struct city *pcity;
2304
2305 pcity = city_from_wonder(pplayer, building);
2306 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2307 return 1;
2308 }
2309 } else {
2310 log_error("Island-ranged requirements are only supported for wonders.");
2311 }
2312 return 0;
2313}
2314
2315/**********************************************************************/
2323static enum fc_tristate
2325 const struct req_context *context,
2326 const struct req_context *other_context,
2327 const struct requirement *req)
2328{
2329 const struct impr_type *building;
2330
2331 /* Can't use this assertion, as both VUT_IMPROVEMENT and VUT_SITE
2332 * are handled here. */
2333 /* IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT); */
2334
2335 building = req->source.value.building;
2336
2337 /* Check if it's certain that the building is obsolete given the
2338 * specification we have */
2339 if (req->source.kind == VUT_IMPROVEMENT
2340 && improvement_obsolete(context->player, building, context->city)) {
2341 return TRI_NO;
2342 }
2343
2344 if (req->survives) {
2345
2346 /* Check whether condition has ever held, using cached information. */
2347 switch (req->range) {
2348 case REQ_RANGE_WORLD:
2349 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2350 case REQ_RANGE_ALLIANCE:
2351 case REQ_RANGE_TEAM:
2352 if (context->player == nullptr) {
2353 return TRI_MAYBE;
2354 }
2355 players_iterate_alive(plr2) {
2356 if (players_in_same_range(context->player, plr2, req->range)
2357 && player_has_ever_built(plr2, building)) {
2358 return TRI_YES;
2359 }
2361 return TRI_NO;
2362 case REQ_RANGE_PLAYER:
2363 if (context->player == nullptr) {
2364 return TRI_MAYBE;
2365 }
2367 building));
2370 case REQ_RANGE_CITY:
2371 case REQ_RANGE_LOCAL:
2372 case REQ_RANGE_TILE:
2374 case REQ_RANGE_ADJACENT:
2375 /* There is no sources cache for this. */
2376 log_error("Surviving requirements are only supported at "
2377 "World/Alliance/Team/Player ranges.");
2378 return TRI_NO;
2379 case REQ_RANGE_COUNT:
2380 break;
2381 }
2382
2383 } else {
2384
2385 /* Non-surviving requirement. */
2386 switch (req->range) {
2387 case REQ_RANGE_WORLD:
2388 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2389 case REQ_RANGE_ALLIANCE:
2390 case REQ_RANGE_TEAM:
2391 if (context->player == nullptr) {
2392 return TRI_MAYBE;
2393 }
2394 players_iterate_alive(plr2) {
2395 if (players_in_same_range(context->player, plr2, req->range)
2396 && num_player_buildings(plr2, building) > 0) {
2397 return TRI_YES;
2398 }
2400 return TRI_NO;
2401 case REQ_RANGE_PLAYER:
2402 if (context->player == nullptr) {
2403 return TRI_MAYBE;
2404 }
2406 building)
2407 > 0);
2409 /* At present, "Continent" effects can affect only
2410 * cities and units in cities. */
2411 if (context->player && context->city) {
2412 int continent = tile_continent(context->city->tile);
2414 continent, building)
2415 > 0);
2416 } else {
2417 return TRI_MAYBE;
2418 }
2420 if (context->city) {
2421 if (city_has_building(context->city, building)) {
2422 return TRI_YES;
2423 } else {
2424 enum fc_tristate ret = TRI_NO;
2425
2427 if (trade_partner == nullptr) {
2428 ret = TRI_MAYBE;
2429 } else if (city_has_building(trade_partner, building)) {
2430 return TRI_YES;
2431 }
2433
2434 return ret;
2435 }
2436 } else {
2437 return TRI_MAYBE;
2438 }
2439 case REQ_RANGE_CITY:
2440 if (context->city) {
2441 return BOOL_TO_TRISTATE(city_has_building(context->city, building));
2442 } else {
2443 return TRI_MAYBE;
2444 }
2445 case REQ_RANGE_LOCAL:
2446 if (context->building) {
2447 if (context->building == building) {
2448 return TRI_YES;
2449 } else {
2450 return TRI_NO;
2451 }
2452 } else {
2453 /* TODO: Other local targets */
2454 return TRI_MAYBE;
2455 }
2456 case REQ_RANGE_TILE:
2457 if (context->tile) {
2458 const struct city *pcity = tile_city(context->tile);
2459
2460 if (pcity) {
2461 return BOOL_TO_TRISTATE(city_has_building(pcity, building));
2462 } else {
2463 return TRI_NO;
2464 }
2465 } else {
2466 return TRI_MAYBE;
2467 }
2469 case REQ_RANGE_ADJACENT:
2470 case REQ_RANGE_COUNT:
2471 break;
2472 }
2473
2474 }
2475
2476 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2477 return TRI_NO;
2478}
2479
2480/**********************************************************************/
2488static enum fc_tristate
2490 const struct req_context *context,
2491 const struct req_context *other_context,
2492 const struct requirement *req)
2493{
2495
2496 return (context->building ? BOOL_TO_TRISTATE(
2497 context->building->genus
2498 == req->source.value.impr_genus)
2499 : TRI_MAYBE);
2500}
2501
2502/**********************************************************************/
2506 enum impr_flag_id flag)
2507{
2508 struct player *owner;
2509
2510 if (pcity == nullptr) {
2511 return TRI_MAYBE;
2512 }
2513
2515 city_built_iterate(pcity, impr) {
2516 if (improvement_has_flag(impr, flag)
2517 && !improvement_obsolete(owner, impr, pcity)) {
2518 return TRI_YES;
2519 }
2521
2522 return TRI_NO;
2523}
2524
2525/**********************************************************************/
2533static enum fc_tristate
2535 const struct req_context *context,
2536 const struct req_context *other_context,
2537 const struct requirement *req)
2538{
2540
2541 switch (req->range) {
2542 case REQ_RANGE_LOCAL:
2543 return (context->building
2545 req->source.value.impr_flag))
2546 : TRI_MAYBE);
2547 case REQ_RANGE_CITY:
2549 case REQ_RANGE_TILE:
2550 if (context->tile == nullptr) {
2551 return TRI_MAYBE;
2552 }
2554 req->source.value.impr_flag);
2556 case REQ_RANGE_ADJACENT:
2559 case REQ_RANGE_PLAYER:
2560 case REQ_RANGE_ALLIANCE:
2561 case REQ_RANGE_TEAM:
2562 case REQ_RANGE_WORLD:
2563 case REQ_RANGE_COUNT:
2564 break;
2565 }
2566
2567 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2568
2569 return TRI_MAYBE;
2570}
2571
2572/**********************************************************************/
2580static enum fc_tristate
2582 const struct req_context *context,
2583 const struct req_context *other_context,
2584 const struct requirement *req)
2585{
2587
2588 switch (req->range) {
2589 case REQ_RANGE_PLAYER:
2590 return (context->player != nullptr
2592 req->source.value.plr_flag))
2593 : TRI_MAYBE);
2594 case REQ_RANGE_LOCAL:
2595 case REQ_RANGE_CITY:
2596 case REQ_RANGE_TILE:
2598 case REQ_RANGE_ADJACENT:
2601 case REQ_RANGE_ALLIANCE:
2602 case REQ_RANGE_TEAM:
2603 case REQ_RANGE_WORLD:
2604 case REQ_RANGE_COUNT:
2605 break;
2606 }
2607
2608 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2609
2610 return TRI_MAYBE;
2611}
2612
2613/**********************************************************************/
2621static enum fc_tristate
2623 const struct req_context *context,
2624 const struct req_context *other_context,
2625 const struct requirement *req)
2626{
2628
2629 switch (req->range) {
2630 case REQ_RANGE_PLAYER:
2631 return (context->player != nullptr
2633 req->source.value.plrstate))
2634 : TRI_MAYBE);
2635 case REQ_RANGE_LOCAL:
2636 case REQ_RANGE_CITY:
2637 case REQ_RANGE_TILE:
2639 case REQ_RANGE_ADJACENT:
2642 case REQ_RANGE_ALLIANCE:
2643 case REQ_RANGE_TEAM:
2644 case REQ_RANGE_WORLD:
2645 case REQ_RANGE_COUNT:
2646 break;
2647 }
2648
2649 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2650
2651 return TRI_MAYBE;
2652}
2653
2654/**********************************************************************/
2662static enum fc_tristate
2664 const struct req_context *context,
2665 const struct req_context *other_context,
2666 const struct requirement *req)
2667{
2668 Tech_type_id tech;
2669
2671
2672 tech = advance_number(req->source.value.advance);
2673
2674 if (req->survives) {
2677 }
2678
2679 /* Not a 'surviving' requirement. */
2680 switch (req->range) {
2681 case REQ_RANGE_PLAYER:
2682 if (context->player != nullptr) {
2684 (research_get(context->player), tech));
2685 } else {
2686 return TRI_MAYBE;
2687 }
2688 case REQ_RANGE_TEAM:
2689 case REQ_RANGE_ALLIANCE:
2690 case REQ_RANGE_WORLD:
2691 if (context->player == nullptr) {
2692 return TRI_MAYBE;
2693 }
2694 players_iterate_alive(plr2) {
2695 if (players_in_same_range(context->player, plr2, req->range)) {
2696 if (research_invention_state(research_get(plr2), tech)
2697 == TECH_KNOWN) {
2698 return TRI_YES;
2699 }
2700 }
2702
2703 return TRI_NO;
2704 case REQ_RANGE_LOCAL:
2705 if (context->player == nullptr) {
2706 return TRI_MAYBE;
2707 }
2708 if (research_get(context->player)->researching == tech) {
2709 return TRI_YES;
2710 }
2711 return TRI_NO;
2712 case REQ_RANGE_TILE:
2714 case REQ_RANGE_ADJACENT:
2715 case REQ_RANGE_CITY:
2718 case REQ_RANGE_COUNT:
2719 break;
2720 }
2721
2722 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2723
2724 return TRI_MAYBE;
2725}
2726
2727/**********************************************************************/
2735static enum fc_tristate
2737 const struct req_context *context,
2738 const struct req_context *other_context,
2739 const struct requirement *req)
2740{
2741 enum tech_flag_id techflag;
2742
2744
2745 techflag = req->source.value.techflag;
2746
2747 switch (req->range) {
2748 case REQ_RANGE_PLAYER:
2749 if (context->player != nullptr) {
2751 techflag));
2752 } else {
2753 return TRI_MAYBE;
2754 }
2755 break;
2756 case REQ_RANGE_TEAM:
2757 case REQ_RANGE_ALLIANCE:
2758 if (context->player == nullptr) {
2759 return TRI_MAYBE;
2760 }
2761 players_iterate_alive(plr2) {
2762 if (players_in_same_range(context->player, plr2, req->range)
2763 && player_knows_techs_with_flag(plr2, techflag)) {
2764 return TRI_YES;
2765 }
2767 return TRI_NO;
2768 case REQ_RANGE_WORLD:
2769 players_iterate(pplayer) {
2770 if (player_knows_techs_with_flag(pplayer, techflag)) {
2771 return TRI_YES;
2772 }
2774
2775 return TRI_NO;
2776 case REQ_RANGE_LOCAL:
2777 if (context->player == nullptr) {
2778 return TRI_MAYBE;
2779 }
2780 if (advance_has_flag(research_get(context->player)->researching, techflag)) {
2781 return TRI_YES;
2782 }
2783 return TRI_NO;
2784 case REQ_RANGE_TILE:
2786 case REQ_RANGE_ADJACENT:
2787 case REQ_RANGE_CITY:
2790 case REQ_RANGE_COUNT:
2791 break;
2792 }
2793
2794 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2795
2796 return TRI_MAYBE;
2797}
2798
2799/**********************************************************************/
2807static enum fc_tristate
2809 const struct req_context *context,
2810 const struct req_context *other_context,
2811 const struct requirement *req)
2812{
2813 int minculture;
2814
2816
2817 minculture = req->source.value.minculture;
2818
2819 switch (req->range) {
2820 case REQ_RANGE_CITY:
2821 if (!context->city) {
2822 return TRI_MAYBE;
2823 }
2824 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2826 if (!context->city) {
2827 return TRI_MAYBE;
2828 }
2829 if (city_culture(context->city) >= minculture) {
2830 return TRI_YES;
2831 } else {
2832 enum fc_tristate ret = TRI_NO;
2833
2835 if (trade_partner == nullptr) {
2836 ret = TRI_MAYBE;
2837 } else if (city_culture(trade_partner) >= minculture) {
2838 return TRI_YES;
2839 }
2841
2842 return ret;
2843 }
2844 case REQ_RANGE_PLAYER:
2845 case REQ_RANGE_TEAM:
2846 case REQ_RANGE_ALLIANCE:
2847 case REQ_RANGE_WORLD:
2848 if (context->player == nullptr) {
2849 return TRI_MAYBE;
2850 }
2851 players_iterate_alive(plr2) {
2852 if (players_in_same_range(context->player, plr2, req->range)) {
2853 if (player_culture(plr2) >= minculture) {
2854 return TRI_YES;
2855 }
2856 }
2858 return TRI_NO;
2859 case REQ_RANGE_LOCAL:
2860 case REQ_RANGE_TILE:
2862 case REQ_RANGE_ADJACENT:
2864 case REQ_RANGE_COUNT:
2865 break;
2866 }
2867
2868 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2869
2870 return TRI_MAYBE;
2871}
2872
2873/**********************************************************************/
2881static enum fc_tristate
2883 const struct req_context *context,
2884 const struct req_context *other_context,
2885 const struct requirement *req)
2886{
2888
2890
2892
2893 switch (req->range) {
2894 case REQ_RANGE_CITY:
2895 if (!context->city) {
2896 return TRI_MAYBE;
2897 }
2899 / city_size_get(context->city);
2902 if (!context->city) {
2903 return TRI_MAYBE;
2904 }
2906 / city_size_get(context->city);
2908 return TRI_YES;
2909 } else {
2910 enum fc_tristate ret = TRI_NO;
2911
2913 if (trade_partner == nullptr) {
2914 ret = TRI_MAYBE;
2915 } else {
2919 return TRI_YES;
2920 }
2921 }
2923
2924 return ret;
2925 }
2926 case REQ_RANGE_PLAYER:
2927 case REQ_RANGE_TEAM:
2928 case REQ_RANGE_ALLIANCE:
2929 case REQ_RANGE_WORLD:
2930 case REQ_RANGE_LOCAL:
2931 case REQ_RANGE_TILE:
2933 case REQ_RANGE_ADJACENT:
2935 case REQ_RANGE_COUNT:
2936 break;
2937 }
2938
2939 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2940
2941 return TRI_MAYBE;
2942}
2943
2944/**********************************************************************/
2952static enum fc_tristate
2954 const struct req_context *context,
2955 const struct req_context *other_context,
2956 const struct requirement *req)
2957{
2958 int max_units;
2959
2961
2963
2964 /* TODO: If can't see V_INVIS -> TRI_MAYBE */
2965 switch (req->range) {
2966 case REQ_RANGE_TILE:
2967 if (!context->tile) {
2968 return TRI_MAYBE;
2969 }
2970 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
2972 if (!context->tile) {
2973 return TRI_MAYBE;
2974 }
2975 if (unit_list_size(context->tile->units) <= max_units) {
2976 return TRI_YES;
2977 }
2979 if (unit_list_size(adjc_tile->units) <= max_units) {
2980 return TRI_YES;
2981 }
2983 return TRI_NO;
2984 case REQ_RANGE_ADJACENT:
2985 if (!context->tile) {
2986 return TRI_MAYBE;
2987 }
2988 if (unit_list_size(context->tile->units) <= max_units) {
2989 return TRI_YES;
2990 }
2992 if (unit_list_size(adjc_tile->units) <= max_units) {
2993 return TRI_YES;
2994 }
2996 return TRI_NO;
2997 case REQ_RANGE_CITY:
3000 case REQ_RANGE_PLAYER:
3001 case REQ_RANGE_TEAM:
3002 case REQ_RANGE_ALLIANCE:
3003 case REQ_RANGE_WORLD:
3004 case REQ_RANGE_LOCAL:
3005 case REQ_RANGE_COUNT:
3006 break;
3007 }
3008
3009 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3010
3011 return TRI_MAYBE;
3012}
3013
3014
3015/**********************************************************************/
3023static enum fc_tristate
3025 const struct req_context *context,
3026 const struct req_context *other_context,
3027 const struct requirement *req)
3028{
3029 int max_units;
3030 int count;
3031
3033
3035
3036 /* TODO: If can't see V_INVIS -> TRI_MAYBE */
3037 switch (req->range) {
3038 case REQ_RANGE_TILE:
3039 if (!context->tile) {
3040 return TRI_MAYBE;
3041 }
3042 count = 0;
3043 unit_list_iterate(context->tile->units, punit) {
3044 if (!unit_transported(punit)) {
3045 count++;
3046 }
3048 return BOOL_TO_TRISTATE(count <= max_units);
3050 if (!context->tile) {
3051 return TRI_MAYBE;
3052 }
3053 count = 0;
3054 unit_list_iterate(context->tile->units, punit) {
3055 if (!unit_transported(punit)) {
3056 count++;
3057 }
3059 if (count <= max_units) {
3060 return TRI_YES;
3061 }
3063 count = 0;
3065 if (!unit_transported(punit)) {
3066 count++;
3067 }
3069 if (count <= max_units) {
3070 return TRI_YES;
3071 }
3073
3074 return TRI_NO;
3075 case REQ_RANGE_ADJACENT:
3076 if (!context->tile) {
3077 return TRI_MAYBE;
3078 }
3079 count = 0;
3080 unit_list_iterate(context->tile->units, punit) {
3081 if (!unit_transported(punit)) {
3082 count++;
3083 }
3085 if (count <= max_units) {
3086 return TRI_YES;
3087 }
3089 count = 0;
3091 if (!unit_transported(punit)) {
3092 count++;
3093 }
3095 if (count <= max_units) {
3096 return TRI_YES;
3097 }
3099 return TRI_NO;
3100 case REQ_RANGE_CITY:
3103 case REQ_RANGE_PLAYER:
3104 case REQ_RANGE_TEAM:
3105 case REQ_RANGE_ALLIANCE:
3106 case REQ_RANGE_WORLD:
3107 case REQ_RANGE_LOCAL:
3108 case REQ_RANGE_COUNT:
3109 break;
3110 }
3111
3112 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3113
3114 return TRI_MAYBE;
3115}
3116
3117/**********************************************************************/
3125static enum fc_tristate
3127 const struct req_context *context,
3128 const struct req_context *other_context,
3129 const struct requirement *req)
3130{
3131 const struct extra_type *pextra;
3132 enum fc_tristate ret;
3133
3135
3136 pextra = req->source.value.extra;
3137
3138 switch (req->range) {
3139 case REQ_RANGE_LOCAL:
3140 if (!context->extra) {
3141 return TRI_MAYBE;
3142 }
3143 return BOOL_TO_TRISTATE(context->extra == pextra);
3144 case REQ_RANGE_TILE:
3145 /* The requirement is filled if the tile has extra of requested type. */
3146 if (!context->tile) {
3147 return TRI_MAYBE;
3148 }
3149 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
3151 if (!context->tile) {
3152 return TRI_MAYBE;
3153 }
3154 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
3155 || is_extra_card_near(nmap, context->tile, pextra));
3156 case REQ_RANGE_ADJACENT:
3157 if (!context->tile) {
3158 return TRI_MAYBE;
3159 }
3160 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
3161 || is_extra_near_tile(nmap, context->tile, pextra));
3162 case REQ_RANGE_CITY:
3163 if (!context->city) {
3164 return TRI_MAYBE;
3165 }
3167 city_tile(context->city), ptile) {
3168 if (tile_has_extra(ptile, pextra)) {
3169 return TRI_YES;
3170 }
3172
3173 return TRI_NO;
3174
3176 if (!context->city) {
3177 return TRI_MAYBE;
3178 }
3180 city_tile(context->city), ptile) {
3181 if (tile_has_extra(ptile, pextra)) {
3182 return TRI_YES;
3183 }
3185
3186 ret = TRI_NO;
3188 if (trade_partner == nullptr) {
3189 ret = TRI_MAYBE;
3190 } else {
3192 city_tile(trade_partner), ptile) {
3193 if (tile_has_extra(ptile, pextra)) {
3194 return TRI_YES;
3195 }
3197 }
3199
3200 return ret;
3201
3203 case REQ_RANGE_PLAYER:
3204 case REQ_RANGE_TEAM:
3205 case REQ_RANGE_ALLIANCE:
3206 case REQ_RANGE_WORLD:
3207 case REQ_RANGE_COUNT:
3208 break;
3209 }
3210
3211 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3212
3213 return TRI_MAYBE;
3214}
3215
3216/**********************************************************************/
3224static enum fc_tristate
3226 const struct req_context *context,
3227 const struct req_context *other_context,
3228 const struct requirement *req)
3229{
3230 const struct tiledef *ptdef;
3231 enum fc_tristate ret;
3232
3234
3235 ptdef = req->source.value.tiledef;
3236
3237 switch (req->range) {
3238 case REQ_RANGE_TILE:
3239 /* The requirement is filled if the tile has tiledef of requested type. */
3240 if (!context->tile) {
3241 return TRI_MAYBE;
3242 }
3245 if (!context->tile) {
3246 return TRI_MAYBE;
3247 }
3250 case REQ_RANGE_ADJACENT:
3251 if (!context->tile) {
3252 return TRI_MAYBE;
3253 }
3256 case REQ_RANGE_CITY:
3257 if (!context->city) {
3258 return TRI_MAYBE;
3259 }
3261 city_tile(context->city), ptile) {
3262 if (tile_matches_tiledef(ptdef, ptile)) {
3263 return TRI_YES;
3264 }
3266
3267 return TRI_NO;
3268
3270 if (!context->city) {
3271 return TRI_MAYBE;
3272 }
3274 city_tile(context->city), ptile) {
3275 if (tile_matches_tiledef(ptdef, ptile)) {
3276 return TRI_YES;
3277 }
3279
3280 ret = TRI_NO;
3282 if (trade_partner == nullptr) {
3283 ret = TRI_MAYBE;
3284 } else {
3286 city_tile(trade_partner), ptile) {
3287 if (tile_matches_tiledef(ptdef, ptile)) {
3288 return TRI_YES;
3289 }
3291 }
3293
3294 return ret;
3295
3296 case REQ_RANGE_LOCAL:
3298 case REQ_RANGE_PLAYER:
3299 case REQ_RANGE_TEAM:
3300 case REQ_RANGE_ALLIANCE:
3301 case REQ_RANGE_WORLD:
3302 case REQ_RANGE_COUNT:
3303 break;
3304 }
3305
3306 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3307
3308 return TRI_MAYBE;
3309}
3310
3311/**********************************************************************/
3319static enum fc_tristate
3321 const struct req_context *context,
3322 const struct req_context *other_context,
3323 const struct requirement *req)
3324{
3325 const struct goods_type *pgood;
3326
3328
3329 pgood = req->source.value.good;
3330
3331 switch (req->range) {
3332 case REQ_RANGE_LOCAL:
3333 case REQ_RANGE_CITY:
3334 /* The requirement is filled if the city imports good of requested type. */
3335 if (!context->city) {
3336 return TRI_MAYBE;
3337 }
3341 nullptr)));
3342 case REQ_RANGE_TILE:
3344 case REQ_RANGE_ADJACENT:
3347 case REQ_RANGE_PLAYER:
3348 case REQ_RANGE_TEAM:
3349 case REQ_RANGE_ALLIANCE:
3350 case REQ_RANGE_WORLD:
3351 case REQ_RANGE_COUNT:
3352 break;
3353 }
3354
3355 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3356
3357 return TRI_MAYBE;
3358}
3359
3360/**********************************************************************/
3368static enum fc_tristate
3370 const struct req_context *context,
3371 const struct req_context *other_context,
3372 const struct requirement *req)
3373{
3375
3376 if (context->action) {
3377 return BOOL_TO_TRISTATE(action_number(context->action)
3378 == action_number(req->source.value.action));
3379 }
3380
3381 if (context->unit != nullptr && context->unit->action != ACTION_NONE) {
3382 log_normal("Unit action %s", action_id_rule_name(context->unit->action));
3383 return BOOL_TO_TRISTATE(context->unit->action
3384 == action_number(req->source.value.action));
3385 }
3386
3387 return TRI_NO;
3388}
3389
3390/**********************************************************************/
3398static enum fc_tristate
3400 const struct req_context *context,
3401 const struct req_context *other_context,
3402 const struct requirement *req)
3403{
3405
3406 return BOOL_TO_TRISTATE(context->output
3407 && context->output->index
3408 == req->source.value.outputtype);
3409}
3410
3411/**********************************************************************/
3419static enum fc_tristate
3421 const struct req_context *context,
3422 const struct req_context *other_context,
3423 const struct requirement *req)
3424{
3426
3427 return BOOL_TO_TRISTATE(context->specialist
3428 && context->specialist
3429 == req->source.value.specialist);
3430}
3431
3432/**********************************************************************/
3440static enum fc_tristate
3442 const struct req_context *context,
3443 const struct req_context *other_context,
3444 const struct requirement *req)
3445{
3446 const struct terrain *pterrain;
3447
3449
3450 pterrain = req->source.value.terrain;
3451
3452 switch (req->range) {
3453 case REQ_RANGE_TILE:
3454 /* The requirement is filled if the tile has the terrain. */
3455 if (!context->tile) {
3456 return TRI_MAYBE;
3457 }
3458 return pterrain && tile_terrain(context->tile) == pterrain;
3460 if (!context->tile) {
3461 return TRI_MAYBE;
3462 }
3463 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
3464 case REQ_RANGE_ADJACENT:
3465 if (!context->tile) {
3466 return TRI_MAYBE;
3467 }
3468 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
3469 case REQ_RANGE_CITY:
3470 if (!context->city) {
3471 return TRI_MAYBE;
3472 }
3473 if (pterrain != nullptr) {
3475 city_tile(context->city), ptile) {
3476 if (tile_terrain(ptile) == pterrain) {
3477 return TRI_YES;
3478 }
3480 }
3481 return TRI_NO;
3483 if (!context->city) {
3484 return TRI_MAYBE;
3485 }
3486 if (pterrain != nullptr) {
3487 enum fc_tristate ret;
3488
3490 city_tile(context->city), ptile) {
3491 if (tile_terrain(ptile) == pterrain) {
3492 return TRI_YES;
3493 }
3495
3496 ret = TRI_NO;
3498 if (trade_partner == nullptr) {
3499 ret = TRI_MAYBE;
3500 } else {
3502 city_tile(trade_partner), ptile) {
3503 if (tile_terrain(ptile) == pterrain) {
3504 return TRI_YES;
3505 }
3507 }
3509
3510 return ret;
3511 }
3512
3513 return TRI_MAYBE;
3515 case REQ_RANGE_PLAYER:
3516 case REQ_RANGE_TEAM:
3517 case REQ_RANGE_ALLIANCE:
3518 case REQ_RANGE_WORLD:
3519 case REQ_RANGE_LOCAL:
3520 case REQ_RANGE_COUNT:
3521 break;
3522 }
3523
3524 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3525
3526 return TRI_MAYBE;
3527}
3528
3529/**********************************************************************/
3537static enum fc_tristate
3539 const struct req_context *context,
3540 const struct req_context *other_context,
3541 const struct requirement *req)
3542{
3543 enum terrain_class pclass;
3544 enum fc_tristate ret;
3545
3547
3549
3550 switch (req->range) {
3551 case REQ_RANGE_TILE:
3552 /* The requirement is filled if the tile has the terrain of correct class. */
3553 if (!context->tile) {
3554 return TRI_MAYBE;
3555 }
3558 if (!context->tile) {
3559 return TRI_MAYBE;
3560 }
3563 case REQ_RANGE_ADJACENT:
3564 if (!context->tile) {
3565 return TRI_MAYBE;
3566 }
3569 case REQ_RANGE_CITY:
3570 if (!context->city) {
3571 return TRI_MAYBE;
3572 }
3574 city_tile(context->city), ptile) {
3575 const struct terrain *pterrain = tile_terrain(ptile);
3576
3577 if (pterrain != T_UNKNOWN
3578 && terrain_type_terrain_class(pterrain) == pclass) {
3579 return TRI_YES;
3580 }
3582
3583 return TRI_NO;
3585 if (!context->city) {
3586 return TRI_MAYBE;
3587 }
3589 city_tile(context->city), ptile) {
3590 const struct terrain *pterrain = tile_terrain(ptile);
3591
3592 if (pterrain != T_UNKNOWN
3593 && terrain_type_terrain_class(pterrain) == pclass) {
3594 return TRI_YES;
3595 }
3597
3598 ret = TRI_NO;
3600 if (trade_partner == nullptr) {
3601 ret = TRI_MAYBE;
3602 } else {
3604 city_tile(trade_partner), ptile) {
3605 const struct terrain *pterrain = tile_terrain(ptile);
3606
3607 if (pterrain != T_UNKNOWN
3608 && terrain_type_terrain_class(pterrain) == pclass) {
3609 return TRI_YES;
3610 }
3612 }
3614
3615 return ret;
3617 case REQ_RANGE_PLAYER:
3618 case REQ_RANGE_TEAM:
3619 case REQ_RANGE_ALLIANCE:
3620 case REQ_RANGE_WORLD:
3621 case REQ_RANGE_LOCAL:
3622 case REQ_RANGE_COUNT:
3623 break;
3624 }
3625
3626 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3627
3628 return TRI_MAYBE;
3629}
3630
3631/**********************************************************************/
3639static enum fc_tristate
3641 const struct req_context *context,
3642 const struct req_context *other_context,
3643 const struct requirement *req)
3644{
3646 enum fc_tristate ret;
3647
3649
3651
3652 switch (req->range) {
3653 case REQ_RANGE_TILE:
3654 /* The requirement is fulfilled if the tile has a terrain with
3655 * correct flag. */
3656 if (!context->tile) {
3657 return TRI_MAYBE;
3658 }
3660 terrflag));
3662 if (!context->tile) {
3663 return TRI_MAYBE;
3664 }
3666 terrflag)
3668 terrflag));
3669 case REQ_RANGE_ADJACENT:
3670 if (!context->tile) {
3671 return TRI_MAYBE;
3672 }
3674 terrflag)
3676 terrflag));
3677 case REQ_RANGE_CITY:
3678 if (!context->city) {
3679 return TRI_MAYBE;
3680 }
3682 city_tile(context->city), ptile) {
3683 const struct terrain *pterrain = tile_terrain(ptile);
3684
3685 if (pterrain != T_UNKNOWN
3686 && terrain_has_flag(pterrain, terrflag)) {
3687 return TRI_YES;
3688 }
3690
3691 return TRI_NO;
3693 if (!context->city) {
3694 return TRI_MAYBE;
3695 }
3697 city_tile(context->city), ptile) {
3698 const struct terrain *pterrain = tile_terrain(ptile);
3699
3700 if (pterrain != T_UNKNOWN
3701 && terrain_has_flag(pterrain, terrflag)) {
3702 return TRI_YES;
3703 }
3705
3706 ret = TRI_NO;
3708 if (trade_partner == nullptr) {
3709 ret = TRI_MAYBE;
3710 } else {
3712 city_tile(trade_partner), ptile) {
3713 const struct terrain *pterrain = tile_terrain(ptile);
3714
3715 if (pterrain != T_UNKNOWN
3716 && terrain_has_flag(pterrain, terrflag)) {
3717 return TRI_YES;
3718 }
3720 }
3722
3723 return ret;
3725 case REQ_RANGE_PLAYER:
3726 case REQ_RANGE_TEAM:
3727 case REQ_RANGE_ALLIANCE:
3728 case REQ_RANGE_WORLD:
3729 case REQ_RANGE_LOCAL:
3730 case REQ_RANGE_COUNT:
3731 break;
3732 }
3733
3734 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3735
3736 return TRI_MAYBE;
3737}
3738
3739/**********************************************************************/
3747static enum fc_tristate
3749 const struct req_context *context,
3750 const struct req_context *other_context,
3751 const struct requirement *req)
3752{
3753 enum road_flag_id roadflag;
3754 enum fc_tristate ret;
3755
3757
3758 roadflag = req->source.value.roadflag;
3759
3760 switch (req->range) {
3761 case REQ_RANGE_LOCAL:
3762 {
3763 if (!context->extra) {
3764 return TRI_MAYBE;
3765 }
3766 struct road_type *r = extra_road_get(context->extra);
3767
3768 return BOOL_TO_TRISTATE(
3769 r && road_has_flag(r, roadflag)
3770 );
3771 }
3772 case REQ_RANGE_TILE:
3773 /* The requirement is filled if the tile has a road with correct flag. */
3774 if (!context->tile) {
3775 return TRI_MAYBE;
3776 }
3777 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3779 if (!context->tile) {
3780 return TRI_MAYBE;
3781 }
3782 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3784 roadflag));
3785 case REQ_RANGE_ADJACENT:
3786 if (!context->tile) {
3787 return TRI_MAYBE;
3788 }
3789 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3791 roadflag));
3792 case REQ_RANGE_CITY:
3793 if (!context->city) {
3794 return TRI_MAYBE;
3795 }
3797 city_tile(context->city), ptile) {
3798 if (tile_has_road_flag(ptile, roadflag)) {
3799 return TRI_YES;
3800 }
3802
3803 return TRI_NO;
3805 if (!context->city) {
3806 return TRI_MAYBE;
3807 }
3809 city_tile(context->city), ptile) {
3810 if (tile_has_road_flag(ptile, roadflag)) {
3811 return TRI_YES;
3812 }
3814
3815 ret = TRI_NO;
3817 if (trade_partner == nullptr) {
3818 ret = TRI_MAYBE;
3819 } else {
3821 city_tile(trade_partner), ptile) {
3822 if (tile_has_road_flag(ptile, roadflag)) {
3823 return TRI_YES;
3824 }
3826 }
3828
3829 return ret;
3831 case REQ_RANGE_PLAYER:
3832 case REQ_RANGE_TEAM:
3833 case REQ_RANGE_ALLIANCE:
3834 case REQ_RANGE_WORLD:
3835 case REQ_RANGE_COUNT:
3836 break;
3837 }
3838
3839 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3840
3841 return TRI_MAYBE;
3842}
3843
3844/**********************************************************************/
3852static enum fc_tristate
3854 const struct req_context *context,
3855 const struct req_context *other_context,
3856 const struct requirement *req)
3857{
3858 enum extra_flag_id extraflag;
3859 enum fc_tristate ret;
3860
3862
3863 extraflag = req->source.value.extraflag;
3864
3865 switch (req->range) {
3866 case REQ_RANGE_LOCAL:
3867 if (!context->extra) {
3868 return TRI_MAYBE;
3869 }
3870 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3871 case REQ_RANGE_TILE:
3872 /* The requirement is filled if the tile has an extra with correct flag. */
3873 if (!context->tile) {
3874 return TRI_MAYBE;
3875 }
3876 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3878 if (!context->tile) {
3879 return TRI_MAYBE;
3880 }
3881 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3882 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3883 case REQ_RANGE_ADJACENT:
3884 if (!context->tile) {
3885 return TRI_MAYBE;
3886 }
3887 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3888 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3889 case REQ_RANGE_CITY:
3890 if (!context->city) {
3891 return TRI_MAYBE;
3892 }
3894 city_tile(context->city), ptile) {
3895 if (tile_has_extra_flag(ptile, extraflag)) {
3896 return TRI_YES;
3897 }
3899
3900 return TRI_NO;
3902 if (!context->city) {
3903 return TRI_MAYBE;
3904 }
3906 city_tile(context->city), ptile) {
3907 if (tile_has_extra_flag(ptile, extraflag)) {
3908 return TRI_YES;
3909 }
3911
3912 ret = TRI_NO;
3914 if (trade_partner == nullptr) {
3915 ret = TRI_MAYBE;
3916 } else {
3918 city_tile(trade_partner), ptile) {
3919 if (tile_has_extra_flag(ptile, extraflag)) {
3920 return TRI_YES;
3921 }
3923 }
3925
3926 return ret;
3928 case REQ_RANGE_PLAYER:
3929 case REQ_RANGE_TEAM:
3930 case REQ_RANGE_ALLIANCE:
3931 case REQ_RANGE_WORLD:
3932 case REQ_RANGE_COUNT:
3933 break;
3934 }
3935
3936 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3937
3938 return TRI_MAYBE;
3939}
3940
3941/**********************************************************************/
3949static enum fc_tristate
3951 const struct req_context *context,
3952 const struct req_context *other_context,
3953 const struct requirement *req)
3954{
3956
3958
3960
3961 if (!context->tile) {
3962 return TRI_MAYBE;
3963 }
3964
3965 switch (req->range) {
3966 case REQ_RANGE_TILE:
3970 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
3971 case REQ_RANGE_CITY:
3974 case REQ_RANGE_PLAYER:
3975 case REQ_RANGE_TEAM:
3976 case REQ_RANGE_ALLIANCE:
3977 case REQ_RANGE_WORLD:
3978 case REQ_RANGE_LOCAL:
3979 case REQ_RANGE_COUNT:
3980 break;
3981 }
3982
3983 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3984
3985 return TRI_MAYBE;
3986}
3987
3988/**********************************************************************/
3996static enum fc_tristate
3998 const struct req_context *context,
3999 const struct req_context *other_context,
4000 const struct requirement *req)
4001{
4003
4004 if (context->player == nullptr) {
4005 return TRI_MAYBE;
4006 } else {
4008 == req->source.value.govern);
4009 }
4010}
4011
4012/**********************************************************************/
4020static enum fc_tristate
4022 const struct req_context *context,
4023 const struct req_context *other_context,
4024 const struct requirement *req)
4025{
4027
4028 if (context->player == nullptr) {
4029 return TRI_MAYBE;
4030 } else {
4032 req->source.value.govflag));
4033 }
4034}
4035
4036/**********************************************************************/
4044static enum fc_tristate
4046 const struct req_context *context,
4047 const struct req_context *other_context,
4048 const struct requirement *req)
4049{
4051
4052 if (context->player == nullptr) {
4053 return TRI_MAYBE;
4054 } else {
4055 return BOOL_TO_TRISTATE(context->player->style
4056 == req->source.value.style);
4057 }
4058}
4059
4060/**********************************************************************/
4068static enum fc_tristate
4070 const struct req_context *context,
4071 const struct req_context *other_context,
4072 const struct requirement *req)
4073{
4075
4076 switch (req->range) {
4077 case REQ_RANGE_WORLD:
4078 /* "None" does not count */
4079 return ((game.info.global_advance_count - 1)
4080 >= req->source.value.min_techs);
4081 case REQ_RANGE_PLAYER:
4082 if (context->player == nullptr) {
4083 return TRI_MAYBE;
4084 } else {
4085 /* "None" does not count */
4086 return BOOL_TO_TRISTATE(
4087 (research_get(context->player)->techs_researched - 1)
4088 >= req->source.value.min_techs
4089 );
4090 }
4091 default:
4092 return TRI_MAYBE;
4093 }
4094}
4095
4096/**********************************************************************/
4104static enum fc_tristate
4106 const struct req_context *context,
4107 const struct req_context *other_context,
4108 const struct requirement *req)
4109{
4111
4112 switch (req->range) {
4113 case REQ_RANGE_WORLD:
4115 if (research_get(plr)->future_tech
4116 >= req->source.value.future_techs) {
4117 return TRI_YES;
4118 }
4120
4121 return TRI_NO;
4122 case REQ_RANGE_PLAYER:
4123 if (context->player == nullptr) {
4124 return TRI_MAYBE;
4125 } else {
4127 >= req->source.value.future_techs);
4128 }
4129 default:
4130 return TRI_MAYBE;
4131 }
4132}
4133
4134/**********************************************************************/
4142static enum fc_tristate
4144 const struct req_context *context,
4145 const struct req_context *other_context,
4146 const struct requirement *req)
4147{
4149
4150 switch (req->range) {
4151 case REQ_RANGE_PLAYER:
4152 if (context->player == nullptr) {
4153 return TRI_MAYBE;
4154 } else {
4155 /* "None" does not count */
4156 return BOOL_TO_TRISTATE(
4157 city_list_size(context->player->cities)
4158 >= req->source.value.min_cities
4159 );
4160 }
4161 default:
4162 return TRI_MAYBE;
4163 }
4164}
4165
4166/**********************************************************************/
4174static enum fc_tristate
4176 const struct req_context *context,
4177 const struct req_context *other_context,
4178 const struct requirement *req)
4179{
4181
4182 if (context->player == nullptr) {
4183 return TRI_MAYBE;
4184 } else {
4185 return BOOL_TO_TRISTATE(is_ai(context->player)
4186 && context->player->ai_common.skill_level
4187 == req->source.value.ai_level);
4188 }
4189}
4190
4191/**********************************************************************/
4199static enum fc_tristate
4201 const struct req_context *context,
4202 const struct req_context *other_context,
4203 const struct requirement *req)
4204{
4205 const struct nation_type *nation;
4206
4208
4209 nation = req->source.value.nation;
4210
4211 switch (req->range) {
4212 case REQ_RANGE_PLAYER:
4213 if (context->player == nullptr) {
4214 return TRI_MAYBE;
4215 }
4216 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
4217 case REQ_RANGE_TEAM:
4218 case REQ_RANGE_ALLIANCE:
4219 if (context->player == nullptr) {
4220 return TRI_MAYBE;
4221 }
4222 players_iterate_alive(plr2) {
4223 if (players_in_same_range(context->player, plr2, req->range)) {
4224 if (nation_of_player(plr2) == nation) {
4225 return TRI_YES;
4226 }
4227 }
4229 return TRI_NO;
4230 case REQ_RANGE_WORLD:
4231 /* NB: if a player is ever removed outright from the game
4232 * (e.g. via /remove), rather than just dying, this 'survives'
4233 * requirement will stop being true for their nation.
4234 * create_command_newcomer() can also cause this to happen. */
4235 return BOOL_TO_TRISTATE(nation->player != nullptr
4236 && (req->survives || nation->player->is_alive));
4237 case REQ_RANGE_LOCAL:
4238 case REQ_RANGE_TILE:
4240 case REQ_RANGE_ADJACENT:
4241 case REQ_RANGE_CITY:
4244 case REQ_RANGE_COUNT:
4245 break;
4246 }
4247
4248 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4249
4250 return TRI_MAYBE;
4251}
4252
4253/**********************************************************************/
4261static enum fc_tristate
4263 const struct req_context *context,
4264 const struct req_context *other_context,
4265 const struct requirement *req)
4266{
4267 const struct nation_group *ngroup;
4268
4270
4272
4273 switch (req->range) {
4274 case REQ_RANGE_PLAYER:
4275 if (context->player == nullptr) {
4276 return TRI_MAYBE;
4277 }
4279 nation_of_player(context->player), ngroup));
4280 case REQ_RANGE_TEAM:
4281 case REQ_RANGE_ALLIANCE:
4282 case REQ_RANGE_WORLD:
4283 if (context->player == nullptr) {
4284 return TRI_MAYBE;
4285 }
4286 players_iterate_alive(plr2) {
4287 if (players_in_same_range(context->player, plr2, req->range)) {
4289 return TRI_YES;
4290 }
4291 }
4293 return TRI_NO;
4294 case REQ_RANGE_LOCAL:
4295 case REQ_RANGE_TILE:
4297 case REQ_RANGE_ADJACENT:
4298 case REQ_RANGE_CITY:
4301 case REQ_RANGE_COUNT:
4302 break;
4303 }
4304
4305 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4306
4307 return TRI_MAYBE;
4308}
4309
4310/**********************************************************************/
4318static enum fc_tristate
4320 const struct req_context *context,
4321 const struct req_context *other_context,
4322 const struct requirement *req)
4323{
4324 const struct nation_type *nationality;
4325 enum fc_tristate ret;
4326
4328
4329 nationality = req->source.value.nationality;
4330
4331 switch (req->range) {
4332 case REQ_RANGE_CITY:
4333 if (context->city == nullptr) {
4334 return TRI_MAYBE;
4335 }
4336 citizens_iterate(context->city, slot, count) {
4337 if (player_slot_get_player(slot)->nation == nationality) {
4338 return TRI_YES;
4339 }
4341
4342 return TRI_NO;
4344 if (context->city == nullptr) {
4345 return TRI_MAYBE;
4346 }
4347 citizens_iterate(context->city, slot, count) {
4348 if (player_slot_get_player(slot)->nation == nationality) {
4349 return TRI_YES;
4350 }
4352
4353 ret = TRI_NO;
4355 if (trade_partner == nullptr) {
4356 ret = TRI_MAYBE;
4357 } else {
4358 citizens_iterate(trade_partner, slot, count) {
4359 if (player_slot_get_player(slot)->nation == nationality) {
4360 return TRI_YES;
4361 }
4363 }
4365
4366 return ret;
4367 case REQ_RANGE_PLAYER:
4368 case REQ_RANGE_TEAM:
4369 case REQ_RANGE_ALLIANCE:
4370 case REQ_RANGE_WORLD:
4371 case REQ_RANGE_LOCAL:
4372 case REQ_RANGE_TILE:
4374 case REQ_RANGE_ADJACENT:
4376 case REQ_RANGE_COUNT:
4377 break;
4378 }
4379
4380 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4381
4382 return TRI_MAYBE;
4383}
4384
4385/**********************************************************************/
4393static enum fc_tristate
4395 const struct req_context *context,
4396 const struct req_context *other_context,
4397 const struct requirement *req)
4398{
4399 const struct nation_type *nation;
4400
4402
4403 nation = req->source.value.origowner;
4404
4405 switch (req->range) {
4406 case REQ_RANGE_CITY:
4407 if (context->city == nullptr || context->city->original == nullptr) {
4408 return TRI_MAYBE;
4409 }
4410 if (player_nation(context->city->original) == nation) {
4411 return TRI_YES;
4412 }
4413
4414 return TRI_NO;
4416 case REQ_RANGE_PLAYER:
4417 case REQ_RANGE_TEAM:
4418 case REQ_RANGE_ALLIANCE:
4419 case REQ_RANGE_WORLD:
4420 case REQ_RANGE_LOCAL:
4421 case REQ_RANGE_TILE:
4423 case REQ_RANGE_ADJACENT:
4425 case REQ_RANGE_COUNT:
4426 break;
4427 }
4428
4429 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4430
4431 return TRI_MAYBE;
4432}
4433
4434/**********************************************************************/
4438 const struct player *other_player,
4439 enum req_range range,
4440 int diplrel)
4441{
4442 switch (range) {
4443 case REQ_RANGE_PLAYER:
4444 if (target_player == nullptr) {
4445 return TRI_MAYBE;
4446 }
4448 case REQ_RANGE_TEAM:
4449 case REQ_RANGE_ALLIANCE:
4450 case REQ_RANGE_WORLD:
4451 if (target_player == nullptr) {
4452 return TRI_MAYBE;
4453 }
4454 players_iterate_alive(plr2) {
4456 if (is_diplrel_to_other(plr2, diplrel)) {
4457 return TRI_YES;
4458 }
4459 }
4461 return TRI_NO;
4462 case REQ_RANGE_LOCAL:
4463 if (target_player == nullptr || other_player == nullptr) {
4464 return TRI_MAYBE;
4465 }
4466 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
4467 case REQ_RANGE_TILE:
4469 case REQ_RANGE_ADJACENT:
4470 case REQ_RANGE_CITY:
4473 case REQ_RANGE_COUNT:
4474 break;
4475 }
4476
4477 fc_assert_msg(FALSE, "Invalid range %d.", range);
4478
4479 return TRI_MAYBE;
4480}
4481
4482/**********************************************************************/
4490static enum fc_tristate
4492 const struct req_context *context,
4493 const struct req_context *other_context,
4494 const struct requirement *req)
4495{
4497
4498 return is_diplrel_in_range(context->player, other_context->player,
4499 req->range, req->source.value.diplrel);
4500}
4501
4502/**********************************************************************/
4510static enum fc_tristate
4512 const struct req_context *context,
4513 const struct req_context *other_context,
4514 const struct requirement *req)
4515{
4517
4518 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4519 : nullptr,
4520 context->player,
4521 req->range,
4522 req->source.value.diplrel);
4523}
4524
4525/**********************************************************************/
4534static enum fc_tristate
4536 const struct req_context *context,
4537 const struct req_context *other_context,
4538 const struct requirement *req)
4539{
4541
4542 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4543 : nullptr,
4544 other_context->player,
4545 req->range,
4546 req->source.value.diplrel);
4547}
4548
4549/**********************************************************************/
4552static enum fc_tristate
4554 const struct player *other_player,
4555 enum req_range range,
4556 int diplrel)
4557{
4558 enum fc_tristate out = TRI_NO;
4559
4560 if (target_tile == nullptr) {
4561 return TRI_MAYBE;
4562 }
4563
4566 unit_owner(target_unit), other_player, range, diplrel);
4567
4570
4571 return out;
4572}
4573
4574/**********************************************************************/
4583static enum fc_tristate
4585 const struct req_context *context,
4586 const struct req_context *other_context,
4587 const struct requirement *req)
4588{
4590
4591 return is_diplrel_unitany_in_range(context->tile, context->player,
4592 req->range,
4593 req->source.value.diplrel);
4594}
4595
4596/**********************************************************************/
4605static enum fc_tristate
4607 const struct req_context *context,
4608 const struct req_context *other_context,
4609 const struct requirement *req)
4610{
4612
4614 req->range,
4615 req->source.value.diplrel);
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 const struct unit_type *punittype;
4633
4635
4636 punittype = req->source.value.utype;
4637
4638 switch (req->range) {
4639 case REQ_RANGE_LOCAL:
4640 if (!context->unittype) {
4641 return TRI_MAYBE;
4642 }
4643 return BOOL_TO_TRISTATE(context->unittype == punittype);
4644 case REQ_RANGE_TILE:
4646 case REQ_RANGE_ADJACENT:
4647 if (context->tile == nullptr) {
4648 return TRI_MAYBE;
4649 }
4650
4651 unit_list_iterate(context->tile->units, punit) {
4652 if (punit->utype == punittype) {
4653 return TRI_YES;
4654 }
4656
4657 if (req->range == REQ_RANGE_TILE) {
4658 return TRI_NO;
4659 }
4660
4661 if (req->range == REQ_RANGE_CADJACENT) {
4664 if (punit->utype == punittype) {
4665 return TRI_YES;
4666 }
4669 } else {
4671
4674 if (punit->utype == punittype) {
4675 return TRI_YES;
4676 }
4679 }
4680
4681 return TRI_NO;
4682
4683 case REQ_RANGE_CITY:
4686 case REQ_RANGE_PLAYER:
4687 case REQ_RANGE_TEAM:
4688 case REQ_RANGE_ALLIANCE:
4689 case REQ_RANGE_WORLD:
4690 case REQ_RANGE_COUNT:
4692 break;
4693 }
4694
4695 return TRI_NO;
4696}
4697
4698/**********************************************************************/
4706static enum fc_tristate
4708 const struct req_context *context,
4709 const struct req_context *other_context,
4710 const struct requirement *req)
4711{
4712 enum unit_type_flag_id unitflag;
4713
4715
4716 unitflag = req->source.value.unitflag;
4717
4718 switch (req->range) {
4719 case REQ_RANGE_LOCAL:
4720 if (!context->unittype) {
4721 return TRI_MAYBE;
4722 }
4723 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4724 case REQ_RANGE_TILE:
4726 case REQ_RANGE_ADJACENT:
4727 if (context->tile == nullptr) {
4728 return TRI_MAYBE;
4729 }
4730
4731 unit_list_iterate(context->tile->units, punit) {
4732 if (unit_has_type_flag(punit, unitflag)) {
4733 return TRI_YES;
4734 }
4736
4737 if (req->range == REQ_RANGE_TILE) {
4738 return TRI_NO;
4739 }
4740
4741 if (req->range == REQ_RANGE_CADJACENT) {
4744 if (unit_has_type_flag(punit, unitflag)) {
4745 return TRI_YES;
4746 }
4749 } else {
4751
4754 if (unit_has_type_flag(punit, unitflag)) {
4755 return TRI_YES;
4756 }
4759 }
4760
4761 return TRI_NO;
4762
4763 case REQ_RANGE_CITY:
4766 case REQ_RANGE_PLAYER:
4767 case REQ_RANGE_TEAM:
4768 case REQ_RANGE_ALLIANCE:
4769 case REQ_RANGE_WORLD:
4770 case REQ_RANGE_COUNT:
4772 break;
4773 }
4774
4775 return TRI_NO;
4776}
4777
4778/**********************************************************************/
4786static enum fc_tristate
4788 const struct req_context *context,
4789 const struct req_context *other_context,
4790 const struct requirement *req)
4791{
4792 const struct unit_class *pclass;
4793
4795
4796 pclass = req->source.value.uclass;
4797
4798 switch (req->range) {
4799 case REQ_RANGE_LOCAL:
4800 if (!context->unittype) {
4801 return TRI_MAYBE;
4802 }
4803 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4804 case REQ_RANGE_TILE:
4806 case REQ_RANGE_ADJACENT:
4807 if (context->tile == nullptr) {
4808 return TRI_MAYBE;
4809 }
4810
4811 unit_list_iterate(context->tile->units, punit) {
4812 if (unit_class_get(punit) == pclass) {
4813 return TRI_YES;
4814 }
4816
4817 if (req->range == REQ_RANGE_TILE) {
4818 return TRI_NO;
4819 }
4820
4821 if (req->range == REQ_RANGE_CADJACENT) {
4824 if (unit_class_get(punit) == pclass) {
4825 return TRI_YES;
4826 }
4829 } else {
4831
4834 if (unit_class_get(punit) == pclass) {
4835 return TRI_YES;
4836 }
4839 }
4840
4841 return TRI_NO;
4842
4843 case REQ_RANGE_CITY:
4846 case REQ_RANGE_PLAYER:
4847 case REQ_RANGE_TEAM:
4848 case REQ_RANGE_ALLIANCE:
4849 case REQ_RANGE_WORLD:
4850 case REQ_RANGE_COUNT:
4852 break;
4853 }
4854
4855 return TRI_NO;
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
4875
4877
4878 switch (req->range) {
4879 case REQ_RANGE_LOCAL:
4880 if (!context->unittype) {
4881 return TRI_MAYBE;
4882 }
4884 case REQ_RANGE_TILE:
4886 case REQ_RANGE_ADJACENT:
4887 if (context->tile == nullptr) {
4888 return TRI_MAYBE;
4889 }
4890
4891 unit_list_iterate(context->tile->units, punit) {
4893 return TRI_YES;
4894 }
4896
4897 if (req->range == REQ_RANGE_TILE) {
4898 return TRI_NO;
4899 }
4900
4901 if (req->range == REQ_RANGE_CADJACENT) {
4905 return TRI_YES;
4906 }
4909 } else {
4911
4915 return TRI_YES;
4916 }
4919 }
4920
4921 return TRI_NO;
4922
4923 case REQ_RANGE_CITY:
4926 case REQ_RANGE_PLAYER:
4927 case REQ_RANGE_TEAM:
4928 case REQ_RANGE_ALLIANCE:
4929 case REQ_RANGE_WORLD:
4930 case REQ_RANGE_COUNT:
4932 break;
4933 }
4934
4935 return TRI_NO;
4936}
4937
4938/**********************************************************************/
4946static enum fc_tristate
4948 const struct req_context *context,
4949 const struct req_context *other_context,
4950 const struct requirement *req)
4951{
4952 enum ustate_prop uprop;
4953
4955
4957
4959 "Unsupported range \"%s\"",
4960 req_range_name(req->range));
4961
4962 /* Could be asked with incomplete data.
4963 * is_req_active() will handle it based on prob_type. */
4964 if (context->unit == nullptr) {
4965 return TRI_MAYBE;
4966 }
4967
4968 switch (uprop) {
4969 case USP_TRANSPORTED:
4970 return BOOL_TO_TRISTATE(context->unit->transporter != nullptr);
4971 case USP_LIVABLE_TILE:
4972 return BOOL_TO_TRISTATE(
4974 unit_tile(context->unit)));
4975 break;
4976 case USP_TRANSPORTING:
4978 case USP_HAS_HOME_CITY:
4979 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
4980 case USP_NATIVE_TILE:
4981 return BOOL_TO_TRISTATE(
4983 unit_tile(context->unit)));
4984 break;
4985 case USP_NATIVE_EXTRA:
4986 return BOOL_TO_TRISTATE(
4988 unit_type_get(context->unit)));
4989 break;
4991 return BOOL_TO_TRISTATE(context->unit->moved);
4992 case USP_COUNT:
4993 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
4994 /* Invalid property is unknowable. */
4995 return TRI_NO;
4996 }
4997
4998 /* Should never be reached */
4999 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
5000
5001 return TRI_NO;
5002}
5003
5004/**********************************************************************/
5012static enum fc_tristate
5014 const struct req_context *context,
5015 const struct req_context *other_context,
5016 const struct requirement *req)
5017{
5018 enum unit_activity activity;
5019
5021
5022 activity = req->source.value.activity;
5023
5025 "Unsupported range \"%s\"",
5026 req_range_name(req->range));
5027
5028 if (context->unit == nullptr) {
5029 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
5030 * it's the zero value that context has by default - so many callers
5031 * who meant not to set specific activity actually have ACTIVITY_IDLE
5032 * instead of ACTIVITY_LAST */
5033 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
5034 return BOOL_TO_TRISTATE(activity == context->activity);
5035 }
5036
5037 /* Could be asked with incomplete data.
5038 * is_req_active() will handle it based on prob_type. */
5039 return TRI_MAYBE;
5040 }
5041
5042 switch (context->unit->activity) {
5043 case ACTIVITY_IDLE:
5044 case ACTIVITY_SENTRY:
5045 case ACTIVITY_GOTO:
5046 case ACTIVITY_EXPLORE:
5047 /* Seen as idle. */
5048 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
5049 default:
5050 /* Handled below. */
5051 break;
5052 }
5053
5054 return BOOL_TO_TRISTATE(context->unit->activity == activity);
5055}
5056
5057/**********************************************************************/
5065static enum fc_tristate
5067 const struct req_context *context,
5068 const struct req_context *other_context,
5069 const struct requirement *req)
5070{
5072
5073 if (context->unit == nullptr) {
5074 return TRI_MAYBE;
5075 } else {
5076 return BOOL_TO_TRISTATE(context->unit->veteran
5077 >= req->source.value.minveteran);
5078 }
5079}
5080
5081/**********************************************************************/
5089static enum fc_tristate
5091 const struct req_context *context,
5092 const struct req_context *other_context,
5093 const struct requirement *req)
5094{
5096
5097 if (context->unit == nullptr) {
5098 return TRI_MAYBE;
5099 } else {
5101 <= context->unit->moves_left);
5102 }
5103}
5104
5105/**********************************************************************/
5113static enum fc_tristate
5115 const struct req_context *context,
5116 const struct req_context *other_context,
5117 const struct requirement *req)
5118{
5120
5121 if (context->unit == nullptr) {
5122 return TRI_MAYBE;
5123 } else {
5125 <= context->unit->hp);
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{
5144
5145 switch (req->range) {
5146 case REQ_RANGE_LOCAL:
5147 if (context->unit == nullptr || !is_server()) {
5148 return TRI_MAYBE;
5149 } else {
5150 return BOOL_TO_TRISTATE(
5151 req->source.value.age <=
5152 game.info.turn - context->unit->birth_turn);
5153 }
5154 break;
5155 case REQ_RANGE_CITY:
5156 if (context->city == nullptr) {
5157 return TRI_MAYBE;
5158 } else {
5159 return BOOL_TO_TRISTATE(
5160 req->source.value.age <=
5161 game.info.turn - context->city->turn_founded);
5162 }
5163 break;
5164 case REQ_RANGE_PLAYER:
5165 if (context->player == nullptr) {
5166 return TRI_MAYBE;
5167 } else {
5168 return BOOL_TO_TRISTATE(req->source.value.age
5169 <= player_age(context->player));
5170 }
5171 break;
5172 default:
5173 return TRI_MAYBE;
5174 break;
5175 }
5176}
5177
5178/**********************************************************************/
5186static enum fc_tristate
5188 const struct req_context *context,
5189 const struct req_context *other_context,
5190 const struct requirement *req)
5191{
5193
5194 switch (req->range) {
5195 case REQ_RANGE_LOCAL:
5196 if (context->unit == nullptr || !is_server()) {
5197 return TRI_MAYBE;
5198 } else {
5199 return BOOL_TO_TRISTATE(
5200 req->source.value.form_age <=
5201 game.info.turn - context->unit->current_form_turn);
5202 }
5203 break;
5204 default:
5205 return TRI_MAYBE;
5206 break;
5207 }
5208}
5209
5210/**********************************************************************/
5214static inline enum fc_tristate
5216{
5218 bool whole_known;
5219
5220 if (cont > 0) {
5223
5224 if (actual_surrounder > 0) {
5225 return TRI_NO;
5226 }
5227 } else if (cont < 0) {
5230
5231 if (actual_surrounder < 0) {
5232 return TRI_NO;
5233 }
5234 } else {
5235 return TRI_MAYBE;
5236 }
5237
5238 if (actual_surrounder == 0 || surrounder == 0) {
5239 return TRI_MAYBE;
5240 } else if (actual_surrounder != surrounder) {
5241 return TRI_NO;
5242 } else if (!whole_known) {
5243 return TRI_MAYBE;
5244 } else {
5245 return TRI_YES;
5246 }
5247}
5248
5249/**********************************************************************/
5257static enum fc_tristate
5259 const struct req_context *context,
5260 const struct req_context *other_context,
5261 const struct requirement *req)
5262{
5264
5265 if (context->tile == nullptr || other_context->tile == nullptr) {
5266 /* Note: For some values, we might be able to give a definitive
5267 * TRI_NO answer even if one of the tiles is missing, but that's
5268 * probably not worth the added effort. */
5269 return TRI_MAYBE;
5270 }
5271
5272 switch (req->source.value.tilerel) {
5273 case TREL_SAME_TCLASS:
5274 if (tile_terrain(other_context->tile) == T_UNKNOWN) {
5275 return TRI_MAYBE;
5276 }
5278 || req->range == REQ_RANGE_CADJACENT
5279 || req->range == REQ_RANGE_ADJACENT),
5280 TRI_MAYBE,
5281 "Invalid range %d for tile relation \"%s\" req",
5283 {
5286 bool seen_unknown = FALSE;
5287 const struct terrain *terr;
5288
5289 if ((terr = tile_terrain(context->tile)) == T_UNKNOWN) {
5291 } else if (terrain_type_terrain_class(terr) == cls) {
5292 return TRUE;
5293 }
5294
5296 if ((terr = tile_terrain(adj_tile)) == T_UNKNOWN) {
5298 } else if (terrain_type_terrain_class(terr) == cls) {
5299 return TRUE;
5300 }
5302
5303 if (seen_unknown) {
5304 return TRI_MAYBE;
5305 } else {
5306 return TRI_NO;
5307 }
5308 }
5309 break;
5310 case TREL_SAME_REGION:
5311 if (tile_continent(other_context->tile) == 0) {
5312 return TRI_MAYBE;
5313 }
5315 || req->range == REQ_RANGE_CADJACENT
5316 || req->range == REQ_RANGE_ADJACENT),
5317 TRI_MAYBE,
5318 "Invalid range %d for tile relation \"%s\" req",
5320
5321 if (tile_continent(context->tile)
5322 == tile_continent(other_context->tile)) {
5323 return TRI_YES;
5324 } else {
5325 bool seen_unknown = (tile_continent(context->tile) == 0);
5327
5330
5331 if (adj_cont == cont) {
5332 return TRI_YES;
5333 } else if (adj_cont == 0) {
5335 }
5337
5338 if (seen_unknown) {
5339 return TRI_MAYBE;
5340 } else {
5341 return TRI_NO;
5342 }
5343 }
5344 break;
5346 if (tile_continent(context->tile) == 0
5347 || tile_continent(other_context->tile) == 0) {
5348 /* Note: We could still give a definitive TRI_NO answer if there are
5349 * too many different adjacent continents, but that's probably not
5350 * worth the added effort. */
5351 return TRI_MAYBE;
5352 }
5354 || req->range == REQ_RANGE_ADJACENT),
5355 TRI_MAYBE,
5356 "Invalid range %d for tile relation \"%s\" req",
5357 req->range,
5359
5360 {
5361 bool seen_unknown = FALSE;
5362 Continent_id cont = tile_continent(context->tile);
5364
5367
5368 if (adj_cont == 0) {
5370 } else if (adj_cont != cont && adj_cont != other_cont) {
5371 return TRI_NO;
5372 }
5374
5375 if (seen_unknown) {
5376 return TRI_MAYBE;
5377 } else {
5378 return TRI_YES;
5379 }
5380 }
5381 break;
5384 || req->range == REQ_RANGE_CADJACENT
5385 || req->range == REQ_RANGE_ADJACENT),
5386 TRI_MAYBE,
5387 "Invalid range %d for tile relation \"%s\" req",
5388 req->range,
5390
5391 {
5392 bool seen_maybe = FALSE;
5394
5396 wanted)) {
5397 case TRI_YES:
5398 return TRI_YES;
5399 case TRI_MAYBE:
5400 seen_maybe = TRUE;
5401 break;
5402 default:
5403 break;
5404 }
5405
5408 wanted)) {
5409 case TRI_YES:
5410 return TRI_YES;
5411 case TRI_MAYBE:
5412 seen_maybe = TRUE;
5413 break;
5414 default:
5415 break;
5416 }
5418
5419 if (seen_maybe) {
5420 return TRI_MAYBE;
5421 } else {
5422 return TRI_NO;
5423 }
5424 }
5425 break;
5426 default:
5427 break;
5428 }
5429
5431 "Illegal value %d for tile relationship requirement.",
5432 req->source.value.tilerel);
5433 return TRI_MAYBE;
5434}
5435
5436/**********************************************************************/
5439static bool is_city_in_tile(const struct tile *ptile,
5440 const struct city *pcity)
5441{
5442 if (pcity == nullptr) {
5443 return tile_city(ptile) != nullptr;
5444 } else {
5445 return is_city_center(pcity, ptile);
5446 }
5447}
5448
5449/**********************************************************************/
5457static enum fc_tristate
5459 const struct req_context *context,
5460 const struct req_context *other_context,
5461 const struct requirement *req)
5462{
5463 enum citytile_type citytile;
5464
5466
5467 citytile = req->source.value.citytile;
5468
5470 if (context->tile == nullptr) {
5471 return TRI_MAYBE;
5472 }
5473
5474 switch (citytile) {
5475 case CITYT_CENTER:
5476 switch (req->range) {
5477 case REQ_RANGE_TILE:
5479 context->city));
5481 if (is_city_in_tile(context->tile, context->city)) {
5482 return TRI_YES;
5483 }
5485 if (is_city_in_tile(adjc_tile, context->city)) {
5486 return TRI_YES;
5487 }
5489
5490 return TRI_NO;
5491 case REQ_RANGE_ADJACENT:
5492 if (is_city_in_tile(context->tile, context->city)) {
5493 return TRI_YES;
5494 }
5496 if (is_city_in_tile(adjc_tile, context->city)) {
5497 return TRI_YES;
5498 }
5500
5501 return TRI_NO;
5502 case REQ_RANGE_CITY:
5505 case REQ_RANGE_PLAYER:
5506 case REQ_RANGE_TEAM:
5507 case REQ_RANGE_ALLIANCE:
5508 case REQ_RANGE_WORLD:
5509 case REQ_RANGE_LOCAL:
5510 case REQ_RANGE_COUNT:
5511 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5512 break;
5513 }
5514
5515 return TRI_MAYBE;
5516 case CITYT_CLAIMED:
5517 switch (req->range) {
5518 case REQ_RANGE_TILE:
5519 return BOOL_TO_TRISTATE(context->tile->owner != nullptr);
5521 if (context->tile->owner != nullptr) {
5522 return TRI_YES;
5523 }
5525 if (adjc_tile->owner != nullptr) {
5526 return TRI_YES;
5527 }
5529
5530 return TRI_NO;
5531 case REQ_RANGE_ADJACENT:
5532 if (context->tile->owner != nullptr) {
5533 return TRI_YES;
5534 }
5536 if (adjc_tile->owner != nullptr) {
5537 return TRI_YES;
5538 }
5540
5541 return TRI_NO;
5542 case REQ_RANGE_CITY:
5545 case REQ_RANGE_PLAYER:
5546 case REQ_RANGE_TEAM:
5547 case REQ_RANGE_ALLIANCE:
5548 case REQ_RANGE_WORLD:
5549 case REQ_RANGE_LOCAL:
5550 case REQ_RANGE_COUNT:
5551 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5552 break;
5553 }
5554
5555 return TRI_MAYBE;
5556 case CITYT_EXTRAS_OWNED:
5557 switch (req->range) {
5558 case REQ_RANGE_TILE:
5559 return BOOL_TO_TRISTATE(context->tile->extras_owner != nullptr);
5561 if (context->tile->extras_owner != nullptr) {
5562 return TRI_YES;
5563 }
5565 if (adjc_tile->extras_owner != nullptr) {
5566 return TRI_YES;
5567 }
5569
5570 return TRI_NO;
5571 case REQ_RANGE_ADJACENT:
5572 if (context->tile->extras_owner != nullptr) {
5573 return TRI_YES;
5574 }
5576 if (adjc_tile->extras_owner != nullptr) {
5577 return TRI_YES;
5578 }
5580
5581 return TRI_NO;
5582 case REQ_RANGE_CITY:
5585 case REQ_RANGE_PLAYER:
5586 case REQ_RANGE_TEAM:
5587 case REQ_RANGE_ALLIANCE:
5588 case REQ_RANGE_WORLD:
5589 case REQ_RANGE_LOCAL:
5590 case REQ_RANGE_COUNT:
5591 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5592 break;
5593 }
5594
5595 return TRI_MAYBE;
5596 case CITYT_WORKED:
5597 switch (req->range) {
5598 case REQ_RANGE_TILE:
5599 return BOOL_TO_TRISTATE(context->tile->worked != nullptr);
5601 if (context->tile->worked != nullptr) {
5602 return TRI_YES;
5603 }
5605 if (adjc_tile->worked != nullptr) {
5606 return TRI_YES;
5607 }
5609
5610 return TRI_NO;
5611 case REQ_RANGE_ADJACENT:
5612 if (context->tile->worked != nullptr) {
5613 return TRI_YES;
5614 }
5616 if (adjc_tile->worked != nullptr) {
5617 return TRI_YES;
5618 }
5620
5621 return TRI_NO;
5622 case REQ_RANGE_CITY:
5625 case REQ_RANGE_PLAYER:
5626 case REQ_RANGE_TEAM:
5627 case REQ_RANGE_ALLIANCE:
5628 case REQ_RANGE_WORLD:
5629 case REQ_RANGE_LOCAL:
5630 case REQ_RANGE_COUNT:
5631 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5632 break;
5633 }
5634
5635 return TRI_MAYBE;
5637 {
5639 const struct tile *target_tile = context->tile, *cc_tile;
5640
5641 if (!context->city) {
5642 return TRI_MAYBE;
5643 }
5644 cc_tile = city_tile(context->city);
5645 if (!cc_tile) {
5646 /* Unplaced virtual city */
5647 return TRI_MAYBE;
5648 }
5650 /* Note: No special treatment of 0 == cc here*/
5651 switch (req->range) {
5652 case REQ_RANGE_TILE:
5655 if (tile_continent(target_tile) == cc) {
5656 return TRI_YES;
5657 }
5659 if (tile_continent(adjc_tile) == cc) {
5660 return TRI_YES;
5661 }
5663
5664 return TRI_NO;
5665 case REQ_RANGE_ADJACENT:
5666 if (tile_continent(target_tile) == cc) {
5667 return TRI_YES;
5668 }
5670 if (tile_continent(adjc_tile) == cc) {
5671 return TRI_YES;
5672 }
5674
5675 return TRI_NO;
5676 case REQ_RANGE_CITY:
5679 case REQ_RANGE_PLAYER:
5680 case REQ_RANGE_TEAM:
5681 case REQ_RANGE_ALLIANCE:
5682 case REQ_RANGE_WORLD:
5683 case REQ_RANGE_LOCAL:
5684 case REQ_RANGE_COUNT:
5685 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5686 break;
5687 }
5688 }
5689
5690 return TRI_MAYBE;
5692 {
5693 int n = 0;
5695 bool ukt = FALSE;
5696 const struct tile *target_tile = context->tile, *cc_tile;
5697
5698 if (!context->city) {
5699 return TRI_MAYBE;
5700 }
5701 cc_tile = city_tile(context->city);
5702 if (!cc_tile) {
5703 /* Unplaced virtual city */
5704 return TRI_MAYBE;
5705 }
5707 if (!cc) {
5708 /* Don't know the city center terrain class.
5709 * Maybe, the city floats? Even if the rules prohibit it... */
5710 return TRI_MAYBE;
5711 }
5714
5715 if (0 != tc) {
5716 bool seen = FALSE;
5717 int i = n;
5718
5719 if (tc == cc) {
5720 continue;
5721 }
5722 while (--i >= 0) {
5723 if (adjc_cont[i] == tc) {
5724 seen = TRUE;
5725 break;
5726 }
5727 }
5728 if (seen) {
5729 continue;
5730 }
5732 } else {
5733 /* Likely, it's a black tile in client and we don't know
5734 * We possibly can calculate, but keep it simple. */
5735 ukt = TRUE;
5736 }
5738 if (0 == n) {
5739 return ukt ? TRI_MAYBE : TRI_NO;
5740 }
5741
5742 switch (req->range) {
5743 case REQ_RANGE_TILE:
5744 {
5746
5747 if (cc == tc) {
5748 return TRI_NO;
5749 }
5750 if (0 == tc || ukt) {
5751 return TRI_MAYBE;
5752 }
5753 for (int i = 0; i < n; i++) {
5754 if (tc == adjc_cont[i]) {
5755 return TRI_YES;
5756 }
5757 }
5758 }
5759
5760 return TRI_NO;
5761 case REQ_RANGE_ADJACENT:
5762 if (ukt) {
5763 /* If ALL the tiles in range are on cc, we can say it's false */
5765 if (tile_continent(adjc_tile) != cc) {
5766 return TRI_MAYBE;
5767 }
5769
5770 return TRI_NO;
5771 } else {
5774
5775 if (0 == tc) {
5776 return TRI_MAYBE;
5777 }
5778 for (int i = 0; i < n; i++) {
5779 if (tc == adjc_cont[i]) {
5780 return TRI_YES;
5781 }
5782 }
5784 }
5785
5786 return TRI_NO;
5788 if (ukt) {
5789 /* If ALL the tiles in range are on cc, we can say it's false */
5791 if (tile_continent(cadjc_tile) != cc) {
5792 return TRI_MAYBE;
5793 }
5795 } else {
5798
5799 if (0 == tc) {
5800 return TRI_MAYBE;
5801 }
5802 for (int i = 0; i < n; i++) {
5803 if (tc == adjc_cont[i]) {
5804 return TRI_YES;
5805 }
5806 }
5808 }
5809
5810 return TRI_NO;
5811 case REQ_RANGE_CITY:
5814 case REQ_RANGE_PLAYER:
5815 case REQ_RANGE_TEAM:
5816 case REQ_RANGE_ALLIANCE:
5817 case REQ_RANGE_WORLD:
5818 case REQ_RANGE_LOCAL:
5819 case REQ_RANGE_COUNT:
5820 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5821 break;
5822 }
5823 }
5824
5825 return TRI_MAYBE;
5826 case CITYT_LAST:
5827 /* Handled below */
5828 break;
5829 }
5830
5831 /* Not implemented */
5832 log_error("is_req_active(): citytile %d not supported.",
5833 citytile);
5834 return TRI_MAYBE;
5835}
5836
5837/**********************************************************************/
5845static enum fc_tristate
5847 const struct req_context *context,
5848 const struct req_context *other_context,
5849 const struct requirement *req)
5850{
5851 enum citystatus_type citystatus;
5852
5854
5855 citystatus = req->source.value.citystatus;
5856
5857 if (context->city == nullptr) {
5858 return TRI_MAYBE;
5859 }
5860
5861 switch (citystatus) {
5863 switch (req->range) {
5864 case REQ_RANGE_CITY:
5865 if (context->city->original == nullptr) {
5866 return TRI_MAYBE;
5867 }
5868 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
5870 {
5871 enum fc_tristate ret;
5872
5873 if (city_owner(context->city) == context->city->original) {
5874 return TRI_YES;
5875 }
5876
5877 ret = TRI_NO;
5879 if (trade_partner == nullptr || trade_partner->original == nullptr) {
5880 ret = TRI_MAYBE;
5881 } else if (city_owner(trade_partner) == trade_partner->original) {
5882 return TRI_YES;
5883 }
5885
5886 return ret;
5887 }
5888 case REQ_RANGE_LOCAL:
5889 case REQ_RANGE_TILE:
5891 case REQ_RANGE_ADJACENT:
5893 case REQ_RANGE_PLAYER:
5894 case REQ_RANGE_TEAM:
5895 case REQ_RANGE_ALLIANCE:
5896 case REQ_RANGE_WORLD:
5897 case REQ_RANGE_COUNT:
5898 break;
5899 }
5900
5901 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
5902 req->range);
5903
5904 return TRI_MAYBE;
5905
5906 case CITYS_STARVED:
5907 switch (req->range) {
5908 case REQ_RANGE_CITY:
5909 return BOOL_TO_TRISTATE(context->city->had_famine);
5911 {
5912 enum fc_tristate ret;
5913
5914 if (context->city->had_famine) {
5915 return TRI_YES;
5916 }
5917
5918 ret = TRI_NO;
5920 if (trade_partner == nullptr) {
5921 ret = TRI_MAYBE;
5922 } else if (trade_partner->had_famine) {
5923 return TRI_YES;
5924 }
5926
5927 return ret;
5928 }
5929 case REQ_RANGE_LOCAL:
5930 case REQ_RANGE_TILE:
5932 case REQ_RANGE_ADJACENT:
5934 case REQ_RANGE_PLAYER:
5935 case REQ_RANGE_TEAM:
5936 case REQ_RANGE_ALLIANCE:
5937 case REQ_RANGE_WORLD:
5938 case REQ_RANGE_COUNT:
5939 break;
5940 }
5941
5942 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
5943 req->range);
5944
5945 return TRI_MAYBE;
5946
5947 case CITYS_DISORDER:
5948 switch (req->range) {
5949 case REQ_RANGE_CITY:
5950 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
5952 {
5953 enum fc_tristate ret;
5954
5955 if (context->city->anarchy > 0) {
5956 return TRI_YES;
5957 }
5958
5959 ret = TRI_NO;
5961 if (trade_partner == nullptr) {
5962 ret = TRI_MAYBE;
5963 } else if (trade_partner->anarchy > 0) {
5964 return TRI_YES;
5965 }
5967
5968 return ret;
5969 }
5970 case REQ_RANGE_LOCAL:
5971 case REQ_RANGE_TILE:
5973 case REQ_RANGE_ADJACENT:
5975 case REQ_RANGE_PLAYER:
5976 case REQ_RANGE_TEAM:
5977 case REQ_RANGE_ALLIANCE:
5978 case REQ_RANGE_WORLD:
5979 case REQ_RANGE_COUNT:
5980 break;
5981 }
5982
5983 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
5984 req->range);
5985
5986 return TRI_MAYBE;
5987
5988 case CITYS_CELEBRATION:
5989 switch (req->range) {
5990 case REQ_RANGE_CITY:
5991 return BOOL_TO_TRISTATE(context->city->rapture > 0);
5993 {
5994 enum fc_tristate ret;
5995
5996 if (context->city->rapture > 0) {
5997 return TRI_YES;
5998 }
5999
6000 ret = TRI_NO;
6002 if (trade_partner == nullptr) {
6003 ret = TRI_MAYBE;
6004 } else if (trade_partner->rapture > 0) {
6005 return TRI_YES;
6006 }
6008
6009 return ret;
6010 }
6011 case REQ_RANGE_LOCAL:
6012 case REQ_RANGE_TILE:
6014 case REQ_RANGE_ADJACENT:
6016 case REQ_RANGE_PLAYER:
6017 case REQ_RANGE_TEAM:
6018 case REQ_RANGE_ALLIANCE:
6019 case REQ_RANGE_WORLD:
6020 case REQ_RANGE_COUNT:
6021 break;
6022 }
6023
6024 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
6025 req->range);
6026
6027 return TRI_MAYBE;
6028
6029 case CITYS_TRANSFERRED:
6030 switch (req->range) {
6031 case REQ_RANGE_CITY:
6032 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
6034 {
6035 enum fc_tristate ret;
6036
6037 if (context->city->acquire_t != CACQ_FOUNDED) {
6038 return TRI_YES;
6039 }
6040
6041 ret = TRI_NO;
6043 if (trade_partner == nullptr) {
6044 ret = TRI_MAYBE;
6045 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
6046 return TRI_YES;
6047 }
6049
6050 return ret;
6051 }
6052 case REQ_RANGE_LOCAL:
6053 case REQ_RANGE_TILE:
6055 case REQ_RANGE_ADJACENT:
6057 case REQ_RANGE_PLAYER:
6058 case REQ_RANGE_TEAM:
6059 case REQ_RANGE_ALLIANCE:
6060 case REQ_RANGE_WORLD:
6061 case REQ_RANGE_COUNT:
6062 break;
6063 }
6064
6065 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
6066 req->range);
6067
6068 return TRI_MAYBE;
6069
6071 if (!is_server()) {
6072 /* Client has no idea. */
6073 return TRI_MAYBE;
6074 }
6075
6076 switch (req->range) {
6077 case REQ_RANGE_CITY:
6078 return BOOL_TO_TRISTATE(context->city->server.aarea != nullptr
6079 && context->city->server.aarea->capital);
6081 {
6082 enum fc_tristate ret;
6083
6084 if (context->city->server.aarea != nullptr
6085 && context->city->server.aarea->capital) {
6086 return TRI_YES;
6087 }
6088
6089 ret = TRI_NO;
6091 if (trade_partner == nullptr) {
6092 ret = TRI_MAYBE;
6093 } else if (trade_partner->server.aarea != nullptr
6094 && trade_partner->server.aarea->capital) {
6095 return TRI_YES;
6096 }
6098
6099 return ret;
6100 }
6101 case REQ_RANGE_LOCAL:
6102 case REQ_RANGE_TILE:
6104 case REQ_RANGE_ADJACENT:
6106 case REQ_RANGE_PLAYER:
6107 case REQ_RANGE_TEAM:
6108 case REQ_RANGE_ALLIANCE:
6109 case REQ_RANGE_WORLD:
6110 case REQ_RANGE_COUNT:
6111 break;
6112 }
6113
6114 fc_assert_msg(FALSE, "Invalid range %d for citystatus CapitalConnected.",
6115 req->range);
6116
6117 return TRI_MAYBE;
6118
6119 case CITYS_LAST:
6120 break;
6121 }
6122
6123 /* Not implemented */
6124 log_error("is_req_active(): citystatus %d not supported.",
6125 citystatus);
6126
6127 return TRI_MAYBE;
6128}
6129
6130/**********************************************************************/
6138static enum fc_tristate
6140 const struct req_context *context,
6141 const struct req_context *other_context,
6142 const struct requirement *req)
6143{
6145
6146 if (context->city == nullptr) {
6147 return TRI_MAYBE;
6148 } else {
6149 if (req->range == REQ_RANGE_TRADE_ROUTE) {
6150 enum fc_tristate ret;
6151
6152 if (city_size_get(context->city) >= req->source.value.minsize) {
6153 return TRI_YES;
6154 }
6155
6156 ret = TRI_NO;
6158 if (trade_partner == nullptr) {
6159 ret = TRI_MAYBE;
6160 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
6161 return TRI_YES;
6162 }
6164
6165 return ret;
6166 } else {
6168 >= req->source.value.minsize);
6169 }
6170 }
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{
6187 const struct counter *count;
6188
6190
6191 count = req->source.value.counter;
6192
6193 if (context->city == nullptr) {
6194 return TRI_MAYBE;
6195 }
6196 return BOOL_TO_TRISTATE(count->checkpoint <=
6197 context->city->counter_values[
6198 counter_index(count)]);
6199}
6200
6201/**********************************************************************/
6209static enum fc_tristate
6211 const struct req_context *context,
6212 const struct req_context *other_context,
6213 const struct requirement *req)
6214{
6215 const struct achievement *achievement;
6216
6218
6220
6221 if (req->range == REQ_RANGE_WORLD) {
6223 } else if (context->player == nullptr) {
6224 return TRI_MAYBE;
6225 } else if (req->range == REQ_RANGE_ALLIANCE
6226 || req->range == REQ_RANGE_TEAM) {
6227 players_iterate_alive(plr2) {
6228 if (players_in_same_range(context->player, plr2, req->range)
6230 return TRI_YES;
6231 }
6233 return TRI_NO;
6234 } else if (req->range == REQ_RANGE_PLAYER) {
6236 return TRI_YES;
6237 } else {
6238 return TRI_NO;
6239 }
6240 }
6241
6242 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
6243
6244 return TRI_MAYBE;
6245}
6246
6247/**********************************************************************/
6255static enum fc_tristate
6257 const struct req_context *context,
6258 const struct req_context *other_context,
6259 const struct requirement *req)
6260{
6261 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
6262
6263 fc_assert_ret_val(req != nullptr, TRI_MAYBE);
6264 fc_assert(context != nullptr);
6265
6266 switch (req->source.kind) {
6267 case VUT_MINLATITUDE:
6268 min = req->source.value.latitude;
6269 break;
6270 case VUT_MAXLATITUDE:
6271 max = req->source.value.latitude;
6272 break;
6273 default:
6275 || req->source.kind == VUT_MAXLATITUDE);
6276 break;
6277 }
6278
6279 switch (req->range) {
6280 case REQ_RANGE_WORLD:
6282 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
6283
6284 case REQ_RANGE_TILE:
6285 if (context->tile == nullptr) {
6286 return TRI_MAYBE;
6287 } else {
6289
6291 }
6292
6294 if (context->tile == nullptr) {
6295 return TRI_MAYBE;
6296 }
6297
6300
6302 return TRI_YES;
6303 }
6305 return TRI_NO;
6306
6307 case REQ_RANGE_ADJACENT:
6308 if (!context->tile) {
6309 return TRI_MAYBE;
6310 }
6311
6314
6316 return TRI_YES;
6317 }
6319 return TRI_NO;
6320
6321 case REQ_RANGE_CITY:
6324 case REQ_RANGE_PLAYER:
6325 case REQ_RANGE_TEAM:
6326 case REQ_RANGE_ALLIANCE:
6327 case REQ_RANGE_LOCAL:
6328 case REQ_RANGE_COUNT:
6329 break;
6330 }
6331
6333 "Illegal range %d for latitude requirement.", req->range);
6334
6335 return TRI_MAYBE;
6336}
6337
6338/**********************************************************************/
6346static enum fc_tristate
6348 const struct req_context *context,
6349 const struct req_context *other_context,
6350 const struct requirement *req)
6351{
6353
6354 switch (req->range) {
6355 case REQ_RANGE_TILE:
6356 if (context->tile == nullptr || other_context->tile == nullptr) {
6357 return TRI_MAYBE;
6358 }
6359 return BOOL_TO_TRISTATE(
6361 <= req->source.value.distance_sq
6362 );
6363 default:
6364 break;
6365 }
6366
6368 "Illegal range %d for max squared distance requirement.",
6369 req->range);
6370
6371 return TRI_MAYBE;
6372}
6373
6374/**********************************************************************/
6382static enum fc_tristate
6384 const struct req_context *context,
6385 const struct req_context *other_context,
6386 const struct requirement *req)
6387{
6388 int max_tiles, min_tiles = 1;
6389
6391
6392 switch (req->range) {
6394 case REQ_RANGE_ADJACENT:
6395 if (context->tile == nullptr) {
6396 /* The tile itself is included in the range */
6397 max_tiles = 1 + ((req->range == REQ_RANGE_CADJACENT)
6398 ? nmap->num_cardinal_dirs
6399 : nmap->num_valid_dirs);
6400
6401 break;
6402 } else {
6403 Continent_id cont = tile_continent(context->tile);
6404
6405 /* Count how many adjacent tiles there actually are as we go along */
6406 max_tiles = 1;
6407
6410
6411 if (adj_cont == 0 || cont == 0) {
6412 max_tiles++;
6413 } else if (adj_cont == cont) {
6414 min_tiles++;
6415 max_tiles++;
6416 }
6418 }
6419 break;
6421 {
6422 Continent_id cont = context->tile ? tile_continent(context->tile) : 0;
6423
6426
6427 /* Note: We could come up with a better upper bound by subtracting
6428 * all other continent/ocean sizes, or all except the largest if we
6429 * don't know the tile.
6430 * We could even do a flood-fill count of the unknown area bordered
6431 * by known tiles of the continent.
6432 * Probably not worth the effort though. */
6433 max_tiles = nmap->xsize * nmap->ysize;
6434
6435 if (cont > 0) {
6436 min_tiles = nmap->continent_sizes[cont];
6437 if (is_whole_continent_known(cont)) {
6439 }
6440 } else if (cont < 0) {
6441 min_tiles = nmap->ocean_sizes[-cont];
6442 if (is_whole_ocean_known(-cont)) {
6444 }
6445 }
6446 }
6447 break;
6448 default:
6450 "Illegal range %d for max region tiles requirement.",
6451 req->range);
6452 return TRI_MAYBE;
6453 }
6454
6455 if (min_tiles > req->source.value.region_tiles) {
6456 return TRI_NO;
6457 } else if (max_tiles <= req->source.value.region_tiles) {
6458 return TRI_YES;
6459 }
6460 return TRI_MAYBE;
6461}
6462
6463/**********************************************************************/
6471static enum fc_tristate
6473 const struct req_context *context,
6474 const struct req_context *other_context,
6475 const struct requirement *req)
6476{
6478
6480}
6481
6482/**********************************************************************/
6490static enum fc_tristate
6492 const struct req_context *context,
6493 const struct req_context *other_context,
6494 const struct requirement *req)
6495{
6497
6499 >= req->source.value.mincalfrag);
6500}
6501
6502/**********************************************************************/
6510static enum fc_tristate
6512 const struct req_context *context,
6513 const struct req_context *other_context,
6514 const struct requirement *req)
6515{
6517
6518 return BOOL_TO_TRISTATE(
6520}
6521
6522/**********************************************************************/
6530static enum fc_tristate
6532 const struct req_context *context,
6533 const struct req_context *other_context,
6534 const struct requirement *req)
6535{
6537
6538 return BOOL_TO_TRISTATE(
6540}
6541
6542/**********************************************************************/
6550static enum fc_tristate
6552 const struct req_context *context,
6553 const struct req_context *other_context,
6554 const struct requirement *req)
6555{
6557
6559 req->source.value.ssetval));
6560}
6561
6562/* Not const for potential ruleset-related adjustment */
6565
6566 /* Alphabetical order of enum constant */
6633};
6634
6635/**********************************************************************/
6649 const struct req_context *other_context,
6650 const struct requirement *req,
6651 const enum req_problem_type prob_type)
6652{
6653 const struct civ_map *nmap = &(wld.map);
6655 req);
6656
6657 if (eval == TRI_MAYBE) {
6658 if (prob_type == RPT_POSSIBLE) {
6659 return TRUE;
6660 } else {
6661 return FALSE;
6662 }
6663 }
6664 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
6665}
6666
6667/**********************************************************************/
6676static
6678 const struct req_context *context,
6679 const struct req_context *other_context,
6680 const struct requirement *req)
6681{
6682 if (!context) {
6684 }
6685 if (!other_context) {
6687 }
6688
6689 if (req->source.kind >= VUT_COUNT) {
6690 log_error("tri_req_present(): invalid source kind %d.",
6691 req->source.kind);
6692 return TRI_NO;
6693 }
6694
6696
6697 return req_definitions[req->source.kind].cb(nmap, context,
6698 other_context, req);
6699}
6700
6701/**********************************************************************/
6711 const struct req_context *other_context,
6712 const struct requirement *req)
6713{
6714 const struct civ_map *nmap = &(wld.map);
6716
6717 if (!req->present) {
6718 if (TRI_NO == eval) {
6719 return TRI_YES;
6720 }
6721 if (TRI_YES == eval) {
6722 return TRI_NO;
6723 }
6724 }
6725
6726 return eval;
6727}
6728
6729/**********************************************************************/
6745 const struct req_context *other_context,
6746 const struct requirement_vector *reqs,
6747 const enum req_problem_type prob_type)
6748{
6751 return FALSE;
6752 }
6754
6755 return TRUE;
6756}
6757
6758/**********************************************************************/
6763 const enum req_range max_range,
6764 const struct req_context *context,
6765 const struct req_context *other_context,
6766 const struct requirement_vector *reqs,
6767 const enum req_problem_type prob_type)
6768{
6770 if (preq->range >= min_range && preq->range <= max_range) {
6772 return FALSE;
6773 }
6774 }
6776
6777 return TRUE;
6778}
6779
6780/**********************************************************************/
6786enum fc_tristate
6788 const struct req_context *context,
6789 const struct req_context *other_context,
6790 const struct requirement *req)
6791{
6792 /* FIXME: Doubles code from calendar.c */
6796 int fragment1 = fragment; /* If fragments don't advance */
6797 int year_inc, year_inc1;
6800 bool present, present1;
6801
6802 fc_assert(pass >= 0 && period >= 0);
6803 if (slowdown >= 3) {
6804 if (ypt > 1) {
6805 ypt = 1;
6806 }
6807 } else if (slowdown >= 2) {
6808 if (ypt > 2) {
6809 ypt = 2;
6810 }
6811 } else if (slowdown >= 1) {
6812 if (ypt > 5) {
6813 ypt = 5;
6814 }
6815 }
6816 year_inc = ypt * pass;
6819 int fragment_years;
6820
6821 fragment += fpt * pass;
6829 }
6831 if (year_inc + game.info.year >= 0) {
6832 year_inc++;
6833 year_inc1++;
6834 } else if (year_inc1 + game.info.year >= 0) {
6835 year_inc1++;
6836 }
6837 }
6838
6839 switch (req->source.kind) {
6840 case VUT_AGE:
6841 switch (req->range) {
6842 case REQ_RANGE_LOCAL:
6843 if (context->unit == nullptr || !is_server()) {
6844 return TRI_MAYBE;
6845 } else {
6846 int ua = game.info.turn + pass - context->unit->birth_turn;
6847
6848 present = req->source.value.age <= ua;
6849 present1 = req->source.value.age <= ua + period;
6850 }
6851 break;
6852 case REQ_RANGE_CITY:
6853 if (context->city == nullptr) {
6854 return TRI_MAYBE;
6855 } else {
6856 int ca = game.info.turn + pass - context->city->turn_founded;
6857
6858 present = req->source.value.age <= ca;
6859 present1 = req->source.value.age <= ca + period;
6860 }
6861 break;
6862 case REQ_RANGE_PLAYER:
6863 if (context->player == nullptr) {
6864 return TRI_MAYBE;
6865 } else {
6866 present = req->source.value.age
6867 <= player_age(context->player) + pass;
6868 present1 = req->source.value.age
6869 <= player_age(context->player) + pass + period;
6870 }
6871 break;
6872 default:
6873 return TRI_MAYBE;
6874 }
6875 break;
6876 case VUT_FORM_AGE:
6877 if (context->unit == nullptr || !is_server()) {
6878 return TRI_MAYBE;
6879 } else {
6880 int ua = game.info.turn + pass - context->unit->current_form_turn;
6881
6882 present = req->source.value.form_age <= ua;
6883 present1 = req->source.value.form_age <= ua + period;
6884 }
6885 break;
6886 case VUT_MINYEAR:
6887 present = game.info.year + year_inc >= req->source.value.minyear;
6889 break;
6890 case VUT_MINCALFRAG:
6892 /* Hope that the requirement is valid and fragments advance fine */
6893 return TRI_YES;
6894 }
6895 present = fragment >= req->source.value.mincalfrag;
6897 break;
6898 default:
6899 /* No special handling invented */
6900 return tri_req_active(context, other_context, req);
6901 }
6902 return BOOL_TO_TRISTATE(req->present
6903 ? present || present1 : !(present && present1));
6904}
6905
6906/**********************************************************************/
6912 (const struct req_context *context,
6913 const struct req_context *other_context,
6914 const struct requirement *req,
6915 void *data, int n_data)
6916{
6917 int i;
6918
6919 fc_assert_ret_val(data || n_data == 0, TRI_NO);
6920
6921 for (i = 0; i < n_data; i++) {
6922 if (are_requirements_contradictions(&((struct requirement *) data)[i],
6923 req)) {
6924 return TRI_NO;
6925 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
6926 return TRI_YES;
6927 }
6928 }
6929
6930 return tri_req_active(context, other_context, req);
6931}
6932
6933/**********************************************************************/
6939enum fc_tristate
6941 const struct req_context *other_context,
6942 const struct requirement_vector *reqs,
6945 void *data, int n_data)
6946{
6947 bool active = TRUE;
6948 bool certain = TRUE;
6949
6950 fc_assert_ret_val(tester != nullptr, TRI_NO);
6951
6954 data, n_data)) {
6955 case TRI_NO:
6956 active = FALSE;
6957 certain = TRUE;
6958 break;
6959 case TRI_YES:
6960 break;
6961 case TRI_MAYBE:
6962 certain = FALSE;
6963 if (maybe_reqs) {
6965 }
6966 break;
6967 default:
6969 active = FALSE;
6970 }
6971 if (!active) {
6972 break;
6973 }
6975
6976 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
6977}
6978
6979/**********************************************************************/
6989 const struct requirement *req)
6990{
6991 enum req_unchanging_status s;
6992 const struct civ_map *nmap = &(wld.map);
6993
6996 "Invalid source kind %d.", req->source.kind);
6998
6999 if (req->survives) {
7000 /* Special case for surviving requirements */
7001 /* Buildings may obsolete even here */
7002 if (VUT_IMPROVEMENT == req->source.kind) {
7003 const struct impr_type *b = req->source.value.building;
7004
7006 if (improvement_obsolete(context->player, b, context->city)) {
7007 /* FIXME: Sometimes can unobsolete, but considering it
7008 * may sometimes put the function on endless recursion */
7009 return REQUCH_ACT; /* Mostly about techs */
7010 } else {
7011 /* NOTE: May obsoletion reqs be unchanging? Hardly but why not. */
7012 return REQUCH_NO;
7013 }
7014 }
7015 }
7016 s = unchanging_present(nmap, s, context, req);
7017 if (s != REQUCH_NO) {
7018 return unchanging_noally(nmap, s, context, req);
7019 }
7020 } else {
7023
7024 if (cond) {
7025 return cond(nmap, s, context, req);
7026 }
7027 }
7028
7029 return s;
7030}
7031
7032/**********************************************************************/
7037 const struct req_context *other_context,
7038 const struct requirement *req,
7040{
7042
7043 if (REQUCH_NO != u) {
7044 /* Presence is precalculated */
7045 bool auto_present = (req->survives
7046 && !(VUT_IMPROVEMENT == req->source.kind
7050
7051 if (auto_present ? req->present
7053 /* Unchanging but does not block */
7054 return REQUCH_NO;
7055 }
7056 }
7057
7058 return u;
7059}
7060
7061/**********************************************************************/
7065bool is_req_in_vec(const struct requirement *req,
7066 const struct requirement_vector *vec)
7067{
7069 if (are_requirements_equal(req, preq)) {
7070 return TRUE;
7071 }
7073
7074 return FALSE;
7075}
7076
7077/**********************************************************************/
7085 enum universals_n kind)
7086{
7088 if (preq->present && preq->source.kind == kind) {
7089 return TRUE;
7090 }
7092 return FALSE;
7093}
7094
7095/**********************************************************************/
7104{
7105 switch (source->kind) {
7106 case VUT_ACTION:
7107 return !action_is_in_use(source->value.action);
7108 case VUT_UTFLAG:
7109 return !utype_flag_is_in_use(source->value.unitflag);
7110 case VUT_UCFLAG:
7111 return !uclass_flag_is_in_use(source->value.unitclassflag);
7112 case VUT_EXTRAFLAG:
7113 return !extra_flag_is_in_use(source->value.extraflag);
7114 case VUT_MINLATITUDE:
7115 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
7116 case VUT_MAXLATITUDE:
7117 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
7118 case VUT_COUNTER:
7119 case VUT_OTYPE:
7120 case VUT_SPECIALIST:
7121 case VUT_AI_LEVEL:
7122 case VUT_CITYTILE:
7123 case VUT_CITYSTATUS:
7124 case VUT_STYLE:
7125 case VUT_TOPO:
7126 case VUT_WRAP:
7127 case VUT_SERVERSETTING:
7128 case VUT_NATION:
7129 case VUT_NATIONGROUP:
7130 case VUT_ADVANCE:
7131 case VUT_TECHFLAG:
7132 case VUT_GOVERNMENT:
7133 case VUT_GOVFLAG:
7134 case VUT_ACHIEVEMENT:
7135 case VUT_IMPROVEMENT:
7136 case VUT_SITE:
7137 case VUT_IMPR_GENUS:
7138 case VUT_IMPR_FLAG:
7139 case VUT_PLAYER_FLAG:
7140 case VUT_PLAYER_STATE:
7141 case VUT_MINSIZE:
7142 case VUT_MINCULTURE:
7143 case VUT_MINFOREIGNPCT:
7144 case VUT_MINTECHS:
7145 case VUT_FUTURETECHS:
7146 case VUT_MINCITIES:
7147 case VUT_NATIONALITY:
7148 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
7149 case VUT_DIPLREL:
7150 case VUT_DIPLREL_TILE:
7151 case VUT_DIPLREL_TILE_O:
7156 case VUT_UTYPE:
7157 case VUT_UCLASS:
7158 case VUT_MINVETERAN:
7159 case VUT_UNITSTATE:
7160 case VUT_ACTIVITY:
7161 case VUT_MINMOVES:
7162 case VUT_MINHP:
7163 case VUT_AGE:
7164 case VUT_FORM_AGE:
7165 case VUT_ROADFLAG:
7166 case VUT_MINCALFRAG:
7167 case VUT_TERRAIN:
7168 case VUT_EXTRA:
7169 case VUT_TILEDEF:
7170 case VUT_GOOD:
7171 case VUT_TERRAINCLASS:
7172 case VUT_TERRFLAG:
7173 case VUT_TERRAINALTER:
7174 case VUT_MINYEAR:
7177 case VUT_TILE_REL:
7178 case VUT_NONE:
7179 case VUT_COUNT:
7180 /* Not implemented. */
7181 break;
7182 }
7183
7184 return FALSE;
7185}
7186
7187/**********************************************************************/
7196{
7197 /* Not known to be impossible to fulfill */
7198 return req->present && universal_never_there(&req->source);
7199}
7200
7201/**********************************************************************/
7210{
7213 return TRUE;
7214 }
7216
7217 /* Not known to be impossible to fulfill */
7218 return FALSE;
7219}
7220
7221/**********************************************************************/
7231 const struct requirement_vector *vec)
7232{
7233 if (vec) {
7234 return 0;
7235 } else {
7236 return -1;
7237 }
7238}
7239
7240/********************************************************************/
7249struct requirement_vector *
7251{
7252 fc_assert_ret_val(number == 0, nullptr);
7253
7254 return (struct requirement_vector *)parent_item;
7255}
7256
7257/**********************************************************************/
7268const char *req_vec_change_translation(const struct req_vec_change *change,
7270{
7271 const char *req_vec_description;
7272 static char buf[MAX_LEN_NAME * 3];
7273 struct astring astr;
7274
7275 fc_assert_ret_val(change, nullptr);
7277 nullptr);
7278
7279 /* Get rid of the previous. */
7280 buf[0] = '\0';
7281
7282 if (namer == nullptr) {
7283 /* TRANS: default description of a requirement vector
7284 * (used in ruledit) */
7285 req_vec_description = _("the requirement vector");
7286 } else {
7288 }
7289
7290 switch (change->operation) {
7291 case RVCO_REMOVE:
7292 fc_snprintf(buf, sizeof(buf),
7293 /* TRANS: remove a requirement from a requirement vector
7294 * (in ruledit).
7295 * The first %s is the operation.
7296 * The second %s is the requirement.
7297 * The third %s is a description of the requirement vector,
7298 * like "actor_reqs" */
7299 _("%s %s from %s"),
7301 req_to_fstring(&change->req, &astr),
7303 astr_free(&astr);
7304 break;
7305 case RVCO_APPEND:
7306 fc_snprintf(buf, sizeof(buf),
7307 /* TRANS: append a requirement to a requirement vector
7308 * (in ruledit).
7309 * The first %s is the operation.
7310 * The second %s is the requirement.
7311 * The third %s is a description of the requirement vector,
7312 * like "actor_reqs" */
7313 _("%s %s to %s"),
7315 req_to_fstring(&change->req, &astr),
7317 astr_free(&astr);
7318 break;
7319 case RVCO_NOOP:
7320 fc_snprintf(buf, sizeof(buf),
7321 /* TRANS: do nothing to a requirement vector (in ruledit).
7322 * The first %s is a description of the requirement vector,
7323 * like "actor_reqs" */
7324 _("Do nothing to %s"), req_vec_description);
7325 break;
7326 }
7327
7328 return buf;
7329}
7330
7331/**********************************************************************/
7344 const void *parent_item)
7345{
7346 struct requirement_vector *target
7347 = getter(parent_item, modification->vector_number);
7348 int i = 0;
7349
7350 switch (modification->operation) {
7351 case RVCO_APPEND:
7353 return TRUE;
7354 case RVCO_REMOVE:
7358 return TRUE;
7359 }
7360 i++;
7362 return FALSE;
7363 case RVCO_NOOP:
7364 return FALSE;
7365 }
7366
7367 return FALSE;
7368}
7369
7370/**********************************************************************/
7380struct req_vec_problem *
7382 const char *description,
7383 const char *description_translated)
7384{
7385 struct req_vec_problem *out;
7386 int i;
7387
7388 out = fc_malloc(sizeof(*out));
7389
7390 fc_strlcpy(out->description, description, sizeof(out->description));
7391 fc_strlcpy(out->description_translated, _(description_translated),
7392 sizeof(out->description_translated));
7393
7394 out->num_suggested_solutions = num_suggested_solutions;
7395 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
7396 * sizeof(struct req_vec_change));
7397 for (i = 0; i < out->num_suggested_solutions; i++) {
7398 /* No suggestions are ready yet. */
7399 out->suggested_solutions[i].operation = RVCO_NOOP;
7400 out->suggested_solutions[i].vector_number = -1;
7401 out->suggested_solutions[i].req.source.kind = VUT_NONE;
7402 }
7403
7404 return out;
7405}
7406
7407/**********************************************************************/
7417 const char *descr, ...)
7418{
7419 char description[500];
7420 char description_translated[500];
7421 va_list ap;
7422
7423 va_start(ap, descr);
7424 fc_vsnprintf(description, sizeof(description), descr, ap);
7425 va_end(ap);
7426
7427 va_start(ap, descr);
7429 _(descr), ap);
7430 va_end(ap);
7431
7434}
7435
7436/**********************************************************************/
7443{
7444 FC_FREE(issue->suggested_solutions);
7445 issue->num_suggested_solutions = 0;
7446
7447 FC_FREE(issue);
7448}
7449
7450/**********************************************************************/
7462struct req_vec_problem *
7465 const void *parent_item)
7466{
7467 int i, j;
7469
7470 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7471 /* No vector. */
7472 return nullptr;
7473 }
7474
7475 if (get_num == nullptr || parent_item == nullptr) {
7476 vec_num = 0;
7477 } else {
7478 vec_num = get_num(parent_item, vec);
7479 }
7480
7481 /* Look for contradictions */
7482 for (i = 0; i < requirement_vector_size(vec); i++) {
7483 struct requirement *preq = requirement_vector_get(vec, i);
7484 for (j = 0; j < requirement_vector_size(vec); j++) {
7485 struct requirement *nreq = requirement_vector_get(vec, j);
7486
7488 struct req_vec_problem *problem;
7489 struct astring astr;
7490 struct astring nastr;
7491
7493 N_("Requirements {%s} and {%s} contradict each other."),
7495
7496 astr_free(&astr);
7497 astr_free(&nastr);
7498
7499 /* The solution is to remove one of the contradictions. */
7500 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7501 problem->suggested_solutions[0].vector_number = vec_num;
7502 problem->suggested_solutions[0].req = *preq;
7503
7504 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7505 problem->suggested_solutions[1].vector_number = vec_num;
7506 problem->suggested_solutions[1].req = *nreq;
7507
7508 /* Only the first contradiction is reported. */
7509 return problem;
7510 }
7511 }
7512 }
7513
7514 return nullptr;
7515}
7516
7517/**********************************************************************/
7528struct req_vec_problem *
7531 const void *parent_item)
7532{
7533 /* Check for self contradictins. */
7535}
7536
7537/**********************************************************************/
7550struct req_vec_problem *
7553 const void *parent_item)
7554{
7555 int i;
7557 struct req_vec_problem *problem = nullptr;
7558
7559 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7560 /* No vector. */
7561 return nullptr;
7562 }
7563
7564 if (get_num == nullptr || parent_item == nullptr) {
7565 vec_num = 0;
7566 } else {
7567 vec_num = get_num(parent_item, vec);
7568 }
7569
7570 /* Look for contradictions */
7571 for (i = 0; i < requirement_vector_size(vec); i++) {
7572 struct requirement *preq = requirement_vector_get(vec, i);
7573
7574 if (universal_never_there(&preq->source)) {
7575 struct astring astr;
7576
7577 if (preq->present) {
7578 /* The requirement vector can never be fulfilled. Removing the
7579 * requirement makes it possible to fulfill it. This is a rule
7580 * change and shouldn't be "fixed" without thinking. Don't offer any
7581 * automatic solution to prevent mindless "fixes". */
7582 /* TRANS: Ruledit warns a user about an unused requirement vector
7583 * that never can be fulfilled because it asks for something that
7584 * never will be there. */
7585 if (problem == nullptr) {
7587 N_("Requirement {%s} requires %s but it will never be"
7588 " there."),
7590 astr_free(&astr);
7591 }
7592
7593 /* Continue to check if other problems have a solution proposal,
7594 * and prefer to return those. */
7595 continue;
7596 }
7597
7598 if (problem != nullptr) {
7599 /* Free previous one (one with no solution proposals) */
7601 }
7602
7604 N_("Requirement {%s} mentions %s but it will never be there."),
7606
7607 astr_free(&astr);
7608
7609 /* The solution is to remove the reference to the missing
7610 * universal. */
7611 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7612 problem->suggested_solutions[0].vector_number = vec_num;
7613 problem->suggested_solutions[0].req = *preq;
7614
7615 /* Only the first missing universal is reported. */
7616 return problem;
7617 }
7618 }
7619
7620 return problem;
7621}
7622
7623/**********************************************************************/
7636struct req_vec_problem *
7639 const void *parent_item)
7640{
7641 int i, j;
7643
7644 if (vec == nullptr || requirement_vector_size(vec) == 0) {
7645 /* No vector. */
7646 return nullptr;
7647 }
7648
7649 if (get_num == nullptr || parent_item == nullptr) {
7650 vec_num = 0;
7651 } else {
7652 vec_num = get_num(parent_item, vec);
7653 }
7654
7655 /* Look for repeated requirements */
7656 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
7657 struct requirement *preq = requirement_vector_get(vec, i);
7658 for (j = i + 1; j < requirement_vector_size(vec); j++) {
7659 struct requirement *nreq = requirement_vector_get(vec, j);
7660
7662 struct req_vec_problem *problem;
7663 struct astring astr;
7664 struct astring nastr;
7665
7667 N_("Requirements {%s} and {%s} are the same."),
7669
7670 astr_free(&astr);
7671 astr_free(&nastr);
7672
7673 /* The solution is to remove one of the redundant requirements. */
7674 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7675 problem->suggested_solutions[0].vector_number = vec_num;
7676 problem->suggested_solutions[0].req = *preq;
7677
7678 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7679 problem->suggested_solutions[1].vector_number = vec_num;
7680 problem->suggested_solutions[1].req = *nreq;
7681
7682 /* Only the first redundancy is reported. */
7683 return problem;
7684 }
7685 }
7686 }
7687
7688 return nullptr;
7689}
7690
7691/**********************************************************************/
7703struct req_vec_problem *
7706 const void *parent_item)
7707{
7708 struct req_vec_problem *out;
7709
7711 if (out != nullptr) {
7712 /* A bug, not just a potential improvement */
7713 return out;
7714 }
7715
7716 /* Check if a universal that never will appear in the game is checked. */
7718 if (out != nullptr) {
7719 return out;
7720 }
7721
7722 /* Check if a requirement is redundant. */
7724 return out;
7725}
7726
7727/**********************************************************************/
7732 const struct universal *psource2)
7733{
7734 if (psource1->kind != psource2->kind) {
7735 return FALSE;
7736 }
7737 switch (psource1->kind) {
7738 case VUT_NONE:
7739 return TRUE;
7740 case VUT_COUNTER:
7741 return psource1->value.counter == psource2->value.counter;
7742 case VUT_ADVANCE:
7743 return psource1->value.advance == psource2->value.advance;
7744 case VUT_TECHFLAG:
7745 return psource1->value.techflag == psource2->value.techflag;
7746 case VUT_GOVERNMENT:
7747 return psource1->value.govern == psource2->value.govern;
7748 case VUT_GOVFLAG:
7749 return psource1->value.govflag == psource2->value.govflag;
7750 case VUT_ACHIEVEMENT:
7751 return psource1->value.achievement == psource2->value.achievement;
7752 case VUT_STYLE:
7753 return psource1->value.style == psource2->value.style;
7754 case VUT_IMPROVEMENT:
7755 case VUT_SITE:
7756 return psource1->value.building == psource2->value.building;
7757 case VUT_IMPR_GENUS:
7758 return psource1->value.impr_genus == psource2->value.impr_genus;
7759 case VUT_IMPR_FLAG:
7760 return psource1->value.impr_flag == psource2->value.impr_flag;
7761 case VUT_PLAYER_FLAG:
7762 return psource1->value.plr_flag == psource2->value.plr_flag;
7763 case VUT_PLAYER_STATE:
7764 return psource1->value.plrstate == psource2->value.plrstate;
7765 case VUT_EXTRA:
7766 return psource1->value.extra == psource2->value.extra;
7767 case VUT_TILEDEF:
7768 return psource1->value.tiledef == psource2->value.tiledef;
7769 case VUT_GOOD:
7770 return psource1->value.good == psource2->value.good;
7771 case VUT_TERRAIN:
7772 return psource1->value.terrain == psource2->value.terrain;
7773 case VUT_TERRFLAG:
7774 return psource1->value.terrainflag == psource2->value.terrainflag;
7775 case VUT_NATION:
7776 return psource1->value.nation == psource2->value.nation;
7777 case VUT_NATIONGROUP:
7778 return psource1->value.nationgroup == psource2->value.nationgroup;
7779 case VUT_NATIONALITY:
7780 return psource1->value.nationality == psource2->value.nationality;
7781 case VUT_ORIGINAL_OWNER:
7782 return psource1->value.origowner == psource2->value.origowner;
7783 case VUT_DIPLREL:
7784 case VUT_DIPLREL_TILE:
7785 case VUT_DIPLREL_TILE_O:
7788 return psource1->value.diplrel == psource2->value.diplrel;
7789 case VUT_UTYPE:
7790 return psource1->value.utype == psource2->value.utype;
7791 case VUT_UTFLAG:
7792 return psource1->value.unitflag == psource2->value.unitflag;
7793 case VUT_UCLASS:
7794 return psource1->value.uclass == psource2->value.uclass;
7795 case VUT_UCFLAG:
7796 return psource1->value.unitclassflag == psource2->value.unitclassflag;
7797 case VUT_MINVETERAN:
7798 return psource1->value.minveteran == psource2->value.minveteran;
7799 case VUT_UNITSTATE:
7800 return psource1->value.unit_state == psource2->value.unit_state;
7801 case VUT_ACTIVITY:
7802 return psource1->value.activity == psource2->value.activity;
7803 case VUT_MINMOVES:
7804 return psource1->value.minmoves == psource2->value.minmoves;
7805 case VUT_MINHP:
7806 return psource1->value.min_hit_points == psource2->value.min_hit_points;
7807 case VUT_AGE:
7808 return psource1->value.age == psource2->value.age;
7809 case VUT_FORM_AGE:
7810 return psource1->value.form_age == psource2->value.form_age;
7811 case VUT_MINTECHS:
7812 return psource1->value.min_techs == psource2->value.min_techs;
7813 case VUT_FUTURETECHS:
7814 return psource1->value.future_techs == psource2->value.future_techs;
7815 case VUT_MINCITIES:
7816 return psource1->value.min_cities == psource2->value.min_cities;
7817 case VUT_ACTION:
7818 return (action_number(psource1->value.action)
7819 == action_number(psource2->value.action));
7820 case VUT_OTYPE:
7821 return psource1->value.outputtype == psource2->value.outputtype;
7822 case VUT_SPECIALIST:
7823 return psource1->value.specialist == psource2->value.specialist;
7824 case VUT_MINSIZE:
7825 return psource1->value.minsize == psource2->value.minsize;
7826 case VUT_MINCULTURE:
7827 return psource1->value.minculture == psource2->value.minculture;
7828 case VUT_MINFOREIGNPCT:
7829 return psource1->value.minforeignpct == psource2->value.minforeignpct;
7830 case VUT_AI_LEVEL:
7831 return psource1->value.ai_level == psource2->value.ai_level;
7833 return psource1->value.max_tile_total_units == psource2->value.max_tile_total_units;
7835 return psource1->value.max_tile_top_units == psource2->value.max_tile_top_units;
7836 case VUT_TERRAINCLASS:
7837 return psource1->value.terrainclass == psource2->value.terrainclass;
7838 case VUT_ROADFLAG:
7839 return psource1->value.roadflag == psource2->value.roadflag;
7840 case VUT_EXTRAFLAG:
7841 return psource1->value.extraflag == psource2->value.extraflag;
7842 case VUT_MINYEAR:
7843 return psource1->value.minyear == psource2->value.minyear;
7844 case VUT_MINCALFRAG:
7845 return psource1->value.mincalfrag == psource2->value.mincalfrag;
7846 case VUT_TOPO:
7847 return psource1->value.topo_property == psource2->value.topo_property;
7848 case VUT_WRAP:
7849 return psource1->value.wrap_property == psource2->value.wrap_property;
7850 case VUT_SERVERSETTING:
7851 return psource1->value.ssetval == psource2->value.ssetval;
7852 case VUT_TERRAINALTER:
7853 return psource1->value.terrainalter == psource2->value.terrainalter;
7854 case VUT_CITYTILE:
7855 return psource1->value.citytile == psource2->value.citytile;
7856 case VUT_CITYSTATUS:
7857 return psource1->value.citystatus == psource2->value.citystatus;
7858 case VUT_TILE_REL:
7859 return psource1->value.tilerel == psource2->value.tilerel;
7860 case VUT_MINLATITUDE:
7861 case VUT_MAXLATITUDE:
7862 return psource1->value.latitude == psource2->value.latitude;
7864 return psource1->value.distance_sq == psource2->value.distance_sq;
7866 return psource1->value.region_tiles == psource2->value.region_tiles;
7867 case VUT_COUNT:
7868 break;
7869 }
7870
7871 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
7872 return FALSE;
7873}
7874
7875/**********************************************************************/
7879const char *universal_rule_name(const struct universal *psource)
7880{
7881 static char buffer[10];
7882
7883 switch (psource->kind) {
7884 case VUT_NONE:
7885 return "(none)";
7886 case VUT_COUNTER:
7887 return counter_rule_name(psource->value.counter);
7888 case VUT_CITYTILE:
7889 return citytile_type_name(psource->value.citytile);
7890 case VUT_CITYSTATUS:
7891 return citystatus_type_name(psource->value.citystatus);
7892 case VUT_TILE_REL:
7893 return tilerel_type_name(psource->value.tilerel);
7894 case VUT_MINYEAR:
7895 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
7896
7897 return buffer;
7898 case VUT_MINCALFRAG:
7899 /* Rule name is 0-based number, not pretty name from ruleset */
7900 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
7901
7902 return buffer;
7903 case VUT_TOPO:
7904 return topo_flag_name(psource->value.topo_property);
7905 case VUT_WRAP:
7906 return wrap_flag_name(psource->value.wrap_property);
7907 case VUT_SERVERSETTING:
7908 return ssetv_rule_name(psource->value.ssetval);
7909 case VUT_ADVANCE:
7910 return advance_rule_name(psource->value.advance);
7911 case VUT_TECHFLAG:
7912 return tech_flag_id_name(psource->value.techflag);
7913 case VUT_GOVERNMENT:
7914 return government_rule_name(psource->value.govern);
7915 case VUT_GOVFLAG:
7916 return gov_flag_id_name(psource->value.govflag);
7917 case VUT_ACHIEVEMENT:
7918 return achievement_rule_name(psource->value.achievement);
7919 case VUT_STYLE:
7920 return style_rule_name(psource->value.style);
7921 case VUT_IMPROVEMENT:
7922 case VUT_SITE:
7923 return improvement_rule_name(psource->value.building);
7924 case VUT_IMPR_GENUS:
7925 return impr_genus_id_name(psource->value.impr_genus);
7926 case VUT_IMPR_FLAG:
7927 return impr_flag_id_name(psource->value.impr_flag);
7928 case VUT_PLAYER_FLAG:
7929 return plr_flag_id_name(psource->value.plr_flag);
7930 case VUT_PLAYER_STATE:
7931 return plrstate_type_name(psource->value.plrstate);
7932 case VUT_EXTRA:
7933 return extra_rule_name(psource->value.extra);
7934 case VUT_TILEDEF:
7935 return tiledef_rule_name(psource->value.tiledef);
7936 case VUT_GOOD:
7937 return goods_rule_name(psource->value.good);
7938 case VUT_TERRAIN:
7939 return terrain_rule_name(psource->value.terrain);
7940 case VUT_TERRFLAG:
7941 return terrain_flag_id_name(psource->value.terrainflag);
7942 case VUT_NATION:
7943 return nation_rule_name(psource->value.nation);
7944 case VUT_NATIONGROUP:
7945 return nation_group_rule_name(psource->value.nationgroup);
7946 case VUT_DIPLREL:
7947 case VUT_DIPLREL_TILE:
7948 case VUT_DIPLREL_TILE_O:
7951 return diplrel_rule_name(psource->value.diplrel);
7952 case VUT_NATIONALITY:
7953 return nation_rule_name(psource->value.nationality);
7954 case VUT_ORIGINAL_OWNER:
7955 return nation_rule_name(psource->value.origowner);
7956 case VUT_UTYPE:
7957 return utype_rule_name(psource->value.utype);
7958 case VUT_UTFLAG:
7959 return unit_type_flag_id_name(psource->value.unitflag);
7960 case VUT_UCLASS:
7961 return uclass_rule_name(psource->value.uclass);
7962 case VUT_UCFLAG:
7963 return unit_class_flag_id_name(psource->value.unitclassflag);
7964 case VUT_MINVETERAN:
7965 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
7966
7967 return buffer;
7968 case VUT_UNITSTATE:
7969 return ustate_prop_name(psource->value.unit_state);
7970 case VUT_ACTIVITY:
7971 return unit_activity_name(psource->value.activity);
7972 case VUT_MINMOVES:
7973 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
7974
7975 return buffer;
7976 case VUT_MINHP:
7977 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
7978
7979 return buffer;
7980 case VUT_AGE:
7981 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
7982
7983 return buffer;
7984 case VUT_FORM_AGE:
7985 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
7986
7987 return buffer;
7988 case VUT_MINTECHS:
7989 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
7990
7991 return buffer;
7992 case VUT_FUTURETECHS:
7993 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.future_techs);
7994
7995 return buffer;
7996 case VUT_MINCITIES:
7997 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_cities);
7998
7999 return buffer;
8000 case VUT_ACTION:
8001 return action_rule_name(psource->value.action);
8002 case VUT_OTYPE:
8003 return get_output_identifier(psource->value.outputtype);
8004 case VUT_SPECIALIST:
8005 return specialist_rule_name(psource->value.specialist);
8006 case VUT_MINSIZE:
8007 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
8008
8009 return buffer;
8010 case VUT_MINCULTURE:
8011 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
8012
8013 return buffer;
8014 case VUT_MINFOREIGNPCT:
8015 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
8016
8017 return buffer;
8018 case VUT_AI_LEVEL:
8019 return ai_level_name(psource->value.ai_level);
8021 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_total_units);
8022 return buffer;
8024 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_top_units);
8025 return buffer;
8026 case VUT_TERRAINCLASS:
8027 return terrain_class_name(psource->value.terrainclass);
8028 case VUT_ROADFLAG:
8029 return road_flag_id_name(psource->value.roadflag);
8030 case VUT_EXTRAFLAG:
8031 return extra_flag_id_name(psource->value.extraflag);
8032 case VUT_TERRAINALTER:
8033 return terrain_alteration_name(psource->value.terrainalter);
8034 case VUT_MINLATITUDE:
8035 case VUT_MAXLATITUDE:
8036 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
8037
8038 return buffer;
8040 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.distance_sq);
8041
8042 return buffer;
8044 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.region_tiles);
8045
8046 return buffer;
8047 case VUT_COUNT:
8048 break;
8049 }
8050
8051 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8052
8053 return nullptr;
8054}
8055
8056/**********************************************************************/
8065 char *buf, size_t bufsz)
8066{
8067 buf[0] = '\0'; /* to be safe. */
8068 switch (psource->kind) {
8069 case VUT_NONE:
8070 /* TRANS: missing value */
8071 fc_strlcat(buf, _("(none)"), bufsz);
8072 return buf;
8073 case VUT_ADVANCE:
8075 return buf;
8076 case VUT_COUNTER:
8078 return buf;
8079 case VUT_TECHFLAG:
8080 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
8081 tech_flag_id_translated_name(psource->value.techflag));
8082 return buf;
8083 case VUT_GOVERNMENT:
8085 bufsz);
8086 return buf;
8087 case VUT_GOVFLAG:
8088 cat_snprintf(buf, bufsz, _("\"%s\" gov"),
8089 gov_flag_id_translated_name(psource->value.govflag));
8090 return buf;
8091 case VUT_ACHIEVEMENT:
8093 bufsz);
8094 return buf;
8095 case VUT_STYLE:
8097 bufsz);
8098 return buf;
8099 case VUT_IMPROVEMENT:
8101 bufsz);
8102 return buf;
8103 case VUT_SITE:
8104 {
8105 char local_buf[1024];
8106
8107 fc_snprintf(local_buf, sizeof(local_buf), _("%s site"),
8108 improvement_name_translation(psource->value.building));
8110 }
8111
8112 return buf;
8113 case VUT_IMPR_GENUS:
8115 impr_genus_id_translated_name(psource->value.impr_genus),
8116 bufsz);
8117 return buf;
8118 case VUT_IMPR_FLAG:
8120 impr_flag_id_translated_name(psource->value.impr_flag),
8121 bufsz);
8122 return buf;
8123 case VUT_PLAYER_FLAG:
8125 plr_flag_id_translated_name(psource->value.plr_flag),
8126 bufsz);
8127 return buf;
8128 case VUT_PLAYER_STATE:
8130 plrstate_type_translated_name(psource->value.plrstate),
8131 bufsz);
8132 return buf;
8133 case VUT_EXTRA:
8135 return buf;
8136 case VUT_TILEDEF:
8138 return buf;
8139 case VUT_GOOD:
8141 return buf;
8142 case VUT_TERRAIN:
8144 return buf;
8145 case VUT_NATION:
8147 bufsz);
8148 return buf;
8149 case VUT_NATIONGROUP:
8151 bufsz);
8152 return buf;
8153 case VUT_NATIONALITY:
8154 cat_snprintf(buf, bufsz, _("%s citizens"),
8155 nation_adjective_translation(psource->value.nationality));
8156 return buf;
8157 case VUT_ORIGINAL_OWNER:
8158 /* TRANS: Keep short. City founding nation. */
8159 cat_snprintf(buf, bufsz, _("%s original owner"),
8160 nation_adjective_translation(psource->value.origowner));
8161 return buf;
8162 case VUT_DIPLREL:
8163 case VUT_DIPLREL_TILE:
8164 case VUT_DIPLREL_TILE_O:
8168 bufsz);
8169 return buf;
8170 case VUT_UTYPE:
8172 return buf;
8173 case VUT_UTFLAG:
8175 /* TRANS: Unit type flag */
8176 Q_("?utflag:\"%s\" units"),
8178 psource->value.unitflag));
8179 return buf;
8180 case VUT_UCLASS:
8182 /* TRANS: Unit class */
8183 _("%s units"),
8184 uclass_name_translation(psource->value.uclass));
8185 return buf;
8186 case VUT_UCFLAG:
8188 /* TRANS: Unit class flag */
8189 Q_("?ucflag:\"%s\" units"),
8191 psource->value.unitclassflag));
8192 return buf;
8193 case VUT_MINVETERAN:
8194 /* FIXME */
8195 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
8196 psource->value.minveteran);
8197 return buf;
8198 case VUT_UNITSTATE:
8199 switch (psource->value.unit_state) {
8200 case USP_TRANSPORTED:
8201 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
8202 cat_snprintf(buf, bufsz, _("Transported"));
8203 break;
8204 case USP_LIVABLE_TILE:
8206 /* TRANS: unit state. (appears in strings like
8207 * "Missile+On livable tile") */
8208 _("On livable tile"));
8209 break;
8210 case USP_TRANSPORTING:
8211 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
8212 cat_snprintf(buf, bufsz, _("Transporting"));
8213 break;
8214 case USP_HAS_HOME_CITY:
8215 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
8216 cat_snprintf(buf, bufsz, _("Has a home city"));
8217 break;
8218 case USP_NATIVE_TILE:
8220 /* TRANS: unit state. (appears in strings like
8221 * "Missile+On native tile") */
8222 _("On native tile"));
8223 break;
8224 case USP_NATIVE_EXTRA:
8226 /* TRANS: unit state. (appears in strings like
8227 * "Missile+In native extra") */
8228 _("In native extra"));
8229 break;
8231 /* TRANS: unit state. (appears in strings like
8232 * "Missile+Has moved this turn") */
8233 cat_snprintf(buf, bufsz, _("Has moved this turn"));
8234 break;
8235 case USP_COUNT:
8236 fc_assert_msg(psource->value.unit_state != USP_COUNT,
8237 "Invalid unit state property.");
8238 break;
8239 }
8240 return buf;
8241 case VUT_ACTIVITY:
8242 cat_snprintf(buf, bufsz, _("%s activity"),
8243 Q_(unit_activity_name(psource->value.activity)));
8244 return buf;
8245 case VUT_MINMOVES:
8246 /* TRANS: Minimum unit movement points left for requirement to be met
8247 * (%s is a string like "1" or "2 1/3") */
8248 cat_snprintf(buf, bufsz, _("%s MP"),
8249 move_points_text(psource->value.minmoves, TRUE));
8250 return buf;
8251 case VUT_MINHP:
8252 /* TRANS: HP = hit points */
8253 cat_snprintf(buf, bufsz, _("%d HP"),
8254 psource->value.min_hit_points);
8255 return buf;
8256 case VUT_AGE:
8257 cat_snprintf(buf, bufsz, _("Age %d"),
8258 psource->value.age);
8259 return buf;
8260 case VUT_FORM_AGE:
8261 cat_snprintf(buf, bufsz, _("Form age %d"),
8262 psource->value.form_age);
8263 return buf;
8264 case VUT_MINTECHS:
8265 cat_snprintf(buf, bufsz, _("%d Techs"),
8266 psource->value.min_techs);
8267 return buf;
8268 case VUT_FUTURETECHS:
8269 cat_snprintf(buf, bufsz, _("%d Future techs"),
8270 psource->value.future_techs);
8271 return buf;
8272 case VUT_MINCITIES:
8273 cat_snprintf(buf, bufsz, _("%d Cities"),
8274 psource->value.min_cities);
8275 return buf;
8276 case VUT_ACTION:
8278 bufsz);
8279 return buf;
8280 case VUT_OTYPE:
8281 /* FIXME */
8282 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
8283 return buf;
8284 case VUT_SPECIALIST:
8286 bufsz);
8287 return buf;
8288 case VUT_MINSIZE:
8289 cat_snprintf(buf, bufsz, _("Size %d"),
8290 psource->value.minsize);
8291 return buf;
8292 case VUT_MINCULTURE:
8293 cat_snprintf(buf, bufsz, _("Culture %d"),
8294 psource->value.minculture);
8295 return buf;
8296 case VUT_MINFOREIGNPCT:
8297 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
8298 psource->value.minforeignpct);
8299 return buf;
8300 case VUT_AI_LEVEL:
8301 /* TRANS: "Hard AI" */
8302 cat_snprintf(buf, bufsz, _("%s AI"),
8303 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
8304 return buf;
8306 /* TRANS: here <= means 'less than or equal' */
8307 cat_snprintf(buf, bufsz, PL_("<=%d total unit",
8308 "<=%d total units",
8309 psource->value.max_tile_total_units),
8310 psource->value.max_tile_total_units);
8311 return buf;
8313 /* TRANS: here <= means 'less than or equal' */
8314 cat_snprintf(buf, bufsz, PL_("<=%d unit",
8315 "<=%d units", psource->value.max_tile_top_units),
8316 psource->value.max_tile_top_units);
8317 return buf;
8318 case VUT_TERRAINCLASS:
8319 /* TRANS: Terrain class: "Land terrain" */
8320 cat_snprintf(buf, bufsz, _("%s terrain"),
8321 terrain_class_name_translation(psource->value.terrainclass));
8322 return buf;
8323 case VUT_TERRFLAG:
8325 /* TRANS: Terrain flag */
8326 Q_("?terrflag:\"%s\" terrain"),
8328 psource->value.terrainflag));
8329 return buf;
8330 case VUT_ROADFLAG:
8332 /* TRANS: Road flag */
8333 Q_("?roadflag:\"%s\" road"),
8334 road_flag_id_translated_name(psource->value.roadflag));
8335 return buf;
8336 case VUT_EXTRAFLAG:
8338 /* TRANS: Extra flag */
8339 Q_("?extraflag:\"%s\" extra"),
8340 extra_flag_id_translated_name(psource->value.extraflag));
8341 return buf;
8342 case VUT_MINYEAR:
8343 cat_snprintf(buf, bufsz, _("After %s"),
8344 textyear(psource->value.minyear));
8345 return buf;
8346 case VUT_MINCALFRAG:
8347 /* TRANS: here >= means 'greater than or equal'.
8348 * %s identifies a calendar fragment (may be bare number). */
8349 cat_snprintf(buf, bufsz, _(">=%s"),
8350 textcalfrag(psource->value.mincalfrag));
8351 return buf;
8352 case VUT_TOPO:
8353 /* TRANS: topology flag name ("Hex", "ISO") */
8354 cat_snprintf(buf, bufsz, _("%s map"),
8355 _(topo_flag_name(psource->value.topo_property)));
8356 return buf;
8357 case VUT_WRAP:
8358 /* TRANS: wrap flag name ("WrapX", "WrapY") */
8359 cat_snprintf(buf, bufsz, _("%s map"),
8360 _(wrap_flag_name(psource->value.wrap_property)));
8361 return buf;
8362 case VUT_SERVERSETTING:
8364 bufsz);
8365 return buf;
8366 case VUT_TERRAINALTER:
8367 /* TRANS: "Irrigation possible" */
8368 cat_snprintf(buf, bufsz, _("%s possible"),
8369 Q_(terrain_alteration_name(psource->value.terrainalter)));
8370 return buf;
8371 case VUT_CITYTILE:
8372 switch (psource->value.citytile) {
8373 case CITYT_CENTER:
8374 fc_strlcat(buf, _("City center"), bufsz);
8375 break;
8376 case CITYT_CLAIMED:
8377 fc_strlcat(buf, _("Tile claimed"), bufsz);
8378 break;
8379 case CITYT_EXTRAS_OWNED:
8380 fc_strlcat(buf, _("Extras owned"), bufsz);
8381 break;
8382 case CITYT_WORKED:
8383 fc_strlcat(buf, _("Worked tile"), bufsz);
8384 break;
8386 fc_strlcat(buf, _("Same continent tile"), bufsz);
8387 break;
8389 /* TRANS: Short for "a tile of other terrain class mass near city" */
8390 fc_strlcat(buf, _("Port reachable tile"), bufsz);
8391 break;
8392 case CITYT_LAST:
8393 fc_assert(psource->value.citytile != CITYT_LAST);
8394 fc_strlcat(buf, "error", bufsz);
8395 break;
8396 }
8397 return buf;
8398 case VUT_CITYSTATUS:
8399 switch (psource->value.citystatus) {
8401 fc_strlcat(buf, _("Owned by original"), bufsz);
8402 break;
8403 case CITYS_STARVED:
8404 fc_strlcat(buf, _("Starved"), bufsz);
8405 break;
8406 case CITYS_DISORDER:
8407 fc_strlcat(buf, _("Disorder"), bufsz);
8408 break;
8409 case CITYS_CELEBRATION:
8410 fc_strlcat(buf, _("Celebration"), bufsz);
8411 break;
8412 case CITYS_TRANSFERRED:
8413 /* TRANS: CityStatus value - city has changed hands */
8414 fc_strlcat(buf, _("Transferred"), bufsz);
8415 break;
8417 fc_strlcat(buf, _("CapitalConnected"), bufsz);
8418 break;
8419 case CITYS_LAST:
8420 fc_assert(psource->value.citystatus != CITYS_LAST);
8421 fc_strlcat(buf, "error", bufsz);
8422 break;
8423 }
8424 return buf;
8425 case VUT_TILE_REL:
8426 switch (psource->value.tilerel) {
8427 case TREL_SAME_TCLASS:
8428 fc_strlcat(buf, _("Same terrain class"), bufsz);
8429 break;
8430 case TREL_SAME_REGION:
8431 fc_strlcat(buf, _("Same continent/ocean"), bufsz);
8432 break;
8434 fc_strlcat(buf, _("Only other continent/ocean"), bufsz);
8435 break;
8437 fc_strlcat(buf, _("Lake/island surrounded"), bufsz);
8438 break;
8439 case TREL_COUNT:
8440 fc_assert(psource->value.tilerel != TREL_COUNT);
8441 fc_strlcat(buf, "error", bufsz);
8442 break;
8443 }
8444 return buf;
8445 case VUT_MINLATITUDE:
8446 /* TRANS: here >= means 'greater than or equal'. */
8447 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
8448 psource->value.latitude);
8449 return buf;
8450 case VUT_MAXLATITUDE:
8451 /* TRANS: here <= means 'less than or equal'. */
8452 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
8453 psource->value.latitude);
8454 return buf;
8456 /* TRANS: here <= means 'less than or equal'. */
8457 cat_snprintf(buf, bufsz, _("Squared distance <= %d"),
8458 psource->value.distance_sq);
8459 return buf;
8461 cat_snprintf(buf, bufsz, _("%d or fewer region tiles"),
8462 psource->value.region_tiles);
8463 return buf;
8464 case VUT_COUNT:
8465 break;
8466 }
8467
8468 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8469 return buf;
8470}
8471
8472/**********************************************************************/
8476{
8477 return universals_n_name(psource->kind);
8478}
8479
8480/**********************************************************************/
8484 const struct universal *target)
8485{
8486 switch (target->kind) {
8487 case VUT_IMPROVEMENT:
8488 case VUT_SITE:
8489 return impr_build_shield_cost(pcity, target->value.building);
8490 case VUT_UTYPE:
8491 return utype_build_shield_cost(pcity, nullptr, target->value.utype);
8492 default:
8493 break;
8494 }
8495 return FC_INFINITY;
8496}
8497
8498/**********************************************************************/
8504 const struct universal *to_replace,
8505 const struct universal *replacement)
8506{
8507 bool changed = FALSE;
8508
8511 preq->source = *replacement;
8512 changed = TRUE;
8513 }
8515
8516 return changed;
8517}
8518
8519/**********************************************************************/
8524 const struct requirement_vector *reqs,
8525 const struct universal *psource)
8526{
8529 return TRUE;
8530 }
8532
8533 return FALSE;
8534}
8535
8536/**********************************************************************/
8547 struct universal *unis,
8548 size_t n_unis)
8549{
8550 int i;
8551
8552 for (i = 0; i < n_unis; i++) {
8554 /* This universal makes it impossible to fulfill the specified
8555 * requirement vector */
8556 return TRUE;
8557 }
8558 }
8559
8560 /* No specified universal is known to guarantee that the requirement
8561 * vector never will be fulfilled. */
8562 return FALSE;
8563}
8564
8565/**********************************************************************/
8581 struct universal *unis,
8582 size_t n_unis)
8583{
8585 int i;
8587
8588 for (i = 0; i < n_unis; i++) {
8589 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
8590 case ITF_NO:
8591 case ITF_YES:
8592 /* this req matched this source */
8594 break;
8595 case ITF_NOT_APPLICABLE:
8596 /* Not a mention. */
8597 break;
8598 }
8599 }
8600
8602 /* A requirement not relevant to any of the specified universals was
8603 * found in the requirement vector. */
8604 return FALSE;
8605 }
8607
8608 /* No requirement not relevant to any of the specified universals was
8609 * found in the requirement vector. */
8610 return TRUE;
8611}
8612
8613/**********************************************************************/
8616enum req_item_found
8618 const struct universal *source)
8619{
8622 "No req item found function for %s",
8624
8625 return (*universal_found_function[source->kind])(preq, source);
8626}
8627
8628/**********************************************************************/
8639 const struct requirement_vector *reqs,
8640 const struct universal *source)
8641{
8642 bool necessary = FALSE;
8643
8646 "No req item found function for %s",
8648
8650 switch ((*universal_found_function[source->kind])(preq, source)) {
8651 case ITF_NOT_APPLICABLE:
8652 continue;
8653 case ITF_NO:
8654 if (preq->present) {
8655 return FALSE;
8656 }
8657 break;
8658 case ITF_YES:
8659 if (preq->present) {
8660 necessary = TRUE;
8661 } else {
8662 return FALSE;
8663 }
8664 break;
8665 }
8667
8668 return (!check_necessary || necessary);
8669}
8670
8671/**********************************************************************/
8676 const struct universal *source)
8677{
8678 switch (universal_fulfills_requirement(req, source)) {
8679 case ITF_NOT_APPLICABLE:
8680 return FALSE;
8681 case ITF_NO:
8682 case ITF_YES:
8683 return TRUE;
8684 }
8685
8686 log_error("Unhandled item_found value");
8687 return FALSE;
8688}
8689
8690/**********************************************************************/
8694 const struct universal *source)
8695{
8696 fc_assert(source->value.nation);
8697
8698 switch (preq->source.kind) {
8699 case VUT_NATION:
8700 return preq->source.value.nation == source->value.nation ? ITF_YES
8701 : ITF_NO;
8702 case VUT_NATIONGROUP:
8703 return nation_is_in_group(source->value.nation,
8704 preq->source.value.nationgroup) ? ITF_YES
8705 : ITF_NO;
8706 default:
8707 break;
8708 }
8709
8710 return ITF_NOT_APPLICABLE;
8711}
8712
8713/**********************************************************************/
8717 const struct universal *source)
8718{
8719 fc_assert(source->value.govern);
8720
8721 if (preq->source.kind == VUT_GOVERNMENT) {
8722 return preq->source.value.govern == source->value.govern ? ITF_YES
8723 : ITF_NO;
8724 } else if (preq->source.kind == VUT_GOVFLAG) {
8725 return BV_ISSET(source->value.govern->flags, preq->source.value.govflag)
8726 ? ITF_YES : ITF_NO;
8727 }
8728
8729 return ITF_NOT_APPLICABLE;
8730}
8731
8732/**********************************************************************/
8736 const struct universal *source)
8737{
8738 fc_assert(source->value.min_cities);
8739
8740 if (preq->source.kind == VUT_MINCITIES) {
8741 return preq->source.value.min_cities <= source->value.min_cities ? ITF_YES
8742 : ITF_NO;
8743 }
8744
8745 return ITF_NOT_APPLICABLE;
8746}
8747
8748/**********************************************************************/
8752 const struct universal *source)
8753{
8754 fc_assert(source->value.building);
8755
8756 /* We only ever return ITF_YES, because requiring a different
8757 * improvement does not mean that the improvement under consideration
8758 * cannot fulfill the requirements. This is necessary to allow
8759 * requirement vectors to specify multiple required improvements. */
8760
8761 switch (preq->source.kind) {
8762 case VUT_IMPROVEMENT:
8763 case VUT_SITE:
8764 if (source->value.building == preq->source.value.building) {
8765 return ITF_YES;
8766 }
8767 break;
8768 case VUT_IMPR_GENUS:
8769 if (source->value.building->genus == preq->source.value.impr_genus) {
8770 return ITF_YES;
8771 }
8772 break;
8773 case VUT_IMPR_FLAG:
8774 if (improvement_has_flag(source->value.building,
8775 preq->source.value.impr_flag)) {
8776 return ITF_YES;
8777 }
8778 break;
8779 default:
8780 break;
8781 }
8782
8783 return ITF_NOT_APPLICABLE;
8784}
8785
8786/**********************************************************************/
8790 const struct universal *source)
8791{
8792 fc_assert(source->value.uclass);
8793
8794 switch (preq->source.kind) {
8795 case VUT_UCLASS:
8796 return source->value.uclass == preq->source.value.uclass ? ITF_YES
8797 : ITF_NO;
8798 case VUT_UCFLAG:
8799 return uclass_has_flag(source->value.uclass,
8800 preq->source.value.unitclassflag) ? ITF_YES
8801 : ITF_NO;
8802
8803 default:
8804 /* Not found and not relevant. */
8805 return ITF_NOT_APPLICABLE;
8806 };
8807}
8808
8809/**********************************************************************/
8813 const struct universal *source)
8814{
8815 fc_assert(source->value.utype);
8816
8817 switch (preq->source.kind) {
8818 case VUT_UTYPE:
8819 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
8820 case VUT_UCLASS:
8821 return utype_class(source->value.utype) == preq->source.value.uclass
8822 ? ITF_YES : ITF_NO;
8823 case VUT_UTFLAG:
8824 return utype_has_flag(source->value.utype,
8825 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
8826 case VUT_UCFLAG:
8827 return uclass_has_flag(utype_class(source->value.utype),
8828 preq->source.value.unitclassflag) ? ITF_YES
8829 : ITF_NO;
8830 default:
8831 /* Not found and not relevant. */
8832 return ITF_NOT_APPLICABLE;
8833 };
8834}
8835
8836/**********************************************************************/
8839static enum req_item_found
8841 const struct universal *source)
8842{
8845
8846 switch (preq->source.kind) {
8847 case VUT_ACTIVITY:
8848 return source->value.activity == preq->source.value.activity ? ITF_YES
8849 : ITF_NO;
8850 default:
8851 /* Not found and not relevant. */
8852 return ITF_NOT_APPLICABLE;
8853 };
8854}
8855
8856/**********************************************************************/
8860 const struct universal *source)
8861{
8862 fc_assert(source->value.terrain);
8863
8864 switch (preq->source.kind) {
8865 case VUT_TERRAIN:
8866 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
8867 case VUT_TERRAINCLASS:
8868 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
8869 ? ITF_YES : ITF_NO;
8870 case VUT_TERRFLAG:
8871 return terrain_has_flag(source->value.terrain,
8872 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
8873 case VUT_TERRAINALTER:
8874 return (terrain_can_support_alteration(source->value.terrain,
8875 preq->source.value.terrainalter)
8876 ? ITF_YES : ITF_NO);
8877 default:
8878 /* Not found and not relevant. */
8879 return ITF_NOT_APPLICABLE;
8880 };
8881}
8882
8883/**********************************************************************/
8887 const struct universal *source)
8888{
8891
8892 switch (preq->source.kind) {
8893 case VUT_CITYTILE:
8894 return (source->value.citytile == preq->source.value.citytile
8895 ? ITF_YES
8896 /* The presence of one tile state doesn't block another */
8898 default:
8899 /* Not found and not relevant. */
8900 return ITF_NOT_APPLICABLE;
8901 };
8902}
8903
8904/**********************************************************************/
8910 const struct universal *source)
8911{
8912 fc_assert(source->value.extra);
8913
8914 switch (preq->source.kind) {
8915 case VUT_EXTRA:
8916 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
8917 case VUT_EXTRAFLAG:
8918 return extra_has_flag(source->value.extra,
8919 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
8920 case VUT_ROADFLAG:
8921 {
8922 struct road_type *r = extra_road_get(source->value.extra);
8923 return r && road_has_flag(r, preq->source.value.roadflag)
8924 ? ITF_YES : ITF_NO;
8925 }
8926 default:
8927 /* Not found and not relevant. */
8928 return ITF_NOT_APPLICABLE;
8929 }
8930}
8931
8932/**********************************************************************/
8936 const struct universal *source)
8937{
8938 fc_assert(source->value.action);
8939
8940 if (preq->source.kind == VUT_ACTION) {
8941 return preq->source.value.action == source->value.action ? ITF_YES
8942 : ITF_NO;
8943 }
8944
8945 return ITF_NOT_APPLICABLE;
8946}
8947
8948/**********************************************************************/
8952 const struct universal *source)
8953{
8955 || source->kind == VUT_DIPLREL_TILE
8956 || source->kind == VUT_DIPLREL_TILE_O
8957 || source->kind == VUT_DIPLREL_UNITANY
8958 || source->kind == VUT_DIPLREL_UNITANY_O),
8960
8961 if (preq->source.kind == source->kind) {
8962 if (preq->source.value.diplrel == source->value.diplrel) {
8963 /* The diplrel itself. */
8964 return ITF_YES;
8965 }
8966 if (preq->source.value.diplrel == DRO_FOREIGN
8967 && source->value.diplrel < DS_LAST) {
8968 /* All diplstate_type values are to foreigners. */
8969 return ITF_YES;
8970 }
8971 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
8972 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
8973 /* A real embassy is an embassy. */
8974 return ITF_YES;
8975 }
8976 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
8977 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
8978 /* A real embassy is an embassy. */
8979 return ITF_YES;
8980 }
8981 if (preq->source.value.diplrel < DS_LAST
8982 && source->value.diplrel < DS_LAST
8983 && preq->range == REQ_RANGE_LOCAL) {
8984 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
8985 ITF_YES);
8986 /* Can only have one diplstate_type to a specific player. */
8987 return ITF_NO;
8988 }
8989 /* Can't say this diplrel blocks the other diplrel. */
8990 return ITF_NOT_APPLICABLE;
8991 }
8992
8993 /* Not relevant. */
8994 return ITF_NOT_APPLICABLE;
8995}
8996
8997/**********************************************************************/
9001 const struct universal *source)
9002{
9003 switch (preq->source.kind) {
9004 case VUT_OTYPE:
9005 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
9006 : ITF_NO;
9007 default:
9008 /* Not found and not relevant. */
9009 return ITF_NOT_APPLICABLE;
9010 }
9011}
9012
9013/**********************************************************************/
9017 const struct universal *source)
9018{
9019 if (preq->range != REQ_RANGE_LOCAL) {
9020 return ITF_NOT_APPLICABLE;
9021 }
9022
9023 if (preq->source.kind == VUT_UNITSTATE) {
9024 switch (source->value.unit_state) {
9025 case USP_TRANSPORTED:
9026 case USP_TRANSPORTING:
9027 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
9028 case USP_LIVABLE_TILE:
9029 case USP_NATIVE_TILE:
9030 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
9031 * UTYF_COAST_STRICT. */
9032 case USP_HAS_HOME_CITY:
9033 case USP_NATIVE_EXTRA:
9035 if (source->value.unit_state == preq->source.value.unit_state) {
9036 /* The other unit states doesn't contradict */
9037 return ITF_YES;
9038 }
9039 break;
9040 case USP_COUNT:
9041 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
9043 }
9044 }
9045
9046 /* Not found and not relevant. */
9047 return ITF_NOT_APPLICABLE;
9048}
9049
9050/**********************************************************************/
9075
9076/**********************************************************************/
9084int requirement_kind_ereq(const int value,
9085 const enum req_range range,
9086 const bool present,
9087 const int max_value)
9088{
9089 /* The enumerators in each range starts with present for every possible
9090 * value followed by !present for every possible value. */
9091 const int pres_start = (present ? 0 : max_value);
9092
9093 /* The enumerators for every range follows all the positions of the
9094 * previous range(s). */
9095 const int range_start = ((max_value - 1) * 2) * range;
9096
9097 return range_start + pres_start + value;
9098}
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
struct achievement * achievement_by_number(int id)
int achievement_number(const struct achievement *pach)
const char * achievement_rule_name(struct achievement *pach)
struct achievement * achievement_by_rule_name(const char *name)
const char * achievement_name_translation(struct achievement *pach)
bool achievement_claimed(const struct achievement *pach)
const char * action_name_translation(const struct action *paction)
Definition actions.c:1251
bool action_is_in_use(struct action *paction)
Definition actions.c:5910
struct action * action_by_rule_name(const char *name)
Definition actions.c:1100
const char * action_rule_name(const struct action *action)
Definition actions.c:1237
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1260
int action_number(const struct action *action)
Definition actions.c:1229
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define ACTION_NONE
Definition actions.h:59
void astr_free(struct astring *astr)
Definition astring.c:148
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:251
void astr_init(struct astring *astr)
Definition astring.c:139
#define n
Definition astring.c:77
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
const char * textcalfrag(int frag)
Definition calendar.c:101
const char * textyear(int year)
Definition calendar.c:121
citizens citizens_nation_foreign(const struct city *pcity)
Definition citizens.c:91
#define citizens_iterate_end
Definition citizens.h:54
#define citizens_iterate(_pcity, _pslot, _nationality)
Definition citizens.h:48
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c: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:564
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
#define city_owner(_pcity_)
Definition city.h:563
static bool is_city_center(const struct city *pcity, const struct tile *ptile)
Definition city.h:869
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:228
#define city_tile_iterate_end
Definition city.h:236
#define city_built_iterate(_pcity, _p)
Definition city.h:835
#define city_built_iterate_end
Definition city.h:841
char * incite_cost
Definition comments.c:77
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:238
req_problem_type
Definition fc_types.h:514
@ RPT_POSSIBLE
Definition fc_types.h:515
#define MAX_LEN_NAME
Definition fc_types.h:68
@ VC_SPACERACE
Definition fc_types.h:966
@ O_LAST
Definition fc_types.h:103
signed short Continent_id
Definition fc_types.h:233
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
const char * government_name_translation(const struct government *pgovern)
Definition government.c:145
struct government * government_by_number(const Government_type_id gov)
Definition government.c:105
struct government * government_of_player(const struct player *pplayer)
Definition government.c:116
Government_type_id government_number(const struct government *pgovern)
Definition government.c:93
const char * government_rule_name(const struct government *pgovern)
Definition government.c:135
struct government * government_by_rule_name(const char *name)
Definition government.c:57
struct city * owner
Definition citydlg.c:226
static GtkWidget * source
Definition gotodlg.c:58
GType type
Definition repodlgs.c:1313
static const int bufsz
Definition helpdlg.c:70
struct impr_type * improvement_by_number(const Impr_type_id id)
bool great_wonder_is_built(const struct impr_type *pimprove)
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
bool wonder_is_built(const struct player *pplayer, const struct impr_type *pimprove)
Impr_type_id improvement_number(const struct impr_type *pimprove)
bool can_improvement_go_obsolete(const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
struct city * city_from_wonder(const struct player *pplayer, const struct impr_type *pimprove)
int impr_build_shield_cost(const struct city *pcity, const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
bool improvement_obsolete(const struct player *pplayer, const struct impr_type *pimprove, const struct city *pcity)
bool improvement_has_flag(const struct impr_type *pimprove, enum impr_flag_id flag)
struct impr_type * improvement_by_rule_name(const char *name)
const char * improvement_name_translation(const struct impr_type *pimprove)
bool great_wonder_is_available(const struct impr_type *pimprove)
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition log.h:209
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:686
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:1067
int map_signed_latitude(const struct tile *ptile)
Definition map.c:1692
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:1076
int get_island_surrounder(Continent_id id)
Definition map.c:842
int get_lake_surrounder(Continent_id id)
Definition map.c:875
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:699
#define current_topo_has_flag(flag)
Definition map.h:43
#define range_adjc_iterate(nmap, center_tile, range, itr_tile)
Definition map.h: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:1066
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:350
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:362
struct nation_group * nation_group_by_rule_name(const char *name)
Definition nation.c:1016
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:484
const char * nation_adjective_translation(const struct nation_type *pnation)
Definition nation.c:149
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:472
const char * nation_group_rule_name(const struct nation_group *pgroup)
Definition nation.c:1071
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:443
bool nation_is_in_group(const struct nation_type *pnation, const struct nation_group *pgroup)
Definition nation.c:1088
const char * nation_group_name_translation(const struct nation_group *pgroup)
Definition nation.c:1080
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
struct nation_group * nation_group_by_number(int id)
Definition nation.c:999
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:945
#define NO_NATION_SELECTED
Definition nation.h:30
bool player_knows_techs_with_flag(const struct player *pplayer, enum tech_flag_id flag)
Definition player.c:1316
bool player_has_state(const struct player *pplayer, enum plrstate_type state)
Definition player.c:1987
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Definition player.c:1812
int diplrel_by_rule_name(const char *value)
Definition player.c:1568
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1468
bool is_diplrel_to_other(const struct player *pplayer, int diplrel)
Definition player.c:1551
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1979
const char * diplrel_name_translation(int value)
Definition player.c:1614
bool is_diplrel_between(const struct player *player1, const struct player *player2, int diplrel)
Definition player.c:1504
int player_age(const struct player *pplayer)
Definition player.c:946
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1397
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:432
const char * diplrel_rule_name(int value)
Definition player.c:1602
#define players_iterate_end
Definition player.h:552
#define players_iterate(_pplayer)
Definition player.h:547
#define player_nation(_plr_)
Definition player.h:413
#define is_ai(plr)
Definition player.h:232
#define players_iterate_alive_end
Definition player.h:562
#define players_iterate_alive(_pplayer)
Definition player.h:557
static enum req_item_found terrain_type_found(const struct requirement *preq, const struct universal *source)
bool universal_never_there(const struct universal *source)
static enum fc_tristate is_unitclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unitflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_relevant_to_requirement(const struct requirement *req, const struct universal *source)
static enum fc_tristate is_futuretechs_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define EXTRACT_INFO(req)
bool is_req_in_vec(const struct requirement *req, const struct requirement_vector *vec)
int universal_build_shield_cost(const struct city *pcity, const struct universal *target)
static enum fc_tristate is_terrainflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found city_tile_found(const struct requirement *preq, const struct universal *source)
struct req_vec_problem * req_vec_get_first_contradiction(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static universal_found universal_found_function[VUT_COUNT]
static enum req_unchanging_status unchanging_local(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
#define REQUC_CITYSTATUS
const struct req_context * req_context_empty(void)
static enum fc_tristate is_action_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found unit_type_found(const struct requirement *preq, const struct universal *source)
void universal_extraction(const struct universal *source, int *kind, int *value)
static int num_player_buildings(const struct player *pplayer, const struct impr_type *building)
static enum fc_tristate is_tech_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_none_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static int num_continent_buildings(const struct player *pplayer, int continent, const struct impr_type *building)
static enum fc_tristate is_minveteran_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * req_to_fstring(const struct requirement *req, struct astring *astr)
static enum fc_tristate is_counter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
req_vec_num_in_item req_vec_vector_number(const void *parent_item, const struct requirement_vector *vec)
static bool present_implies_not_present(const struct requirement *req1, const struct requirement *req2)
enum fc_tristate tri_req_active(const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct requirement_vector * req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
bool universal_fulfills_requirements(bool check_necessary, const struct requirement_vector *reqs, const struct universal *source)
static bool activity_is_valid_in_requirement(enum unit_activity act)
enum fc_tristate tri_reqs_cb_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, struct requirement_vector *maybe_reqs, req_tester_cb tester, void *data, int n_data)
static enum fc_tristate is_minsize_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_ai_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_noally(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_max_distance_sq_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_vec_change_apply(const struct req_vec_change *modification, requirement_vector_by_number getter, const void *parent_item)
void universal_copy(struct universal *dst, const struct universal *src)
static enum fc_tristate is_minculture_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_building(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_terrain_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_requirements_equal(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_minforeignpct_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_minyear_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found extra_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_buildingflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_in_range(const struct tile *target_tile, const struct player *other_player, enum req_range range, int diplrel)
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
struct requirement req_from_str(const char *type, const char *range, bool survives, bool present, bool quiet, const char *value)
struct req_vec_problem * req_vec_suggest_repair(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum fc_tristate is_wrap_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void universal_value_from_str(struct universal *source, const char *value)
static enum fc_tristate is_buildingflag_in_city(const struct city *pcity, enum impr_flag_id flag)
static enum fc_tristate is_latitude_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_get_values(const struct requirement *req, int *type, int *range, bool *survives, bool *present, bool *quiet, int *value)
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
static enum fc_tristate is_nationality_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * universal_rule_name(const struct universal *psource)
static enum req_unchanging_status unchanging_present(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
bool universal_replace_in_req_vec(struct requirement_vector *reqs, const struct universal *to_replace, const struct universal *replacement)
static enum req_item_found action_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_minmovefrags_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_requirements_contradictions(const struct requirement *req1, const struct requirement *req2)
#define REQUC_IMPR
struct req_vec_problem * req_vec_problem_new(int num_suggested_solutions, const char *descr,...)
static enum fc_tristate is_buildinggenus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_in_range(const struct player *target_player, const struct player *other_player, enum req_range range, int diplrel)
static enum fc_tristate is_mintechs_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool is_req_active(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, const enum req_problem_type prob_type)
static enum fc_tristate is_originalowner_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool are_bounds_contradictions(int bound1, bool is_upper1, int bound2, bool is_upper2)
static enum fc_tristate is_diplrel_tile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_legal_in_requirement(const struct universal *univ)
enum fc_tristate default_tester_cb(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, void *data, int n_data)
static enum fc_tristate tri_req_present(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
int requirement_kind_ereq(const int value, const enum req_range range, const bool present, const int max_value)
static enum fc_tristate is_achievement_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_vec_problem_free(struct req_vec_problem *issue)
static struct req_def req_definitions[VUT_COUNT]
static bool impr_contra_flag(const struct requirement *impr_req, const struct requirement *flag_req)
bool are_reqs_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
static enum req_item_found improvement_found(const struct requirement *preq, const struct universal *source)
struct req_vec_problem * req_vec_get_first_missing_univ(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum req_item_found mincities_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_extraflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum req_unchanging_status is_req_preventing(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, enum req_problem_type prob_type)
static enum fc_tristate is_plr_state_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool players_in_same_range(const struct player *pplayer1, const struct player *pplayer2, enum req_range range)
struct requirement * req_vec_first_contradiction_in_vec(const struct requirement *req, const struct requirement_vector *vec)
enum req_item_found(* universal_found)(const struct requirement *, const struct universal *)
static enum fc_tristate is_terrainclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct universal universal_by_number(const enum universals_n kind, const int value)
static enum fc_tristate is_roadflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum req_item_found universal_fulfills_requirement(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_building_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_reqs_active_ranges(const enum req_range min_range, const enum req_range max_range, const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
static enum fc_tristate is_gov_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_tile_o_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_good_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unitstate_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool city_center_contra(const struct requirement *cc_req, const struct requirement *ct_req)
static enum req_item_found ustate_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_terrainalter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unittype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_vec_wants_type(const struct requirement_vector *reqs, enum universals_n kind)
static int num_world_buildings_total(const struct impr_type *building)
static enum req_unchanging_status unchanging_citytile(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_tiledef_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found output_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_citystatus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_tile_rel_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct req_vec_problem * req_vec_get_first_redundant_req(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum fc_tristate is_mincities_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool is_city_in_tile(const struct tile *ptile, const struct city *pcity)
bool does_req_contradicts_reqs(const struct requirement *req, const struct requirement_vector *vec)
static enum req_item_found government_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate does_region_surrounder_match(Continent_id cont, Continent_id surrounder)
static enum fc_tristate is_extra_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_world(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_mincalfrag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_maxtopunitsontile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_activity_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
static enum fc_tristate is_max_region_tiles_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct req_vec_problem * req_vec_problem_new_transl(int num_suggested_solutions, const char *description, const char *description_translated)
static enum fc_tristate is_nationgroup_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define REQUC_NALLY
static enum req_item_found unit_activity_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_minhitpoints_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum fc_tristate tri_req_active_turns(int pass, int period, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_outputtype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define REQUC_LOCAL
bool universals_say_everything(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
static enum fc_tristate is_unitclassflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found nation_found(const struct requirement *preq, const struct universal *source)
#define REQUC_WORLD
static enum fc_tristate is_govflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * universal_type_rule_name(const struct universal *psource)
#define REQUC_PRESENT
static enum fc_tristate is_maxtotalunitsontile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void universal_found_functions_init(void)
static enum fc_tristate is_style_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found unit_class_found(const struct requirement *preq, const struct universal *source)
#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind)
int universal_number(const struct universal *source)
static enum fc_tristate is_techflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_mentioned_by_requirements(const struct requirement_vector *reqs, const struct universal *psource)
#define REQUC_CITYTILE
static enum fc_tristate is_citytile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found diplrel_found(const struct requirement *preq, const struct universal *source)
bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
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:130
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:622
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Definition road.c:416
bool is_road_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:446
bool is_road_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:425
bool ssetv_setting_has_value(ssetv val)
ssetv ssetv_by_rule_name(const char *name)
const char * ssetv_rule_name(ssetv val)
const char * ssetv_human_readable(ssetv val, bool present)
#define SSETV_NONE
enum fc_tristate fc_tristate_or(enum fc_tristate one, enum fc_tristate two)
Definition shared.c:143
fc_tristate
Definition shared.h:46
@ TRI_YES
Definition shared.h:46
@ TRI_NO
Definition shared.h:46
@ TRI_MAYBE
Definition shared.h:46
#define BOOL_TO_TRISTATE(tri)
Definition shared.h:47
#define FC_INFINITY
Definition shared.h:36
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c:123
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:110
Specialist_type_id specialist_number(const struct specialist *sp)
Definition specialist.c:100
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:157
const char * specialist_plural_translation(const struct specialist *sp)
Definition specialist.c:166
Definition city.h:318
struct packet_game_info info
Definition game.h:89
struct packet_calendar_info calendar
Definition game.h:90
int checkpoint
Definition counters.h:33
bv_gov_flags flags
Definition government.h:67
struct player * player
Definition nation.h:118
bool global_advances[A_LAST]
bool is_alive
Definition player.h:268
enum req_unchanging_status unchanging
req_unchanging_cond_cb unchanging_cond
const is_req_active_cb cb
req_vec_num_in_item vector_number
enum req_vec_change_operation operation
struct requirement req
char description[500]
char description_translated[500]
enum req_range range
struct universal source
Tech_type_id researching
Definition research.h:52
int future_tech
Definition research.h:42
int techs_researched
Definition research.h:42
Definition tile.h:50
struct tile * tile
Definition unit.h:142
const struct unit_type * utype
Definition unit.h:141
enum universals_n kind
Definition fc_types.h:595
universals_u value
Definition fc_types.h:594
struct civ_map map
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
struct nation_style * style_by_number(int id)
Definition style.c:88
const char * style_name_translation(const struct nation_style *pstyle)
Definition style.c:99
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:108
int style_number(const struct nation_style *pstyle)
Definition style.c:68
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:822
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define bool
Definition support.h:71
#define fc__fallthrough
Definition support.h:119
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c: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:188
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:615
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:594
const char * terrain_class_name_translation(enum terrain_class tclass)
Definition terrain.c:664
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:240
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:157
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Definition terrain.c:676
bool is_terrain_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:330
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:249
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:585
bool is_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:461
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:148
bool is_terrain_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:441
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:351
#define T_UNKNOWN
Definition terrain.h:62
#define terrain_has_flag(terr, flag)
Definition terrain.h:177
bool tile_has_extra_flag(const struct tile *ptile, enum extra_flag_id flag)
Definition tile.c:887
bool tile_has_native_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:325
bool tile_has_road_flag(const struct tile *ptile, enum road_flag_id flag)
Definition tile.c:869
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_terrain(_tile)
Definition tile.h:115
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#define tile_owner(_tile)
Definition tile.h:97
const char * tiledef_rule_name(const struct tiledef *td)
Definition tiledef.c:104
int tiledef_number(const struct tiledef *td)
Definition tiledef.c:62
struct tiledef * tiledef_by_number(int id)
Definition tiledef.c:84
struct tiledef * tiledef_by_rule_name(const char *name)
Definition tiledef.c:113
bool tile_matches_tiledef(const struct tiledef *td, const struct tile *ptile)
Definition tiledef.c:150
bool is_tiledef_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct tiledef *ptd)
Definition tiledef.c:165
bool is_tiledef_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct tiledef *ptd)
Definition tiledef.c:181
const char * tiledef_name_translation(const struct tiledef *td)
Definition tiledef.c:95
bool goods_can_be_provided(const struct city *pcity, const struct goods_type *pgood, const struct unit *punit)
Goods_type_id goods_number(const struct goods_type *pgood)
bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
const char * goods_name_translation(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
#define trade_partners_iterate_end
#define trade_partners_iterate(c, p)
const struct unit_type * utype
Definition fc_types.h:536
struct tiledef * tiledef
Definition fc_types.h:538
int region_tiles
Definition fc_types.h:584
struct nation_style * style
Definition fc_types.h:541
enum ai_level ai_level
Definition fc_types.h:545
struct specialist * specialist
Definition fc_types.h:533
enum impr_genus_id impr_genus
Definition fc_types.h:569
enum citytile_type citytile
Definition fc_types.h:546
struct nation_group * nationgroup
Definition fc_types.h:540
struct extra_type * extra
Definition fc_types.h:537
enum wrap_flag wrap_property
Definition fc_types.h:587
enum plrstate_type plrstate
Definition fc_types.h:548
enum tilerel_type tilerel
Definition fc_types.h:549
struct nation_type * nation
Definition fc_types.h:530
int terrainclass
Definition fc_types.h:556
int unitclassflag
Definition fc_types.h:559
struct government * govern
Definition fc_types.h:528
struct nation_type * origowner
Definition fc_types.h:532
enum impr_flag_id impr_flag
Definition fc_types.h:570
int terrainalter
Definition fc_types.h:557
enum citystatus_type citystatus
Definition fc_types.h:547
int minforeignpct
Definition fc_types.h:552
const struct impr_type * building
Definition fc_types.h:529
int max_tile_total_units
Definition fc_types.h:573
int max_tile_top_units
Definition fc_types.h:574
struct achievement * achievement
Definition fc_types.h:539
ssetv ssetval
Definition fc_types.h:588
struct advance * advance
Definition fc_types.h:526
enum unit_activity activity
Definition fc_types.h:568
struct goods_type * good
Definition fc_types.h:543
struct terrain * terrain
Definition fc_types.h:534
int terrainflag
Definition fc_types.h:561
enum ustate_prop unit_state
Definition fc_types.h:567
Output_type_id outputtype
Definition fc_types.h:555
int distance_sq
Definition fc_types.h:583
enum topo_flag topo_property
Definition fc_types.h:586
struct counter * counter
Definition fc_types.h:527
int min_hit_points
Definition fc_types.h:576
struct unit_class * uclass
Definition fc_types.h:535
struct nation_type * nationality
Definition fc_types.h:531
struct action * action
Definition fc_types.h:542
int future_techs
Definition fc_types.h:580
enum plr_flag_id plr_flag
Definition fc_types.h:571
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1847
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2529
#define unit_tile(_pu)
Definition unit.h:407
#define unit_owner(_pu)
Definition unit.h:406
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const char * uclass_name_translation(const struct unit_class *pclass)
Definition unittype.c:1658
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126
bool unit_has_class_flag(const struct unit *punit, enum unit_class_flag_id flag)
Definition unittype.c:1675
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1793
bool uclass_flag_is_in_use(enum unit_class_flag_id ucflag)
Definition unittype.c:3013
struct unit_class * uclass_by_number(const Unit_Class_id id)
Definition unittype.c:2506
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1604
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2530
struct unit_type * utype_by_number(const Unit_type_id id)
Definition unittype.c:114
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:215
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1667
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:102
struct unit_class * unit_class_by_rule_name(const char *s)
Definition unittype.c:1810
bool utype_flag_is_in_use(enum unit_type_flag_id uflag)
Definition unittype.c:3032
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1463
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2497
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1586
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:773
#define utype_class(_t_)
Definition unittype.h:756
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
bool victory_enabled(enum victory_condition_type victory)
Definition victory.c:26