Freeciv-3.3
Loading...
Searching...
No Matches
requirements.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2004 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17#include <stdarg.h>
18
19/* utility */
20#include "astring.h"
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "achievements.h"
27#include "calendar.h"
28#include "citizens.h"
29#include "counters.h"
30#include "culture.h"
31#include "game.h"
32#include "government.h"
33#include "improvement.h"
34#include "movement.h"
35#include "nation.h"
36#include "player.h"
37#include "map.h"
38#include "research.h"
39#include "road.h"
40#include "server_settings.h"
41#include "specialist.h"
42#include "style.h"
43#include "victory.h" /* victory_enabled() */
44
45#include "requirements.h"
46
47/************************************************************************
48 Container for req_item_found functions
49************************************************************************/
50typedef enum req_item_found (*universal_found)(const struct requirement *,
51 const struct universal *);
53
54static
56 const struct req_context *context,
57 const struct req_context *other_context,
58 const struct requirement *req);
59
60/* Function pointer for requirement-type-specific is_req_active handlers */
61typedef enum fc_tristate
62(*is_req_active_cb)(const struct civ_map *nmap,
63 const struct req_context *context,
64 const struct req_context *other_context,
65 const struct requirement *req);
66
67static inline bool are_tiles_in_range(const struct tile *tile1,
68 const struct tile *tile2,
69 enum req_range range);
70
71/**********************************************************************/
76static enum req_unchanging_status
78 enum req_unchanging_status def,
79 const struct req_context *context,
80 const struct requirement *req)
81{
82 return req->range == REQ_RANGE_LOCAL ? REQUCH_YES : def;
83}
84#define REQUC_LOCAL unchanging_local
85
86/**********************************************************************/
89static enum req_unchanging_status
91 enum req_unchanging_status def,
92 const struct req_context *context,
93 const struct requirement *req)
94{
95 if (TRI_YES != tri_req_present(nmap, context, NULL, req)) {
96 return REQUCH_NO;
97 }
98 return def;
99}
100#define REQUC_PRESENT unchanging_present
101
102/**********************************************************************/
105static enum req_unchanging_status
107 enum req_unchanging_status def,
108 const struct req_context *context,
109 const struct requirement *req)
110{
111 return
113 context, req);
114}
115#define REQUC_WORLD unchanging_world
116
117/**********************************************************************/
121static enum req_unchanging_status
123 enum req_unchanging_status def,
124 const struct req_context *context,
125 const struct requirement *req)
126{
127 if (REQ_RANGE_ALLIANCE == req->range
128 || REQ_RANGE_TEAM == req->range) {
129 struct requirement preq;
130
131 req_copy(&preq, req);
132 preq.range = REQ_RANGE_PLAYER;
134 return REQ_RANGE_TEAM == req->range ? REQUCH_ACT : REQUCH_NO;
135 }
136 }
137 return def;
138}
139#define REQUC_NALLY unchanging_noally
140
141/**********************************************************************/
144static enum req_unchanging_status
146 enum req_unchanging_status def,
147 const struct req_context *context,
148 const struct requirement *req)
149{
153 && NULL != context->city && NULL != context->tile
154 && NULL != city_tile(context->city)
156 req->range))){
157 /* Cities don't move, and most reqs are present on city center */
158 return REQUCH_YES;
159 }
160 return def;
161}
162#define REQUC_CITYTILE unchanging_citytile
163
164/**********************************************************************/
167static enum req_unchanging_status
169 enum req_unchanging_status def,
170 const struct req_context *context,
171 const struct requirement *req)
172{
174
175 if (REQ_RANGE_CITY == req->range
178 return REQUCH_CTRL;
179 }
180
181 return def;
182}
183#define REQUC_CITYSTATUS unchanging_citystatus
184
185/**********************************************************************/
190static enum req_unchanging_status
192 enum req_unchanging_status def,
193 const struct req_context *context,
194 const struct requirement *req)
195{
196 const struct impr_type *b = req->source.value.building;
197
199 if (REQ_RANGE_LOCAL == req->range) {
200 /* Likely, won't be questioned for an obsolete building */
201 return REQUCH_YES;
202 }
203
204 if (improvement_obsolete(context->player, b, context->city)) {
205 /* FIXME: sometimes can unobsolete, but considering it
206 * may sometimes put the function on endless recursion */
207 return REQUCH_ACT; /* Mostly about techs */
208 }
209 if (is_great_wonder(b)) {
212 && (req->range <= REQ_RANGE_CITY && TRI_YES
213 == tri_req_present(nmap, context, NULL, req)))) {
214 /* If the wonder stays somewhere, it may either remain there
215 * or be destroyed. If it is destroyed, it is nowhere. */
216 return REQUCH_SCRIPTS;
217 }
218 }
219 return def;
220}
221#define REQUC_IMPR unchanging_building
222
228
229/**********************************************************************/
237 const char *value)
238{
239 struct universal source;
240
242 if (!universals_n_is_valid(source.kind)) {
243 return source;
244 }
245
247
248 return source;
249}
250
251/**********************************************************************/
256{
257 return unit_activity_is_valid(act)
258 && act != ACTIVITY_SENTRY
259 && act != ACTIVITY_GOTO
260 && act != ACTIVITY_EXPLORE;
261}
262
263/**********************************************************************/
268{
269 if (univ->kind == VUT_ACTIVITY) {
271 }
272
273 return TRUE;
274}
275
276/**********************************************************************/
281{
282 /* Finally scan the value string based on the type of the source. */
283 switch (source->kind) {
284 case VUT_NONE:
285 return;
286 case VUT_ADVANCE:
287 source->value.advance = advance_by_rule_name(value);
288 if (source->value.advance != NULL) {
289 return;
290 }
291 break;
292 case VUT_TECHFLAG:
293 source->value.techflag
295 if (tech_flag_id_is_valid(source->value.techflag)) {
296 return;
297 }
298 break;
299 case VUT_GOVERNMENT:
300 source->value.govern = government_by_rule_name(value);
301 if (source->value.govern != NULL) {
302 return;
303 }
304 break;
305 case VUT_ACHIEVEMENT:
306 source->value.achievement = achievement_by_rule_name(value);
307 if (source->value.achievement != NULL) {
308 return;
309 }
310 break;
311 case VUT_STYLE:
312 source->value.style = style_by_rule_name(value);
313 if (source->value.style != NULL) {
314 return;
315 }
316 break;
317 case VUT_IMPROVEMENT:
318 source->value.building = improvement_by_rule_name(value);
319 if (source->value.building != NULL) {
320 return;
321 }
322 break;
323 case VUT_IMPR_GENUS:
324 source->value.impr_genus = impr_genus_id_by_name(value, fc_strcasecmp);
325 if (impr_genus_id_is_valid(source->value.impr_genus)) {
326 return;
327 }
328 break;
329 case VUT_IMPR_FLAG:
330 source->value.impr_flag = impr_flag_id_by_name(value, fc_strcasecmp);
331 if (impr_flag_id_is_valid(source->value.impr_flag)) {
332 return;
333 }
334 break;
335 case VUT_PLAYER_FLAG:
336 source->value.plr_flag = plr_flag_id_by_name(value, fc_strcasecmp);
337 if (plr_flag_id_is_valid(source->value.plr_flag)) {
338 return;
339 }
340 break;
341 case VUT_EXTRA:
342 source->value.extra = extra_type_by_rule_name(value);
343 if (source->value.extra != NULL) {
344 return;
345 }
346 break;
347 case VUT_GOOD:
348 source->value.good = goods_by_rule_name(value);
349 if (source->value.good != NULL) {
350 return;
351 }
352 break;
353 case VUT_TERRAIN:
354 source->value.terrain = terrain_by_rule_name(value);
355 if (source->value.terrain != T_UNKNOWN) {
356 return;
357 }
358 break;
359 case VUT_TERRFLAG:
360 source->value.terrainflag
362 if (terrain_flag_id_is_valid(source->value.terrainflag)) {
363 return;
364 }
365 break;
366 case VUT_NATION:
367 source->value.nation = nation_by_rule_name(value);
368 if (source->value.nation != NO_NATION_SELECTED) {
369 return;
370 }
371 break;
372 case VUT_NATIONGROUP:
373 source->value.nationgroup = nation_group_by_rule_name(value);
374 if (source->value.nationgroup != NULL) {
375 return;
376 }
377 break;
378 case VUT_NATIONALITY:
379 source->value.nationality = nation_by_rule_name(value);
380 if (source->value.nationality != NO_NATION_SELECTED) {
381 return;
382 }
383 break;
385 source->value.origowner = nation_by_rule_name(value);
386 if (source->value.origowner != NO_NATION_SELECTED) {
387 return;
388 }
389 break;
390 case VUT_DIPLREL:
391 case VUT_DIPLREL_TILE:
395 source->value.diplrel = diplrel_by_rule_name(value);
396 if (source->value.diplrel != diplrel_other_invalid()) {
397 return;
398 }
399 break;
400 case VUT_UTYPE:
401 source->value.utype = unit_type_by_rule_name(value);
402 if (source->value.utype) {
403 return;
404 }
405 break;
406 case VUT_UTFLAG:
408 if (unit_type_flag_id_is_valid(source->value.unitflag)) {
409 return;
410 }
411 break;
412 case VUT_UCLASS:
413 source->value.uclass = unit_class_by_rule_name(value);
414 if (source->value.uclass) {
415 return;
416 }
417 break;
418 case VUT_UCFLAG:
419 source->value.unitclassflag
421 if (unit_class_flag_id_is_valid(source->value.unitclassflag)) {
422 return;
423 }
424 break;
425 case VUT_MINVETERAN:
426 source->value.minveteran = atoi(value);
427 if (source->value.minveteran > 0) {
428 return;
429 }
430 break;
431 case VUT_UNITSTATE:
432 source->value.unit_state = ustate_prop_by_name(value, fc_strcasecmp);
433 if (ustate_prop_is_valid(source->value.unit_state)) {
434 return;
435 }
436 break;
437 case VUT_ACTIVITY:
439 if (activity_is_valid_in_requirement(source->value.activity)) {
440 return;
441 }
442 break;
443 case VUT_MINMOVES:
444 source->value.minmoves = atoi(value);
445 if (source->value.minmoves > 0) {
446 return;
447 }
448 break;
449 case VUT_MINHP:
450 source->value.min_hit_points = atoi(value);
451 if (source->value.min_hit_points > 0) {
452 return;
453 }
454 break;
455 case VUT_AGE:
456 source->value.age = atoi(value);
457 if (source->value.age > 0) {
458 return;
459 }
460 break;
461 case VUT_FORM_AGE:
462 source->value.form_age = atoi(value);
463 if (source->value.form_age > 0) {
464 return;
465 }
466 break;
467 case VUT_MINTECHS:
468 source->value.min_techs = atoi(value);
469 if (source->value.min_techs > 0) {
470 return;
471 }
472 break;
473 case VUT_MINCITIES:
474 source->value.min_cities = atoi(value);
475 if (source->value.min_cities > 0) {
476 return;
477 }
478 break;
479 case VUT_ACTION:
480 source->value.action = action_by_rule_name(value);
481 if (source->value.action != NULL) {
482 return;
483 }
484 break;
485 case VUT_OTYPE:
486 source->value.outputtype = output_type_by_identifier(value);
487 if (source->value.outputtype != O_LAST) {
488 return;
489 }
490 break;
491 case VUT_SPECIALIST:
492 source->value.specialist = specialist_by_rule_name(value);
493 if (source->value.specialist) {
494 return;
495 }
496 break;
497 case VUT_MINSIZE:
498 source->value.minsize = atoi(value);
499 if (source->value.minsize > 0) {
500 return;
501 }
502 break;
503 case VUT_MINCULTURE:
504 source->value.minculture = atoi(value);
505 if (source->value.minculture > 0) {
506 return;
507 }
508 break;
510 source->value.minforeignpct = atoi(value);
511 if (source->value.minforeignpct > 0) {
512 return;
513 }
514 break;
515 case VUT_AI_LEVEL:
516 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
517 if (ai_level_is_valid(source->value.ai_level)) {
518 return;
519 }
520 break;
521 case VUT_MAXTILEUNITS:
522 source->value.max_tile_units = atoi(value);
523 if (0 <= source->value.max_tile_units) {
524 return;
525 }
526 break;
527 case VUT_TERRAINCLASS:
528 source->value.terrainclass
530 if (terrain_class_is_valid(source->value.terrainclass)) {
531 return;
532 }
533 break;
534 case VUT_ROADFLAG:
536 if (road_flag_id_is_valid(source->value.roadflag)) {
537 return;
538 }
539 break;
540 case VUT_EXTRAFLAG:
541 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
542 if (extra_flag_id_is_valid(source->value.extraflag)) {
543 return;
544 }
545 break;
546 case VUT_MINYEAR:
547 source->value.minyear = atoi(value);
548 return;
549 case VUT_MINCALFRAG:
550 /* Rule names are 0-based numbers, not pretty names from ruleset */
551 source->value.mincalfrag = atoi(value);
552 if (source->value.mincalfrag >= 0) {
553 /* More range checking done later, in sanity_check_req_individual() */
554 return;
555 }
556 break;
557 case VUT_TOPO:
558 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
559 if (topo_flag_is_valid(source->value.topo_property)) {
560 return;
561 }
562 break;
563 case VUT_WRAP:
564 source->value.wrap_property = wrap_flag_by_name(value, fc_strcasecmp);
565 if (wrap_flag_is_valid(source->value.wrap_property)) {
566 return;
567 }
568 break;
570 source->value.ssetval = ssetv_by_rule_name(value);
571 if (source->value.ssetval != SSETV_NONE) {
572 return;
573 }
574 break;
575 case VUT_TERRAINALTER:
576 source->value.terrainalter
578 if (terrain_alteration_is_valid(source->value.terrainalter)) {
579 return;
580 }
581 break;
582 case VUT_CITYTILE:
584 if (source->value.citytile != CITYT_LAST) {
585 return;
586 }
587 break;
588 case VUT_CITYSTATUS:
590 if (source->value.citystatus != CITYS_LAST) {
591 return;
592 }
593 break;
594 case VUT_PLAYER_STATE:
596 if (source->value.plrstate != PLRS_LAST) {
597 return;
598 }
599 break;
600 case VUT_MINLATITUDE:
601 case VUT_MAXLATITUDE:
602 source->value.latitude = atoi(value);
603 if (source->value.latitude >= -MAP_MAX_LATITUDE
604 && source->value.latitude <= MAP_MAX_LATITUDE) {
605 return;
606 }
607 break;
608 case VUT_COUNTER:
609 source->value.counter = counter_by_rule_name(value);
610 if (source->value.counter != NULL) {
611 return;
612 }
613 break;
614 case VUT_COUNT:
615 break;
616 }
617
618 /* If we reach here there's been an error. */
620}
621
622/**********************************************************************/
629{
630 struct universal source;
631
632 source.kind = kind;
633
634 switch (source.kind) {
635 case VUT_NONE:
636 /* Avoid compiler warning about unitialized source.value */
637 source.value.advance = NULL;
638
639 return source;
640 case VUT_ADVANCE:
641 source.value.advance = advance_by_number(value);
642 if (source.value.advance != NULL) {
643 return source;
644 }
645 break;
646 case VUT_TECHFLAG:
647 source.value.techflag = value;
648 return source;
649 case VUT_GOVERNMENT:
651 if (source.value.govern != NULL) {
652 return source;
653 }
654 break;
655 case VUT_ACHIEVEMENT:
656 source.value.achievement = achievement_by_number(value);
657 if (source.value.achievement != NULL) {
658 return source;
659 }
660 break;
661 case VUT_STYLE:
662 source.value.style = style_by_number(value);
663 if (source.value.style != NULL) {
664 return source;
665 }
666 break;
667 case VUT_IMPROVEMENT:
668 source.value.building = improvement_by_number(value);
669 if (source.value.building != NULL) {
670 return source;
671 }
672 break;
673 case VUT_IMPR_GENUS:
674 source.value.impr_genus = value;
675 return source;
676 case VUT_IMPR_FLAG:
677 source.value.impr_flag = value;
678 return source;
679 case VUT_PLAYER_FLAG:
680 source.value.plr_flag = value;
681 return source;
682 case VUT_EXTRA:
684 return source;
685 case VUT_GOOD:
686 source.value.good = goods_by_number(value);
687 return source;
688 case VUT_TERRAIN:
689 source.value.terrain = terrain_by_number(value);
690 if (source.value.terrain != NULL) {
691 return source;
692 }
693 break;
694 case VUT_TERRFLAG:
695 source.value.terrainflag = value;
696 return source;
697 case VUT_NATION:
699 if (source.value.nation != NULL) {
700 return source;
701 }
702 break;
703 case VUT_NATIONGROUP:
704 source.value.nationgroup = nation_group_by_number(value);
705 if (source.value.nationgroup != NULL) {
706 return source;
707 }
708 break;
709 case VUT_DIPLREL:
710 case VUT_DIPLREL_TILE:
714 source.value.diplrel = value;
715 if (source.value.diplrel != diplrel_other_invalid()) {
716 return source;
717 }
718 break;
719 case VUT_NATIONALITY:
721 if (source.value.nationality != NULL) {
722 return source;
723 }
724 break;
726 source.value.origowner = nation_by_number(value);
727 if (source.value.origowner != NULL) {
728 return source;
729 }
730 break;
731 case VUT_UTYPE:
732 source.value.utype = utype_by_number(value);
733 if (source.value.utype != NULL) {
734 return source;
735 }
736 break;
737 case VUT_UTFLAG:
738 source.value.unitflag = value;
739 return source;
740 case VUT_UCLASS:
742 if (source.value.uclass != NULL) {
743 return source;
744 }
745 break;
746 case VUT_UCFLAG:
747 source.value.unitclassflag = value;
748 return source;
749 case VUT_MINVETERAN:
750 source.value.minveteran = value;
751 return source;
752 case VUT_UNITSTATE:
753 source.value.unit_state = value;
754 return source;
755 case VUT_ACTIVITY:
756 source.value.activity = value;
757 return source;
758 case VUT_MINMOVES:
759 source.value.minmoves = value;
760 return source;
761 case VUT_MINHP:
763 return source;
764 case VUT_AGE:
765 source.value.age = value;
766 return source;
767 case VUT_FORM_AGE:
768 source.value.form_age = value;
769 return source;
770 case VUT_MINTECHS:
771 source.value.min_techs = value;
772 return source;
773 case VUT_MINCITIES:
774 source.value.min_cities = value;
775 return source;
776 case VUT_ACTION:
778 if (source.value.action != NULL) {
779 return source;
780 }
781 break;
782 case VUT_OTYPE:
783 source.value.outputtype = value;
784 return source;
785 case VUT_SPECIALIST:
787 return source;
788 case VUT_MINSIZE:
789 source.value.minsize = value;
790 return source;
791 case VUT_MINCULTURE:
792 source.value.minculture = value;
793 return source;
795 source.value.minforeignpct = value;
796 return source;
797 case VUT_AI_LEVEL:
798 source.value.ai_level = value;
799 return source;
800 case VUT_MAXTILEUNITS:
802 return source;
803 case VUT_TERRAINCLASS:
804 source.value.terrainclass = value;
805 return source;
806 case VUT_ROADFLAG:
807 source.value.roadflag = value;
808 return source;
809 case VUT_EXTRAFLAG:
810 source.value.extraflag = value;
811 return source;
812 case VUT_MINYEAR:
813 source.value.minyear = value;
814 return source;
815 case VUT_MINCALFRAG:
816 source.value.mincalfrag = value;
817 return source;
818 case VUT_TOPO:
819 source.value.topo_property = value;
820 return source;
821 case VUT_WRAP:
822 source.value.wrap_property = value;
823 return source;
825 source.value.ssetval = value;
826 return source;
827 case VUT_TERRAINALTER:
828 source.value.terrainalter = value;
829 return source;
830 case VUT_CITYTILE:
831 source.value.citytile = value;
832 return source;
833 case VUT_CITYSTATUS:
834 source.value.citystatus = value;
835 return source;
836 case VUT_PLAYER_STATE:
837 source.value.plrstate = value;
838 return source;
839 case VUT_COUNTER:
841 return source;
842 case VUT_MINLATITUDE:
843 case VUT_MAXLATITUDE:
844 source.value.latitude = value;
845 return source;
846 case VUT_COUNT:
847 break;
848 }
849
850 /* If we reach here there's been an error. */
852 /* Avoid compiler warning about unitialized source.value */
853 source.value.advance = NULL;
854
855 return source;
856}
857
858/**********************************************************************/
861void universal_copy(struct universal *dst, const struct universal *src)
862{
863 dst->value = src->value;
864 dst->kind = src->kind;
865}
866
867/**********************************************************************/
872 int *kind, int *value)
873{
874 *kind = source->kind;
876}
877
878/**********************************************************************/
882{
883 switch (source->kind) {
884 case VUT_NONE:
885 return 0;
886 case VUT_ADVANCE:
887 return advance_number(source->value.advance);
888 case VUT_TECHFLAG:
889 return source->value.techflag;
890 case VUT_GOVERNMENT:
891 return government_number(source->value.govern);
892 case VUT_ACHIEVEMENT:
893 return achievement_number(source->value.achievement);
894 case VUT_STYLE:
895 return style_number(source->value.style);
896 case VUT_IMPROVEMENT:
897 return improvement_number(source->value.building);
898 case VUT_IMPR_GENUS:
899 return source->value.impr_genus;
900 case VUT_IMPR_FLAG:
901 return source->value.impr_flag;
902 case VUT_PLAYER_FLAG:
903 return source->value.plr_flag;
904 case VUT_EXTRA:
905 return extra_number(source->value.extra);
906 case VUT_GOOD:
907 return goods_number(source->value.good);
908 case VUT_TERRAIN:
909 return terrain_number(source->value.terrain);
910 case VUT_TERRFLAG:
911 return source->value.terrainflag;
912 case VUT_NATION:
913 return nation_number(source->value.nation);
914 case VUT_NATIONGROUP:
915 return nation_group_number(source->value.nationgroup);
916 case VUT_NATIONALITY:
917 return nation_number(source->value.nationality);
919 return nation_number(source->value.origowner);
920 case VUT_DIPLREL:
921 case VUT_DIPLREL_TILE:
925 return source->value.diplrel;
926 case VUT_UTYPE:
927 return utype_number(source->value.utype);
928 case VUT_UTFLAG:
929 return source->value.unitflag;
930 case VUT_UCLASS:
931 return uclass_number(source->value.uclass);
932 case VUT_UCFLAG:
933 return source->value.unitclassflag;
934 case VUT_MINVETERAN:
935 return source->value.minveteran;
936 case VUT_UNITSTATE:
937 return source->value.unit_state;
938 case VUT_ACTIVITY:
939 return source->value.activity;
940 case VUT_MINMOVES:
941 return source->value.minmoves;
942 case VUT_MINHP:
943 return source->value.min_hit_points;
944 case VUT_AGE:
945 return source->value.age;
946 case VUT_FORM_AGE:
947 return source->value.form_age;
948 case VUT_MINTECHS:
949 return source->value.min_techs;
950 case VUT_MINCITIES:
951 return source->value.min_cities;
952 case VUT_ACTION:
953 return action_number(source->value.action);
954 case VUT_OTYPE:
955 return source->value.outputtype;
956 case VUT_SPECIALIST:
957 return specialist_number(source->value.specialist);
958 case VUT_MINSIZE:
959 return source->value.minsize;
960 case VUT_MINCULTURE:
961 return source->value.minculture;
963 return source->value.minforeignpct;
964 case VUT_AI_LEVEL:
965 return source->value.ai_level;
966 case VUT_MAXTILEUNITS:
967 return source->value.max_tile_units;
968 case VUT_TERRAINCLASS:
969 return source->value.terrainclass;
970 case VUT_ROADFLAG:
971 return source->value.roadflag;
972 case VUT_EXTRAFLAG:
973 return source->value.extraflag;
974 case VUT_MINYEAR:
975 return source->value.minyear;
976 case VUT_MINCALFRAG:
977 return source->value.mincalfrag;
978 case VUT_TOPO:
979 return source->value.topo_property;
980 case VUT_WRAP:
981 return source->value.wrap_property;
983 return source->value.ssetval;
984 case VUT_TERRAINALTER:
985 return source->value.terrainalter;
986 case VUT_CITYTILE:
987 return source->value.citytile;
988 case VUT_CITYSTATUS:
989 return source->value.citystatus;
990 case VUT_PLAYER_STATE:
991 return source->value.plrstate;
992 case VUT_COUNTER:
993 return counter_id(source->value.counter);
994 case VUT_MINLATITUDE:
995 case VUT_MAXLATITUDE:
996 return source->value.latitude;
997 case VUT_COUNT:
998 break;
999 }
1000
1001 /* If we reach here there's been an error. */
1002 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
1003 source->kind);
1004 return 0;
1005}
1006
1007
1008/**********************************************************************/
1012{
1013 static const struct req_context empty = {};
1014 return &empty;
1015}
1016
1017
1018/**********************************************************************/
1026const char *req_to_fstring(const struct requirement *req,
1027 struct astring *astr)
1028{
1029 astr_init(astr);
1030
1031 astr_set(astr, "%s%s %s %s%s",
1032 req->survives ? "surviving " : "",
1033 req_range_name(req->range),
1035 req->present ? "" : "!",
1037
1038 return astr_str(astr);
1039}
1040
1041/**********************************************************************/
1049 bool survives, bool present, bool quiet,
1050 const char *value)
1051{
1052 struct requirement req;
1053 bool invalid;
1054 const char *error = NULL;
1055
1056 req.source = universal_by_rule_name(type, value);
1057
1059 if (invalid) {
1060 error = "bad type or name";
1061 } else {
1062 /* Scan the range string to find the range. If no range is given a
1063 * default fallback is used rather than giving an error. */
1064 if (range != NULL) {
1066 if (!req_range_is_valid(req.range)) {
1067 invalid = TRUE;
1068 }
1069 } else {
1070 switch (req.source.kind) {
1071 case VUT_NONE:
1072 case VUT_COUNT:
1073 break;
1074 case VUT_IMPROVEMENT:
1075 case VUT_IMPR_GENUS:
1076 case VUT_IMPR_FLAG:
1077 case VUT_UTYPE:
1078 case VUT_UTFLAG:
1079 case VUT_UCLASS:
1080 case VUT_UCFLAG:
1081 case VUT_MINVETERAN:
1082 case VUT_UNITSTATE:
1083 case VUT_ACTIVITY:
1084 case VUT_MINMOVES:
1085 case VUT_MINHP:
1086 case VUT_AGE:
1087 case VUT_FORM_AGE:
1088 case VUT_ACTION:
1089 case VUT_OTYPE:
1090 case VUT_SPECIALIST:
1091 case VUT_DIPLREL_TILE_O:
1093 req.range = REQ_RANGE_LOCAL;
1094 break;
1095 case VUT_EXTRA:
1096 case VUT_ROADFLAG:
1097 case VUT_EXTRAFLAG:
1098 /* Keep old behavior */
1099 req.range = REQ_RANGE_TILE;
1100 break;
1101 case VUT_TERRAIN:
1102 case VUT_TERRFLAG:
1103 case VUT_TERRAINCLASS:
1104 case VUT_TERRAINALTER:
1105 case VUT_CITYTILE:
1106 case VUT_MAXTILEUNITS:
1107 case VUT_MINLATITUDE:
1108 case VUT_MAXLATITUDE:
1109 req.range = REQ_RANGE_TILE;
1110 break;
1111 case VUT_COUNTER:
1112 case VUT_MINSIZE:
1113 case VUT_MINCULTURE:
1114 case VUT_MINFOREIGNPCT:
1115 case VUT_NATIONALITY:
1116 case VUT_ORIGINAL_OWNER:
1117 case VUT_CITYSTATUS:
1118 case VUT_GOOD:
1119 req.range = REQ_RANGE_CITY;
1120 break;
1121 case VUT_GOVERNMENT:
1122 case VUT_ACHIEVEMENT:
1123 case VUT_STYLE:
1124 case VUT_ADVANCE:
1125 case VUT_TECHFLAG:
1126 case VUT_NATION:
1127 case VUT_NATIONGROUP:
1128 case VUT_DIPLREL:
1129 case VUT_DIPLREL_TILE:
1131 case VUT_AI_LEVEL:
1132 case VUT_PLAYER_FLAG:
1133 case VUT_PLAYER_STATE:
1134 case VUT_MINCITIES:
1135 req.range = REQ_RANGE_PLAYER;
1136 break;
1137 case VUT_MINYEAR:
1138 case VUT_MINCALFRAG:
1139 case VUT_TOPO:
1140 case VUT_WRAP:
1141 case VUT_MINTECHS:
1142 case VUT_SERVERSETTING:
1143 req.range = REQ_RANGE_WORLD;
1144 break;
1145 }
1146 }
1147
1148 req.survives = survives;
1149 req.present = present;
1150 req.quiet = quiet;
1151
1152 /* These checks match what combinations are supported inside
1153 * is_req_active(). However, it's only possible to do basic checks,
1154 * not anything that might depend on the rest of the ruleset which
1155 * might not have been loaded yet. */
1156 switch (req.source.kind) {
1157 case VUT_TERRAIN:
1158 case VUT_TERRAINCLASS:
1159 case VUT_TERRFLAG:
1160 invalid = (req.range != REQ_RANGE_TILE
1161 && req.range != REQ_RANGE_CADJACENT
1162 && req.range != REQ_RANGE_ADJACENT
1163 && req.range != REQ_RANGE_CITY
1164 && req.range != REQ_RANGE_TRADE_ROUTE);
1165 break;
1166 case VUT_EXTRA:
1167 case VUT_ROADFLAG:
1168 case VUT_EXTRAFLAG:
1170 break;
1171 case VUT_TECHFLAG:
1172 case VUT_ACHIEVEMENT:
1173 case VUT_MINTECHS:
1174 invalid = (req.range < REQ_RANGE_PLAYER);
1175 break;
1176 case VUT_ADVANCE:
1178 && req.range != REQ_RANGE_LOCAL);
1179 break;
1180 case VUT_GOVERNMENT:
1181 case VUT_AI_LEVEL:
1182 case VUT_STYLE:
1183 case VUT_MINCITIES:
1184 invalid = (req.range != REQ_RANGE_PLAYER);
1185 break;
1186 case VUT_MINSIZE:
1187 case VUT_MINFOREIGNPCT:
1188 case VUT_NATIONALITY:
1189 case VUT_CITYSTATUS:
1190 invalid = (req.range != REQ_RANGE_CITY
1191 && req.range != REQ_RANGE_TRADE_ROUTE);
1192 break;
1193 case VUT_GOOD:
1194 case VUT_ORIGINAL_OWNER:
1195 invalid = (req.range != REQ_RANGE_CITY);
1196 break;
1197 case VUT_MINCULTURE:
1198 invalid = (req.range != REQ_RANGE_CITY
1200 && req.range != REQ_RANGE_PLAYER
1201 && req.range != REQ_RANGE_TEAM
1202 && req.range != REQ_RANGE_ALLIANCE
1203 && req.range != REQ_RANGE_WORLD);
1204 break;
1205 case VUT_DIPLREL:
1206 invalid = (req.range != REQ_RANGE_LOCAL
1207 && req.range != REQ_RANGE_PLAYER
1208 && req.range != REQ_RANGE_TEAM
1209 && req.range != REQ_RANGE_ALLIANCE
1210 && req.range != REQ_RANGE_WORLD)
1211 /* Non local foreign makes no sense. */
1212 || (req.source.value.diplrel == DRO_FOREIGN
1213 && req.range != REQ_RANGE_LOCAL);
1214 break;
1215 case VUT_DIPLREL_TILE:
1216 invalid = (req.range != REQ_RANGE_LOCAL
1217 && req.range != REQ_RANGE_PLAYER
1218 && req.range != REQ_RANGE_TEAM
1219 && req.range != REQ_RANGE_ALLIANCE)
1220 /* Non local foreign makes no sense. */
1221 || (req.source.value.diplrel == DRO_FOREIGN
1222 && req.range != REQ_RANGE_LOCAL);
1223 break;
1224 case VUT_DIPLREL_TILE_O:
1225 invalid = (req.range != REQ_RANGE_LOCAL);
1226 break;
1228 invalid = (req.range != REQ_RANGE_LOCAL
1229 && req.range != REQ_RANGE_PLAYER
1230 && req.range != REQ_RANGE_TEAM
1231 && req.range != REQ_RANGE_ALLIANCE)
1232 /* Non local foreign makes no sense. */
1233 || (req.source.value.diplrel == DRO_FOREIGN
1234 && req.range != REQ_RANGE_LOCAL);
1235 break;
1237 invalid = (req.range != REQ_RANGE_LOCAL);
1238 break;
1239 case VUT_NATION:
1240 case VUT_NATIONGROUP:
1242 && req.range != REQ_RANGE_TEAM
1243 && req.range != REQ_RANGE_ALLIANCE
1244 && req.range != REQ_RANGE_WORLD);
1245 break;
1246 case VUT_MINVETERAN:
1247 case VUT_UNITSTATE:
1248 case VUT_ACTIVITY:
1249 case VUT_MINMOVES:
1250 case VUT_MINHP:
1251 case VUT_ACTION:
1252 case VUT_OTYPE:
1253 case VUT_SPECIALIST:
1254 invalid = (req.range != REQ_RANGE_LOCAL);
1255 break;
1256 case VUT_UTYPE:
1257 case VUT_UTFLAG:
1258 case VUT_UCLASS:
1259 case VUT_UCFLAG:
1260 invalid = (req.range != REQ_RANGE_LOCAL
1261 && req.range != REQ_RANGE_TILE
1262 && req.range != REQ_RANGE_CADJACENT
1263 && req.range != REQ_RANGE_ADJACENT);
1264 break;
1265 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1266 invalid = (req.range != REQ_RANGE_TILE);
1267 break;
1268 case VUT_CITYTILE:
1269 case VUT_MAXTILEUNITS:
1270 invalid = (req.range != REQ_RANGE_TILE
1271 && req.range != REQ_RANGE_CADJACENT
1272 && req.range != REQ_RANGE_ADJACENT);
1273 break;
1274 case VUT_MINLATITUDE:
1275 case VUT_MAXLATITUDE:
1276 invalid = (req.range != REQ_RANGE_TILE
1277 && req.range != REQ_RANGE_CADJACENT
1278 && req.range != REQ_RANGE_ADJACENT
1279 && req.range != REQ_RANGE_WORLD)
1280 /* Avoid redundancy at tile range: no negated requirements
1281 * that could be emulated by a present requirement of the
1282 * other type */
1283 || (req.range == REQ_RANGE_TILE && !req.present);
1284 break;
1285 case VUT_MINYEAR:
1286 case VUT_MINCALFRAG:
1287 case VUT_TOPO:
1288 case VUT_WRAP:
1289 case VUT_SERVERSETTING:
1290 invalid = (req.range != REQ_RANGE_WORLD);
1291 break;
1292 case VUT_AGE:
1293 /* FIXME: could support TRADE_ROUTE, TEAM, etc */
1294 invalid = (req.range != REQ_RANGE_LOCAL
1295 && req.range != REQ_RANGE_CITY
1296 && req.range != REQ_RANGE_PLAYER);
1297 break;
1298 case VUT_FORM_AGE:
1299 invalid = (req.range != REQ_RANGE_LOCAL);
1300 break;
1301 case VUT_IMPR_GENUS:
1302 /* TODO: Support other ranges too. */
1303 invalid = (req.range != REQ_RANGE_LOCAL);
1304 break;
1305 case VUT_IMPR_FLAG:
1306 invalid = (req.range != REQ_RANGE_LOCAL
1307 && req.range != REQ_RANGE_TILE
1308 && req.range != REQ_RANGE_CITY);
1309 break;
1310 case VUT_COUNTER:
1311 invalid = req.range != REQ_RANGE_CITY;
1312 break;
1313 case VUT_PLAYER_FLAG:
1314 case VUT_PLAYER_STATE:
1315 invalid = (req.range != REQ_RANGE_PLAYER);
1316 break;
1317 case VUT_IMPROVEMENT:
1318 /* Valid ranges depend on the building genus (wonder/improvement),
1319 * which might not have been loaded from the ruleset yet.
1320 * So we allow anything here, and do a proper check once ruleset
1321 * loading is complete, in sanity_check_req_individual(). */
1322 case VUT_NONE:
1323 invalid = FALSE;
1324 break;
1325 case VUT_COUNT:
1326 break;
1327 }
1328 if (invalid) {
1329 error = "bad range";
1330 }
1331 }
1332
1333 if (!invalid) {
1334 /* Check 'survives'. */
1335 switch (req.source.kind) {
1336 case VUT_IMPROVEMENT:
1337 /* See buildings_in_range(). */
1339 break;
1340 case VUT_NATION:
1341 case VUT_ADVANCE:
1343 break;
1344 case VUT_COUNTER:
1345 case VUT_IMPR_GENUS:
1346 case VUT_IMPR_FLAG:
1347 case VUT_PLAYER_FLAG:
1348 case VUT_PLAYER_STATE:
1349 case VUT_GOVERNMENT:
1350 case VUT_TERRAIN:
1351 case VUT_UTYPE:
1352 case VUT_UTFLAG:
1353 case VUT_UCLASS:
1354 case VUT_UCFLAG:
1355 case VUT_MINVETERAN:
1356 case VUT_UNITSTATE:
1357 case VUT_ACTIVITY:
1358 case VUT_MINMOVES:
1359 case VUT_MINHP:
1360 case VUT_AGE:
1361 case VUT_FORM_AGE:
1362 case VUT_ACTION:
1363 case VUT_OTYPE:
1364 case VUT_SPECIALIST:
1365 case VUT_MINSIZE:
1366 case VUT_MINCULTURE:
1367 case VUT_MINFOREIGNPCT:
1368 case VUT_AI_LEVEL:
1369 case VUT_TERRAINCLASS:
1370 case VUT_MINYEAR:
1371 case VUT_MINCALFRAG:
1372 case VUT_TOPO:
1373 case VUT_WRAP:
1374 case VUT_SERVERSETTING:
1375 case VUT_TERRAINALTER:
1376 case VUT_CITYTILE:
1377 case VUT_CITYSTATUS:
1378 case VUT_TERRFLAG:
1379 case VUT_NATIONALITY:
1380 case VUT_ORIGINAL_OWNER:
1381 case VUT_ROADFLAG:
1382 case VUT_EXTRAFLAG:
1383 case VUT_EXTRA:
1384 case VUT_GOOD:
1385 case VUT_TECHFLAG:
1386 case VUT_ACHIEVEMENT:
1387 case VUT_NATIONGROUP:
1388 case VUT_STYLE:
1389 case VUT_DIPLREL:
1390 case VUT_DIPLREL_TILE:
1391 case VUT_DIPLREL_TILE_O:
1394 case VUT_MAXTILEUNITS:
1395 case VUT_MINTECHS:
1396 case VUT_MINCITIES:
1397 case VUT_MINLATITUDE:
1398 case VUT_MAXLATITUDE:
1399 /* Most requirements don't support 'survives'. */
1400 invalid = survives;
1401 break;
1402 case VUT_NONE:
1403 case VUT_COUNT:
1404 break;
1405 }
1406 if (invalid) {
1407 error = "bad 'survives'";
1408 }
1409 }
1410
1411 if (invalid) {
1412 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1413 type, range, survives ? "survives" : "",
1414 present ? "present" : "", value, error);
1416 }
1417
1418 return req;
1419}
1420
1421/**********************************************************************/
1427 int value)
1428{
1429 struct requirement req;
1430
1431 req.source = universal_by_number(type, value);
1432 req.range = range;
1433 req.survives = survives;
1434 req.present = present;
1435 req.quiet = quiet;
1436
1437 return req;
1438}
1439
1440/**********************************************************************/
1444void req_get_values(const struct requirement *req,
1445 int *type, int *range,
1446 bool *survives, bool *present, bool *quiet,
1447 int *value)
1448{
1449 universal_extraction(&req->source, type, value);
1450 *range = req->range;
1451 *survives = req->survives;
1452 *present = req->present;
1453 *quiet = req->quiet;
1454}
1455
1456/**********************************************************************/
1459void req_copy(struct requirement *dst, const struct requirement *src)
1460{
1461 universal_copy(&(dst->source), &(src->source));
1462 dst->range = src->range;
1463 dst->survives = src->survives;
1464 dst->present = src->present;
1465 dst->quiet = src->quiet;
1466}
1467
1468/**********************************************************************/
1472bool are_requirements_equal(const struct requirement *req1,
1473 const struct requirement *req2)
1474{
1475 return (are_universals_equal(&req1->source, &req2->source)
1476 && req1->range == req2->range
1477 && req1->survives == req2->survives
1478 && req1->present == req2->present);
1479}
1480
1481/**********************************************************************/
1484static bool are_requirements_opposites(const struct requirement *req1,
1485 const struct requirement *req2)
1486{
1487 return (are_universals_equal(&req1->source, &req2->source)
1488 && req1->range == req2->range
1489 && req1->survives == req2->survives
1490 && req1->present != req2->present);
1491}
1492
1493/**********************************************************************/
1497static bool impr_contra_genus(const struct requirement *impr_req,
1498 const struct requirement *genus_req)
1499{
1500 /* The input is sane. */
1503
1504 if (impr_req->range == REQ_RANGE_LOCAL
1505 && genus_req->range == REQ_RANGE_LOCAL) {
1506 /* Applies to the same target building. */
1507
1508 if (impr_req->present && !genus_req->present) {
1509 /* The target building can't not have the genus it has. */
1510 return (impr_req->source.value.building->genus
1511 == genus_req->source.value.impr_genus);
1512 }
1513
1514 if (impr_req->present && genus_req->present) {
1515 /* The target building can't have another genus than it has. */
1516 return (impr_req->source.value.building->genus
1517 != genus_req->source.value.impr_genus);
1518 }
1519 }
1520
1521 /* No special knowledge. */
1522 return FALSE;
1523}
1524
1525/**********************************************************************/
1529static bool impr_contra_flag(const struct requirement *impr_req,
1530 const struct requirement *flag_req)
1531{
1532 /* The input is sane. */
1535
1536 if (impr_req->range == REQ_RANGE_LOCAL
1537 && flag_req->range == REQ_RANGE_LOCAL) {
1538 /* Applies to the same target building. */
1539
1540 if (impr_req->present && !flag_req->present) {
1541 /* The target building can't not have the flag it has. */
1542 return improvement_has_flag(impr_req->source.value.building,
1543 flag_req->source.value.impr_flag);
1544 }
1545
1546 if (impr_req->present && flag_req->present) {
1547 /* The target building can't have another flag than it has. */
1548 return !improvement_has_flag(impr_req->source.value.building,
1549 flag_req->source.value.impr_flag);
1550 }
1551 }
1552
1553 /* No special knowledge. */
1554 return FALSE;
1555}
1556
1557/**********************************************************************/
1562 const struct requirement *group_req)
1563{
1564 /* The input is sane. */
1565 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1567
1568 if (nation_req->range == REQ_RANGE_PLAYER
1569 && group_req->range == REQ_RANGE_PLAYER) {
1570 /* Applies to the same target building. */
1571
1572 if (nation_req->present && !group_req->present) {
1573 /* The target nation can't be in the group. */
1574 return nation_is_in_group(nation_req->source.value.nation,
1575 group_req->source.value.nationgroup);
1576 }
1577 }
1578
1579 /* No special knowledge. */
1580 return FALSE;
1581}
1582
1583/**********************************************************************/
1587static bool city_center_contra(const struct requirement *cc_req,
1588 const struct requirement *ct_req)
1589{
1590 /* The input is sane. */
1591 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1592 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1593
1594 if (cc_req->source.value.citytile == CITYT_CENTER
1595 && cc_req->present && cc_req->range <= ct_req->range) {
1596 switch (ct_req->source.value.citytile) {
1597 case CITYT_CENTER:
1598 case CITYT_CLAIMED:
1599 case CITYT_EXTRAS_OWNED:
1600 case CITYT_WORKED:
1602 /* Should be always on city center */
1603 return !ct_req->present;
1605 /* Handled later */
1606 break;
1607 case CITYT_LAST:
1608 /* Error */
1609 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1610 }
1611 }
1612 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1613 || cc_req->source.value.citytile == CITYT_CENTER)
1614 && ct_req->source.value.citytile
1616 && REQ_RANGE_TILE == cc_req->range
1617 && REQ_RANGE_TILE == ct_req->range) {
1618 /* Can't coexist */
1619 return cc_req->present ? ct_req->present : !ct_req->present;
1620 }
1621
1622 return FALSE;
1623}
1624
1625/**********************************************************************/
1630static bool present_implies_not_present(const struct requirement *req1,
1631 const struct requirement *req2)
1632{
1633 const struct requirement *absent, *present;
1634
1635 if (req1->present == req2->present) {
1636 /* Can't use the knowledge in universal_found_function when both are
1637 * required to be absent or when both are required to be present.
1638 * It is no contradiction to require !Spy unit and !Missile unit class.
1639 * It is no contradiction to require River and Irrigation at the same
1640 * tile. */
1641 return FALSE;
1642 }
1643
1644 if (req1->present) {
1645 absent = req2;
1646 present = req1;
1647 } else {
1648 absent = req1;
1649 present = req2;
1650 }
1651
1652 if (!universal_found_function[present->source.kind]) {
1653 /* No knowledge to exploit. */
1654 return FALSE;
1655 }
1656
1657 if (present->range != absent->range) {
1658 /* Larger ranges are not always strict supersets of smaller ranges.
1659 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1660 * but not in Trade Route. */
1661 return FALSE;
1662 }
1663
1665 &present->source);
1666}
1667
1668/**********************************************************************/
1671bool req_implies_req(const struct requirement *req1,
1672 const struct requirement *req2)
1673{
1674 struct requirement nreq2;
1675
1676 req_copy(&nreq2, req2);
1677 nreq2.present = !nreq2.present;
1679}
1680
1681/**********************************************************************/
1689 const struct requirement *req2)
1690{
1691 if (are_requirements_opposites(req1, req2)) {
1692 /* The exact opposite. */
1693 return TRUE;
1694 }
1695
1696 if (present_implies_not_present(req1, req2)) {
1697 return TRUE;
1698 }
1699
1700 switch (req1->source.kind) {
1701 case VUT_IMPROVEMENT:
1702 if (req2->source.kind == VUT_IMPR_GENUS) {
1703 return impr_contra_genus(req1, req2);
1704 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1705 return impr_contra_flag(req1, req2);
1706 } else if (req2->source.kind == VUT_CITYTILE
1707 && req2->source.value.citytile == CITYT_CENTER
1708 && REQ_RANGE_TILE == req2->range
1709 && REQ_RANGE_TILE == req1->range
1710 && req1->present) {
1711 /* A building must be in a city */
1712 return !req2->present;
1713 }
1714
1715 /* No special knowledge. */
1716 return FALSE;
1717 case VUT_IMPR_GENUS:
1718 if (req2->source.kind == VUT_IMPROVEMENT) {
1719 return impr_contra_genus(req2, req1);
1720 }
1721
1722 /* No special knowledge. */
1723 return FALSE;
1724 case VUT_IMPR_FLAG:
1725 if (req2->source.kind == VUT_IMPROVEMENT) {
1726 return impr_contra_flag(req2, req1);
1727 }
1728
1729 /* No special knowledge. */
1730 return FALSE;
1731 case VUT_DIPLREL:
1732 case VUT_DIPLREL_TILE:
1733 case VUT_DIPLREL_TILE_O:
1736 if (req2->source.kind != req1->source.kind) {
1737 /* Finding contradictions across requirement kinds aren't supported
1738 * for DiplRel requirements. */
1739 return FALSE;
1740 } else {
1741 /* Use the special knowledge about DiplRel requirements to find
1742 * contradictions. */
1743
1745 int req2_pos;
1746
1749 req2->range,
1750 req2->present);
1751
1752 return BV_ISSET(req1_contra, req2_pos);
1753 }
1754 break;
1755 case VUT_MINMOVES:
1756 if (req2->source.kind != VUT_MINMOVES) {
1757 /* Finding contradictions across requirement kinds aren't supported
1758 * for MinMoveFrags requirements. */
1759 return FALSE;
1760 } else if (req1->present == req2->present) {
1761 /* No contradiction possible. */
1762 return FALSE;
1763 } else {
1764 /* Number of move fragments left can't be larger than the number
1765 * required to be present and smaller than the number required to not
1766 * be present when the number required to be present is smaller than
1767 * the number required to not be present. */
1768 if (req1->present) {
1769 return req1->source.value.minmoves >= req2->source.value.minmoves;
1770 } else {
1771 return req1->source.value.minmoves <= req2->source.value.minmoves;
1772 }
1773 }
1774 break;
1775 case VUT_MINLATITUDE:
1776 case VUT_MAXLATITUDE:
1777 if (req2->source.kind != VUT_MINLATITUDE
1778 && req2->source.kind != VUT_MAXLATITUDE) {
1779 /* Finding contradictions across requirement kinds other than each
1780 * other is not supported for MinLatitude and MaxLatitude. */
1781 return FALSE;
1782 } else {
1783 /* For a contradiction, we need
1784 * - a minimum (present MinLatitude or negated MaxLatitude)
1785 * - a maximum (negated MinLatitude or present MaxLatitude)
1786 * - the maximum to be less than the minimum
1787 * - a requirement at the larger range that applies to the entire
1788 * range (i.e. a negated requirement, unless the range is Tile)
1789 * Otherwise, the two requirements could still be fulfilled
1790 * simultaneously by different tiles in the range */
1791
1792 /* Initial values beyond the boundaries to avoid edge cases */
1793 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
1795
1796#define EXTRACT_INFO(req) \
1797 if (req->present) { \
1798 if (req->source.kind == VUT_MINLATITUDE) { \
1799 /* present MinLatitude */ \
1800 minimum = MAX(minimum, req->source.value.latitude); \
1801 } else { \
1802 /* present MaxLatitude */ \
1803 maximum = MIN(maximum, req->source.value.latitude); \
1804 } \
1805 } else { \
1806 covered_range = MAX(covered_range, req->range); \
1807 if (req->source.kind == VUT_MINLATITUDE) { \
1808 /* negated MinLatitude */ \
1809 maximum = MIN(maximum, req->source.value.latitude - 1); \
1810 } else { \
1811 /* negated MaxLatitude */ \
1812 minimum = MAX(minimum, req->source.value.latitude + 1); \
1813 } \
1814 }
1815
1816 EXTRACT_INFO(req1);
1817 EXTRACT_INFO(req2);
1818
1819#undef EXTRACT_INFO
1820
1821 return (maximum < minimum
1822 && covered_range >= req1->range
1823 && covered_range >= req2->range);
1824 }
1825 break;
1826 case VUT_NATION:
1827 if (req2->source.kind == VUT_NATIONGROUP) {
1828 return nation_contra_group(req1, req2);
1829 }
1830
1831 /* No special knowledge. */
1832 return FALSE;
1833 break;
1834 case VUT_NATIONGROUP:
1835 if (req2->source.kind == VUT_NATION) {
1836 return nation_contra_group(req2, req1);
1837 }
1838
1839 /* No special knowledge. */
1840 return FALSE;
1841 break;
1842 case VUT_CITYTILE:
1843 if (req2->source.kind == VUT_CITYTILE) {
1844 return city_center_contra(req1, req2)
1845 || city_center_contra(req2, req1);
1846 } else if (req1->source.value.citytile == CITYT_CENTER
1847 && req2->source.kind == VUT_IMPROVEMENT
1848 && REQ_RANGE_TILE == req2->range
1849 && REQ_RANGE_TILE == req1->range
1850 && req2->present) {
1851 /* A building must be in a city */
1852 return !req1->present;
1853 }
1854
1855 return FALSE;
1856 default:
1857 /* No special knowledge exists. The requirements aren't the exact
1858 * opposite of each other per the initial check. */
1859 return FALSE;
1860 }
1861}
1862
1863/**********************************************************************/
1868 const struct requirement_vector *vec)
1869{
1870 /* If the requirement is contradicted by any requirement in the vector it
1871 * contradicts the entire requirement vector. */
1874 return TRUE;
1875 }
1877
1878 /* Not a singe requirement in the requirement vector is contradicted be
1879 * the specified requirement. */
1880 return FALSE;
1881}
1882
1883/**********************************************************************/
1886static inline bool are_tiles_in_range(const struct tile *tile1,
1887 const struct tile *tile2,
1888 enum req_range range)
1889{
1890 switch (range) {
1891 case REQ_RANGE_ADJACENT:
1893 return TRUE;
1894 }
1896 case REQ_RANGE_TILE:
1897 return same_pos(tile1, tile2);
1899 return map_distance(tile1, tile2) <= 1;
1900 case REQ_RANGE_CITY:
1902 case REQ_RANGE_LOCAL:
1904 case REQ_RANGE_PLAYER:
1905 case REQ_RANGE_TEAM:
1906 case REQ_RANGE_ALLIANCE:
1907 case REQ_RANGE_WORLD:
1908 case REQ_RANGE_COUNT:
1909 /* Invalid */
1911 }
1912 return FALSE;
1913}
1914
1915/**********************************************************************/
1918static inline bool players_in_same_range(const struct player *pplayer1,
1919 const struct player *pplayer2,
1920 enum req_range range)
1921{
1922 switch (range) {
1923 case REQ_RANGE_WORLD:
1924 return TRUE;
1925 case REQ_RANGE_ALLIANCE:
1927 case REQ_RANGE_TEAM:
1929 case REQ_RANGE_PLAYER:
1930 return pplayer1 == pplayer2;
1933 case REQ_RANGE_CITY:
1934 case REQ_RANGE_ADJACENT:
1936 case REQ_RANGE_TILE:
1937 case REQ_RANGE_LOCAL:
1938 case REQ_RANGE_COUNT:
1939 break;
1940 }
1941
1942 fc_assert_msg(FALSE, "Invalid range %d.", range);
1943 return FALSE;
1944}
1945
1946#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
1947{ \
1948 fc_assert_ret_val(req != NULL, TRI_MAYBE); \
1949 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
1950 fc_assert(context != NULL); \
1951}
1952
1953/**********************************************************************/
1961static enum fc_tristate
1963 const struct req_context *context,
1964 const struct req_context *other_context,
1965 const struct requirement *req)
1966{
1968
1969 return TRI_YES;
1970}
1971
1972/**********************************************************************/
1976static int num_world_buildings_total(const struct impr_type *building)
1977{
1978 if (is_great_wonder(building)) {
1979 return (great_wonder_is_built(building)
1980 || great_wonder_is_destroyed(building) ? 1 : 0);
1981 } else {
1982 log_error("World-ranged requirements are only supported for wonders.");
1983 return 0;
1984 }
1985}
1986
1987/**********************************************************************/
1990static int num_world_buildings(const struct impr_type *building)
1991{
1992 if (is_great_wonder(building)) {
1993 return (great_wonder_is_built(building) ? 1 : 0);
1994 } else {
1995 log_error("World-ranged requirements are only supported for wonders.");
1996 return 0;
1997 }
1998}
1999
2000/**********************************************************************/
2011static bool player_has_ever_built(const struct player *pplayer,
2012 const struct impr_type *building)
2013{
2014 if (is_wonder(building)) {
2015 return (wonder_is_built(pplayer, building)
2016 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2017 } else {
2018 log_error("Player-ranged requirements are only supported for wonders.");
2019 return FALSE;
2020 }
2021}
2022
2023/**********************************************************************/
2026static int num_player_buildings(const struct player *pplayer,
2027 const struct impr_type *building)
2028{
2029 if (is_wonder(building)) {
2030 return (wonder_is_built(pplayer, building) ? 1 : 0);
2031 } else {
2032 log_error("Player-ranged requirements are only supported for wonders.");
2033 return 0;
2034 }
2035}
2036
2037/**********************************************************************/
2040static int num_continent_buildings(const struct player *pplayer,
2041 int continent,
2042 const struct impr_type *building)
2043{
2044 if (is_wonder(building)) {
2045 const struct city *pcity;
2046
2047 pcity = city_from_wonder(pplayer, building);
2048 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2049 return 1;
2050 }
2051 } else {
2052 log_error("Island-ranged requirements are only supported for wonders.");
2053 }
2054 return 0;
2055}
2056
2057/**********************************************************************/
2065static enum fc_tristate
2067 const struct req_context *context,
2068 const struct req_context *other_context,
2069 const struct requirement *req)
2070{
2071 const struct impr_type *building;
2072
2074
2075 building = req->source.value.building;
2076
2077 /* Check if it's certain that the building is obsolete given the
2078 * specification we have */
2079 if (improvement_obsolete(context->player, building, context->city)) {
2080 return TRI_NO;
2081 }
2082
2083 if (req->survives) {
2084
2085 /* Check whether condition has ever held, using cached information. */
2086 switch (req->range) {
2087 case REQ_RANGE_WORLD:
2088 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2089 case REQ_RANGE_ALLIANCE:
2090 case REQ_RANGE_TEAM:
2091 if (context->player == NULL) {
2092 return TRI_MAYBE;
2093 }
2094 players_iterate_alive(plr2) {
2095 if (players_in_same_range(context->player, plr2, req->range)
2096 && player_has_ever_built(plr2, building)) {
2097 return TRI_YES;
2098 }
2100 return TRI_NO;
2101 case REQ_RANGE_PLAYER:
2102 if (context->player == NULL) {
2103 return TRI_MAYBE;
2104 }
2106 building));
2109 case REQ_RANGE_CITY:
2110 case REQ_RANGE_LOCAL:
2111 case REQ_RANGE_TILE:
2113 case REQ_RANGE_ADJACENT:
2114 /* There is no sources cache for this. */
2115 log_error("Surviving requirements are only supported at "
2116 "World/Alliance/Team/Player ranges.");
2117 return TRI_NO;
2118 case REQ_RANGE_COUNT:
2119 break;
2120 }
2121
2122 } else {
2123
2124 /* Non-surviving requirement. */
2125 switch (req->range) {
2126 case REQ_RANGE_WORLD:
2127 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2128 case REQ_RANGE_ALLIANCE:
2129 case REQ_RANGE_TEAM:
2130 if (context->player == NULL) {
2131 return TRI_MAYBE;
2132 }
2133 players_iterate_alive(plr2) {
2134 if (players_in_same_range(context->player, plr2, req->range)
2135 && num_player_buildings(plr2, building) > 0) {
2136 return TRI_YES;
2137 }
2139 return TRI_NO;
2140 case REQ_RANGE_PLAYER:
2141 if (context->player == NULL) {
2142 return TRI_MAYBE;
2143 }
2145 building)
2146 > 0);
2148 /* At present, "Continent" effects can affect only
2149 * cities and units in cities. */
2150 if (context->player && context->city) {
2151 int continent = tile_continent(context->city->tile);
2153 continent, building)
2154 > 0);
2155 } else {
2156 return TRI_MAYBE;
2157 }
2159 if (context->city) {
2160 if (city_has_building(context->city, building)) {
2161 return TRI_YES;
2162 } else {
2163 enum fc_tristate ret = TRI_NO;
2164
2166 if (trade_partner == NULL) {
2167 ret = TRI_MAYBE;
2168 } else if (city_has_building(trade_partner, building)) {
2169 return TRI_YES;
2170 }
2172
2173 return ret;
2174 }
2175 } else {
2176 return TRI_MAYBE;
2177 }
2178 case REQ_RANGE_CITY:
2179 if (context->city) {
2180 return BOOL_TO_TRISTATE(city_has_building(context->city, building));
2181 } else {
2182 return TRI_MAYBE;
2183 }
2184 case REQ_RANGE_LOCAL:
2185 if (context->building) {
2186 if (context->building == building) {
2187 return TRI_YES;
2188 } else {
2189 return TRI_NO;
2190 }
2191 } else {
2192 /* TODO: other local targets */
2193 return TRI_MAYBE;
2194 }
2195 case REQ_RANGE_TILE:
2196 if (context->tile) {
2197 const struct city *pcity = tile_city(context->tile);
2198
2199 if (pcity) {
2200 return BOOL_TO_TRISTATE(city_has_building(pcity, building));
2201 } else {
2202 return TRI_NO;
2203 }
2204 } else {
2205 return TRI_MAYBE;
2206 }
2208 case REQ_RANGE_ADJACENT:
2209 case REQ_RANGE_COUNT:
2210 break;
2211 }
2212
2213 }
2214
2215 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2216 return TRI_NO;
2217}
2218
2219/**********************************************************************/
2227static enum fc_tristate
2229 const struct req_context *context,
2230 const struct req_context *other_context,
2231 const struct requirement *req)
2232{
2234
2235 return (context->building ? BOOL_TO_TRISTATE(
2236 context->building->genus
2237 == req->source.value.impr_genus)
2238 : TRI_MAYBE);
2239}
2240
2241/**********************************************************************/
2244static enum fc_tristate is_buildingflag_in_city(const struct city *pcity,
2245 enum impr_flag_id flag)
2246{
2247 struct player *owner;
2248
2249 if (pcity == NULL) {
2250 return TRI_MAYBE;
2251 }
2252
2253 owner = city_owner(pcity);
2254 city_built_iterate(pcity, impr) {
2255 if (improvement_has_flag(impr, flag)
2256 && !improvement_obsolete(owner, impr, pcity)) {
2257 return TRI_YES;
2258 }
2260
2261 return TRI_NO;
2262}
2263
2264/**********************************************************************/
2272static enum fc_tristate
2274 const struct req_context *context,
2275 const struct req_context *other_context,
2276 const struct requirement *req)
2277{
2279
2280 switch (req->range) {
2281 case REQ_RANGE_LOCAL:
2282 return (context->building
2284 req->source.value.impr_flag))
2285 : TRI_MAYBE);
2286 case REQ_RANGE_CITY:
2288 case REQ_RANGE_TILE:
2289 if (context->tile == NULL) {
2290 return TRI_MAYBE;
2291 }
2293 req->source.value.impr_flag);
2295 case REQ_RANGE_ADJACENT:
2298 case REQ_RANGE_PLAYER:
2299 case REQ_RANGE_ALLIANCE:
2300 case REQ_RANGE_TEAM:
2301 case REQ_RANGE_WORLD:
2302 case REQ_RANGE_COUNT:
2303 break;
2304 }
2305
2306 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2307
2308 return TRI_MAYBE;
2309}
2310
2311/**********************************************************************/
2319static enum fc_tristate
2321 const struct req_context *context,
2322 const struct req_context *other_context,
2323 const struct requirement *req)
2324{
2326
2327 switch (req->range) {
2328 case REQ_RANGE_PLAYER:
2329 return (context->player != NULL
2331 req->source.value.plr_flag))
2332 : TRI_MAYBE);
2333 case REQ_RANGE_LOCAL:
2334 case REQ_RANGE_CITY:
2335 case REQ_RANGE_TILE:
2337 case REQ_RANGE_ADJACENT:
2340 case REQ_RANGE_ALLIANCE:
2341 case REQ_RANGE_TEAM:
2342 case REQ_RANGE_WORLD:
2343 case REQ_RANGE_COUNT:
2344 break;
2345 }
2346
2347 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2348
2349 return TRI_MAYBE;
2350}
2351
2352/**********************************************************************/
2360static enum fc_tristate
2362 const struct req_context *context,
2363 const struct req_context *other_context,
2364 const struct requirement *req)
2365{
2367
2368 switch (req->range) {
2369 case REQ_RANGE_PLAYER:
2370 return (context->player != NULL
2372 req->source.value.plrstate))
2373 : TRI_MAYBE);
2374 case REQ_RANGE_LOCAL:
2375 case REQ_RANGE_CITY:
2376 case REQ_RANGE_TILE:
2378 case REQ_RANGE_ADJACENT:
2381 case REQ_RANGE_ALLIANCE:
2382 case REQ_RANGE_TEAM:
2383 case REQ_RANGE_WORLD:
2384 case REQ_RANGE_COUNT:
2385 break;
2386 }
2387
2388 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2389
2390 return TRI_MAYBE;
2391}
2392
2393/**********************************************************************/
2401static enum fc_tristate
2403 const struct req_context *context,
2404 const struct req_context *other_context,
2405 const struct requirement *req)
2406{
2407 Tech_type_id tech;
2408
2410
2411 tech = advance_number(req->source.value.advance);
2412
2413 if (req->survives) {
2416 }
2417
2418 /* Not a 'surviving' requirement. */
2419 switch (req->range) {
2420 case REQ_RANGE_PLAYER:
2421 if (context->player != nullptr) {
2423 (research_get(context->player), tech));
2424 } else {
2425 return TRI_MAYBE;
2426 }
2427 case REQ_RANGE_TEAM:
2428 case REQ_RANGE_ALLIANCE:
2429 case REQ_RANGE_WORLD:
2430 if (context->player == nullptr) {
2431 return TRI_MAYBE;
2432 }
2433 players_iterate_alive(plr2) {
2434 if (players_in_same_range(context->player, plr2, req->range)) {
2435 if (research_invention_state(research_get(plr2), tech)
2436 == TECH_KNOWN) {
2437 return TRI_YES;
2438 }
2439 }
2441
2442 return TRI_NO;
2443 case REQ_RANGE_LOCAL:
2444 if (context->player == nullptr) {
2445 return TRI_MAYBE;
2446 }
2447 if (research_get(context->player)->researching == tech) {
2448 return TRI_YES;
2449 }
2450 return TRI_NO;
2451 case REQ_RANGE_TILE:
2453 case REQ_RANGE_ADJACENT:
2454 case REQ_RANGE_CITY:
2457 case REQ_RANGE_COUNT:
2458 break;
2459 }
2460
2461 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2462
2463 return TRI_MAYBE;
2464}
2465
2466/**********************************************************************/
2474static enum fc_tristate
2476 const struct req_context *context,
2477 const struct req_context *other_context,
2478 const struct requirement *req)
2479{
2480 enum tech_flag_id techflag;
2481
2483
2484 techflag = req->source.value.techflag;
2485
2486 switch (req->range) {
2487 case REQ_RANGE_PLAYER:
2488 if (NULL != context->player) {
2490 techflag));
2491 } else {
2492 return TRI_MAYBE;
2493 }
2494 break;
2495 case REQ_RANGE_TEAM:
2496 case REQ_RANGE_ALLIANCE:
2497 if (NULL == context->player) {
2498 return TRI_MAYBE;
2499 }
2500 players_iterate_alive(plr2) {
2501 if (players_in_same_range(context->player, plr2, req->range)
2502 && player_knows_techs_with_flag(plr2, techflag)) {
2503 return TRI_YES;
2504 }
2506 return TRI_NO;
2507 case REQ_RANGE_WORLD:
2508 players_iterate(pplayer) {
2509 if (player_knows_techs_with_flag(pplayer, techflag)) {
2510 return TRI_YES;
2511 }
2513
2514 return TRI_NO;
2515 case REQ_RANGE_LOCAL:
2516 case REQ_RANGE_TILE:
2518 case REQ_RANGE_ADJACENT:
2519 case REQ_RANGE_CITY:
2522 case REQ_RANGE_COUNT:
2523 break;
2524 }
2525
2526 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2527
2528 return TRI_MAYBE;
2529}
2530
2531/**********************************************************************/
2539static enum fc_tristate
2541 const struct req_context *context,
2542 const struct req_context *other_context,
2543 const struct requirement *req)
2544{
2545 int minculture;
2546
2548
2549 minculture = req->source.value.minculture;
2550
2551 switch (req->range) {
2552 case REQ_RANGE_CITY:
2553 if (!context->city) {
2554 return TRI_MAYBE;
2555 }
2556 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2558 if (!context->city) {
2559 return TRI_MAYBE;
2560 }
2561 if (city_culture(context->city) >= minculture) {
2562 return TRI_YES;
2563 } else {
2564 enum fc_tristate ret = TRI_NO;
2565
2567 if (trade_partner == NULL) {
2568 ret = TRI_MAYBE;
2569 } else if (city_culture(trade_partner) >= minculture) {
2570 return TRI_YES;
2571 }
2573
2574 return ret;
2575 }
2576 case REQ_RANGE_PLAYER:
2577 case REQ_RANGE_TEAM:
2578 case REQ_RANGE_ALLIANCE:
2579 case REQ_RANGE_WORLD:
2580 if (NULL == context->player) {
2581 return TRI_MAYBE;
2582 }
2583 players_iterate_alive(plr2) {
2584 if (players_in_same_range(context->player, plr2, req->range)) {
2585 if (player_culture(plr2) >= minculture) {
2586 return TRI_YES;
2587 }
2588 }
2590 return TRI_NO;
2591 case REQ_RANGE_LOCAL:
2592 case REQ_RANGE_TILE:
2594 case REQ_RANGE_ADJACENT:
2596 case REQ_RANGE_COUNT:
2597 break;
2598 }
2599
2600 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2601
2602 return TRI_MAYBE;
2603}
2604
2605/**********************************************************************/
2613static enum fc_tristate
2615 const struct req_context *context,
2616 const struct req_context *other_context,
2617 const struct requirement *req)
2618{
2620
2622
2624
2625 switch (req->range) {
2626 case REQ_RANGE_CITY:
2627 if (!context->city) {
2628 return TRI_MAYBE;
2629 }
2631 / city_size_get(context->city);
2634 if (!context->city) {
2635 return TRI_MAYBE;
2636 }
2638 / city_size_get(context->city);
2640 return TRI_YES;
2641 } else {
2642 enum fc_tristate ret = TRI_NO;
2643
2645 if (trade_partner == NULL) {
2646 ret = TRI_MAYBE;
2647 } else {
2651 return TRI_YES;
2652 }
2653 }
2655
2656 return ret;
2657 }
2658 case REQ_RANGE_PLAYER:
2659 case REQ_RANGE_TEAM:
2660 case REQ_RANGE_ALLIANCE:
2661 case REQ_RANGE_WORLD:
2662 case REQ_RANGE_LOCAL:
2663 case REQ_RANGE_TILE:
2665 case REQ_RANGE_ADJACENT:
2667 case REQ_RANGE_COUNT:
2668 break;
2669 }
2670
2671 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2672
2673 return TRI_MAYBE;
2674}
2675
2676/**********************************************************************/
2684static enum fc_tristate
2686 const struct req_context *context,
2687 const struct req_context *other_context,
2688 const struct requirement *req)
2689{
2690 int max_units;
2691
2693
2695
2696 /* TODO: if can't see V_INVIS -> TRI_MAYBE */
2697 switch (req->range) {
2698 case REQ_RANGE_TILE:
2699 if (!context->tile) {
2700 return TRI_MAYBE;
2701 }
2702 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
2704 if (!context->tile) {
2705 return TRI_MAYBE;
2706 }
2707 if (unit_list_size(context->tile->units) <= max_units) {
2708 return TRI_YES;
2709 }
2711 if (unit_list_size(adjc_tile->units) <= max_units) {
2712 return TRI_YES;
2713 }
2715 return TRI_NO;
2716 case REQ_RANGE_ADJACENT:
2717 if (!context->tile) {
2718 return TRI_MAYBE;
2719 }
2720 if (unit_list_size(context->tile->units) <= max_units) {
2721 return TRI_YES;
2722 }
2724 if (unit_list_size(adjc_tile->units) <= max_units) {
2725 return TRI_YES;
2726 }
2728 return TRI_NO;
2729 case REQ_RANGE_CITY:
2732 case REQ_RANGE_PLAYER:
2733 case REQ_RANGE_TEAM:
2734 case REQ_RANGE_ALLIANCE:
2735 case REQ_RANGE_WORLD:
2736 case REQ_RANGE_LOCAL:
2737 case REQ_RANGE_COUNT:
2738 break;
2739 }
2740
2741 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2742
2743 return TRI_MAYBE;
2744}
2745
2746/**********************************************************************/
2754static enum fc_tristate
2756 const struct req_context *context,
2757 const struct req_context *other_context,
2758 const struct requirement *req)
2759{
2760 const struct extra_type *pextra;
2761 enum fc_tristate ret;
2762
2764
2765 pextra = req->source.value.extra;
2766
2767 switch (req->range) {
2768 case REQ_RANGE_LOCAL:
2769 if (!context->extra) {
2770 return TRI_MAYBE;
2771 }
2772 return BOOL_TO_TRISTATE(context->extra == pextra);
2773 case REQ_RANGE_TILE:
2774 /* The requirement is filled if the tile has extra of requested type. */
2775 if (!context->tile) {
2776 return TRI_MAYBE;
2777 }
2778 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
2780 if (!context->tile) {
2781 return TRI_MAYBE;
2782 }
2783 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2784 || is_extra_card_near(nmap, context->tile, pextra));
2785 case REQ_RANGE_ADJACENT:
2786 if (!context->tile) {
2787 return TRI_MAYBE;
2788 }
2789 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2790 || is_extra_near_tile(nmap, context->tile, pextra));
2791 case REQ_RANGE_CITY:
2792 if (!context->city) {
2793 return TRI_MAYBE;
2794 }
2796 city_tile(context->city), ptile) {
2797 if (tile_has_extra(ptile, pextra)) {
2798 return TRI_YES;
2799 }
2801
2802 return TRI_NO;
2803
2805 if (!context->city) {
2806 return TRI_MAYBE;
2807 }
2809 city_tile(context->city), ptile) {
2810 if (tile_has_extra(ptile, pextra)) {
2811 return TRI_YES;
2812 }
2814
2815 ret = TRI_NO;
2817 if (trade_partner == NULL) {
2818 ret = TRI_MAYBE;
2819 } else {
2821 city_tile(trade_partner), ptile) {
2822 if (tile_has_extra(ptile, pextra)) {
2823 return TRI_YES;
2824 }
2826 }
2828
2829 return ret;
2830
2832 case REQ_RANGE_PLAYER:
2833 case REQ_RANGE_TEAM:
2834 case REQ_RANGE_ALLIANCE:
2835 case REQ_RANGE_WORLD:
2836 case REQ_RANGE_COUNT:
2837 break;
2838 }
2839
2840 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2841
2842 return TRI_MAYBE;
2843}
2844
2845/**********************************************************************/
2853static enum fc_tristate
2855 const struct req_context *context,
2856 const struct req_context *other_context,
2857 const struct requirement *req)
2858{
2859 const struct goods_type *pgood;
2860
2862
2863 pgood = req->source.value.good;
2864
2865 switch (req->range) {
2866 case REQ_RANGE_LOCAL:
2867 case REQ_RANGE_CITY:
2868 /* The requirement is filled if the city imports good of requested type. */
2869 if (!context->city) {
2870 return TRI_MAYBE;
2871 }
2875 case REQ_RANGE_TILE:
2877 case REQ_RANGE_ADJACENT:
2880 case REQ_RANGE_PLAYER:
2881 case REQ_RANGE_TEAM:
2882 case REQ_RANGE_ALLIANCE:
2883 case REQ_RANGE_WORLD:
2884 case REQ_RANGE_COUNT:
2885 break;
2886 }
2887
2888 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2889
2890 return TRI_MAYBE;
2891}
2892
2893/**********************************************************************/
2901static enum fc_tristate
2903 const struct req_context *context,
2904 const struct req_context *other_context,
2905 const struct requirement *req)
2906{
2908
2909 if (context->action) {
2910 return BOOL_TO_TRISTATE(action_number(context->action)
2911 == action_number(req->source.value.action));
2912 }
2913
2914 if (context->unit != nullptr && context->unit->action != ACTION_NONE) {
2915 log_normal("Unit action %s", action_id_rule_name(context->unit->action));
2916 return BOOL_TO_TRISTATE(context->unit->action
2917 == action_number(req->source.value.action));
2918 }
2919
2920 return TRI_NO;
2921}
2922
2923/**********************************************************************/
2931static enum fc_tristate
2933 const struct req_context *context,
2934 const struct req_context *other_context,
2935 const struct requirement *req)
2936{
2938
2939 return BOOL_TO_TRISTATE(context->output
2940 && context->output->index
2941 == req->source.value.outputtype);
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{
2959
2960 return BOOL_TO_TRISTATE(context->specialist
2961 && context->specialist
2962 == req->source.value.specialist);
2963}
2964
2965/**********************************************************************/
2973static enum fc_tristate
2975 const struct req_context *context,
2976 const struct req_context *other_context,
2977 const struct requirement *req)
2978{
2979 const struct terrain *pterrain;
2980
2982
2983 pterrain = req->source.value.terrain;
2984
2985 switch (req->range) {
2986 case REQ_RANGE_TILE:
2987 /* The requirement is filled if the tile has the terrain. */
2988 if (!context->tile) {
2989 return TRI_MAYBE;
2990 }
2991 return pterrain && tile_terrain(context->tile) == pterrain;
2993 if (!context->tile) {
2994 return TRI_MAYBE;
2995 }
2996 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
2997 case REQ_RANGE_ADJACENT:
2998 if (!context->tile) {
2999 return TRI_MAYBE;
3000 }
3001 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
3002 case REQ_RANGE_CITY:
3003 if (!context->city) {
3004 return TRI_MAYBE;
3005 }
3006 if (pterrain != NULL) {
3008 city_tile(context->city), ptile) {
3009 if (tile_terrain(ptile) == pterrain) {
3010 return TRI_YES;
3011 }
3013 }
3014 return TRI_NO;
3016 if (!context->city) {
3017 return TRI_MAYBE;
3018 }
3019 if (pterrain != NULL) {
3020 enum fc_tristate ret;
3021
3023 city_tile(context->city), ptile) {
3024 if (tile_terrain(ptile) == pterrain) {
3025 return TRI_YES;
3026 }
3028
3029 ret = TRI_NO;
3031 if (trade_partner == NULL) {
3032 ret = TRI_MAYBE;
3033 } else {
3035 city_tile(trade_partner), ptile) {
3036 if (tile_terrain(ptile) == pterrain) {
3037 return TRI_YES;
3038 }
3040 }
3042
3043 return ret;
3044 }
3045
3046 return TRI_MAYBE;
3048 case REQ_RANGE_PLAYER:
3049 case REQ_RANGE_TEAM:
3050 case REQ_RANGE_ALLIANCE:
3051 case REQ_RANGE_WORLD:
3052 case REQ_RANGE_LOCAL:
3053 case REQ_RANGE_COUNT:
3054 break;
3055 }
3056
3057 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3058
3059 return TRI_MAYBE;
3060}
3061
3062/**********************************************************************/
3070static enum fc_tristate
3072 const struct req_context *context,
3073 const struct req_context *other_context,
3074 const struct requirement *req)
3075{
3076 enum terrain_class pclass;
3077 enum fc_tristate ret;
3078
3080
3082
3083 switch (req->range) {
3084 case REQ_RANGE_TILE:
3085 /* The requirement is filled if the tile has the terrain of correct class. */
3086 if (!context->tile) {
3087 return TRI_MAYBE;
3088 }
3091 if (!context->tile) {
3092 return TRI_MAYBE;
3093 }
3096 case REQ_RANGE_ADJACENT:
3097 if (!context->tile) {
3098 return TRI_MAYBE;
3099 }
3102 case REQ_RANGE_CITY:
3103 if (!context->city) {
3104 return TRI_MAYBE;
3105 }
3107 city_tile(context->city), ptile) {
3108 const struct terrain *pterrain = tile_terrain(ptile);
3109
3110 if (pterrain != T_UNKNOWN
3111 && terrain_type_terrain_class(pterrain) == pclass) {
3112 return TRI_YES;
3113 }
3115
3116 return TRI_NO;
3118 if (!context->city) {
3119 return TRI_MAYBE;
3120 }
3122 city_tile(context->city), ptile) {
3123 const struct terrain *pterrain = tile_terrain(ptile);
3124
3125 if (pterrain != T_UNKNOWN
3126 && terrain_type_terrain_class(pterrain) == pclass) {
3127 return TRI_YES;
3128 }
3130
3131 ret = TRI_NO;
3133 if (trade_partner == NULL) {
3134 ret = TRI_MAYBE;
3135 } else {
3137 city_tile(trade_partner), ptile) {
3138 const struct terrain *pterrain = tile_terrain(ptile);
3139
3140 if (pterrain != T_UNKNOWN
3141 && terrain_type_terrain_class(pterrain) == pclass) {
3142 return TRI_YES;
3143 }
3145 }
3147
3148 return ret;
3150 case REQ_RANGE_PLAYER:
3151 case REQ_RANGE_TEAM:
3152 case REQ_RANGE_ALLIANCE:
3153 case REQ_RANGE_WORLD:
3154 case REQ_RANGE_LOCAL:
3155 case REQ_RANGE_COUNT:
3156 break;
3157 }
3158
3159 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3160
3161 return TRI_MAYBE;
3162}
3163
3164/**********************************************************************/
3172static enum fc_tristate
3174 const struct req_context *context,
3175 const struct req_context *other_context,
3176 const struct requirement *req)
3177{
3179 enum fc_tristate ret;
3180
3182
3184
3185 switch (req->range) {
3186 case REQ_RANGE_TILE:
3187 /* The requirement is fulfilled if the tile has a terrain with
3188 * correct flag. */
3189 if (!context->tile) {
3190 return TRI_MAYBE;
3191 }
3193 terrflag));
3195 if (!context->tile) {
3196 return TRI_MAYBE;
3197 }
3199 terrflag)
3201 terrflag));
3202 case REQ_RANGE_ADJACENT:
3203 if (!context->tile) {
3204 return TRI_MAYBE;
3205 }
3207 terrflag)
3209 terrflag));
3210 case REQ_RANGE_CITY:
3211 if (!context->city) {
3212 return TRI_MAYBE;
3213 }
3215 city_tile(context->city), ptile) {
3216 const struct terrain *pterrain = tile_terrain(ptile);
3217
3218 if (pterrain != T_UNKNOWN
3219 && terrain_has_flag(pterrain, terrflag)) {
3220 return TRI_YES;
3221 }
3223
3224 return TRI_NO;
3226 if (!context->city) {
3227 return TRI_MAYBE;
3228 }
3230 city_tile(context->city), ptile) {
3231 const struct terrain *pterrain = tile_terrain(ptile);
3232
3233 if (pterrain != T_UNKNOWN
3234 && terrain_has_flag(pterrain, terrflag)) {
3235 return TRI_YES;
3236 }
3238
3239 ret = TRI_NO;
3241 if (trade_partner == NULL) {
3242 ret = TRI_MAYBE;
3243 } else {
3245 city_tile(trade_partner), ptile) {
3246 const struct terrain *pterrain = tile_terrain(ptile);
3247
3248 if (pterrain != T_UNKNOWN
3249 && terrain_has_flag(pterrain, terrflag)) {
3250 return TRI_YES;
3251 }
3253 }
3255
3256 return ret;
3258 case REQ_RANGE_PLAYER:
3259 case REQ_RANGE_TEAM:
3260 case REQ_RANGE_ALLIANCE:
3261 case REQ_RANGE_WORLD:
3262 case REQ_RANGE_LOCAL:
3263 case REQ_RANGE_COUNT:
3264 break;
3265 }
3266
3267 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3268
3269 return TRI_MAYBE;
3270}
3271
3272/**********************************************************************/
3280static enum fc_tristate
3282 const struct req_context *context,
3283 const struct req_context *other_context,
3284 const struct requirement *req)
3285{
3286 enum road_flag_id roadflag;
3287 enum fc_tristate ret;
3288
3290
3291 roadflag = req->source.value.roadflag;
3292
3293 switch (req->range) {
3294 case REQ_RANGE_LOCAL:
3295 {
3296 if (!context->extra) {
3297 return TRI_MAYBE;
3298 }
3299 struct road_type *r = extra_road_get(context->extra);
3300
3301 return BOOL_TO_TRISTATE(
3302 r && road_has_flag(r, roadflag)
3303 );
3304 }
3305 case REQ_RANGE_TILE:
3306 /* The requirement is filled if the tile has a road with correct flag. */
3307 if (!context->tile) {
3308 return TRI_MAYBE;
3309 }
3310 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3312 if (!context->tile) {
3313 return TRI_MAYBE;
3314 }
3315 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3317 roadflag));
3318 case REQ_RANGE_ADJACENT:
3319 if (!context->tile) {
3320 return TRI_MAYBE;
3321 }
3322 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3324 roadflag));
3325 case REQ_RANGE_CITY:
3326 if (!context->city) {
3327 return TRI_MAYBE;
3328 }
3330 city_tile(context->city), ptile) {
3331 if (tile_has_road_flag(ptile, roadflag)) {
3332 return TRI_YES;
3333 }
3335
3336 return TRI_NO;
3338 if (!context->city) {
3339 return TRI_MAYBE;
3340 }
3342 city_tile(context->city), ptile) {
3343 if (tile_has_road_flag(ptile, roadflag)) {
3344 return TRI_YES;
3345 }
3347
3348 ret = TRI_NO;
3350 if (trade_partner == NULL) {
3351 ret = TRI_MAYBE;
3352 } else {
3354 city_tile(trade_partner), ptile) {
3355 if (tile_has_road_flag(ptile, roadflag)) {
3356 return TRI_YES;
3357 }
3359 }
3361
3362 return ret;
3364 case REQ_RANGE_PLAYER:
3365 case REQ_RANGE_TEAM:
3366 case REQ_RANGE_ALLIANCE:
3367 case REQ_RANGE_WORLD:
3368 case REQ_RANGE_COUNT:
3369 break;
3370 }
3371
3372 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3373
3374 return TRI_MAYBE;
3375}
3376
3377/**********************************************************************/
3385static enum fc_tristate
3387 const struct req_context *context,
3388 const struct req_context *other_context,
3389 const struct requirement *req)
3390{
3391 enum extra_flag_id extraflag;
3392 enum fc_tristate ret;
3393
3395
3396 extraflag = req->source.value.extraflag;
3397
3398 switch (req->range) {
3399 case REQ_RANGE_LOCAL:
3400 if (!context->extra) {
3401 return TRI_MAYBE;
3402 }
3403 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3404 case REQ_RANGE_TILE:
3405 /* The requirement is filled if the tile has an extra with correct flag. */
3406 if (!context->tile) {
3407 return TRI_MAYBE;
3408 }
3409 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3411 if (!context->tile) {
3412 return TRI_MAYBE;
3413 }
3414 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3415 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3416 case REQ_RANGE_ADJACENT:
3417 if (!context->tile) {
3418 return TRI_MAYBE;
3419 }
3420 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3421 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3422 case REQ_RANGE_CITY:
3423 if (!context->city) {
3424 return TRI_MAYBE;
3425 }
3427 city_tile(context->city), ptile) {
3428 if (tile_has_extra_flag(ptile, extraflag)) {
3429 return TRI_YES;
3430 }
3432
3433 return TRI_NO;
3435 if (!context->city) {
3436 return TRI_MAYBE;
3437 }
3439 city_tile(context->city), ptile) {
3440 if (tile_has_extra_flag(ptile, extraflag)) {
3441 return TRI_YES;
3442 }
3444
3445 ret = TRI_NO;
3447 if (trade_partner == NULL) {
3448 ret = TRI_MAYBE;
3449 } else {
3451 city_tile(trade_partner), ptile) {
3452 if (tile_has_extra_flag(ptile, extraflag)) {
3453 return TRI_YES;
3454 }
3456 }
3458
3459 return ret;
3461 case REQ_RANGE_PLAYER:
3462 case REQ_RANGE_TEAM:
3463 case REQ_RANGE_ALLIANCE:
3464 case REQ_RANGE_WORLD:
3465 case REQ_RANGE_COUNT:
3466 break;
3467 }
3468
3469 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3470
3471 return TRI_MAYBE;
3472}
3473
3474/**********************************************************************/
3482static enum fc_tristate
3484 const struct req_context *context,
3485 const struct req_context *other_context,
3486 const struct requirement *req)
3487{
3489
3491
3493
3494 if (!context->tile) {
3495 return TRI_MAYBE;
3496 }
3497
3498 switch (req->range) {
3499 case REQ_RANGE_TILE:
3503 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
3504 case REQ_RANGE_CITY:
3507 case REQ_RANGE_PLAYER:
3508 case REQ_RANGE_TEAM:
3509 case REQ_RANGE_ALLIANCE:
3510 case REQ_RANGE_WORLD:
3511 case REQ_RANGE_LOCAL:
3512 case REQ_RANGE_COUNT:
3513 break;
3514 }
3515
3516 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3517
3518 return TRI_MAYBE;
3519}
3520
3521/**********************************************************************/
3529static enum fc_tristate
3531 const struct req_context *context,
3532 const struct req_context *other_context,
3533 const struct requirement *req)
3534{
3536
3537 if (context->player == NULL) {
3538 return TRI_MAYBE;
3539 } else {
3541 == req->source.value.govern);
3542 }
3543}
3544
3545/**********************************************************************/
3553static enum fc_tristate
3555 const struct req_context *context,
3556 const struct req_context *other_context,
3557 const struct requirement *req)
3558{
3560
3561 if (context->player == NULL) {
3562 return TRI_MAYBE;
3563 } else {
3564 return BOOL_TO_TRISTATE(context->player->style
3565 == req->source.value.style);
3566 }
3567}
3568
3569/**********************************************************************/
3577static enum fc_tristate
3579 const struct req_context *context,
3580 const struct req_context *other_context,
3581 const struct requirement *req)
3582{
3584
3585 switch (req->range) {
3586 case REQ_RANGE_WORLD:
3587 /* "None" does not count */
3588 return ((game.info.global_advance_count - 1)
3589 >= req->source.value.min_techs);
3590 case REQ_RANGE_PLAYER:
3591 if (context->player == NULL) {
3592 return TRI_MAYBE;
3593 } else {
3594 /* "None" does not count */
3595 return BOOL_TO_TRISTATE(
3596 (research_get(context->player)->techs_researched - 1)
3597 >= req->source.value.min_techs
3598 );
3599 }
3600 default:
3601 return TRI_MAYBE;
3602 }
3603}
3604
3605/**********************************************************************/
3613static enum fc_tristate
3615 const struct req_context *context,
3616 const struct req_context *other_context,
3617 const struct requirement *req)
3618{
3620
3621 switch (req->range) {
3622 case REQ_RANGE_PLAYER:
3623 if (context->player == NULL) {
3624 return TRI_MAYBE;
3625 } else {
3626 /* "None" does not count */
3627 return BOOL_TO_TRISTATE(
3628 city_list_size(context->player->cities)
3629 >= req->source.value.min_cities
3630 );
3631 }
3632 default:
3633 return TRI_MAYBE;
3634 }
3635}
3636
3637/**********************************************************************/
3645static enum fc_tristate
3647 const struct req_context *context,
3648 const struct req_context *other_context,
3649 const struct requirement *req)
3650{
3652
3653 if (context->player == NULL) {
3654 return TRI_MAYBE;
3655 } else {
3656 return BOOL_TO_TRISTATE(is_ai(context->player)
3657 && context->player->ai_common.skill_level
3658 == req->source.value.ai_level);
3659 }
3660}
3661
3662/**********************************************************************/
3670static enum fc_tristate
3672 const struct req_context *context,
3673 const struct req_context *other_context,
3674 const struct requirement *req)
3675{
3676 const struct nation_type *nation;
3677
3679
3680 nation = req->source.value.nation;
3681
3682 switch (req->range) {
3683 case REQ_RANGE_PLAYER:
3684 if (context->player == NULL) {
3685 return TRI_MAYBE;
3686 }
3687 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
3688 case REQ_RANGE_TEAM:
3689 case REQ_RANGE_ALLIANCE:
3690 if (context->player == NULL) {
3691 return TRI_MAYBE;
3692 }
3693 players_iterate_alive(plr2) {
3694 if (players_in_same_range(context->player, plr2, req->range)) {
3695 if (nation_of_player(plr2) == nation) {
3696 return TRI_YES;
3697 }
3698 }
3700 return TRI_NO;
3701 case REQ_RANGE_WORLD:
3702 /* NB: if a player is ever removed outright from the game
3703 * (e.g. via /remove), rather than just dying, this 'survives'
3704 * requirement will stop being true for their nation.
3705 * create_command_newcomer() can also cause this to happen. */
3706 return BOOL_TO_TRISTATE(NULL != nation->player
3707 && (req->survives || nation->player->is_alive));
3708 case REQ_RANGE_LOCAL:
3709 case REQ_RANGE_TILE:
3711 case REQ_RANGE_ADJACENT:
3712 case REQ_RANGE_CITY:
3715 case REQ_RANGE_COUNT:
3716 break;
3717 }
3718
3719 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3720
3721 return TRI_MAYBE;
3722}
3723
3724/**********************************************************************/
3732static enum fc_tristate
3734 const struct req_context *context,
3735 const struct req_context *other_context,
3736 const struct requirement *req)
3737{
3738 const struct nation_group *ngroup;
3739
3741
3743
3744 switch (req->range) {
3745 case REQ_RANGE_PLAYER:
3746 if (context->player == NULL) {
3747 return TRI_MAYBE;
3748 }
3750 nation_of_player(context->player), ngroup));
3751 case REQ_RANGE_TEAM:
3752 case REQ_RANGE_ALLIANCE:
3753 case REQ_RANGE_WORLD:
3754 if (context->player == NULL) {
3755 return TRI_MAYBE;
3756 }
3757 players_iterate_alive(plr2) {
3758 if (players_in_same_range(context->player, plr2, req->range)) {
3760 return TRI_YES;
3761 }
3762 }
3764 return TRI_NO;
3765 case REQ_RANGE_LOCAL:
3766 case REQ_RANGE_TILE:
3768 case REQ_RANGE_ADJACENT:
3769 case REQ_RANGE_CITY:
3772 case REQ_RANGE_COUNT:
3773 break;
3774 }
3775
3776 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3777
3778 return TRI_MAYBE;
3779}
3780
3781/**********************************************************************/
3789static enum fc_tristate
3791 const struct req_context *context,
3792 const struct req_context *other_context,
3793 const struct requirement *req)
3794{
3795 const struct nation_type *nationality;
3796 enum fc_tristate ret;
3797
3799
3800 nationality = req->source.value.nationality;
3801
3802 switch (req->range) {
3803 case REQ_RANGE_CITY:
3804 if (context->city == NULL) {
3805 return TRI_MAYBE;
3806 }
3807 citizens_iterate(context->city, slot, count) {
3808 if (player_slot_get_player(slot)->nation == nationality) {
3809 return TRI_YES;
3810 }
3812
3813 return TRI_NO;
3815 if (context->city == NULL) {
3816 return TRI_MAYBE;
3817 }
3818 citizens_iterate(context->city, slot, count) {
3819 if (player_slot_get_player(slot)->nation == nationality) {
3820 return TRI_YES;
3821 }
3823
3824 ret = TRI_NO;
3826 if (trade_partner == NULL) {
3827 ret = TRI_MAYBE;
3828 } else {
3829 citizens_iterate(trade_partner, slot, count) {
3830 if (player_slot_get_player(slot)->nation == nationality) {
3831 return TRI_YES;
3832 }
3834 }
3836
3837 return ret;
3838 case REQ_RANGE_PLAYER:
3839 case REQ_RANGE_TEAM:
3840 case REQ_RANGE_ALLIANCE:
3841 case REQ_RANGE_WORLD:
3842 case REQ_RANGE_LOCAL:
3843 case REQ_RANGE_TILE:
3845 case REQ_RANGE_ADJACENT:
3847 case REQ_RANGE_COUNT:
3848 break;
3849 }
3850
3851 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3852
3853 return TRI_MAYBE;
3854}
3855
3856/**********************************************************************/
3864static enum fc_tristate
3866 const struct req_context *context,
3867 const struct req_context *other_context,
3868 const struct requirement *req)
3869{
3870 const struct nation_type *nation;
3871
3873
3874 nation = req->source.value.origowner;
3875
3876 switch (req->range) {
3877 case REQ_RANGE_CITY:
3878 if (context->city == NULL || context->city->original == NULL) {
3879 return TRI_MAYBE;
3880 }
3881 if (player_nation(context->city->original) == nation) {
3882 return TRI_YES;
3883 }
3884
3885 return TRI_NO;
3887 case REQ_RANGE_PLAYER:
3888 case REQ_RANGE_TEAM:
3889 case REQ_RANGE_ALLIANCE:
3890 case REQ_RANGE_WORLD:
3891 case REQ_RANGE_LOCAL:
3892 case REQ_RANGE_TILE:
3894 case REQ_RANGE_ADJACENT:
3896 case REQ_RANGE_COUNT:
3897 break;
3898 }
3899
3900 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3901
3902 return TRI_MAYBE;
3903}
3904
3905/**********************************************************************/
3909 const struct player *other_player,
3910 enum req_range range,
3911 int diplrel)
3912{
3913 switch (range) {
3914 case REQ_RANGE_PLAYER:
3915 if (target_player == NULL) {
3916 return TRI_MAYBE;
3917 }
3919 case REQ_RANGE_TEAM:
3920 case REQ_RANGE_ALLIANCE:
3921 case REQ_RANGE_WORLD:
3922 if (target_player == NULL) {
3923 return TRI_MAYBE;
3924 }
3925 players_iterate_alive(plr2) {
3927 if (is_diplrel_to_other(plr2, diplrel)) {
3928 return TRI_YES;
3929 }
3930 }
3932 return TRI_NO;
3933 case REQ_RANGE_LOCAL:
3934 if (target_player == NULL || other_player == NULL) {
3935 return TRI_MAYBE;
3936 }
3937 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
3938 case REQ_RANGE_TILE:
3940 case REQ_RANGE_ADJACENT:
3941 case REQ_RANGE_CITY:
3944 case REQ_RANGE_COUNT:
3945 break;
3946 }
3947
3948 fc_assert_msg(FALSE, "Invalid range %d.", range);
3949
3950 return TRI_MAYBE;
3951}
3952
3953/**********************************************************************/
3961static enum fc_tristate
3963 const struct req_context *context,
3964 const struct req_context *other_context,
3965 const struct requirement *req)
3966{
3968
3969 return is_diplrel_in_range(context->player, other_context->player,
3970 req->range, req->source.value.diplrel);
3971}
3972
3973/**********************************************************************/
3981static enum fc_tristate
3983 const struct req_context *context,
3984 const struct req_context *other_context,
3985 const struct requirement *req)
3986{
3988
3989 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
3990 : NULL,
3991 context->player,
3992 req->range,
3993 req->source.value.diplrel);
3994}
3995
3996/**********************************************************************/
4005static enum fc_tristate
4007 const struct req_context *context,
4008 const struct req_context *other_context,
4009 const struct requirement *req)
4010{
4012
4013 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4014 : NULL,
4015 other_context->player,
4016 req->range,
4017 req->source.value.diplrel);
4018}
4019
4020/**********************************************************************/
4023static enum fc_tristate
4025 const struct player *other_player,
4026 enum req_range range,
4027 int diplrel)
4028{
4029 enum fc_tristate out = TRI_NO;
4030
4031 if (target_tile == NULL) {
4032 return TRI_MAYBE;
4033 }
4034
4037 unit_owner(target_unit), other_player, range, diplrel);
4038
4041
4042 return out;
4043}
4044
4045/**********************************************************************/
4054static enum fc_tristate
4056 const struct req_context *context,
4057 const struct req_context *other_context,
4058 const struct requirement *req)
4059{
4061
4062 return is_diplrel_unitany_in_range(context->tile, context->player,
4063 req->range,
4064 req->source.value.diplrel);
4065}
4066
4067/**********************************************************************/
4076static enum fc_tristate
4078 const struct req_context *context,
4079 const struct req_context *other_context,
4080 const struct requirement *req)
4081{
4083
4085 req->range,
4086 req->source.value.diplrel);
4087}
4088
4089/**********************************************************************/
4097static enum fc_tristate
4099 const struct req_context *context,
4100 const struct req_context *other_context,
4101 const struct requirement *req)
4102{
4103 const struct unit_type *punittype;
4104
4106
4107 punittype = req->source.value.utype;
4108
4109 switch (req->range) {
4110 case REQ_RANGE_LOCAL:
4111 if (!context->unittype) {
4112 return TRI_MAYBE;
4113 }
4114 return BOOL_TO_TRISTATE(context->unittype == punittype);
4115 case REQ_RANGE_TILE:
4117 case REQ_RANGE_ADJACENT:
4118 if (context->tile == nullptr) {
4119 return TRI_MAYBE;
4120 }
4121
4122 unit_list_iterate(context->tile->units, punit) {
4123 if (punit->utype == punittype) {
4124 return TRI_YES;
4125 }
4127
4128 if (req->range == REQ_RANGE_TILE) {
4129 return TRI_NO;
4130 }
4131
4132 if (req->range == REQ_RANGE_CADJACENT) {
4135 if (punit->utype == punittype) {
4136 return TRI_YES;
4137 }
4140 } else {
4142
4145 if (punit->utype == punittype) {
4146 return TRI_YES;
4147 }
4150 }
4151
4152 return TRI_NO;
4153
4154 case REQ_RANGE_CITY:
4157 case REQ_RANGE_PLAYER:
4158 case REQ_RANGE_TEAM:
4159 case REQ_RANGE_ALLIANCE:
4160 case REQ_RANGE_WORLD:
4161 case REQ_RANGE_COUNT:
4163 break;
4164 }
4165
4166 return TRI_NO;
4167}
4168
4169/**********************************************************************/
4177static enum fc_tristate
4179 const struct req_context *context,
4180 const struct req_context *other_context,
4181 const struct requirement *req)
4182{
4183 enum unit_type_flag_id unitflag;
4184
4186
4187 unitflag = req->source.value.unitflag;
4188
4189 switch (req->range) {
4190 case REQ_RANGE_LOCAL:
4191 if (!context->unittype) {
4192 return TRI_MAYBE;
4193 }
4194 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4195 case REQ_RANGE_TILE:
4197 case REQ_RANGE_ADJACENT:
4198 if (context->tile == nullptr) {
4199 return TRI_MAYBE;
4200 }
4201
4202 unit_list_iterate(context->tile->units, punit) {
4203 if (unit_has_type_flag(punit, unitflag)) {
4204 return TRI_YES;
4205 }
4207
4208 if (req->range == REQ_RANGE_TILE) {
4209 return TRI_NO;
4210 }
4211
4212 if (req->range == REQ_RANGE_CADJACENT) {
4215 if (unit_has_type_flag(punit, unitflag)) {
4216 return TRI_YES;
4217 }
4220 } else {
4222
4225 if (unit_has_type_flag(punit, unitflag)) {
4226 return TRI_YES;
4227 }
4230 }
4231
4232 return TRI_NO;
4233
4234 case REQ_RANGE_CITY:
4237 case REQ_RANGE_PLAYER:
4238 case REQ_RANGE_TEAM:
4239 case REQ_RANGE_ALLIANCE:
4240 case REQ_RANGE_WORLD:
4241 case REQ_RANGE_COUNT:
4243 break;
4244 }
4245
4246 return TRI_NO;
4247}
4248
4249/**********************************************************************/
4257static enum fc_tristate
4259 const struct req_context *context,
4260 const struct req_context *other_context,
4261 const struct requirement *req)
4262{
4263 const struct unit_class *pclass;
4264
4266
4267 pclass = req->source.value.uclass;
4268
4269 switch (req->range) {
4270 case REQ_RANGE_LOCAL:
4271 if (!context->unittype) {
4272 return TRI_MAYBE;
4273 }
4274 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4275 case REQ_RANGE_TILE:
4277 case REQ_RANGE_ADJACENT:
4278 if (context->tile == nullptr) {
4279 return TRI_MAYBE;
4280 }
4281
4282 unit_list_iterate(context->tile->units, punit) {
4283 if (unit_class_get(punit) == pclass) {
4284 return TRI_YES;
4285 }
4287
4288 if (req->range == REQ_RANGE_TILE) {
4289 return TRI_NO;
4290 }
4291
4292 if (req->range == REQ_RANGE_CADJACENT) {
4295 if (unit_class_get(punit) == pclass) {
4296 return TRI_YES;
4297 }
4300 } else {
4302
4305 if (unit_class_get(punit) == pclass) {
4306 return TRI_YES;
4307 }
4310 }
4311
4312 return TRI_NO;
4313
4314 case REQ_RANGE_CITY:
4317 case REQ_RANGE_PLAYER:
4318 case REQ_RANGE_TEAM:
4319 case REQ_RANGE_ALLIANCE:
4320 case REQ_RANGE_WORLD:
4321 case REQ_RANGE_COUNT:
4323 break;
4324 }
4325
4326 return TRI_NO;
4327}
4328
4329/**********************************************************************/
4337static enum fc_tristate
4339 const struct req_context *context,
4340 const struct req_context *other_context,
4341 const struct requirement *req)
4342{
4344
4346
4348
4349 switch (req->range) {
4350 case REQ_RANGE_LOCAL:
4351 if (!context->unittype) {
4352 return TRI_MAYBE;
4353 }
4355 case REQ_RANGE_TILE:
4357 case REQ_RANGE_ADJACENT:
4358 if (context->tile == nullptr) {
4359 return TRI_MAYBE;
4360 }
4361
4362 unit_list_iterate(context->tile->units, punit) {
4364 return TRI_YES;
4365 }
4367
4368 if (req->range == REQ_RANGE_TILE) {
4369 return TRI_NO;
4370 }
4371
4372 if (req->range == REQ_RANGE_CADJACENT) {
4376 return TRI_YES;
4377 }
4380 } else {
4382
4386 return TRI_YES;
4387 }
4390 }
4391
4392 return TRI_NO;
4393
4394 case REQ_RANGE_CITY:
4397 case REQ_RANGE_PLAYER:
4398 case REQ_RANGE_TEAM:
4399 case REQ_RANGE_ALLIANCE:
4400 case REQ_RANGE_WORLD:
4401 case REQ_RANGE_COUNT:
4403 break;
4404 }
4405
4406 return TRI_NO;
4407}
4408
4409/**********************************************************************/
4417static enum fc_tristate
4419 const struct req_context *context,
4420 const struct req_context *other_context,
4421 const struct requirement *req)
4422{
4423 enum ustate_prop uprop;
4424
4426
4428
4430 "Unsupported range \"%s\"",
4431 req_range_name(req->range));
4432
4433 /* Could be asked with incomplete data.
4434 * is_req_active() will handle it based on prob_type. */
4435 if (context->unit == NULL) {
4436 return TRI_MAYBE;
4437 }
4438
4439 switch (uprop) {
4440 case USP_TRANSPORTED:
4441 return BOOL_TO_TRISTATE(context->unit->transporter != NULL);
4442 case USP_LIVABLE_TILE:
4443 return BOOL_TO_TRISTATE(
4445 unit_tile(context->unit)));
4446 break;
4447 case USP_TRANSPORTING:
4449 case USP_HAS_HOME_CITY:
4450 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
4451 case USP_NATIVE_TILE:
4452 return BOOL_TO_TRISTATE(
4454 unit_tile(context->unit)));
4455 break;
4456 case USP_NATIVE_EXTRA:
4457 return BOOL_TO_TRISTATE(
4459 unit_type_get(context->unit)));
4460 break;
4462 return BOOL_TO_TRISTATE(context->unit->moved);
4463 case USP_COUNT:
4464 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
4465 /* Invalid property is unknowable. */
4466 return TRI_NO;
4467 }
4468
4469 /* Should never be reached */
4470 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
4471
4472 return TRI_NO;
4473}
4474
4475/**********************************************************************/
4483static enum fc_tristate
4485 const struct req_context *context,
4486 const struct req_context *other_context,
4487 const struct requirement *req)
4488{
4489 enum unit_activity activity;
4490
4492
4493 activity = req->source.value.activity;
4494
4496 "Unsupported range \"%s\"",
4497 req_range_name(req->range));
4498
4499 if (context->unit == NULL) {
4500 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
4501 * it's the zero value that context has by default - so many callers
4502 * who meant not to set specific activity actually have ACTIVITY_IDLE
4503 * instead of ACTIVITY_LAST */
4504 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
4505 return BOOL_TO_TRISTATE(activity == context->activity);
4506 }
4507
4508 /* Could be asked with incomplete data.
4509 * is_req_active() will handle it based on prob_type. */
4510 return TRI_MAYBE;
4511 }
4512
4513 switch (context->unit->activity) {
4514 case ACTIVITY_IDLE:
4515 case ACTIVITY_SENTRY:
4516 case ACTIVITY_GOTO:
4517 case ACTIVITY_EXPLORE:
4518 /* Seen as idle. */
4519 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
4520 default:
4521 /* Handled below. */
4522 break;
4523 }
4524
4525 return BOOL_TO_TRISTATE(context->unit->activity == activity);
4526}
4527
4528/**********************************************************************/
4536static enum fc_tristate
4538 const struct req_context *context,
4539 const struct req_context *other_context,
4540 const struct requirement *req)
4541{
4543
4544 if (context->unit == NULL) {
4545 return TRI_MAYBE;
4546 } else {
4547 return BOOL_TO_TRISTATE(context->unit->veteran
4548 >= req->source.value.minveteran);
4549 }
4550}
4551
4552/**********************************************************************/
4560static enum fc_tristate
4562 const struct req_context *context,
4563 const struct req_context *other_context,
4564 const struct requirement *req)
4565{
4567
4568 if (context->unit == NULL) {
4569 return TRI_MAYBE;
4570 } else {
4572 <= context->unit->moves_left);
4573 }
4574}
4575
4576/**********************************************************************/
4584static enum fc_tristate
4586 const struct req_context *context,
4587 const struct req_context *other_context,
4588 const struct requirement *req)
4589{
4591
4592 if (context->unit == NULL) {
4593 return TRI_MAYBE;
4594 } else {
4596 <= context->unit->hp);
4597 }
4598}
4599
4600/**********************************************************************/
4608static enum fc_tristate
4610 const struct req_context *context,
4611 const struct req_context *other_context,
4612 const struct requirement *req)
4613{
4615
4616 switch (req->range) {
4617 case REQ_RANGE_LOCAL:
4618 if (context->unit == NULL || !is_server()) {
4619 return TRI_MAYBE;
4620 } else {
4621 return BOOL_TO_TRISTATE(
4622 req->source.value.age <=
4623 game.info.turn - context->unit->birth_turn);
4624 }
4625 break;
4626 case REQ_RANGE_CITY:
4627 if (context->city == NULL) {
4628 return TRI_MAYBE;
4629 } else {
4630 return BOOL_TO_TRISTATE(
4631 req->source.value.age <=
4632 game.info.turn - context->city->turn_founded);
4633 }
4634 break;
4635 case REQ_RANGE_PLAYER:
4636 if (context->player == NULL) {
4637 return TRI_MAYBE;
4638 } else {
4639 return BOOL_TO_TRISTATE(req->source.value.age
4640 <= player_age(context->player));
4641 }
4642 break;
4643 default:
4644 return TRI_MAYBE;
4645 break;
4646 }
4647}
4648
4649/**********************************************************************/
4657static enum fc_tristate
4659 const struct req_context *context,
4660 const struct req_context *other_context,
4661 const struct requirement *req)
4662{
4664
4665 switch (req->range) {
4666 case REQ_RANGE_LOCAL:
4667 if (context->unit == NULL || !is_server()) {
4668 return TRI_MAYBE;
4669 } else {
4670 return BOOL_TO_TRISTATE(
4671 req->source.value.form_age <=
4672 game.info.turn - context->unit->current_form_turn);
4673 }
4674 break;
4675 default:
4676 return TRI_MAYBE;
4677 break;
4678 }
4679}
4680
4681/**********************************************************************/
4684static bool is_city_in_tile(const struct tile *ptile,
4685 const struct city *pcity)
4686{
4687 if (pcity == NULL) {
4688 return tile_city(ptile) != NULL;
4689 } else {
4690 return is_city_center(pcity, ptile);
4691 }
4692}
4693
4694/**********************************************************************/
4702static enum fc_tristate
4704 const struct req_context *context,
4705 const struct req_context *other_context,
4706 const struct requirement *req)
4707{
4708 enum citytile_type citytile;
4709
4711
4712 citytile = req->source.value.citytile;
4713
4715 if (context->tile == NULL) {
4716 return TRI_MAYBE;
4717 }
4718
4719 switch (citytile) {
4720 case CITYT_CENTER:
4721 switch (req->range) {
4722 case REQ_RANGE_TILE:
4724 context->city));
4726 if (is_city_in_tile(context->tile, context->city)) {
4727 return TRI_YES;
4728 }
4730 if (is_city_in_tile(adjc_tile, context->city)) {
4731 return TRI_YES;
4732 }
4734
4735 return TRI_NO;
4736 case REQ_RANGE_ADJACENT:
4737 if (is_city_in_tile(context->tile, context->city)) {
4738 return TRI_YES;
4739 }
4741 if (is_city_in_tile(adjc_tile, context->city)) {
4742 return TRI_YES;
4743 }
4745
4746 return TRI_NO;
4747 case REQ_RANGE_CITY:
4750 case REQ_RANGE_PLAYER:
4751 case REQ_RANGE_TEAM:
4752 case REQ_RANGE_ALLIANCE:
4753 case REQ_RANGE_WORLD:
4754 case REQ_RANGE_LOCAL:
4755 case REQ_RANGE_COUNT:
4756 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4757 break;
4758 }
4759
4760 return TRI_MAYBE;
4761 case CITYT_CLAIMED:
4762 switch (req->range) {
4763 case REQ_RANGE_TILE:
4764 return BOOL_TO_TRISTATE(context->tile->owner != NULL);
4766 if (context->tile->owner != NULL) {
4767 return TRI_YES;
4768 }
4770 if (adjc_tile->owner != NULL) {
4771 return TRI_YES;
4772 }
4774
4775 return TRI_NO;
4776 case REQ_RANGE_ADJACENT:
4777 if (context->tile->owner != NULL) {
4778 return TRI_YES;
4779 }
4781 if (adjc_tile->owner != NULL) {
4782 return TRI_YES;
4783 }
4785
4786 return TRI_NO;
4787 case REQ_RANGE_CITY:
4790 case REQ_RANGE_PLAYER:
4791 case REQ_RANGE_TEAM:
4792 case REQ_RANGE_ALLIANCE:
4793 case REQ_RANGE_WORLD:
4794 case REQ_RANGE_LOCAL:
4795 case REQ_RANGE_COUNT:
4796 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4797 break;
4798 }
4799
4800 return TRI_MAYBE;
4801 case CITYT_EXTRAS_OWNED:
4802 switch (req->range) {
4803 case REQ_RANGE_TILE:
4804 return BOOL_TO_TRISTATE(context->tile->extras_owner != NULL);
4806 if (context->tile->extras_owner != NULL) {
4807 return TRI_YES;
4808 }
4810 if (adjc_tile->extras_owner != NULL) {
4811 return TRI_YES;
4812 }
4814
4815 return TRI_NO;
4816 case REQ_RANGE_ADJACENT:
4817 if (context->tile->extras_owner != NULL) {
4818 return TRI_YES;
4819 }
4821 if (adjc_tile->extras_owner != NULL) {
4822 return TRI_YES;
4823 }
4825
4826 return TRI_NO;
4827 case REQ_RANGE_CITY:
4830 case REQ_RANGE_PLAYER:
4831 case REQ_RANGE_TEAM:
4832 case REQ_RANGE_ALLIANCE:
4833 case REQ_RANGE_WORLD:
4834 case REQ_RANGE_LOCAL:
4835 case REQ_RANGE_COUNT:
4836 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4837 break;
4838 }
4839
4840 return TRI_MAYBE;
4841 case CITYT_WORKED:
4842 switch (req->range) {
4843 case REQ_RANGE_TILE:
4844 return BOOL_TO_TRISTATE(context->tile->worked != NULL);
4846 if (context->tile->worked != NULL) {
4847 return TRI_YES;
4848 }
4850 if (adjc_tile->worked != NULL) {
4851 return TRI_YES;
4852 }
4854
4855 return TRI_NO;
4856 case REQ_RANGE_ADJACENT:
4857 if (context->tile->worked != NULL) {
4858 return TRI_YES;
4859 }
4861 if (adjc_tile->worked != NULL) {
4862 return TRI_YES;
4863 }
4865
4866 return TRI_NO;
4867 case REQ_RANGE_CITY:
4870 case REQ_RANGE_PLAYER:
4871 case REQ_RANGE_TEAM:
4872 case REQ_RANGE_ALLIANCE:
4873 case REQ_RANGE_WORLD:
4874 case REQ_RANGE_LOCAL:
4875 case REQ_RANGE_COUNT:
4876 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4877 break;
4878 }
4879
4880 return TRI_MAYBE;
4882 {
4884 const struct tile *target_tile = context->tile, *cc_tile;
4885
4886 if (!context->city) {
4887 return TRI_MAYBE;
4888 }
4889 cc_tile = city_tile(context->city);
4890 if (!cc_tile) {
4891 /* Unplaced virtual city */
4892 return TRI_MAYBE;
4893 }
4895 /* Note: No special treatment of 0 == cc here*/
4896 switch (req->range) {
4897 case REQ_RANGE_TILE:
4900 if (tile_continent(target_tile) == cc) {
4901 return TRI_YES;
4902 }
4904 if (tile_continent(adjc_tile) == cc) {
4905 return TRI_YES;
4906 }
4908
4909 return TRI_NO;
4910 case REQ_RANGE_ADJACENT:
4911 if (tile_continent(target_tile) == cc) {
4912 return TRI_YES;
4913 }
4915 if (tile_continent(adjc_tile) == cc) {
4916 return TRI_YES;
4917 }
4919
4920 return TRI_NO;
4921 case REQ_RANGE_CITY:
4924 case REQ_RANGE_PLAYER:
4925 case REQ_RANGE_TEAM:
4926 case REQ_RANGE_ALLIANCE:
4927 case REQ_RANGE_WORLD:
4928 case REQ_RANGE_LOCAL:
4929 case REQ_RANGE_COUNT:
4930 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4931 break;
4932 }
4933 }
4934
4935 return TRI_MAYBE;
4937 {
4938 int n = 0;
4940 bool ukt = FALSE;
4941 const struct tile *target_tile = context->tile, *cc_tile;
4942
4943 if (!context->city) {
4944 return TRI_MAYBE;
4945 }
4946 cc_tile = city_tile(context->city);
4947 if (!cc_tile) {
4948 /* Unplaced virtual city */
4949 return TRI_MAYBE;
4950 }
4952 if (!cc) {
4953 /* Don't know the city center terrain class.
4954 * Maybe, the city floats? Even if the rules prohibit it... */
4955 return TRI_MAYBE;
4956 }
4959
4960 if (0 != tc) {
4961 bool seen = FALSE;
4962 int i = n;
4963
4964 if (tc == cc) {
4965 continue;
4966 }
4967 while (--i >= 0) {
4968 if (adjc_cont[i] == tc) {
4969 seen = TRUE;
4970 break;
4971 }
4972 }
4973 if (seen) {
4974 continue;
4975 }
4977 } else {
4978 /* Likely, it's a black tile in client and we don't know
4979 * We possibly can calculate, but keep it simple. */
4980 ukt = TRUE;
4981 }
4983 if (0 == n) {
4984 return ukt ? TRI_MAYBE : TRI_NO;
4985 }
4986
4987 switch (req->range) {
4988 case REQ_RANGE_TILE:
4989 {
4991
4992 if (cc == tc) {
4993 return TRI_NO;
4994 }
4995 if (0 == tc || ukt) {
4996 return TRI_MAYBE;
4997 }
4998 for (int i = 0; i < n; i++) {
4999 if (tc == adjc_cont[i]) {
5000 return TRI_YES;
5001 }
5002 }
5003 }
5004
5005 return TRI_NO;
5006 case REQ_RANGE_ADJACENT:
5007 if (ukt) {
5008 /* If ALL the tiles in range are on cc, we can say it's false */
5010 if (tile_continent(adjc_tile) != cc) {
5011 return TRI_MAYBE;
5012 }
5014
5015 return TRI_NO;
5016 } else {
5019
5020 if (0 == tc) {
5021 return TRI_MAYBE;
5022 }
5023 for (int i = 0; i < n; i++) {
5024 if (tc == adjc_cont[i]) {
5025 return TRI_YES;
5026 }
5027 }
5029 }
5030
5031 return TRI_NO;
5033 if (ukt) {
5034 /* If ALL the tiles in range are on cc, we can say it's false */
5036 if (tile_continent(cadjc_tile) != cc) {
5037 return TRI_MAYBE;
5038 }
5040 } else {
5043
5044 if (0 == tc) {
5045 return TRI_MAYBE;
5046 }
5047 for (int i = 0; i < n; i++) {
5048 if (tc == adjc_cont[i]) {
5049 return TRI_YES;
5050 }
5051 }
5053 }
5054
5055 return TRI_NO;
5056 case REQ_RANGE_CITY:
5059 case REQ_RANGE_PLAYER:
5060 case REQ_RANGE_TEAM:
5061 case REQ_RANGE_ALLIANCE:
5062 case REQ_RANGE_WORLD:
5063 case REQ_RANGE_LOCAL:
5064 case REQ_RANGE_COUNT:
5065 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5066 break;
5067 }
5068 }
5069
5070 return TRI_MAYBE;
5071 case CITYT_LAST:
5072 /* Handled below */
5073 break;
5074 }
5075
5076 /* Not implemented */
5077 log_error("is_req_active(): citytile %d not supported.",
5078 citytile);
5079 return TRI_MAYBE;
5080}
5081
5082/**********************************************************************/
5090static enum fc_tristate
5092 const struct req_context *context,
5093 const struct req_context *other_context,
5094 const struct requirement *req)
5095{
5096 enum citystatus_type citystatus;
5097
5099
5100 citystatus = req->source.value.citystatus;
5101
5102 if (context->city == NULL) {
5103 return TRI_MAYBE;
5104 }
5105
5106 switch (citystatus) {
5108 switch (req->range) {
5109 case REQ_RANGE_CITY:
5110 if (context->city->original == NULL) {
5111 return TRI_MAYBE;
5112 }
5113 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
5115 {
5116 enum fc_tristate ret;
5117
5118 if (city_owner(context->city) == context->city->original) {
5119 return TRI_YES;
5120 }
5121
5122 ret = TRI_NO;
5124 if (trade_partner == NULL || trade_partner->original == NULL) {
5125 ret = TRI_MAYBE;
5126 } else if (city_owner(trade_partner) == trade_partner->original) {
5127 return TRI_YES;
5128 }
5130
5131 return ret;
5132 }
5133 case REQ_RANGE_LOCAL:
5134 case REQ_RANGE_TILE:
5136 case REQ_RANGE_ADJACENT:
5138 case REQ_RANGE_PLAYER:
5139 case REQ_RANGE_TEAM:
5140 case REQ_RANGE_ALLIANCE:
5141 case REQ_RANGE_WORLD:
5142 case REQ_RANGE_COUNT:
5143 break;
5144 }
5145
5146 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
5147 req->range);
5148
5149 return TRI_MAYBE;
5150
5151 case CITYS_STARVED:
5152 switch (req->range) {
5153 case REQ_RANGE_CITY:
5154 return BOOL_TO_TRISTATE(context->city->had_famine);
5156 {
5157 enum fc_tristate ret;
5158
5159 if (context->city->had_famine) {
5160 return TRI_YES;
5161 }
5162
5163 ret = TRI_NO;
5165 if (trade_partner == NULL) {
5166 ret = TRI_MAYBE;
5167 } else if (trade_partner->had_famine) {
5168 return TRI_YES;
5169 }
5171
5172 return ret;
5173 }
5174 case REQ_RANGE_LOCAL:
5175 case REQ_RANGE_TILE:
5177 case REQ_RANGE_ADJACENT:
5179 case REQ_RANGE_PLAYER:
5180 case REQ_RANGE_TEAM:
5181 case REQ_RANGE_ALLIANCE:
5182 case REQ_RANGE_WORLD:
5183 case REQ_RANGE_COUNT:
5184 break;
5185 }
5186
5187 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
5188 req->range);
5189
5190 return TRI_MAYBE;
5191
5192 case CITYS_DISORDER:
5193 switch (req->range) {
5194 case REQ_RANGE_CITY:
5195 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
5197 {
5198 enum fc_tristate ret;
5199
5200 if (context->city->anarchy > 0) {
5201 return TRI_YES;
5202 }
5203
5204 ret = TRI_NO;
5206 if (trade_partner == NULL) {
5207 ret = TRI_MAYBE;
5208 } else if (trade_partner->anarchy > 0) {
5209 return TRI_YES;
5210 }
5212
5213 return ret;
5214 }
5215 case REQ_RANGE_LOCAL:
5216 case REQ_RANGE_TILE:
5218 case REQ_RANGE_ADJACENT:
5220 case REQ_RANGE_PLAYER:
5221 case REQ_RANGE_TEAM:
5222 case REQ_RANGE_ALLIANCE:
5223 case REQ_RANGE_WORLD:
5224 case REQ_RANGE_COUNT:
5225 break;
5226 }
5227
5228 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
5229 req->range);
5230
5231 return TRI_MAYBE;
5232
5233 case CITYS_CELEBRATION:
5234 switch (req->range) {
5235 case REQ_RANGE_CITY:
5236 return BOOL_TO_TRISTATE(context->city->rapture > 0);
5238 {
5239 enum fc_tristate ret;
5240
5241 if (context->city->rapture > 0) {
5242 return TRI_YES;
5243 }
5244
5245 ret = TRI_NO;
5247 if (trade_partner == NULL) {
5248 ret = TRI_MAYBE;
5249 } else if (trade_partner->rapture > 0) {
5250 return TRI_YES;
5251 }
5253
5254 return ret;
5255 }
5256 case REQ_RANGE_LOCAL:
5257 case REQ_RANGE_TILE:
5259 case REQ_RANGE_ADJACENT:
5261 case REQ_RANGE_PLAYER:
5262 case REQ_RANGE_TEAM:
5263 case REQ_RANGE_ALLIANCE:
5264 case REQ_RANGE_WORLD:
5265 case REQ_RANGE_COUNT:
5266 break;
5267 }
5268
5269 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
5270 req->range);
5271
5272 return TRI_MAYBE;
5273
5274 case CITYS_TRANSFERRED:
5275 switch (req->range) {
5276 case REQ_RANGE_CITY:
5277 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
5279 {
5280 enum fc_tristate ret;
5281
5282 if (context->city->acquire_t != CACQ_FOUNDED) {
5283 return TRI_YES;
5284 }
5285
5286 ret = TRI_NO;
5288 if (trade_partner == NULL) {
5289 ret = TRI_MAYBE;
5290 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
5291 return TRI_YES;
5292 }
5294
5295 return ret;
5296 }
5297 case REQ_RANGE_LOCAL:
5298 case REQ_RANGE_TILE:
5300 case REQ_RANGE_ADJACENT:
5302 case REQ_RANGE_PLAYER:
5303 case REQ_RANGE_TEAM:
5304 case REQ_RANGE_ALLIANCE:
5305 case REQ_RANGE_WORLD:
5306 case REQ_RANGE_COUNT:
5307 break;
5308 }
5309
5310 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
5311 req->range);
5312
5313 return TRI_MAYBE;
5314
5315 case CITYS_LAST:
5316 break;
5317 }
5318
5319 /* Not implemented */
5320 log_error("is_req_active(): citystatus %d not supported.",
5321 citystatus);
5322
5323 return TRI_MAYBE;
5324}
5325
5326/**********************************************************************/
5334static enum fc_tristate
5336 const struct req_context *context,
5337 const struct req_context *other_context,
5338 const struct requirement *req)
5339{
5341
5342 if (context->city == NULL) {
5343 return TRI_MAYBE;
5344 } else {
5345 if (req->range == REQ_RANGE_TRADE_ROUTE) {
5346 enum fc_tristate ret;
5347
5348 if (city_size_get(context->city) >= req->source.value.minsize) {
5349 return TRI_YES;
5350 }
5351
5352 ret = TRI_NO;
5354 if (trade_partner == NULL) {
5355 ret = TRI_MAYBE;
5356 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
5357 return TRI_YES;
5358 }
5360
5361 return ret;
5362 } else {
5364 >= req->source.value.minsize);
5365 }
5366 }
5367}
5368
5369/**********************************************************************/
5377static enum fc_tristate
5379 const struct req_context *context,
5380 const struct req_context *other_context,
5381 const struct requirement *req)
5382{
5383 const struct counter *count;
5384
5386
5387 count = req->source.value.counter;
5388
5389 if (NULL == context->city) {
5390 return TRI_MAYBE;
5391 }
5392 return BOOL_TO_TRISTATE(count->checkpoint <=
5393 context->city->counter_values[
5394 counter_index(count)]);
5395}
5396
5397/**********************************************************************/
5405static enum fc_tristate
5407 const struct req_context *context,
5408 const struct req_context *other_context,
5409 const struct requirement *req)
5410{
5411 const struct achievement *achievement;
5412
5414
5416
5417 if (req->range == REQ_RANGE_WORLD) {
5419 } else if (context->player == NULL) {
5420 return TRI_MAYBE;
5421 } else if (req->range == REQ_RANGE_ALLIANCE
5422 || req->range == REQ_RANGE_TEAM) {
5423 players_iterate_alive(plr2) {
5424 if (players_in_same_range(context->player, plr2, req->range)
5426 return TRI_YES;
5427 }
5429 return TRI_NO;
5430 } else if (req->range == REQ_RANGE_PLAYER) {
5432 return TRI_YES;
5433 } else {
5434 return TRI_NO;
5435 }
5436 }
5437
5438 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
5439
5440 return TRI_MAYBE;
5441}
5442
5443/**********************************************************************/
5451static enum fc_tristate
5453 const struct req_context *context,
5454 const struct req_context *other_context,
5455 const struct requirement *req)
5456{
5457 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
5458
5461
5462 switch (req->source.kind) {
5463 case VUT_MINLATITUDE:
5464 min = req->source.value.latitude;
5465 break;
5466 case VUT_MAXLATITUDE:
5467 max = req->source.value.latitude;
5468 break;
5469 default:
5471 || req->source.kind == VUT_MAXLATITUDE);
5472 break;
5473 }
5474
5475 switch (req->range) {
5476 case REQ_RANGE_WORLD:
5478 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
5479
5480 case REQ_RANGE_TILE:
5481 if (context->tile == NULL) {
5482 return TRI_MAYBE;
5483 } else {
5485
5487 }
5488
5490 if (context->tile == NULL) {
5491 return TRI_MAYBE;
5492 }
5493
5496
5498 return TRI_YES;
5499 }
5501 return TRI_NO;
5502
5503 case REQ_RANGE_ADJACENT:
5504 if (!context->tile) {
5505 return TRI_MAYBE;
5506 }
5507
5510
5512 return TRI_YES;
5513 }
5515 return TRI_NO;
5516
5517 case REQ_RANGE_CITY:
5520 case REQ_RANGE_PLAYER:
5521 case REQ_RANGE_TEAM:
5522 case REQ_RANGE_ALLIANCE:
5523 case REQ_RANGE_LOCAL:
5524 case REQ_RANGE_COUNT:
5525 break;
5526 }
5527
5529 "Illegal range %d for latitude requirement.", req->range);
5530
5531 return TRI_MAYBE;
5532}
5533
5534/**********************************************************************/
5542static enum fc_tristate
5544 const struct req_context *context,
5545 const struct req_context *other_context,
5546 const struct requirement *req)
5547{
5549
5551}
5552
5553/**********************************************************************/
5561static enum fc_tristate
5563 const struct req_context *context,
5564 const struct req_context *other_context,
5565 const struct requirement *req)
5566{
5568
5570 >= req->source.value.mincalfrag);
5571}
5572
5573/**********************************************************************/
5581static enum fc_tristate
5583 const struct req_context *context,
5584 const struct req_context *other_context,
5585 const struct requirement *req)
5586{
5588
5589 return BOOL_TO_TRISTATE(
5591}
5592
5593/**********************************************************************/
5601static enum fc_tristate
5603 const struct req_context *context,
5604 const struct req_context *other_context,
5605 const struct requirement *req)
5606{
5608
5609 return BOOL_TO_TRISTATE(
5611}
5612
5613/**********************************************************************/
5621static enum fc_tristate
5623 const struct req_context *context,
5624 const struct req_context *other_context,
5625 const struct requirement *req)
5626{
5628
5630 req->source.value.ssetval));
5631}
5632
5633/* Not const for potential ruleset-related adjustment */
5636
5637 /* Alphabetical order of enum constant */
5696};
5697
5698/**********************************************************************/
5712 const struct req_context *other_context,
5713 const struct requirement *req,
5714 const enum req_problem_type prob_type)
5715{
5716 const struct civ_map *nmap = &(wld.map);
5718 req);
5719
5720 if (eval == TRI_MAYBE) {
5721 if (prob_type == RPT_POSSIBLE) {
5722 return TRUE;
5723 } else {
5724 return FALSE;
5725 }
5726 }
5727 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
5728}
5729
5730/**********************************************************************/
5739static
5741 const struct req_context *context,
5742 const struct req_context *other_context,
5743 const struct requirement *req)
5744{
5745 if (!context) {
5747 }
5748 if (!other_context) {
5750 }
5751
5752 if (req->source.kind >= VUT_COUNT) {
5753 log_error("tri_req_present(): invalid source kind %d.",
5754 req->source.kind);
5755 return TRI_NO;
5756 }
5757
5759
5760 return req_definitions[req->source.kind].cb(nmap, context,
5761 other_context, req);
5762}
5763
5764/**********************************************************************/
5774 const struct req_context *other_context,
5775 const struct requirement *req)
5776{
5777 const struct civ_map *nmap = &(wld.map);
5779
5780 if (!req->present) {
5781 if (TRI_NO == eval) {
5782 return TRI_YES;
5783 }
5784 if (TRI_YES == eval) {
5785 return TRI_NO;
5786 }
5787 }
5788
5789 return eval;
5790}
5791
5792/**********************************************************************/
5808 const struct req_context *other_context,
5809 const struct requirement_vector *reqs,
5810 const enum req_problem_type prob_type)
5811{
5814 return FALSE;
5815 }
5817
5818 return TRUE;
5819}
5820
5821/**********************************************************************/
5826 const enum req_range max_range,
5827 const struct req_context *context,
5828 const struct req_context *other_context,
5829 const struct requirement_vector *reqs,
5830 const enum req_problem_type prob_type)
5831{
5833 if (preq->range >= min_range && preq->range <= max_range) {
5835 return FALSE;
5836 }
5837 }
5839
5840 return TRUE;
5841}
5842
5843/**********************************************************************/
5849enum fc_tristate
5851 const struct req_context *context,
5852 const struct req_context *other_context,
5853 const struct requirement *req)
5854{
5855 /* FIXME: doubles code from calendar.c */
5859 int fragment1 = fragment; /* if fragments don't advance */
5860 int year_inc, year_inc1;
5863 bool present, present1;
5864
5865 fc_assert(pass >= 0 && period >= 0);
5866 if (slowdown >= 3) {
5867 if (ypt > 1) {
5868 ypt = 1;
5869 }
5870 } else if (slowdown >= 2) {
5871 if (ypt > 2) {
5872 ypt = 2;
5873 }
5874 } else if (slowdown >= 1) {
5875 if (ypt > 5) {
5876 ypt = 5;
5877 }
5878 }
5879 year_inc = ypt * pass;
5882 int fragment_years;
5883
5884 fragment += fpt * pass;
5892 }
5894 if (year_inc + game.info.year >= 0) {
5895 year_inc++;
5896 year_inc1++;
5897 } else if (year_inc1 + game.info.year >= 0) {
5898 year_inc1++;
5899 }
5900 }
5901
5902 switch (req->source.kind) {
5903 case VUT_AGE:
5904 switch (req->range) {
5905 case REQ_RANGE_LOCAL:
5906 if (context->unit == NULL || !is_server()) {
5907 return TRI_MAYBE;
5908 } else {
5909 int ua = game.info.turn + pass - context->unit->birth_turn;
5910
5911 present = req->source.value.age <= ua;
5912 present1 = req->source.value.age <= ua + period;
5913 }
5914 break;
5915 case REQ_RANGE_CITY:
5916 if (context->city == NULL) {
5917 return TRI_MAYBE;
5918 } else {
5919 int ca = game.info.turn + pass - context->city->turn_founded;
5920
5921 present = req->source.value.age <= ca;
5922 present1 = req->source.value.age <= ca + period;
5923 }
5924 break;
5925 case REQ_RANGE_PLAYER:
5926 if (context->player == NULL) {
5927 return TRI_MAYBE;
5928 } else {
5929 present = req->source.value.age
5930 <= player_age(context->player) + pass;
5931 present1 = req->source.value.age
5932 <= player_age(context->player) + pass + period;
5933 }
5934 break;
5935 default:
5936 return TRI_MAYBE;
5937 }
5938 break;
5939 case VUT_FORM_AGE:
5940 if (context->unit == NULL || !is_server()) {
5941 return TRI_MAYBE;
5942 } else {
5943 int ua = game.info.turn + pass - context->unit->current_form_turn;
5944
5945 present = req->source.value.form_age <= ua;
5946 present1 = req->source.value.form_age <= ua + period;
5947 }
5948 break;
5949 case VUT_MINYEAR:
5950 present = game.info.year + year_inc >= req->source.value.minyear;
5952 break;
5953 case VUT_MINCALFRAG:
5955 /* Hope that the requirement is valid and fragments advance fine */
5956 return TRI_YES;
5957 }
5958 present = fragment >= req->source.value.mincalfrag;
5960 break;
5961 default:
5962 /* No special handling invented */
5963 return tri_req_active(context, other_context, req);
5964 }
5965 return BOOL_TO_TRISTATE(req->present
5966 ? present || present1 : !(present && present1));
5967}
5968
5969/**********************************************************************/
5975 (const struct req_context *context,
5976 const struct req_context *other_context,
5977 const struct requirement *req,
5978 void *data, int n_data)
5979{
5980 int i;
5981
5982 fc_assert_ret_val(data || n_data == 0, TRI_NO);
5983
5984 for (i = 0; i < n_data; i++) {
5985 if (are_requirements_contradictions(&((struct requirement *) data)[i],
5986 req)) {
5987 return TRI_NO;
5988 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
5989 return TRI_YES;
5990 }
5991 }
5992
5993 return tri_req_active(context, other_context, req);
5994}
5995
5996/**********************************************************************/
6002enum fc_tristate
6004 const struct req_context *other_context,
6005 const struct requirement_vector *reqs,
6008 void *data, int n_data)
6009{
6010 bool active = TRUE;
6011 bool certain = TRUE;
6012
6016 data, n_data)) {
6017 case TRI_NO:
6018 active = FALSE;
6019 certain = TRUE;
6020 break;
6021 case TRI_YES:
6022 break;
6023 case TRI_MAYBE:
6024 certain = FALSE;
6025 if (maybe_reqs) {
6027 }
6028 break;
6029 default:
6031 active = FALSE;
6032 }
6033 if (!active) {
6034 break;
6035 }
6037
6038 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
6039}
6040
6041/**********************************************************************/
6051 const struct requirement *req)
6052{
6053 enum req_unchanging_status s;
6054 const struct civ_map *nmap = &(wld.map);
6055
6058 "Invalid source kind %d.", req->source.kind);
6060
6061 if (req->survives) {
6062 /* Special case for surviving requirements */
6063 /* Buildings may obsolete even here */
6064 if (VUT_IMPROVEMENT == req->source.kind) {
6065 const struct impr_type *b = req->source.value.building;
6066
6068 if (improvement_obsolete(context->player, b, context->city)) {
6069 /* FIXME: sometimes can unobsolete, but considering it
6070 * may sometimes put the function on endless recursion */
6071 return REQUCH_ACT; /* Mostly about techs */
6072 } else {
6073 /* NOTE: may obsoletion reqs be unchanging? Hardly but why not. */
6074 return REQUCH_NO;
6075 }
6076 }
6077 }
6078 s = unchanging_present(nmap, s, context, req);
6079 if (s != REQUCH_NO) {
6080 return unchanging_noally(nmap, s, context, req);
6081 }
6082 } else {
6085
6086 if (cond) {
6087 return cond(nmap, s, context, req);
6088 }
6089 }
6090
6091 return s;
6092}
6093
6094/**********************************************************************/
6099 const struct req_context *other_context,
6100 const struct requirement *req,
6102{
6104
6105 if (REQUCH_NO != u) {
6106 /* presence is precalculated */
6107 bool auto_present = (req->survives
6108 && !(VUT_IMPROVEMENT == req->source.kind
6112
6113 if (auto_present ? req->present
6115 /* Unchanging but does not block */
6116 return REQUCH_NO;
6117 }
6118 }
6119
6120 return u;
6121}
6122
6123/**********************************************************************/
6127bool is_req_in_vec(const struct requirement *req,
6128 const struct requirement_vector *vec)
6129{
6131 if (are_requirements_equal(req, preq)) {
6132 return TRUE;
6133 }
6135
6136 return FALSE;
6137}
6138
6139/**********************************************************************/
6146 enum universals_n kind)
6147{
6149 if (preq->present && preq->source.kind == kind) {
6150 return TRUE;
6151 }
6153 return FALSE;
6154}
6155
6156/**********************************************************************/
6165{
6166 switch (source->kind) {
6167 case VUT_ACTION:
6168 return !action_is_in_use(source->value.action);
6169 case VUT_UTFLAG:
6170 return !utype_flag_is_in_use(source->value.unitflag);
6171 case VUT_UCFLAG:
6172 return !uclass_flag_is_in_use(source->value.unitclassflag);
6173 case VUT_EXTRAFLAG:
6174 return !extra_flag_is_in_use(source->value.extraflag);
6175 case VUT_MINLATITUDE:
6176 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
6177 case VUT_MAXLATITUDE:
6178 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
6179 case VUT_COUNTER:
6180 case VUT_OTYPE:
6181 case VUT_SPECIALIST:
6182 case VUT_AI_LEVEL:
6183 case VUT_CITYTILE:
6184 case VUT_CITYSTATUS:
6185 case VUT_STYLE:
6186 case VUT_TOPO:
6187 case VUT_WRAP:
6188 case VUT_SERVERSETTING:
6189 case VUT_NATION:
6190 case VUT_NATIONGROUP:
6191 case VUT_ADVANCE:
6192 case VUT_TECHFLAG:
6193 case VUT_GOVERNMENT:
6194 case VUT_ACHIEVEMENT:
6195 case VUT_IMPROVEMENT:
6196 case VUT_IMPR_GENUS:
6197 case VUT_IMPR_FLAG:
6198 case VUT_PLAYER_FLAG:
6199 case VUT_PLAYER_STATE:
6200 case VUT_MINSIZE:
6201 case VUT_MINCULTURE:
6202 case VUT_MINFOREIGNPCT:
6203 case VUT_MINTECHS:
6204 case VUT_MINCITIES:
6205 case VUT_NATIONALITY:
6206 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
6207 case VUT_DIPLREL:
6208 case VUT_DIPLREL_TILE:
6209 case VUT_DIPLREL_TILE_O:
6212 case VUT_MAXTILEUNITS:
6213 case VUT_UTYPE:
6214 case VUT_UCLASS:
6215 case VUT_MINVETERAN:
6216 case VUT_UNITSTATE:
6217 case VUT_ACTIVITY:
6218 case VUT_MINMOVES:
6219 case VUT_MINHP:
6220 case VUT_AGE:
6221 case VUT_FORM_AGE:
6222 case VUT_ROADFLAG:
6223 case VUT_MINCALFRAG:
6224 case VUT_TERRAIN:
6225 case VUT_EXTRA:
6226 case VUT_GOOD:
6227 case VUT_TERRAINCLASS:
6228 case VUT_TERRFLAG:
6229 case VUT_TERRAINALTER:
6230 case VUT_MINYEAR:
6231 case VUT_NONE:
6232 case VUT_COUNT:
6233 /* Not implemented. */
6234 break;
6235 }
6236
6237 return FALSE;
6238}
6239
6240/**********************************************************************/
6248{
6249 /* Not known to be impossible to fulfill */
6250 return req->present && universal_never_there(&req->source);
6251}
6252
6253/**********************************************************************/
6261{
6264 return TRUE;
6265 }
6267
6268 /* Not known to be impossible to fulfill */
6269 return FALSE;
6270}
6271
6272/**********************************************************************/
6281 const struct requirement_vector *vec)
6282{
6283 if (vec) {
6284 return 0;
6285 } else {
6286 return -1;
6287 }
6288}
6289
6290/********************************************************************/
6298struct requirement_vector *
6300{
6301 fc_assert_ret_val(number == 0, NULL);
6302 return (struct requirement_vector *)parent_item;
6303}
6304
6305/**********************************************************************/
6315const char *req_vec_change_translation(const struct req_vec_change *change,
6317{
6318 const char *req_vec_description;
6319 static char buf[MAX_LEN_NAME * 3];
6320 struct astring astr;
6321
6322 fc_assert_ret_val(change, NULL);
6324 NULL);
6325
6326 /* Get rid of the previous. */
6327 buf[0] = '\0';
6328
6329 if (namer == NULL) {
6330 /* TRANS: default description of a requirement vector
6331 * (used in ruledit) */
6332 req_vec_description = _("the requirement vector");
6333 } else {
6335 }
6336
6337 switch (change->operation) {
6338 case RVCO_REMOVE:
6339 fc_snprintf(buf, sizeof(buf),
6340 /* TRANS: remove a requirement from a requirement vector
6341 * (in ruledit).
6342 * The first %s is the operation.
6343 * The second %s is the requirement.
6344 * The third %s is a description of the requirement vector,
6345 * like "actor_reqs" */
6346 _("%s %s from %s"),
6348 req_to_fstring(&change->req, &astr),
6350 astr_free(&astr);
6351 break;
6352 case RVCO_APPEND:
6353 fc_snprintf(buf, sizeof(buf),
6354 /* TRANS: append a requirement to a requirement vector
6355 * (in ruledit).
6356 * The first %s is the operation.
6357 * The second %s is the requirement.
6358 * The third %s is a description of the requirement vector,
6359 * like "actor_reqs" */
6360 _("%s %s to %s"),
6362 req_to_fstring(&change->req, &astr),
6364 astr_free(&astr);
6365 break;
6366 case RVCO_NOOP:
6367 fc_snprintf(buf, sizeof(buf),
6368 /* TRANS: do nothing to a requirement vector (in ruledit).
6369 * The first %s is a description of the requirement vector,
6370 * like "actor_reqs" */
6371 _("Do nothing to %s"), req_vec_description);
6372 break;
6373 }
6374
6375 return buf;
6376}
6377
6378/**********************************************************************/
6390 const void *parent_item)
6391{
6392 struct requirement_vector *target
6393 = getter(parent_item, modification->vector_number);
6394 int i = 0;
6395
6396 switch (modification->operation) {
6397 case RVCO_APPEND:
6399 return TRUE;
6400 case RVCO_REMOVE:
6404 return TRUE;
6405 }
6406 i++;
6408 return FALSE;
6409 case RVCO_NOOP:
6410 return FALSE;
6411 }
6412
6413 return FALSE;
6414}
6415
6416/**********************************************************************/
6425struct req_vec_problem *
6427 const char *description,
6428 const char *description_translated)
6429{
6430 struct req_vec_problem *out;
6431 int i;
6432
6433 out = fc_malloc(sizeof(*out));
6434
6435 fc_strlcpy(out->description, description, sizeof(out->description));
6436 fc_strlcpy(out->description_translated, _(description_translated),
6437 sizeof(out->description_translated));
6438
6439 out->num_suggested_solutions = num_suggested_solutions;
6440 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
6441 * sizeof(struct req_vec_change));
6442 for (i = 0; i < out->num_suggested_solutions; i++) {
6443 /* No suggestions are ready yet. */
6444 out->suggested_solutions[i].operation = RVCO_NOOP;
6445 out->suggested_solutions[i].vector_number = -1;
6446 out->suggested_solutions[i].req.source.kind = VUT_NONE;
6447 }
6448
6449 return out;
6450}
6451
6452/**********************************************************************/
6461 const char *descr, ...)
6462{
6463 char description[500];
6464 char description_translated[500];
6465 va_list ap;
6466
6467 va_start(ap, descr);
6468 fc_vsnprintf(description, sizeof(description), descr, ap);
6469 va_end(ap);
6470
6471 va_start(ap, descr);
6473 _(descr), ap);
6474 va_end(ap);
6475
6478}
6479
6480/**********************************************************************/
6486{
6487 FC_FREE(issue->suggested_solutions);
6488 issue->num_suggested_solutions = 0;
6489
6490 FC_FREE(issue);
6491}
6492
6493/**********************************************************************/
6504struct req_vec_problem *
6507 const void *parent_item)
6508{
6509 int i, j;
6511
6512 if (vec == NULL || requirement_vector_size(vec) == 0) {
6513 /* No vector. */
6514 return NULL;
6515 }
6516
6517 if (get_num == NULL || parent_item == NULL) {
6518 vec_num = 0;
6519 } else {
6520 vec_num = get_num(parent_item, vec);
6521 }
6522
6523 /* Look for contradictions */
6524 for (i = 0; i < requirement_vector_size(vec); i++) {
6525 struct requirement *preq = requirement_vector_get(vec, i);
6526 for (j = 0; j < requirement_vector_size(vec); j++) {
6527 struct requirement *nreq = requirement_vector_get(vec, j);
6528
6530 struct req_vec_problem *problem;
6531 struct astring astr;
6532 struct astring nastr;
6533
6535 N_("Requirements {%s} and {%s} contradict each other."),
6537
6538 astr_free(&astr);
6539 astr_free(&nastr);
6540
6541 /* The solution is to remove one of the contradictions. */
6542 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6543 problem->suggested_solutions[0].vector_number = vec_num;
6544 problem->suggested_solutions[0].req = *preq;
6545
6546 problem->suggested_solutions[1].operation = RVCO_REMOVE;
6547 problem->suggested_solutions[1].vector_number = vec_num;
6548 problem->suggested_solutions[1].req = *nreq;
6549
6550 /* Only the first contradiction is reported. */
6551 return problem;
6552 }
6553 }
6554 }
6555
6556 return NULL;
6557}
6558
6559/**********************************************************************/
6569struct req_vec_problem *
6572 const void *parent_item)
6573{
6574 /* Check for self contradictins. */
6576}
6577
6578/**********************************************************************/
6590struct req_vec_problem *
6593 const void *parent_item)
6594{
6595 int i;
6597 struct req_vec_problem *problem = NULL;
6598
6599 if (vec == NULL || requirement_vector_size(vec) == 0) {
6600 /* No vector. */
6601 return NULL;
6602 }
6603
6604 if (get_num == NULL || parent_item == NULL) {
6605 vec_num = 0;
6606 } else {
6607 vec_num = get_num(parent_item, vec);
6608 }
6609
6610 /* Look for contradictions */
6611 for (i = 0; i < requirement_vector_size(vec); i++) {
6612 struct requirement *preq = requirement_vector_get(vec, i);
6613
6614 if (universal_never_there(&preq->source)) {
6615 struct astring astr;
6616
6617 if (preq->present) {
6618 /* The requirement vector can never be fulfilled. Removing the
6619 * requirement makes it possible to fulfill it. This is a rule
6620 * change and shouldn't be "fixed" without thinking. Don't offer any
6621 * automatic solution to prevent mindless "fixes". */
6622 /* TRANS: ruledit warns a user about an unused requirement vector
6623 * that never can be fulfilled because it asks for something that
6624 * never will be there. */
6625 if (problem == NULL) {
6627 N_("Requirement {%s} requires %s but it will never be"
6628 " there."),
6630 astr_free(&astr);
6631 }
6632
6633 /* Continue to check if other problems have a solution proposal,
6634 * and prefer to return those. */
6635 continue;
6636 }
6637
6638 if (problem != NULL) {
6639 /* Free previous one (one with no solution proposals) */
6641 }
6642
6644 N_("Requirement {%s} mentions %s but it will never be there."),
6646
6647 astr_free(&astr);
6648
6649 /* The solution is to remove the reference to the missing
6650 * universal. */
6651 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6652 problem->suggested_solutions[0].vector_number = vec_num;
6653 problem->suggested_solutions[0].req = *preq;
6654
6655 /* Only the first missing universal is reported. */
6656 return problem;
6657 }
6658 }
6659
6660 return problem;
6661}
6662
6663/**********************************************************************/
6675struct req_vec_problem *
6678 const void *parent_item)
6679{
6680 int i, j;
6682
6683 if (vec == NULL || requirement_vector_size(vec) == 0) {
6684 /* No vector. */
6685 return NULL;
6686 }
6687
6688 if (get_num == NULL || parent_item == NULL) {
6689 vec_num = 0;
6690 } else {
6691 vec_num = get_num(parent_item, vec);
6692 }
6693
6694 /* Look for repeated requirements */
6695 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
6696 struct requirement *preq = requirement_vector_get(vec, i);
6697 for (j = i + 1; j < requirement_vector_size(vec); j++) {
6698 struct requirement *nreq = requirement_vector_get(vec, j);
6699
6701 struct req_vec_problem *problem;
6702 struct astring astr;
6703 struct astring nastr;
6704
6706 N_("Requirements {%s} and {%s} are the same."),
6708
6709 astr_free(&astr);
6710 astr_free(&nastr);
6711
6712 /* The solution is to remove one of the redundant requirements. */
6713 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6714 problem->suggested_solutions[0].vector_number = vec_num;
6715 problem->suggested_solutions[0].req = *preq;
6716
6717 problem->suggested_solutions[1].operation = RVCO_REMOVE;
6718 problem->suggested_solutions[1].vector_number = vec_num;
6719 problem->suggested_solutions[1].req = *nreq;
6720
6721 /* Only the first redundancy is reported. */
6722 return problem;
6723 }
6724 }
6725 }
6726
6727 return NULL;
6728}
6729
6730/**********************************************************************/
6741struct req_vec_problem *
6744 const void *parent_item)
6745{
6746 struct req_vec_problem *out;
6747
6749 if (out != NULL) {
6750 /* A bug, not just a potential improvement */
6751 return out;
6752 }
6753
6754 /* Check if a universal that never will appear in the game is checked. */
6756 if (out != NULL) {
6757 return out;
6758 }
6759
6760 /* Check if a requirement is redundant. */
6762 return out;
6763}
6764
6765/**********************************************************************/
6770 const struct universal *psource2)
6771{
6772 if (psource1->kind != psource2->kind) {
6773 return FALSE;
6774 }
6775 switch (psource1->kind) {
6776 case VUT_NONE:
6777 return TRUE;
6778 case VUT_COUNTER:
6779 return psource1->value.counter == psource2->value.counter;
6780 case VUT_ADVANCE:
6781 return psource1->value.advance == psource2->value.advance;
6782 case VUT_TECHFLAG:
6783 return psource1->value.techflag == psource2->value.techflag;
6784 case VUT_GOVERNMENT:
6785 return psource1->value.govern == psource2->value.govern;
6786 case VUT_ACHIEVEMENT:
6787 return psource1->value.achievement == psource2->value.achievement;
6788 case VUT_STYLE:
6789 return psource1->value.style == psource2->value.style;
6790 case VUT_IMPROVEMENT:
6791 return psource1->value.building == psource2->value.building;
6792 case VUT_IMPR_GENUS:
6793 return psource1->value.impr_genus == psource2->value.impr_genus;
6794 case VUT_IMPR_FLAG:
6795 return psource1->value.impr_flag == psource2->value.impr_flag;
6796 case VUT_PLAYER_FLAG:
6797 return psource1->value.plr_flag == psource2->value.plr_flag;
6798 case VUT_PLAYER_STATE:
6799 return psource1->value.plrstate == psource2->value.plrstate;
6800 case VUT_EXTRA:
6801 return psource1->value.extra == psource2->value.extra;
6802 case VUT_GOOD:
6803 return psource1->value.good == psource2->value.good;
6804 case VUT_TERRAIN:
6805 return psource1->value.terrain == psource2->value.terrain;
6806 case VUT_TERRFLAG:
6807 return psource1->value.terrainflag == psource2->value.terrainflag;
6808 case VUT_NATION:
6809 return psource1->value.nation == psource2->value.nation;
6810 case VUT_NATIONGROUP:
6811 return psource1->value.nationgroup == psource2->value.nationgroup;
6812 case VUT_NATIONALITY:
6813 return psource1->value.nationality == psource2->value.nationality;
6814 case VUT_ORIGINAL_OWNER:
6815 return psource1->value.origowner == psource2->value.origowner;
6816 case VUT_DIPLREL:
6817 case VUT_DIPLREL_TILE:
6818 case VUT_DIPLREL_TILE_O:
6821 return psource1->value.diplrel == psource2->value.diplrel;
6822 case VUT_UTYPE:
6823 return psource1->value.utype == psource2->value.utype;
6824 case VUT_UTFLAG:
6825 return psource1->value.unitflag == psource2->value.unitflag;
6826 case VUT_UCLASS:
6827 return psource1->value.uclass == psource2->value.uclass;
6828 case VUT_UCFLAG:
6829 return psource1->value.unitclassflag == psource2->value.unitclassflag;
6830 case VUT_MINVETERAN:
6831 return psource1->value.minveteran == psource2->value.minveteran;
6832 case VUT_UNITSTATE:
6833 return psource1->value.unit_state == psource2->value.unit_state;
6834 case VUT_ACTIVITY:
6835 return psource1->value.activity == psource2->value.activity;
6836 case VUT_MINMOVES:
6837 return psource1->value.minmoves == psource2->value.minmoves;
6838 case VUT_MINHP:
6839 return psource1->value.min_hit_points == psource2->value.min_hit_points;
6840 case VUT_AGE:
6841 return psource1->value.age == psource2->value.age;
6842 case VUT_FORM_AGE:
6843 return psource1->value.form_age == psource2->value.form_age;
6844 case VUT_MINTECHS:
6845 return psource1->value.min_techs == psource2->value.min_techs;
6846 case VUT_MINCITIES:
6847 return psource1->value.min_cities == psource2->value.min_cities;
6848 case VUT_ACTION:
6849 return (action_number(psource1->value.action)
6850 == action_number(psource2->value.action));
6851 case VUT_OTYPE:
6852 return psource1->value.outputtype == psource2->value.outputtype;
6853 case VUT_SPECIALIST:
6854 return psource1->value.specialist == psource2->value.specialist;
6855 case VUT_MINSIZE:
6856 return psource1->value.minsize == psource2->value.minsize;
6857 case VUT_MINCULTURE:
6858 return psource1->value.minculture == psource2->value.minculture;
6859 case VUT_MINFOREIGNPCT:
6860 return psource1->value.minforeignpct == psource2->value.minforeignpct;
6861 case VUT_AI_LEVEL:
6862 return psource1->value.ai_level == psource2->value.ai_level;
6863 case VUT_MAXTILEUNITS:
6864 return psource1->value.max_tile_units == psource2->value.max_tile_units;
6865 case VUT_TERRAINCLASS:
6866 return psource1->value.terrainclass == psource2->value.terrainclass;
6867 case VUT_ROADFLAG:
6868 return psource1->value.roadflag == psource2->value.roadflag;
6869 case VUT_EXTRAFLAG:
6870 return psource1->value.extraflag == psource2->value.extraflag;
6871 case VUT_MINYEAR:
6872 return psource1->value.minyear == psource2->value.minyear;
6873 case VUT_MINCALFRAG:
6874 return psource1->value.mincalfrag == psource2->value.mincalfrag;
6875 case VUT_TOPO:
6876 return psource1->value.topo_property == psource2->value.topo_property;
6877 case VUT_WRAP:
6878 return psource1->value.wrap_property == psource2->value.wrap_property;
6879 case VUT_SERVERSETTING:
6880 return psource1->value.ssetval == psource2->value.ssetval;
6881 case VUT_TERRAINALTER:
6882 return psource1->value.terrainalter == psource2->value.terrainalter;
6883 case VUT_CITYTILE:
6884 return psource1->value.citytile == psource2->value.citytile;
6885 case VUT_CITYSTATUS:
6886 return psource1->value.citystatus == psource2->value.citystatus;
6887 case VUT_MINLATITUDE:
6888 case VUT_MAXLATITUDE:
6889 return psource1->value.latitude == psource2->value.latitude;
6890 case VUT_COUNT:
6891 break;
6892 }
6893
6894 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
6895 return FALSE;
6896}
6897
6898/**********************************************************************/
6902const char *universal_rule_name(const struct universal *psource)
6903{
6904 static char buffer[10];
6905
6906 switch (psource->kind) {
6907 case VUT_NONE:
6908 return "(none)";
6909 case VUT_COUNTER:
6910 return counter_rule_name(psource->value.counter);
6911 case VUT_CITYTILE:
6912 return citytile_type_name(psource->value.citytile);
6913 case VUT_CITYSTATUS:
6914 return citystatus_type_name(psource->value.citystatus);
6915 case VUT_MINYEAR:
6916 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
6917
6918 return buffer;
6919 case VUT_MINCALFRAG:
6920 /* Rule name is 0-based number, not pretty name from ruleset */
6921 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
6922
6923 return buffer;
6924 case VUT_TOPO:
6925 return topo_flag_name(psource->value.topo_property);
6926 case VUT_WRAP:
6927 return wrap_flag_name(psource->value.wrap_property);
6928 case VUT_SERVERSETTING:
6929 return ssetv_rule_name(psource->value.ssetval);
6930 case VUT_ADVANCE:
6931 return advance_rule_name(psource->value.advance);
6932 case VUT_TECHFLAG:
6933 return tech_flag_id_name(psource->value.techflag);
6934 case VUT_GOVERNMENT:
6935 return government_rule_name(psource->value.govern);
6936 case VUT_ACHIEVEMENT:
6937 return achievement_rule_name(psource->value.achievement);
6938 case VUT_STYLE:
6939 return style_rule_name(psource->value.style);
6940 case VUT_IMPROVEMENT:
6941 return improvement_rule_name(psource->value.building);
6942 case VUT_IMPR_GENUS:
6943 return impr_genus_id_name(psource->value.impr_genus);
6944 case VUT_IMPR_FLAG:
6945 return impr_flag_id_name(psource->value.impr_flag);
6946 case VUT_PLAYER_FLAG:
6947 return plr_flag_id_name(psource->value.plr_flag);
6948 case VUT_PLAYER_STATE:
6949 return plrstate_type_name(psource->value.plrstate);
6950 case VUT_EXTRA:
6951 return extra_rule_name(psource->value.extra);
6952 case VUT_GOOD:
6953 return goods_rule_name(psource->value.good);
6954 case VUT_TERRAIN:
6955 return terrain_rule_name(psource->value.terrain);
6956 case VUT_TERRFLAG:
6957 return terrain_flag_id_name(psource->value.terrainflag);
6958 case VUT_NATION:
6959 return nation_rule_name(psource->value.nation);
6960 case VUT_NATIONGROUP:
6961 return nation_group_rule_name(psource->value.nationgroup);
6962 case VUT_DIPLREL:
6963 case VUT_DIPLREL_TILE:
6964 case VUT_DIPLREL_TILE_O:
6967 return diplrel_rule_name(psource->value.diplrel);
6968 case VUT_NATIONALITY:
6969 return nation_rule_name(psource->value.nationality);
6970 case VUT_ORIGINAL_OWNER:
6971 return nation_rule_name(psource->value.origowner);
6972 case VUT_UTYPE:
6973 return utype_rule_name(psource->value.utype);
6974 case VUT_UTFLAG:
6975 return unit_type_flag_id_name(psource->value.unitflag);
6976 case VUT_UCLASS:
6977 return uclass_rule_name(psource->value.uclass);
6978 case VUT_UCFLAG:
6979 return unit_class_flag_id_name(psource->value.unitclassflag);
6980 case VUT_MINVETERAN:
6981 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
6982
6983 return buffer;
6984 case VUT_UNITSTATE:
6985 return ustate_prop_name(psource->value.unit_state);
6986 case VUT_ACTIVITY:
6987 return unit_activity_name(psource->value.activity);
6988 case VUT_MINMOVES:
6989 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
6990
6991 return buffer;
6992 case VUT_MINHP:
6993 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
6994
6995 return buffer;
6996 case VUT_AGE:
6997 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
6998
6999 return buffer;
7000 case VUT_FORM_AGE:
7001 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
7002
7003 return buffer;
7004 case VUT_MINTECHS:
7005 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
7006
7007 return buffer;
7008 case VUT_MINCITIES:
7009 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_cities);
7010
7011 return buffer;
7012 case VUT_ACTION:
7013 return action_rule_name(psource->value.action);
7014 case VUT_OTYPE:
7015 return get_output_identifier(psource->value.outputtype);
7016 case VUT_SPECIALIST:
7017 return specialist_rule_name(psource->value.specialist);
7018 case VUT_MINSIZE:
7019 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
7020
7021 return buffer;
7022 case VUT_MINCULTURE:
7023 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
7024
7025 return buffer;
7026 case VUT_MINFOREIGNPCT:
7027 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
7028
7029 return buffer;
7030 case VUT_AI_LEVEL:
7031 return ai_level_name(psource->value.ai_level);
7032 case VUT_MAXTILEUNITS:
7033 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_units);
7034 return buffer;
7035 case VUT_TERRAINCLASS:
7036 return terrain_class_name(psource->value.terrainclass);
7037 case VUT_ROADFLAG:
7038 return road_flag_id_name(psource->value.roadflag);
7039 case VUT_EXTRAFLAG:
7040 return extra_flag_id_name(psource->value.extraflag);
7041 case VUT_TERRAINALTER:
7042 return terrain_alteration_name(psource->value.terrainalter);
7043 case VUT_MINLATITUDE:
7044 case VUT_MAXLATITUDE:
7045 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
7046
7047 return buffer;
7048 case VUT_COUNT:
7049 break;
7050 }
7051
7052 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
7053 return NULL;
7054}
7055
7056/**********************************************************************/
7065 char *buf, size_t bufsz)
7066{
7067 buf[0] = '\0'; /* to be safe. */
7068 switch (psource->kind) {
7069 case VUT_NONE:
7070 /* TRANS: missing value */
7071 fc_strlcat(buf, _("(none)"), bufsz);
7072 return buf;
7073 case VUT_ADVANCE:
7075 return buf;
7076 case VUT_COUNTER:
7078 return buf;
7079 case VUT_TECHFLAG:
7080 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
7081 tech_flag_id_translated_name(psource->value.techflag));
7082 return buf;
7083 case VUT_GOVERNMENT:
7085 bufsz);
7086 return buf;
7087 case VUT_ACHIEVEMENT:
7089 bufsz);
7090 return buf;
7091 case VUT_STYLE:
7093 bufsz);
7094 return buf;
7095 case VUT_IMPROVEMENT:
7097 bufsz);
7098 return buf;
7099 case VUT_IMPR_GENUS:
7101 impr_genus_id_translated_name(psource->value.impr_genus),
7102 bufsz);
7103 return buf;
7104 case VUT_IMPR_FLAG:
7106 impr_flag_id_translated_name(psource->value.impr_flag),
7107 bufsz);
7108 return buf;
7109 case VUT_PLAYER_FLAG:
7111 plr_flag_id_translated_name(psource->value.plr_flag),
7112 bufsz);
7113 return buf;
7114 case VUT_PLAYER_STATE:
7116 plrstate_type_translated_name(psource->value.plrstate),
7117 bufsz);
7118 return buf;
7119 case VUT_EXTRA:
7121 return buf;
7122 case VUT_GOOD:
7124 return buf;
7125 case VUT_TERRAIN:
7127 return buf;
7128 case VUT_NATION:
7130 bufsz);
7131 return buf;
7132 case VUT_NATIONGROUP:
7134 bufsz);
7135 return buf;
7136 case VUT_NATIONALITY:
7137 cat_snprintf(buf, bufsz, _("%s citizens"),
7138 nation_adjective_translation(psource->value.nationality));
7139 return buf;
7140 case VUT_ORIGINAL_OWNER:
7141 /* TRANS: Keep short. City founding nation. */
7142 cat_snprintf(buf, bufsz, _("%s original owner"),
7143 nation_adjective_translation(psource->value.origowner));
7144 return buf;
7145 case VUT_DIPLREL:
7146 case VUT_DIPLREL_TILE:
7147 case VUT_DIPLREL_TILE_O:
7151 bufsz);
7152 return buf;
7153 case VUT_UTYPE:
7155 return buf;
7156 case VUT_UTFLAG:
7158 /* TRANS: Unit type flag */
7159 Q_("?utflag:\"%s\" units"),
7161 psource->value.unitflag));
7162 return buf;
7163 case VUT_UCLASS:
7165 /* TRANS: Unit class */
7166 _("%s units"),
7167 uclass_name_translation(psource->value.uclass));
7168 return buf;
7169 case VUT_UCFLAG:
7171 /* TRANS: Unit class flag */
7172 Q_("?ucflag:\"%s\" units"),
7174 psource->value.unitclassflag));
7175 return buf;
7176 case VUT_MINVETERAN:
7177 /* FIXME */
7178 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
7179 psource->value.minveteran);
7180 return buf;
7181 case VUT_UNITSTATE:
7182 switch (psource->value.unit_state) {
7183 case USP_TRANSPORTED:
7184 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7185 cat_snprintf(buf, bufsz, _("Transported"));
7186 break;
7187 case USP_LIVABLE_TILE:
7189 /* TRANS: unit state. (appears in strings like
7190 * "Missile+On livable tile") */
7191 _("On livable tile"));
7192 break;
7193 case USP_TRANSPORTING:
7194 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7195 cat_snprintf(buf, bufsz, _("Transporting"));
7196 break;
7197 case USP_HAS_HOME_CITY:
7198 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
7199 cat_snprintf(buf, bufsz, _("Has a home city"));
7200 break;
7201 case USP_NATIVE_TILE:
7203 /* TRANS: unit state. (appears in strings like
7204 * "Missile+On native tile") */
7205 _("On native tile"));
7206 break;
7207 case USP_NATIVE_EXTRA:
7209 /* TRANS: unit state. (appears in strings like
7210 * "Missile+In native extra") */
7211 _("In native extra"));
7212 break;
7214 /* TRANS: unit state. (appears in strings like
7215 * "Missile+Has moved this turn") */
7216 cat_snprintf(buf, bufsz, _("Has moved this turn"));
7217 break;
7218 case USP_COUNT:
7219 fc_assert_msg(psource->value.unit_state != USP_COUNT,
7220 "Invalid unit state property.");
7221 break;
7222 }
7223 return buf;
7224 case VUT_ACTIVITY:
7225 cat_snprintf(buf, bufsz, _("%s activity"),
7226 Q_(unit_activity_name(psource->value.activity)));
7227 return buf;
7228 case VUT_MINMOVES:
7229 /* TRANS: Minimum unit movement points left for requirement to be met
7230 * (%s is a string like "1" or "2 1/3") */
7231 cat_snprintf(buf, bufsz, _("%s MP"),
7232 move_points_text(psource->value.minmoves, TRUE));
7233 return buf;
7234 case VUT_MINHP:
7235 /* TRANS: HP = hit points */
7236 cat_snprintf(buf, bufsz, _("%d HP"),
7237 psource->value.min_hit_points);
7238 return buf;
7239 case VUT_AGE:
7240 cat_snprintf(buf, bufsz, _("Age %d"),
7241 psource->value.age);
7242 return buf;
7243 case VUT_FORM_AGE:
7244 cat_snprintf(buf, bufsz, _("Form age %d"),
7245 psource->value.form_age);
7246 return buf;
7247 case VUT_MINTECHS:
7248 cat_snprintf(buf, bufsz, _("%d Techs"),
7249 psource->value.min_techs);
7250 return buf;
7251 case VUT_MINCITIES:
7252 cat_snprintf(buf, bufsz, _("%d Cities"),
7253 psource->value.min_cities);
7254 return buf;
7255 case VUT_ACTION:
7257 bufsz);
7258 return buf;
7259 case VUT_OTYPE:
7260 /* FIXME */
7261 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
7262 return buf;
7263 case VUT_SPECIALIST:
7265 bufsz);
7266 return buf;
7267 case VUT_MINSIZE:
7268 cat_snprintf(buf, bufsz, _("Size %d"),
7269 psource->value.minsize);
7270 return buf;
7271 case VUT_MINCULTURE:
7272 cat_snprintf(buf, bufsz, _("Culture %d"),
7273 psource->value.minculture);
7274 return buf;
7275 case VUT_MINFOREIGNPCT:
7276 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
7277 psource->value.minforeignpct);
7278 return buf;
7279 case VUT_AI_LEVEL:
7280 /* TRANS: "Hard AI" */
7281 cat_snprintf(buf, bufsz, _("%s AI"),
7282 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
7283 return buf;
7284 case VUT_MAXTILEUNITS:
7285 /* TRANS: here <= means 'less than or equal' */
7286 cat_snprintf(buf, bufsz, PL_("<=%d unit",
7287 "<=%d units", psource->value.max_tile_units),
7288 psource->value.max_tile_units);
7289 return buf;
7290 case VUT_TERRAINCLASS:
7291 /* TRANS: Terrain class: "Land terrain" */
7292 cat_snprintf(buf, bufsz, _("%s terrain"),
7293 terrain_class_name_translation(psource->value.terrainclass));
7294 return buf;
7295 case VUT_TERRFLAG:
7297 /* TRANS: Terrain flag */
7298 Q_("?terrflag:\"%s\" terrain"),
7300 psource->value.terrainflag));
7301 return buf;
7302 case VUT_ROADFLAG:
7304 /* TRANS: Road flag */
7305 Q_("?roadflag:\"%s\" road"),
7306 road_flag_id_translated_name(psource->value.roadflag));
7307 return buf;
7308 case VUT_EXTRAFLAG:
7310 /* TRANS: Extra flag */
7311 Q_("?extraflag:\"%s\" extra"),
7312 extra_flag_id_translated_name(psource->value.extraflag));
7313 return buf;
7314 case VUT_MINYEAR:
7315 cat_snprintf(buf, bufsz, _("After %s"),
7316 textyear(psource->value.minyear));
7317 return buf;
7318 case VUT_MINCALFRAG:
7319 /* TRANS: here >= means 'greater than or equal'.
7320 * %s identifies a calendar fragment (may be bare number). */
7321 cat_snprintf(buf, bufsz, _(">=%s"),
7322 textcalfrag(psource->value.mincalfrag));
7323 return buf;
7324 case VUT_TOPO:
7325 /* TRANS: topology flag name ("Hex", "ISO") */
7326 cat_snprintf(buf, bufsz, _("%s map"),
7327 _(topo_flag_name(psource->value.topo_property)));
7328 return buf;
7329 case VUT_WRAP:
7330 /* TRANS: wrap flag name ("WrapX", "WrapY") */
7331 cat_snprintf(buf, bufsz, _("%s map"),
7332 _(wrap_flag_name(psource->value.wrap_property)));
7333 return buf;
7334 case VUT_SERVERSETTING:
7336 bufsz);
7337 return buf;
7338 case VUT_TERRAINALTER:
7339 /* TRANS: "Irrigation possible" */
7340 cat_snprintf(buf, bufsz, _("%s possible"),
7341 Q_(terrain_alteration_name(psource->value.terrainalter)));
7342 return buf;
7343 case VUT_CITYTILE:
7344 switch (psource->value.citytile) {
7345 case CITYT_CENTER:
7346 fc_strlcat(buf, _("City center"), bufsz);
7347 break;
7348 case CITYT_CLAIMED:
7349 fc_strlcat(buf, _("Tile claimed"), bufsz);
7350 break;
7351 case CITYT_EXTRAS_OWNED:
7352 fc_strlcat(buf, _("Extras owned"), bufsz);
7353 break;
7354 case CITYT_WORKED:
7355 fc_strlcat(buf, _("Worked tile"), bufsz);
7356 break;
7358 fc_strlcat(buf, _("Same continent tile"), bufsz);
7359 break;
7361 /* TRANS: Short for "a tile of other terrain class mass near city" */
7362 fc_strlcat(buf, _("Port reachable tile"), bufsz);
7363 break;
7364 case CITYT_LAST:
7365 fc_assert(psource->value.citytile != CITYT_LAST);
7366 fc_strlcat(buf, "error", bufsz);
7367 break;
7368 }
7369 return buf;
7370 case VUT_CITYSTATUS:
7371 switch (psource->value.citystatus) {
7373 fc_strlcat(buf, _("Owned by original"), bufsz);
7374 break;
7375 case CITYS_STARVED:
7376 fc_strlcat(buf, _("Starved"), bufsz);
7377 break;
7378 case CITYS_DISORDER:
7379 fc_strlcat(buf, _("Disorder"), bufsz);
7380 break;
7381 case CITYS_CELEBRATION:
7382 fc_strlcat(buf, _("Celebration"), bufsz);
7383 break;
7384 case CITYS_TRANSFERRED:
7385 /* TRANS: CityStatus value - city has changed hands */
7386 fc_strlcat(buf, _("Transferred"), bufsz);
7387 break;
7388 case CITYS_LAST:
7389 fc_assert(psource->value.citystatus != CITYS_LAST);
7390 fc_strlcat(buf, "error", bufsz);
7391 break;
7392 }
7393 return buf;
7394 case VUT_MINLATITUDE:
7395 /* TRANS: here >= means 'greater than or equal'. */
7396 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
7397 psource->value.latitude);
7398 return buf;
7399 case VUT_MAXLATITUDE:
7400 /* TRANS: here <= means 'less than or equal'. */
7401 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
7402 psource->value.latitude);
7403 return buf;
7404 case VUT_COUNT:
7405 break;
7406 }
7407
7408 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
7409 return buf;
7410}
7411
7412/**********************************************************************/
7416{
7417 return universals_n_name(psource->kind);
7418}
7419
7420/**********************************************************************/
7423int universal_build_shield_cost(const struct city *pcity,
7424 const struct universal *target)
7425{
7426 switch (target->kind) {
7427 case VUT_IMPROVEMENT:
7428 return impr_build_shield_cost(pcity, target->value.building);
7429 case VUT_UTYPE:
7430 return utype_build_shield_cost(pcity, NULL, target->value.utype);
7431 default:
7432 break;
7433 }
7434 return FC_INFINITY;
7435}
7436
7437/**********************************************************************/
7443 const struct universal *to_replace,
7444 const struct universal *replacement)
7445{
7446 bool changed = FALSE;
7447
7450 preq->source = *replacement;
7451 changed = TRUE;
7452 }
7454
7455 return changed;
7456}
7457
7458/**********************************************************************/
7463 const struct requirement_vector *reqs,
7464 const struct universal *psource)
7465{
7468 return TRUE;
7469 }
7471
7472 return FALSE;
7473}
7474
7475/**********************************************************************/
7485 struct universal *unis,
7486 size_t n_unis)
7487{
7488 int i;
7489
7490 for (i = 0; i < n_unis; i++) {
7492 /* This universal makes it impossible to fulfill the specified
7493 * requirement vector */
7494 return TRUE;
7495 }
7496 }
7497
7498 /* No specified universal is known to guarantee that the requirement
7499 * vector never will be fulfilled. */
7500 return FALSE;
7501}
7502
7503/**********************************************************************/
7518 struct universal *unis,
7519 size_t n_unis)
7520{
7522 int i;
7524
7525 for (i = 0; i < n_unis; i++) {
7526 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
7527 case ITF_NO:
7528 case ITF_YES:
7529 /* this req matched this source */
7531 break;
7532 case ITF_NOT_APPLICABLE:
7533 /* Not a mention. */
7534 break;
7535 }
7536 }
7537
7539 /* A requirement not relevant to any of the specified universals was
7540 * found in the requirement vector. */
7541 return FALSE;
7542 }
7544
7545 /* No requirement not relevant to any of the specified universals was
7546 * found in the requirement vector. */
7547 return TRUE;
7548}
7549
7550/**********************************************************************/
7553enum req_item_found
7555 const struct universal *source)
7556{
7559 "No req item found function for %s",
7561
7562 return (*universal_found_function[source->kind])(preq, source);
7563}
7564
7565/**********************************************************************/
7576 const struct requirement_vector *reqs,
7577 const struct universal *source)
7578{
7579 bool necessary = FALSE;
7580
7583 "No req item found function for %s",
7585
7587 switch ((*universal_found_function[source->kind])(preq, source)) {
7588 case ITF_NOT_APPLICABLE:
7589 continue;
7590 case ITF_NO:
7591 if (preq->present) {
7592 return FALSE;
7593 }
7594 break;
7595 case ITF_YES:
7596 if (preq->present) {
7597 necessary = TRUE;
7598 } else {
7599 return FALSE;
7600 }
7601 break;
7602 }
7604
7605 return (!check_necessary || necessary);
7606}
7607
7608/**********************************************************************/
7613 const struct universal *source)
7614{
7615 switch (universal_fulfills_requirement(req, source)) {
7616 case ITF_NOT_APPLICABLE:
7617 return FALSE;
7618 case ITF_NO:
7619 case ITF_YES:
7620 return TRUE;
7621 }
7622
7623 log_error("Unhandled item_found value");
7624 return FALSE;
7625}
7626
7627/**********************************************************************/
7631 const struct universal *source)
7632{
7633 fc_assert(source->value.nation);
7634
7635 switch (preq->source.kind) {
7636 case VUT_NATION:
7637 return preq->source.value.nation == source->value.nation ? ITF_YES
7638 : ITF_NO;
7639 case VUT_NATIONGROUP:
7640 return nation_is_in_group(source->value.nation,
7641 preq->source.value.nationgroup) ? ITF_YES
7642 : ITF_NO;
7643 default:
7644 break;
7645 }
7646
7647 return ITF_NOT_APPLICABLE;
7648}
7649
7650/**********************************************************************/
7654 const struct universal *source)
7655{
7656 fc_assert(source->value.govern);
7657
7658 if (preq->source.kind == VUT_GOVERNMENT) {
7659 return preq->source.value.govern == source->value.govern ? ITF_YES
7660 : ITF_NO;
7661 }
7662
7663 return ITF_NOT_APPLICABLE;
7664}
7665
7666/**********************************************************************/
7670 const struct universal *source)
7671{
7672 fc_assert(source->value.building);
7673
7674 /* We only ever return ITF_YES, because requiring a different
7675 * improvement does not mean that the improvement under consideration
7676 * cannot fulfill the requirements. This is necessary to allow
7677 * requirement vectors to specify multiple required improvements. */
7678
7679 switch (preq->source.kind) {
7680 case VUT_IMPROVEMENT:
7681 if (source->value.building == preq->source.value.building) {
7682 return ITF_YES;
7683 }
7684 break;
7685 case VUT_IMPR_GENUS:
7686 if (source->value.building->genus == preq->source.value.impr_genus) {
7687 return ITF_YES;
7688 }
7689 break;
7690 case VUT_IMPR_FLAG:
7691 if (improvement_has_flag(source->value.building,
7692 preq->source.value.impr_flag)) {
7693 return ITF_YES;
7694 }
7695 break;
7696 default:
7697 break;
7698 }
7699
7700 return ITF_NOT_APPLICABLE;
7701}
7702
7703/**********************************************************************/
7707 const struct universal *source)
7708{
7709 fc_assert(source->value.uclass);
7710
7711 switch (preq->source.kind) {
7712 case VUT_UCLASS:
7713 return source->value.uclass == preq->source.value.uclass ? ITF_YES
7714 : ITF_NO;
7715 case VUT_UCFLAG:
7716 return uclass_has_flag(source->value.uclass,
7717 preq->source.value.unitclassflag) ? ITF_YES
7718 : ITF_NO;
7719
7720 default:
7721 /* Not found and not relevant. */
7722 return ITF_NOT_APPLICABLE;
7723 };
7724}
7725
7726/**********************************************************************/
7730 const struct universal *source)
7731{
7732 fc_assert(source->value.utype);
7733
7734 switch (preq->source.kind) {
7735 case VUT_UTYPE:
7736 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
7737 case VUT_UCLASS:
7738 return utype_class(source->value.utype) == preq->source.value.uclass
7739 ? ITF_YES : ITF_NO;
7740 case VUT_UTFLAG:
7741 return utype_has_flag(source->value.utype,
7742 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
7743 case VUT_UCFLAG:
7744 return uclass_has_flag(utype_class(source->value.utype),
7745 preq->source.value.unitclassflag) ? ITF_YES
7746 : ITF_NO;
7747 default:
7748 /* Not found and not relevant. */
7749 return ITF_NOT_APPLICABLE;
7750 };
7751}
7752
7753/**********************************************************************/
7756static enum req_item_found
7758 const struct universal *source)
7759{
7762
7763 switch (preq->source.kind) {
7764 case VUT_ACTIVITY:
7765 return source->value.activity == preq->source.value.activity ? ITF_YES
7766 : ITF_NO;
7767 default:
7768 /* Not found and not relevant. */
7769 return ITF_NOT_APPLICABLE;
7770 };
7771}
7772
7773/**********************************************************************/
7777 const struct universal *source)
7778{
7779 fc_assert(source->value.terrain);
7780
7781 switch (preq->source.kind) {
7782 case VUT_TERRAIN:
7783 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
7784 case VUT_TERRAINCLASS:
7785 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
7786 ? ITF_YES : ITF_NO;
7787 case VUT_TERRFLAG:
7788 return terrain_has_flag(source->value.terrain,
7789 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
7790 case VUT_TERRAINALTER:
7791 return (terrain_can_support_alteration(source->value.terrain,
7792 preq->source.value.terrainalter)
7793 ? ITF_YES : ITF_NO);
7794 default:
7795 /* Not found and not relevant. */
7796 return ITF_NOT_APPLICABLE;
7797 };
7798}
7799
7800/**********************************************************************/
7804 const struct universal *source)
7805{
7808
7809 switch (preq->source.kind) {
7810 case VUT_CITYTILE:
7811 return (source->value.citytile == preq->source.value.citytile
7812 ? ITF_YES
7813 /* The presence of one tile state doesn't block another */
7815 default:
7816 /* Not found and not relevant. */
7817 return ITF_NOT_APPLICABLE;
7818 };
7819}
7820
7821/**********************************************************************/
7825 const struct universal *source)
7826{
7827 fc_assert(source->value.extra);
7828
7829 switch (preq->source.kind) {
7830 case VUT_EXTRA:
7831 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
7832 case VUT_EXTRAFLAG:
7833 return extra_has_flag(source->value.extra,
7834 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
7835 case VUT_ROADFLAG:
7836 {
7837 struct road_type *r = extra_road_get(source->value.extra);
7838 return r && road_has_flag(r, preq->source.value.roadflag)
7839 ? ITF_YES : ITF_NO;
7840 }
7841 default:
7842 /* Not found and not relevant. */
7843 return ITF_NOT_APPLICABLE;
7844 }
7845}
7846
7847/**********************************************************************/
7851 const struct universal *source)
7852{
7853 fc_assert(source->value.action);
7854
7855 if (preq->source.kind == VUT_ACTION) {
7856 return preq->source.value.action == source->value.action ? ITF_YES
7857 : ITF_NO;
7858 }
7859
7860 return ITF_NOT_APPLICABLE;
7861}
7862
7863/**********************************************************************/
7867 const struct universal *source)
7868{
7870 || source->kind == VUT_DIPLREL_TILE
7871 || source->kind == VUT_DIPLREL_TILE_O
7872 || source->kind == VUT_DIPLREL_UNITANY
7873 || source->kind == VUT_DIPLREL_UNITANY_O),
7875
7876 if (preq->source.kind == source->kind) {
7877 if (preq->source.value.diplrel == source->value.diplrel) {
7878 /* The diplrel itself. */
7879 return ITF_YES;
7880 }
7881 if (preq->source.value.diplrel == DRO_FOREIGN
7882 && source->value.diplrel < DS_LAST) {
7883 /* All diplstate_type values are to foreigners. */
7884 return ITF_YES;
7885 }
7886 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
7887 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
7888 /* A real embassy is an embassy. */
7889 return ITF_YES;
7890 }
7891 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
7892 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
7893 /* A real embassy is an embassy. */
7894 return ITF_YES;
7895 }
7896 if (preq->source.value.diplrel < DS_LAST
7897 && source->value.diplrel < DS_LAST
7898 && preq->range == REQ_RANGE_LOCAL) {
7899 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
7900 ITF_YES);
7901 /* Can only have one diplstate_type to a specific player. */
7902 return ITF_NO;
7903 }
7904 /* Can't say this diplrel blocks the other diplrel. */
7905 return ITF_NOT_APPLICABLE;
7906 }
7907
7908 /* Not relevant. */
7909 return ITF_NOT_APPLICABLE;
7910}
7911
7912/**********************************************************************/
7916 const struct universal *source)
7917{
7918 switch (preq->source.kind) {
7919 case VUT_OTYPE:
7920 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
7921 : ITF_NO;
7922 default:
7923 /* Not found and not relevant. */
7924 return ITF_NOT_APPLICABLE;
7925 }
7926}
7927
7928/**********************************************************************/
7932 const struct universal *source)
7933{
7934 if (preq->range != REQ_RANGE_LOCAL) {
7935 return ITF_NOT_APPLICABLE;
7936 }
7937
7938 if (preq->source.kind == VUT_UNITSTATE) {
7939 switch (source->value.unit_state) {
7940 case USP_TRANSPORTED:
7941 case USP_TRANSPORTING:
7942 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
7943 case USP_LIVABLE_TILE:
7944 case USP_NATIVE_TILE:
7945 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
7946 * UTYF_COAST_STRICT. */
7947 case USP_HAS_HOME_CITY:
7948 case USP_NATIVE_EXTRA:
7950 if (source->value.unit_state == preq->source.value.unit_state) {
7951 /* The other unit states doesn't contradict */
7952 return ITF_YES;
7953 }
7954 break;
7955 case USP_COUNT:
7956 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
7958 }
7959 }
7960
7961 /* Not found and not relevant. */
7962 return ITF_NOT_APPLICABLE;
7963}
7964
7965/**********************************************************************/
7988
7989/**********************************************************************/
7997int requirement_kind_ereq(const int value,
7998 const enum req_range range,
7999 const bool present,
8000 const int max_value)
8001{
8002 /* The enumerators in each range starts with present for every possible
8003 * value followed by !present for every possible value. */
8004 const int pres_start = (present ? 0 : max_value);
8005
8006 /* The enumerators for every range follows all the positions of the
8007 * previous range(s). */
8008 const int range_start = ((max_value - 1) * 2) * range;
8009
8010 return range_start + pres_start + value;
8011}
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:1205
bool action_is_in_use(struct action *paction)
Definition actions.c:5629
struct action * action_by_rule_name(const char *name)
Definition actions.c:1054
const char * action_rule_name(const struct action *action)
Definition actions.c:1191
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1214
int action_number(const struct action *action)
Definition actions.c:1183
static struct action * action_by_number(action_id act_id)
Definition actions.h:390
#define ACTION_NONE
Definition actions.h:55
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:78
const char * textcalfrag(int frag)
Definition calendar.c:101
const char * textyear(int year)
Definition calendar.c:120
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:1236
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:859
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:230
#define city_tile_iterate_end
Definition city.h:238
#define city_built_iterate(_pcity, _p)
Definition city.h:825
#define city_built_iterate_end
Definition city.h:831
char * incite_cost
Definition comments.c:74
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 @21::@22 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:381
req_problem_type
Definition fc_types.h:676
@ RPT_POSSIBLE
Definition fc_types.h:677
#define MAX_LEN_NAME
Definition fc_types.h:66
@ VC_SPACERACE
Definition fc_types.h:1251
@ O_LAST
Definition fc_types.h:101
signed short Continent_id
Definition fc_types.h:376
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
struct civ_game game
Definition game.c:61
struct world wld
Definition game.c:62
const char * government_name_translation(const struct government *pgovern)
Definition government.c:143
struct government * government_by_number(const Government_type_id gov)
Definition government.c:103
struct government * government_of_player(const struct player *pplayer)
Definition government.c:114
Government_type_id government_number(const struct government *pgovern)
Definition government.c:91
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
struct government * government_by_rule_name(const char *name)
Definition government.c:55
struct city * owner
Definition citydlg.c:226
static GtkWidget * source
Definition gotodlg.c:58
GType type
Definition repodlgs.c:1313
static const int bufsz
Definition helpdlg.c:70
struct impr_type * improvement_by_number(const Impr_type_id id)
bool great_wonder_is_built(const struct impr_type *pimprove)
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
bool wonder_is_built(const struct player *pplayer, const struct impr_type *pimprove)
Impr_type_id improvement_number(const struct impr_type *pimprove)
bool can_improvement_go_obsolete(const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
struct city * city_from_wonder(const struct player *pplayer, const struct impr_type *pimprove)
int impr_build_shield_cost(const struct city *pcity, const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
bool improvement_obsolete(const struct player *pplayer, const struct impr_type *pimprove, const struct city *pcity)
bool improvement_has_flag(const struct impr_type *pimprove, enum impr_flag_id flag)
struct impr_type * improvement_by_rule_name(const char *name)
const char * improvement_name_translation(const struct impr_type *pimprove)
bool great_wonder_is_available(const struct impr_type *pimprove)
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_normal(message,...)
Definition log.h:107
#define log_error(message,...)
Definition log.h:103
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition log.h:208
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:941
int map_signed_latitude(const struct tile *ptile)
Definition map.c:1566
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:950
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:660
#define current_topo_has_flag(flag)
Definition map.h:43
#define MAP_MAX_LATITUDE
Definition map.h:560
#define adjc_iterate_end
Definition map.h:419
#define MAP_MAX_REAL_LATITUDE(_nmap)
Definition map.h:572
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:377
#define cardinal_adjc_iterate_end
Definition map.h:445
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:414
#define square_iterate_end
Definition map.h:380
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:441
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:387
#define current_wrap_has_flag(flag)
Definition map.h:46
#define MAP_MIN_REAL_LATITUDE(_nmap)
Definition map.h:574
#define circle_iterate_end
Definition map.h:390
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
const char * move_points_text(int mp, bool reduce)
Definition movement.c:1016
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:318
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:330
struct nation_group * nation_group_by_rule_name(const char *name)
Definition nation.c:1021
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:486
const char * nation_adjective_translation(const struct nation_type *pnation)
Definition nation.c:149
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:475
const char * nation_group_rule_name(const struct nation_group *pgroup)
Definition nation.c:1079
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
bool nation_is_in_group(const struct nation_type *pnation, const struct nation_group *pgroup)
Definition nation.c:1099
const char * nation_group_name_translation(const struct nation_group *pgroup)
Definition nation.c:1090
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
struct nation_group * nation_group_by_number(int id)
Definition nation.c:1004
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:952
#define NO_NATION_SELECTED
Definition nation.h:30
bool player_knows_techs_with_flag(const struct player *pplayer, enum tech_flag_id flag)
Definition player.c:1328
bool player_has_state(const struct player *pplayer, enum plrstate_type state)
Definition player.c:2004
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Definition player.c:1829
int diplrel_by_rule_name(const char *value)
Definition player.c:1585
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1480
bool is_diplrel_to_other(const struct player *pplayer, int diplrel)
Definition player.c:1566
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1996
const char * diplrel_name_translation(int value)
Definition player.c:1631
bool is_diplrel_between(const struct player *player1, const struct player *player2, int diplrel)
Definition player.c:1516
int player_age(const struct player *pplayer)
Definition player.c:954
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1409
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:437
const char * diplrel_rule_name(int value)
Definition player.c:1619
#define players_iterate_end
Definition player.h:539
#define players_iterate(_pplayer)
Definition player.h:534
#define player_nation(_plr_)
Definition player.h:408
#define is_ai(plr)
Definition player.h:232
#define players_iterate_alive_end
Definition player.h:549
#define players_iterate_alive(_pplayer)
Definition player.h:544
static enum req_item_found terrain_type_found(const struct requirement *preq, const struct universal *source)
bool universal_never_there(const struct universal *source)
static enum fc_tristate is_unitclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unitflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_relevant_to_requirement(const struct requirement *req, const struct universal *source)
#define EXTRACT_INFO(req)
bool is_req_in_vec(const struct requirement *req, const struct requirement_vector *vec)
int universal_build_shield_cost(const struct city *pcity, const struct universal *target)
static enum fc_tristate is_terrainflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found city_tile_found(const struct requirement *preq, const struct universal *source)
struct req_vec_problem * req_vec_get_first_contradiction(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static universal_found universal_found_function[VUT_COUNT]
static enum req_unchanging_status unchanging_local(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
#define REQUC_CITYSTATUS
const struct req_context * req_context_empty(void)
static enum fc_tristate is_action_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found unit_type_found(const struct requirement *preq, const struct universal *source)
void universal_extraction(const struct universal *source, int *kind, int *value)
static int num_player_buildings(const struct player *pplayer, const struct impr_type *building)
static enum fc_tristate is_tech_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_none_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static int num_continent_buildings(const struct player *pplayer, int continent, const struct impr_type *building)
static enum fc_tristate is_minveteran_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * req_to_fstring(const struct requirement *req, struct astring *astr)
static enum fc_tristate is_counter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
req_vec_num_in_item req_vec_vector_number(const void *parent_item, const struct requirement_vector *vec)
static bool present_implies_not_present(const struct requirement *req1, const struct requirement *req2)
enum fc_tristate tri_req_active(const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct requirement_vector * req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
bool universal_fulfills_requirements(bool check_necessary, const struct requirement_vector *reqs, const struct universal *source)
static bool activity_is_valid_in_requirement(enum unit_activity act)
enum fc_tristate tri_reqs_cb_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, struct requirement_vector *maybe_reqs, req_tester_cb tester, void *data, int n_data)
static enum fc_tristate is_minsize_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_ai_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_noally(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
bool req_vec_change_apply(const struct req_vec_change *modification, requirement_vector_by_number getter, const void *parent_item)
void universal_copy(struct universal *dst, const struct universal *src)
static enum fc_tristate is_minculture_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_building(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_terrain_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_requirements_equal(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_minforeignpct_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_minyear_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found extra_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_buildingflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_in_range(const struct tile *target_tile, const struct player *other_player, enum req_range range, int diplrel)
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
struct requirement req_from_str(const char *type, const char *range, bool survives, bool present, bool quiet, const char *value)
struct req_vec_problem * req_vec_suggest_repair(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum fc_tristate is_wrap_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void universal_value_from_str(struct universal *source, const char *value)
static enum fc_tristate is_buildingflag_in_city(const struct city *pcity, enum impr_flag_id flag)
static enum fc_tristate is_latitude_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_get_values(const struct requirement *req, int *type, int *range, bool *survives, bool *present, bool *quiet, int *value)
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
static enum fc_tristate is_nationality_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * universal_rule_name(const struct universal *psource)
static enum req_unchanging_status unchanging_present(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
bool universal_replace_in_req_vec(struct requirement_vector *reqs, const struct universal *to_replace, const struct universal *replacement)
static enum req_item_found action_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_minmovefrags_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_requirements_contradictions(const struct requirement *req1, const struct requirement *req2)
#define REQUC_IMPR
static enum fc_tristate is_maxunitsontile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct req_vec_problem * req_vec_problem_new(int num_suggested_solutions, const char *descr,...)
static enum fc_tristate is_buildinggenus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_in_range(const struct player *target_player, const struct player *other_player, enum req_range range, int diplrel)
static enum fc_tristate is_mintechs_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool is_req_active(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, const enum req_problem_type prob_type)
static enum fc_tristate is_originalowner_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static 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 fc_tristate is_extraflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum req_unchanging_status is_req_preventing(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, enum req_problem_type prob_type)
static enum fc_tristate is_plr_state_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool players_in_same_range(const struct player *pplayer1, const struct player *pplayer2, enum req_range range)
enum req_item_found(* universal_found)(const struct requirement *, const struct universal *)
static enum fc_tristate is_terrainclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct universal universal_by_number(const enum universals_n kind, const int value)
static enum fc_tristate is_roadflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum req_item_found universal_fulfills_requirement(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_building_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_reqs_active_ranges(const enum req_range min_range, const enum req_range max_range, const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
static enum fc_tristate is_gov_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_tile_o_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_good_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unitstate_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool city_center_contra(const struct requirement *cc_req, const struct requirement *ct_req)
static enum req_item_found ustate_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_terrainalter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unittype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_vec_wants_type(const struct requirement_vector *reqs, enum universals_n kind)
static int num_world_buildings_total(const struct impr_type *building)
static enum req_unchanging_status unchanging_citytile(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum req_item_found output_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_citystatus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
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 is_extra_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_world(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_mincalfrag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_activity_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
struct req_vec_problem * req_vec_problem_new_transl(int num_suggested_solutions, const char *description, const char *description_translated)
static enum fc_tristate is_nationgroup_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define REQUC_NALLY
static enum req_item_found unit_activity_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_minhitpoints_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum fc_tristate tri_req_active_turns(int pass, int period, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_outputtype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define REQUC_LOCAL
bool universals_say_everything(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
static enum fc_tristate is_unitclassflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found nation_found(const struct requirement *preq, const struct universal *source)
#define REQUC_WORLD
const char * universal_type_rule_name(const struct universal *psource)
#define REQUC_PRESENT
void universal_found_functions_init(void)
static enum fc_tristate is_style_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found unit_class_found(const struct requirement *preq, const struct universal *source)
#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind)
int universal_number(const struct universal *source)
static enum fc_tristate is_techflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_mentioned_by_requirements(const struct requirement_vector *reqs, const struct universal *psource)
#define REQUC_CITYTILE
static enum fc_tristate is_citytile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found diplrel_found(const struct requirement *preq, const struct universal *source)
bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
bool req_implies_req(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_specialist_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_copy(struct requirement *dst, const struct requirement *src)
enum req_unchanging_status is_req_unchanging(const struct req_context *context, const struct requirement *req)
static bool player_has_ever_built(const struct player *pplayer, const struct impr_type *building)
enum fc_tristate(* is_req_active_cb)(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool nation_contra_group(const struct requirement *nation_req, const struct requirement *group_req)
static enum fc_tristate is_serversetting_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_plr_flag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_nation_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_is_impossible_to_fulfill(const struct requirement *req)
static bool are_tiles_in_range(const struct tile *tile1, const struct tile *tile2, enum req_range range)
static bool are_requirements_opposites(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_form_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static int num_world_buildings(const struct impr_type *building)
static enum req_unchanging_status unchanging_citystatus(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_topology_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_o_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
struct universal universal_by_rule_name(const char *kind, const char *value)
bool universals_mean_unfulfilled(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
struct req_vec_problem * req_vec_suggest_improvement(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static bool impr_contra_genus(const struct requirement *impr_req, const struct requirement *genus_req)
enum fc_tristate(* req_tester_cb)(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, void *data, int n_data)
#define requirement_diplrel_ereq(_id_, _range_, _present_)
signed char req_vec_num_in_item
req_vec_num_in_item a requirement vectors number in an item.
req_vec_num_in_item(* requirement_vector_number)(const void *parent_item, const struct requirement_vector *vec)
const char *(* requirement_vector_namer)(req_vec_num_in_item number)
#define universal_is_mentioned_by_requirement(preq, psource)
enum req_unchanging_status(* req_unchanging_cond_cb)(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
#define requirement_vector_iterate_end
struct universal universal_by_number(const enum universals_n kind, const int value)
struct requirement_vector *(* requirement_vector_by_number)(const void *parent_item, req_vec_num_in_item number)
#define requirement_vector_iterate(req_vec, preq)
req_item_found
@ ITF_NO
@ ITF_YES
@ ITF_NOT_APPLICABLE
req_unchanging_status
@ REQUCH_ACT
@ REQUCH_NO
@ REQUCH_SCRIPTS
@ REQUCH_YES
@ REQUCH_HACK
@ REQUCH_CTRL
struct research * research_get(const struct player *pplayer)
Definition research.c:128
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:619
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Definition road.c:416
bool is_road_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:446
bool is_road_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:425
bool ssetv_setting_has_value(ssetv val)
ssetv ssetv_by_rule_name(const char *name)
const char * ssetv_rule_name(ssetv val)
const char * ssetv_human_readable(ssetv val, bool present)
#define SSETV_NONE
enum fc_tristate fc_tristate_or(enum fc_tristate one, enum fc_tristate two)
Definition shared.c:143
fc_tristate
Definition shared.h:46
@ TRI_YES
Definition shared.h:46
@ TRI_NO
Definition shared.h:46
@ TRI_MAYBE
Definition shared.h:46
#define BOOL_TO_TRISTATE(tri)
Definition shared.h:47
#define FC_INFINITY
Definition shared.h:36
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c:112
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:100
Specialist_type_id specialist_number(const struct specialist *sp)
Definition specialist.c:91
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
const char * specialist_plural_translation(const struct specialist *sp)
Definition specialist.c:155
Definition city.h:320
struct tile * tile
Definition city.h:322
struct packet_game_info info
Definition game.h:89
struct packet_calendar_info calendar
Definition game.h:90
int checkpoint
Definition counters.h:33
struct player * player
Definition nation.h:118
bool global_advances[A_LAST]
bool is_alive
Definition player.h:268
enum req_unchanging_status unchanging
req_unchanging_cond_cb unchanging_cond
const is_req_active_cb cb
req_vec_num_in_item vector_number
enum req_vec_change_operation operation
struct requirement req
char description[500]
char description_translated[500]
enum req_range range
struct universal source
Tech_type_id researching
Definition research.h:52
int techs_researched
Definition research.h:42
Definition tile.h:50
struct tile * tile
Definition unit.h:142
const struct unit_type * utype
Definition unit.h:141
enum universals_n kind
Definition fc_types.h:880
universals_u value
Definition fc_types.h:879
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
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:300
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:309
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:186
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:612
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:591
const char * terrain_class_name_translation(enum terrain_class tclass)
Definition terrain.c:661
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:238
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:156
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Definition terrain.c:673
bool is_terrain_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:327
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:582
bool is_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:458
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:147
bool is_terrain_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:438
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:348
#define T_UNKNOWN
Definition terrain.h:62
#define terrain_has_flag(terr, flag)
Definition terrain.h:176
bool tile_has_extra_flag(const struct tile *ptile, enum extra_flag_id flag)
Definition tile.c:886
bool tile_has_native_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:324
bool tile_has_road_flag(const struct tile *ptile, enum road_flag_id flag)
Definition tile.c:868
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_terrain(_tile)
Definition tile.h:111
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
#define tile_owner(_tile)
Definition tile.h:97
bool goods_can_be_provided(const struct city *pcity, const struct goods_type *pgood, const struct unit *punit)
Goods_type_id goods_number(const struct goods_type *pgood)
bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
const char * goods_name_translation(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
#define trade_partners_iterate_end
#define trade_partners_iterate(c, p)
const struct unit_type * utype
Definition fc_types.h:698
struct nation_style * style
Definition fc_types.h:702
enum ai_level ai_level
Definition fc_types.h:706
struct specialist * specialist
Definition fc_types.h:695
enum impr_genus_id impr_genus
Definition fc_types.h:728
enum citytile_type citytile
Definition fc_types.h:707
struct nation_group * nationgroup
Definition fc_types.h:701
struct extra_type * extra
Definition fc_types.h:699
enum wrap_flag wrap_property
Definition fc_types.h:742
enum plrstate_type plrstate
Definition fc_types.h:709
struct nation_type * nation
Definition fc_types.h:692
int terrainclass
Definition fc_types.h:716
int unitclassflag
Definition fc_types.h:718
struct government * govern
Definition fc_types.h:690
struct nation_type * origowner
Definition fc_types.h:694
enum impr_flag_id impr_flag
Definition fc_types.h:729
int max_tile_units
Definition fc_types.h:732
int terrainalter
Definition fc_types.h:717
enum citystatus_type citystatus
Definition fc_types.h:708
int minforeignpct
Definition fc_types.h:712
const struct impr_type * building
Definition fc_types.h:691
struct achievement * achievement
Definition fc_types.h:700
ssetv ssetval
Definition fc_types.h:743
struct advance * advance
Definition fc_types.h:688
enum unit_activity activity
Definition fc_types.h:727
struct goods_type * good
Definition fc_types.h:704
struct terrain * terrain
Definition fc_types.h:696
int terrainflag
Definition fc_types.h:720
enum ustate_prop unit_state
Definition fc_types.h:726
Output_type_id outputtype
Definition fc_types.h:715
enum topo_flag topo_property
Definition fc_types.h:741
struct counter * counter
Definition fc_types.h:689
int min_hit_points
Definition fc_types.h:734
struct unit_class * uclass
Definition fc_types.h:697
struct nation_type * nationality
Definition fc_types.h:693
struct action * action
Definition fc_types.h:703
enum plr_flag_id plr_flag
Definition fc_types.h:730
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1821
#define unit_tile(_pu)
Definition unit.h:397
#define unit_owner(_pu)
Definition unit.h:396
#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:1632
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
bool unit_has_class_flag(const struct unit *punit, enum unit_class_flag_id flag)
Definition unittype.c:1649
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1767
bool uclass_flag_is_in_use(enum unit_class_flag_id ucflag)
Definition unittype.c:2967
struct unit_class * uclass_by_number(const Unit_Class_id id)
Definition unittype.c:2476
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1578
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2498
struct unit_type * utype_by_number(const Unit_type_id id)
Definition unittype.c:112
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:190
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1641
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:100
struct unit_class * unit_class_by_rule_name(const char *s)
Definition unittype.c:1784
bool utype_flag_is_in_use(enum unit_type_flag_id uflag)
Definition unittype.c:2986
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1438
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2467
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
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