Freeciv-3.2
Loading...
Searching...
No Matches
requirements.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2004 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17#include <stdarg.h>
18
19/* utility */
20#include "astring.h"
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "achievements.h"
27#include "calendar.h"
28#include "citizens.h"
29#include "counters.h"
30#include "culture.h"
31#include "game.h"
32#include "government.h"
33#include "improvement.h"
34#include "movement.h"
35#include "nation.h"
36#include "player.h"
37#include "map.h"
38#include "research.h"
39#include "road.h"
40#include "server_settings.h"
41#include "specialist.h"
42#include "style.h"
43#include "victory.h" /* victory_enabled() */
44
45#include "requirements.h"
46
51
52/* get 'struct thr_req_data_list' and related functions: */
53#define SPECLIST_TAG thr_req_data
54#define SPECLIST_TYPE struct thr_req_data
55#include "speclist.h"
56
57#define thr_req_data_list_iterate(trlist, ptrdata) \
58 TYPED_LIST_ITERATE(struct thr_req_data, trlist, ptrdata)
59#define thr_req_data_list_iterate_end LIST_ITERATE_END
60
63
64/************************************************************************
65 Container for req_item_found functions
66************************************************************************/
67typedef enum req_item_found (*universal_found)(const struct requirement *,
68 const struct universal *);
70
71static
73 const struct req_context *context,
74 const struct player *other_player,
75 const struct requirement *req);
76
77/* Function pointer for requirement-type-specific is_req_active handlers */
78typedef enum fc_tristate
79(*is_req_active_cb)(const struct civ_map *nmap,
80 const struct req_context *context,
81 const struct player *other_player,
82 const struct requirement *req);
83
84static inline bool are_tiles_in_range(const struct tile *tile1,
85 const struct tile *tile2,
86 enum req_range range);
87
88/**********************************************************************/
93static enum req_unchanging_status
95 enum req_unchanging_status def,
96 const struct req_context *context,
97 const struct requirement *req)
98{
99 return req->range == REQ_RANGE_LOCAL ? REQUCH_YES : def;
100}
101#define REQUC_LOCAL unchanging_local
102
103/**********************************************************************/
106static enum req_unchanging_status
108 enum req_unchanging_status def,
109 const struct req_context *context,
110 const struct requirement *req)
111{
112 if (TRI_YES != tri_req_present(nmap, context, NULL, req)) {
113 return REQUCH_NO;
114 }
115 return def;
116}
117#define REQUC_PRESENT unchanging_present
118
119/**********************************************************************/
122static enum req_unchanging_status
124 enum req_unchanging_status def,
125 const struct req_context *context,
126 const struct requirement *req)
127{
128 return
130 context, req);
131}
132#define REQUC_WORLD unchanging_world
133
134/**********************************************************************/
138static enum req_unchanging_status
140 enum req_unchanging_status def,
141 const struct req_context *context,
142 const struct requirement *req)
143{
144 if (REQ_RANGE_ALLIANCE == req->range
145 || REQ_RANGE_TEAM == req->range) {
146 struct requirement preq;
147
148 req_copy(&preq, req);
149 preq.range = REQ_RANGE_PLAYER;
151 return REQ_RANGE_TEAM == req->range ? REQUCH_ACT : REQUCH_NO;
152 }
153 }
154 return def;
155}
156#define REQUC_NALLY unchanging_noally
157
158/**********************************************************************/
161static enum req_unchanging_status
163 enum req_unchanging_status def,
164 const struct req_context *context,
165 const struct requirement *req)
166{
170 && NULL != context->city && NULL != context->tile
171 && NULL != city_tile(context->city)
173 req->range))){
174 /* Cities don't move, and most reqs are present on city center */
175 return REQUCH_YES;
176 }
177 return def;
178}
179#define REQUC_CITYTILE unchanging_citytile
180
181/**********************************************************************/
184static enum req_unchanging_status
186 enum req_unchanging_status def,
187 const struct req_context *context,
188 const struct requirement *req)
189{
191
192 if (REQ_RANGE_CITY == req->range
195 return REQUCH_CTRL;
196 }
197
198 return def;
199}
200#define REQUC_CITYSTATUS unchanging_citystatus
201
202/**********************************************************************/
207static enum req_unchanging_status
209 enum req_unchanging_status def,
210 const struct req_context *context,
211 const struct requirement *req)
212{
213 const struct impr_type *b = req->source.value.building;
214
216 || VUT_SITE == req->source.kind, REQUCH_NO);
217 if (REQ_RANGE_LOCAL == req->range) {
218 /* Likely, won't be questioned for an obsolete building */
219 return REQUCH_YES;
220 }
221
222 if (req->source.kind == VUT_IMPROVEMENT
223 && improvement_obsolete(context->player, b, context->city)) {
224 /* FIXME: sometimes can unobsolete, but considering it
225 * may sometimes put the function on endless recursion */
226 return REQUCH_ACT; /* Mostly about techs */
227 }
228 if (is_great_wonder(b)) {
231 && (req->range <= REQ_RANGE_CITY && TRI_YES
232 == tri_req_present(nmap, context, NULL, req)))) {
233 /* If the wonder stays somewhere, it may either remain there
234 * or be destroyed. If it is destroyed, it is nowhere. */
235 return REQUCH_SCRIPTS;
236 }
237 }
238 return def;
239}
240#define REQUC_IMPR unchanging_building
241
247
248/**********************************************************************/
251static void thr_exit_cb(void)
252{
254
257 if (fc_threads_equal(self, data->thr_id)) {
259 free(data);
260 break;
261 }
264}
265
266/**********************************************************************/
275
276/**********************************************************************/
284
285/**********************************************************************/
293 const char *value)
294{
295 struct universal source;
296
298 if (!universals_n_is_valid(source.kind)) {
299 return source;
300 }
301
303
304 return source;
305}
306
307/**********************************************************************/
312{
313 return unit_activity_is_valid(act)
314 && act != ACTIVITY_SENTRY
315 && act != ACTIVITY_GOTO
316 && act != ACTIVITY_EXPLORE;
317}
318
319/**********************************************************************/
324{
325 if (univ->kind == VUT_ACTIVITY) {
327 }
328
329 return TRUE;
330}
331
332/**********************************************************************/
337{
338 /* Finally scan the value string based on the type of the source. */
339 switch (source->kind) {
340 case VUT_NONE:
341 return;
342 case VUT_ADVANCE:
343 source->value.advance = advance_by_rule_name(value);
344 if (source->value.advance != NULL) {
345 return;
346 }
347 break;
348 case VUT_TECHFLAG:
349 source->value.techflag
351 if (tech_flag_id_is_valid(source->value.techflag)) {
352 return;
353 }
354 break;
355 case VUT_GOVERNMENT:
356 source->value.govern = government_by_rule_name(value);
357 if (source->value.govern != NULL) {
358 return;
359 }
360 break;
361 case VUT_ACHIEVEMENT:
362 source->value.achievement = achievement_by_rule_name(value);
363 if (source->value.achievement != NULL) {
364 return;
365 }
366 break;
367 case VUT_STYLE:
368 source->value.style = style_by_rule_name(value);
369 if (source->value.style != NULL) {
370 return;
371 }
372 break;
373 case VUT_IMPROVEMENT:
374 case VUT_SITE:
375 source->value.building = improvement_by_rule_name(value);
376 if (source->value.building != NULL) {
377 return;
378 }
379 break;
380 case VUT_IMPR_GENUS:
381 source->value.impr_genus = impr_genus_id_by_name(value, fc_strcasecmp);
382 if (impr_genus_id_is_valid(source->value.impr_genus)) {
383 return;
384 }
385 break;
386 case VUT_IMPR_FLAG:
387 source->value.impr_flag = impr_flag_id_by_name(value, fc_strcasecmp);
388 if (impr_flag_id_is_valid(source->value.impr_flag)) {
389 return;
390 }
391 break;
392 case VUT_PLAYER_FLAG:
393 source->value.plr_flag = plr_flag_id_by_name(value, fc_strcasecmp);
394 if (plr_flag_id_is_valid(source->value.plr_flag)) {
395 return;
396 }
397 break;
398 case VUT_EXTRA:
399 source->value.extra = extra_type_by_rule_name(value);
400 if (source->value.extra != NULL) {
401 return;
402 }
403 break;
404 case VUT_GOOD:
405 source->value.good = goods_by_rule_name(value);
406 if (source->value.good != NULL) {
407 return;
408 }
409 break;
410 case VUT_TERRAIN:
411 source->value.terrain = terrain_by_rule_name(value);
412 if (source->value.terrain != T_UNKNOWN) {
413 return;
414 }
415 break;
416 case VUT_TERRFLAG:
417 source->value.terrainflag
419 if (terrain_flag_id_is_valid(source->value.terrainflag)) {
420 return;
421 }
422 break;
423 case VUT_NATION:
424 source->value.nation = nation_by_rule_name(value);
425 if (source->value.nation != NO_NATION_SELECTED) {
426 return;
427 }
428 break;
429 case VUT_NATIONGROUP:
430 source->value.nationgroup = nation_group_by_rule_name(value);
431 if (source->value.nationgroup != NULL) {
432 return;
433 }
434 break;
435 case VUT_NATIONALITY:
436 source->value.nationality = nation_by_rule_name(value);
437 if (source->value.nationality != NO_NATION_SELECTED) {
438 return;
439 }
440 break;
442 source->value.origowner = nation_by_rule_name(value);
443 if (source->value.origowner != NO_NATION_SELECTED) {
444 return;
445 }
446 break;
447 case VUT_DIPLREL:
448 case VUT_DIPLREL_TILE:
452 source->value.diplrel = diplrel_by_rule_name(value);
453 if (source->value.diplrel != diplrel_other_invalid()) {
454 return;
455 }
456 break;
457 case VUT_UTYPE:
458 source->value.utype = unit_type_by_rule_name(value);
459 if (source->value.utype) {
460 return;
461 }
462 break;
463 case VUT_UTFLAG:
465 if (unit_type_flag_id_is_valid(source->value.unitflag)) {
466 return;
467 }
468 break;
469 case VUT_UCLASS:
470 source->value.uclass = unit_class_by_rule_name(value);
471 if (source->value.uclass) {
472 return;
473 }
474 break;
475 case VUT_UCFLAG:
476 source->value.unitclassflag
478 if (unit_class_flag_id_is_valid(source->value.unitclassflag)) {
479 return;
480 }
481 break;
482 case VUT_MINVETERAN:
483 source->value.minveteran = atoi(value);
484 if (source->value.minveteran > 0) {
485 return;
486 }
487 break;
488 case VUT_UNITSTATE:
489 source->value.unit_state = ustate_prop_by_name(value, fc_strcasecmp);
490 if (ustate_prop_is_valid(source->value.unit_state)) {
491 return;
492 }
493 break;
494 case VUT_ACTIVITY:
496 if (activity_is_valid_in_requirement(source->value.activity)) {
497 return;
498 }
499 break;
500 case VUT_MINMOVES:
501 source->value.minmoves = atoi(value);
502 if (source->value.minmoves > 0) {
503 return;
504 }
505 break;
506 case VUT_MINHP:
507 source->value.min_hit_points = atoi(value);
508 if (source->value.min_hit_points > 0) {
509 return;
510 }
511 break;
512 case VUT_AGE:
513 source->value.age = atoi(value);
514 if (source->value.age > 0) {
515 return;
516 }
517 break;
518 case VUT_FORM_AGE:
519 source->value.form_age = atoi(value);
520 if (source->value.form_age > 0) {
521 return;
522 }
523 break;
524 case VUT_MINTECHS:
525 source->value.min_techs = atoi(value);
526 if (source->value.min_techs > 0) {
527 return;
528 }
529 break;
530 case VUT_ACTION:
531 source->value.action = action_by_rule_name(value);
532 if (source->value.action != NULL) {
533 return;
534 }
535 break;
536 case VUT_OTYPE:
537 source->value.outputtype = output_type_by_identifier(value);
538 if (source->value.outputtype != O_LAST) {
539 return;
540 }
541 break;
542 case VUT_SPECIALIST:
543 source->value.specialist = specialist_by_rule_name(value);
544 if (source->value.specialist) {
545 return;
546 }
547 break;
548 case VUT_MINSIZE:
549 source->value.minsize = atoi(value);
550 if (source->value.minsize > 0) {
551 return;
552 }
553 break;
554 case VUT_MINCULTURE:
555 source->value.minculture = atoi(value);
556 if (source->value.minculture > 0) {
557 return;
558 }
559 break;
561 source->value.minforeignpct = atoi(value);
562 if (source->value.minforeignpct > 0) {
563 return;
564 }
565 break;
566 case VUT_AI_LEVEL:
567 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
568 if (ai_level_is_valid(source->value.ai_level)) {
569 return;
570 }
571 break;
572 case VUT_MAXTILEUNITS:
573 source->value.max_tile_units = atoi(value);
574 if (0 <= source->value.max_tile_units) {
575 return;
576 }
577 break;
578 case VUT_TERRAINCLASS:
579 source->value.terrainclass
581 if (terrain_class_is_valid(source->value.terrainclass)) {
582 return;
583 }
584 break;
585 case VUT_ROADFLAG:
587 if (road_flag_id_is_valid(source->value.roadflag)) {
588 return;
589 }
590 break;
591 case VUT_EXTRAFLAG:
592 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
593 if (extra_flag_id_is_valid(source->value.extraflag)) {
594 return;
595 }
596 break;
597 case VUT_MINYEAR:
598 source->value.minyear = atoi(value);
599 return;
600 case VUT_MINCALFRAG:
601 /* Rule names are 0-based numbers, not pretty names from ruleset */
602 source->value.mincalfrag = atoi(value);
603 if (source->value.mincalfrag >= 0) {
604 /* More range checking done later, in sanity_check_req_individual() */
605 return;
606 }
607 break;
608 case VUT_TOPO:
609 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
610 if (topo_flag_is_valid(source->value.topo_property)) {
611 return;
612 }
613 break;
614 case VUT_WRAP:
615 source->value.wrap_property = wrap_flag_by_name(value, fc_strcasecmp);
616 if (wrap_flag_is_valid(source->value.wrap_property)) {
617 return;
618 }
619 break;
621 source->value.ssetval = ssetv_by_rule_name(value);
622 if (source->value.ssetval != SSETV_NONE) {
623 return;
624 }
625 break;
626 case VUT_TERRAINALTER:
627 source->value.terrainalter
629 if (terrain_alteration_is_valid(source->value.terrainalter)) {
630 return;
631 }
632 break;
633 case VUT_CITYTILE:
635 if (source->value.citytile != CITYT_LAST) {
636 return;
637 }
638 break;
639 case VUT_CITYSTATUS:
641 if (source->value.citystatus != CITYS_LAST) {
642 return;
643 }
644 break;
645 case VUT_PLAYER_STATE:
647 if (source->value.plrstate != PLRS_LAST) {
648 return;
649 }
650 break;
651 case VUT_MINLATITUDE:
652 case VUT_MAXLATITUDE:
653 source->value.latitude = atoi(value);
654 if (source->value.latitude >= -MAP_MAX_LATITUDE
655 && source->value.latitude <= MAP_MAX_LATITUDE) {
656 return;
657 }
658 break;
659 case VUT_COUNTER:
660 source->value.counter = counter_by_rule_name(value);
661 if (source->value.counter != NULL) {
662 return;
663 }
664 break;
665 case VUT_COUNT:
666 break;
667 }
668
669 /* If we reach here there's been an error. */
671}
672
673/**********************************************************************/
680{
681 struct universal source;
682
683 source.kind = kind;
684
685 switch (source.kind) {
686 case VUT_NONE:
687 /* Avoid compiler warning about uninitialized source.value */
688 source.value.advance = NULL;
689
690 return source;
691 case VUT_ADVANCE:
692 source.value.advance = advance_by_number(value);
693 if (source.value.advance != NULL) {
694 return source;
695 }
696 break;
697 case VUT_TECHFLAG:
698 source.value.techflag = value;
699 return source;
700 case VUT_GOVERNMENT:
702 if (source.value.govern != NULL) {
703 return source;
704 }
705 break;
706 case VUT_ACHIEVEMENT:
707 source.value.achievement = achievement_by_number(value);
708 if (source.value.achievement != NULL) {
709 return source;
710 }
711 break;
712 case VUT_STYLE:
713 source.value.style = style_by_number(value);
714 if (source.value.style != NULL) {
715 return source;
716 }
717 break;
718 case VUT_IMPROVEMENT:
719 case VUT_SITE:
720 source.value.building = improvement_by_number(value);
721 if (source.value.building != NULL) {
722 return source;
723 }
724 break;
725 case VUT_IMPR_GENUS:
726 source.value.impr_genus = value;
727 return source;
728 case VUT_IMPR_FLAG:
729 source.value.impr_flag = value;
730 return source;
731 case VUT_PLAYER_FLAG:
732 source.value.plr_flag = value;
733 return source;
734 case VUT_EXTRA:
736 return source;
737 case VUT_GOOD:
738 source.value.good = goods_by_number(value);
739 return source;
740 case VUT_TERRAIN:
741 source.value.terrain = terrain_by_number(value);
742 if (source.value.terrain != NULL) {
743 return source;
744 }
745 break;
746 case VUT_TERRFLAG:
747 source.value.terrainflag = value;
748 return source;
749 case VUT_NATION:
751 if (source.value.nation != NULL) {
752 return source;
753 }
754 break;
755 case VUT_NATIONGROUP:
756 source.value.nationgroup = nation_group_by_number(value);
757 if (source.value.nationgroup != NULL) {
758 return source;
759 }
760 break;
761 case VUT_DIPLREL:
762 case VUT_DIPLREL_TILE:
766 source.value.diplrel = value;
767 if (source.value.diplrel != diplrel_other_invalid()) {
768 return source;
769 }
770 break;
771 case VUT_NATIONALITY:
773 if (source.value.nationality != NULL) {
774 return source;
775 }
776 break;
778 source.value.origowner = nation_by_number(value);
779 if (source.value.origowner != NULL) {
780 return source;
781 }
782 break;
783 case VUT_UTYPE:
784 source.value.utype = utype_by_number(value);
785 if (source.value.utype != NULL) {
786 return source;
787 }
788 break;
789 case VUT_UTFLAG:
790 source.value.unitflag = value;
791 return source;
792 case VUT_UCLASS:
794 if (source.value.uclass != NULL) {
795 return source;
796 }
797 break;
798 case VUT_UCFLAG:
799 source.value.unitclassflag = value;
800 return source;
801 case VUT_MINVETERAN:
802 source.value.minveteran = value;
803 return source;
804 case VUT_UNITSTATE:
805 source.value.unit_state = value;
806 return source;
807 case VUT_ACTIVITY:
808 source.value.activity = value;
809 return source;
810 case VUT_MINMOVES:
811 source.value.minmoves = value;
812 return source;
813 case VUT_MINHP:
815 return source;
816 case VUT_AGE:
817 source.value.age = value;
818 return source;
819 case VUT_FORM_AGE:
820 source.value.form_age = value;
821 return source;
822 case VUT_MINTECHS:
823 source.value.min_techs = value;
824 return source;
825 case VUT_ACTION:
827 if (source.value.action != NULL) {
828 return source;
829 }
830 break;
831 case VUT_OTYPE:
832 source.value.outputtype = value;
833 return source;
834 case VUT_SPECIALIST:
836 return source;
837 case VUT_MINSIZE:
838 source.value.minsize = value;
839 return source;
840 case VUT_MINCULTURE:
841 source.value.minculture = value;
842 return source;
844 source.value.minforeignpct = value;
845 return source;
846 case VUT_AI_LEVEL:
847 source.value.ai_level = value;
848 return source;
849 case VUT_MAXTILEUNITS:
851 return source;
852 case VUT_TERRAINCLASS:
853 source.value.terrainclass = value;
854 return source;
855 case VUT_ROADFLAG:
856 source.value.roadflag = value;
857 return source;
858 case VUT_EXTRAFLAG:
859 source.value.extraflag = value;
860 return source;
861 case VUT_MINYEAR:
862 source.value.minyear = value;
863 return source;
864 case VUT_MINCALFRAG:
865 source.value.mincalfrag = value;
866 return source;
867 case VUT_TOPO:
868 source.value.topo_property = value;
869 return source;
870 case VUT_WRAP:
871 source.value.wrap_property = value;
872 return source;
874 source.value.ssetval = value;
875 return source;
876 case VUT_TERRAINALTER:
877 source.value.terrainalter = value;
878 return source;
879 case VUT_CITYTILE:
880 source.value.citytile = value;
881 return source;
882 case VUT_CITYSTATUS:
883 source.value.citystatus = value;
884 return source;
885 case VUT_PLAYER_STATE:
886 source.value.plrstate = value;
887 return source;
888 case VUT_COUNTER:
890 return source;
891 case VUT_MINLATITUDE:
892 case VUT_MAXLATITUDE:
893 source.value.latitude = value;
894 return source;
895 case VUT_COUNT:
896 break;
897 }
898
899 /* If we reach here there's been an error. */
901 /* Avoid compiler warning about uninitialized source.value */
902 source.value.advance = NULL;
903
904 return source;
905}
906
907/**********************************************************************/
910void universal_copy(struct universal *dst, const struct universal *src)
911{
912 dst->value = src->value;
913 dst->kind = src->kind;
914}
915
916/**********************************************************************/
921 int *kind, int *value)
922{
923 *kind = source->kind;
925}
926
927/**********************************************************************/
931{
932 switch (source->kind) {
933 case VUT_NONE:
934 return 0;
935 case VUT_ADVANCE:
936 return advance_number(source->value.advance);
937 case VUT_TECHFLAG:
938 return source->value.techflag;
939 case VUT_GOVERNMENT:
940 return government_number(source->value.govern);
941 case VUT_ACHIEVEMENT:
942 return achievement_number(source->value.achievement);
943 case VUT_STYLE:
944 return style_number(source->value.style);
945 case VUT_IMPROVEMENT:
946 case VUT_SITE:
947 return improvement_number(source->value.building);
948 case VUT_IMPR_GENUS:
949 return source->value.impr_genus;
950 case VUT_IMPR_FLAG:
951 return source->value.impr_flag;
952 case VUT_PLAYER_FLAG:
953 return source->value.plr_flag;
954 case VUT_EXTRA:
955 return extra_number(source->value.extra);
956 case VUT_GOOD:
957 return goods_number(source->value.good);
958 case VUT_TERRAIN:
959 return terrain_number(source->value.terrain);
960 case VUT_TERRFLAG:
961 return source->value.terrainflag;
962 case VUT_NATION:
963 return nation_number(source->value.nation);
964 case VUT_NATIONGROUP:
965 return nation_group_number(source->value.nationgroup);
966 case VUT_NATIONALITY:
967 return nation_number(source->value.nationality);
969 return nation_number(source->value.origowner);
970 case VUT_DIPLREL:
971 case VUT_DIPLREL_TILE:
975 return source->value.diplrel;
976 case VUT_UTYPE:
977 return utype_number(source->value.utype);
978 case VUT_UTFLAG:
979 return source->value.unitflag;
980 case VUT_UCLASS:
981 return uclass_number(source->value.uclass);
982 case VUT_UCFLAG:
983 return source->value.unitclassflag;
984 case VUT_MINVETERAN:
985 return source->value.minveteran;
986 case VUT_UNITSTATE:
987 return source->value.unit_state;
988 case VUT_ACTIVITY:
989 return source->value.activity;
990 case VUT_MINMOVES:
991 return source->value.minmoves;
992 case VUT_MINHP:
993 return source->value.min_hit_points;
994 case VUT_AGE:
995 return source->value.age;
996 case VUT_FORM_AGE:
997 return source->value.form_age;
998 case VUT_MINTECHS:
999 return source->value.min_techs;
1000 case VUT_ACTION:
1001 return action_number(source->value.action);
1002 case VUT_OTYPE:
1003 return source->value.outputtype;
1004 case VUT_SPECIALIST:
1005 return specialist_number(source->value.specialist);
1006 case VUT_MINSIZE:
1007 return source->value.minsize;
1008 case VUT_MINCULTURE:
1009 return source->value.minculture;
1010 case VUT_MINFOREIGNPCT:
1011 return source->value.minforeignpct;
1012 case VUT_AI_LEVEL:
1013 return source->value.ai_level;
1014 case VUT_MAXTILEUNITS:
1015 return source->value.max_tile_units;
1016 case VUT_TERRAINCLASS:
1017 return source->value.terrainclass;
1018 case VUT_ROADFLAG:
1019 return source->value.roadflag;
1020 case VUT_EXTRAFLAG:
1021 return source->value.extraflag;
1022 case VUT_MINYEAR:
1023 return source->value.minyear;
1024 case VUT_MINCALFRAG:
1025 return source->value.mincalfrag;
1026 case VUT_TOPO:
1027 return source->value.topo_property;
1028 case VUT_WRAP:
1029 return source->value.wrap_property;
1030 case VUT_SERVERSETTING:
1031 return source->value.ssetval;
1032 case VUT_TERRAINALTER:
1033 return source->value.terrainalter;
1034 case VUT_CITYTILE:
1035 return source->value.citytile;
1036 case VUT_CITYSTATUS:
1037 return source->value.citystatus;
1038 case VUT_PLAYER_STATE:
1039 return source->value.plrstate;
1040 case VUT_COUNTER:
1041 return counter_id(source->value.counter);
1042 case VUT_MINLATITUDE:
1043 case VUT_MAXLATITUDE:
1044 return source->value.latitude;
1045 case VUT_COUNT:
1046 break;
1047 }
1048
1049 /* If we reach here there's been an error. */
1050 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
1051 source->kind);
1052 return 0;
1053}
1054
1055
1056/**********************************************************************/
1060{
1061 static const struct req_context empty = {};
1062 return &empty;
1063}
1064
1065
1066/**********************************************************************/
1074const char *req_to_fstring(const struct requirement *req,
1075 struct astring *astr)
1076{
1077 astr_init(astr);
1078
1079 astr_set(astr, "%s%s %s %s%s",
1080 req->survives ? "surviving " : "",
1081 req_range_name(req->range),
1083 req->present ? "" : "!",
1085
1086 return astr_str(astr);
1087}
1088
1089/**********************************************************************/
1097 bool survives, bool present, bool quiet,
1098 const char *value)
1099{
1100 struct requirement req;
1101 bool invalid;
1102 const char *error = NULL;
1103
1104 req.source = universal_by_rule_name(type, value);
1105
1107 if (invalid) {
1108 error = "bad type or name";
1109 } else {
1110 /* Scan the range string to find the range. If no range is given a
1111 * default fallback is used rather than giving an error. */
1112 if (range != NULL) {
1114 if (!req_range_is_valid(req.range)) {
1115 invalid = TRUE;
1116 }
1117 } else {
1118 switch (req.source.kind) {
1119 case VUT_NONE:
1120 case VUT_COUNT:
1121 break;
1122 case VUT_IMPROVEMENT:
1123 case VUT_SITE:
1124 case VUT_IMPR_GENUS:
1125 case VUT_IMPR_FLAG:
1126 case VUT_UTYPE:
1127 case VUT_UTFLAG:
1128 case VUT_UCLASS:
1129 case VUT_UCFLAG:
1130 case VUT_MINVETERAN:
1131 case VUT_UNITSTATE:
1132 case VUT_ACTIVITY:
1133 case VUT_MINMOVES:
1134 case VUT_MINHP:
1135 case VUT_AGE:
1136 case VUT_FORM_AGE:
1137 case VUT_ACTION:
1138 case VUT_OTYPE:
1139 case VUT_SPECIALIST:
1140 case VUT_DIPLREL_TILE_O:
1142 req.range = REQ_RANGE_LOCAL;
1143 break;
1144 case VUT_EXTRA:
1145 case VUT_ROADFLAG:
1146 case VUT_EXTRAFLAG:
1147 /* keep old behavior */
1148 req.range = REQ_RANGE_TILE;
1149 break;
1150 case VUT_TERRAIN:
1151 case VUT_TERRFLAG:
1152 case VUT_TERRAINCLASS:
1153 case VUT_TERRAINALTER:
1154 case VUT_CITYTILE:
1155 case VUT_MAXTILEUNITS:
1156 case VUT_MINLATITUDE:
1157 case VUT_MAXLATITUDE:
1158 req.range = REQ_RANGE_TILE;
1159 break;
1160 case VUT_COUNTER:
1161 case VUT_MINSIZE:
1162 case VUT_MINCULTURE:
1163 case VUT_MINFOREIGNPCT:
1164 case VUT_NATIONALITY:
1165 case VUT_ORIGINAL_OWNER:
1166 case VUT_CITYSTATUS:
1167 case VUT_GOOD:
1168 req.range = REQ_RANGE_CITY;
1169 break;
1170 case VUT_GOVERNMENT:
1171 case VUT_ACHIEVEMENT:
1172 case VUT_STYLE:
1173 case VUT_ADVANCE:
1174 case VUT_TECHFLAG:
1175 case VUT_NATION:
1176 case VUT_NATIONGROUP:
1177 case VUT_DIPLREL:
1178 case VUT_DIPLREL_TILE:
1180 case VUT_AI_LEVEL:
1181 case VUT_PLAYER_FLAG:
1182 case VUT_PLAYER_STATE:
1183 req.range = REQ_RANGE_PLAYER;
1184 break;
1185 case VUT_MINYEAR:
1186 case VUT_MINCALFRAG:
1187 case VUT_TOPO:
1188 case VUT_WRAP:
1189 case VUT_MINTECHS:
1190 case VUT_SERVERSETTING:
1191 req.range = REQ_RANGE_WORLD;
1192 break;
1193 }
1194 }
1195
1196 req.survives = survives;
1197 req.present = present;
1198 req.quiet = quiet;
1199
1200 /* These checks match what combinations are supported inside
1201 * is_req_active(). However, it's only possible to do basic checks,
1202 * not anything that might depend on the rest of the ruleset which
1203 * might not have been loaded yet. */
1204 switch (req.source.kind) {
1205 case VUT_TERRAIN:
1206 case VUT_TERRAINCLASS:
1207 case VUT_TERRFLAG:
1208 invalid = (req.range != REQ_RANGE_TILE
1209 && req.range != REQ_RANGE_CADJACENT
1210 && req.range != REQ_RANGE_ADJACENT
1211 && req.range != REQ_RANGE_CITY
1212 && req.range != REQ_RANGE_TRADE_ROUTE);
1213 break;
1214 case VUT_EXTRA:
1215 case VUT_ROADFLAG:
1216 case VUT_EXTRAFLAG:
1218 break;
1219 case VUT_ADVANCE:
1220 case VUT_TECHFLAG:
1221 case VUT_ACHIEVEMENT:
1222 case VUT_MINTECHS:
1223 invalid = (req.range < REQ_RANGE_PLAYER);
1224 break;
1225 case VUT_GOVERNMENT:
1226 case VUT_AI_LEVEL:
1227 case VUT_STYLE:
1228 invalid = (req.range != REQ_RANGE_PLAYER);
1229 break;
1230 case VUT_MINSIZE:
1231 case VUT_MINFOREIGNPCT:
1232 case VUT_NATIONALITY:
1233 case VUT_CITYSTATUS:
1234 invalid = (req.range != REQ_RANGE_CITY
1235 && req.range != REQ_RANGE_TRADE_ROUTE);
1236 break;
1237 case VUT_GOOD:
1238 case VUT_ORIGINAL_OWNER:
1239 invalid = (req.range != REQ_RANGE_CITY);
1240 break;
1241 case VUT_MINCULTURE:
1242 invalid = (req.range != REQ_RANGE_CITY
1244 && req.range != REQ_RANGE_PLAYER
1245 && req.range != REQ_RANGE_TEAM
1246 && req.range != REQ_RANGE_ALLIANCE
1247 && req.range != REQ_RANGE_WORLD);
1248 break;
1249 case VUT_DIPLREL:
1250 invalid = (req.range != REQ_RANGE_LOCAL
1251 && req.range != REQ_RANGE_PLAYER
1252 && req.range != REQ_RANGE_TEAM
1253 && req.range != REQ_RANGE_ALLIANCE
1254 && req.range != REQ_RANGE_WORLD)
1255 /* Non local foreign makes no sense. */
1256 || (req.source.value.diplrel == DRO_FOREIGN
1257 && req.range != REQ_RANGE_LOCAL);
1258 break;
1259 case VUT_DIPLREL_TILE:
1260 invalid = (req.range != REQ_RANGE_LOCAL
1261 && req.range != REQ_RANGE_PLAYER
1262 && req.range != REQ_RANGE_TEAM
1263 && req.range != REQ_RANGE_ALLIANCE)
1264 /* Non local foreign makes no sense. */
1265 || (req.source.value.diplrel == DRO_FOREIGN
1266 && req.range != REQ_RANGE_LOCAL);
1267 break;
1268 case VUT_DIPLREL_TILE_O:
1269 invalid = (req.range != REQ_RANGE_LOCAL);
1270 break;
1272 invalid = (req.range != REQ_RANGE_LOCAL
1273 && req.range != REQ_RANGE_PLAYER
1274 && req.range != REQ_RANGE_TEAM
1275 && req.range != REQ_RANGE_ALLIANCE)
1276 /* Non local foreign makes no sense. */
1277 || (req.source.value.diplrel == DRO_FOREIGN
1278 && req.range != REQ_RANGE_LOCAL);
1279 break;
1281 invalid = (req.range != REQ_RANGE_LOCAL);
1282 break;
1283 case VUT_NATION:
1284 case VUT_NATIONGROUP:
1286 && req.range != REQ_RANGE_TEAM
1287 && req.range != REQ_RANGE_ALLIANCE
1288 && req.range != REQ_RANGE_WORLD);
1289 break;
1290 case VUT_UTYPE:
1291 case VUT_UTFLAG:
1292 case VUT_UCLASS:
1293 case VUT_UCFLAG:
1294 case VUT_MINVETERAN:
1295 case VUT_UNITSTATE:
1296 case VUT_ACTIVITY:
1297 case VUT_MINMOVES:
1298 case VUT_MINHP:
1299 case VUT_ACTION:
1300 case VUT_OTYPE:
1301 case VUT_SPECIALIST:
1302 invalid = (req.range != REQ_RANGE_LOCAL);
1303 break;
1304 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1305 invalid = (req.range != REQ_RANGE_TILE);
1306 break;
1307 case VUT_CITYTILE:
1308 case VUT_MAXTILEUNITS:
1309 invalid = (req.range != REQ_RANGE_TILE
1310 && req.range != REQ_RANGE_CADJACENT
1311 && req.range != REQ_RANGE_ADJACENT);
1312 break;
1313 case VUT_MINLATITUDE:
1314 case VUT_MAXLATITUDE:
1315 invalid = (req.range != REQ_RANGE_TILE
1316 && req.range != REQ_RANGE_CADJACENT
1317 && req.range != REQ_RANGE_ADJACENT
1318 && req.range != REQ_RANGE_WORLD)
1319 /* Avoid redundancy at tile range: no negated requirements
1320 * that could be emulated by a present requirement of the
1321 * other type */
1322 || (req.range == REQ_RANGE_TILE && !req.present);
1323 break;
1324 case VUT_MINYEAR:
1325 case VUT_MINCALFRAG:
1326 case VUT_TOPO:
1327 case VUT_WRAP:
1328 case VUT_SERVERSETTING:
1329 invalid = (req.range != REQ_RANGE_WORLD);
1330 break;
1331 case VUT_AGE:
1332 /* FIXME: could support TRADE_ROUTE, TEAM, etc */
1333 invalid = (req.range != REQ_RANGE_LOCAL
1334 && req.range != REQ_RANGE_CITY
1335 && req.range != REQ_RANGE_PLAYER);
1336 break;
1337 case VUT_FORM_AGE:
1338 invalid = (req.range != REQ_RANGE_LOCAL);
1339 break;
1340 case VUT_IMPR_GENUS:
1341 /* TODO: Support other ranges too. */
1342 invalid = (req.range != REQ_RANGE_LOCAL);
1343 break;
1344 case VUT_IMPR_FLAG:
1345 invalid = (req.range != REQ_RANGE_LOCAL
1346 && req.range != REQ_RANGE_TILE
1347 && req.range != REQ_RANGE_CITY);
1348 break;
1349 case VUT_COUNTER:
1350 invalid = req.range != REQ_RANGE_CITY;
1351 break;
1352 case VUT_PLAYER_FLAG:
1353 case VUT_PLAYER_STATE:
1354 invalid = (req.range != REQ_RANGE_PLAYER);
1355 break;
1356 case VUT_IMPROVEMENT:
1357 case VUT_SITE:
1358 /* Valid ranges depend on the building genus (wonder/improvement),
1359 * which might not have been loaded from the ruleset yet.
1360 * So we allow anything here, and do a proper check once ruleset
1361 * loading is complete, in sanity_check_req_individual(). */
1362 case VUT_NONE:
1363 invalid = FALSE;
1364 break;
1365 case VUT_COUNT:
1366 break;
1367 }
1368 if (invalid) {
1369 error = "bad range";
1370 }
1371 }
1372
1373 if (!invalid) {
1374 /* Check 'survives'. */
1375 switch (req.source.kind) {
1376 case VUT_IMPROVEMENT:
1377 case VUT_SITE:
1378 /* See buildings_in_range(). */
1380 break;
1381 case VUT_NATION:
1382 case VUT_ADVANCE:
1384 break;
1385 case VUT_COUNTER:
1386 case VUT_IMPR_GENUS:
1387 case VUT_IMPR_FLAG:
1388 case VUT_PLAYER_FLAG:
1389 case VUT_PLAYER_STATE:
1390 case VUT_GOVERNMENT:
1391 case VUT_TERRAIN:
1392 case VUT_UTYPE:
1393 case VUT_UTFLAG:
1394 case VUT_UCLASS:
1395 case VUT_UCFLAG:
1396 case VUT_MINVETERAN:
1397 case VUT_UNITSTATE:
1398 case VUT_ACTIVITY:
1399 case VUT_MINMOVES:
1400 case VUT_MINHP:
1401 case VUT_AGE:
1402 case VUT_FORM_AGE:
1403 case VUT_ACTION:
1404 case VUT_OTYPE:
1405 case VUT_SPECIALIST:
1406 case VUT_MINSIZE:
1407 case VUT_MINCULTURE:
1408 case VUT_MINFOREIGNPCT:
1409 case VUT_AI_LEVEL:
1410 case VUT_TERRAINCLASS:
1411 case VUT_MINYEAR:
1412 case VUT_MINCALFRAG:
1413 case VUT_TOPO:
1414 case VUT_WRAP:
1415 case VUT_SERVERSETTING:
1416 case VUT_TERRAINALTER:
1417 case VUT_CITYTILE:
1418 case VUT_CITYSTATUS:
1419 case VUT_TERRFLAG:
1420 case VUT_NATIONALITY:
1421 case VUT_ORIGINAL_OWNER:
1422 case VUT_ROADFLAG:
1423 case VUT_EXTRAFLAG:
1424 case VUT_EXTRA:
1425 case VUT_GOOD:
1426 case VUT_TECHFLAG:
1427 case VUT_ACHIEVEMENT:
1428 case VUT_NATIONGROUP:
1429 case VUT_STYLE:
1430 case VUT_DIPLREL:
1431 case VUT_DIPLREL_TILE:
1432 case VUT_DIPLREL_TILE_O:
1435 case VUT_MAXTILEUNITS:
1436 case VUT_MINTECHS:
1437 case VUT_MINLATITUDE:
1438 case VUT_MAXLATITUDE:
1439 /* Most requirements don't support 'survives'. */
1440 invalid = survives;
1441 break;
1442 case VUT_NONE:
1443 case VUT_COUNT:
1444 break;
1445 }
1446 if (invalid) {
1447 error = "bad 'survives'";
1448 }
1449 }
1450
1451 if (invalid) {
1452 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1453 type, range, survives ? "survives" : "",
1454 present ? "present" : "", value, error);
1456 }
1457
1458 return req;
1459}
1460
1461/**********************************************************************/
1467 int value)
1468{
1469 struct requirement req;
1470
1471 req.source = universal_by_number(type, value);
1472 req.range = range;
1473 req.survives = survives;
1474 req.present = present;
1475 req.quiet = quiet;
1476
1477 return req;
1478}
1479
1480/**********************************************************************/
1484void req_get_values(const struct requirement *req,
1485 int *type, int *range,
1486 bool *survives, bool *present, bool *quiet,
1487 int *value)
1488{
1489 universal_extraction(&req->source, type, value);
1490 *range = req->range;
1491 *survives = req->survives;
1492 *present = req->present;
1493 *quiet = req->quiet;
1494}
1495
1496/**********************************************************************/
1499void req_copy(struct requirement *dst, const struct requirement *src)
1500{
1501 universal_copy(&(dst->source), &(src->source));
1502 dst->range = src->range;
1503 dst->survives = src->survives;
1504 dst->present = src->present;
1505 dst->quiet = src->quiet;
1506}
1507
1508/**********************************************************************/
1512bool are_requirements_equal(const struct requirement *req1,
1513 const struct requirement *req2)
1514{
1515 return (are_universals_equal(&req1->source, &req2->source)
1516 && req1->range == req2->range
1517 && req1->survives == req2->survives
1518 && req1->present == req2->present);
1519}
1520
1521/**********************************************************************/
1524static bool are_requirements_opposites(const struct requirement *req1,
1525 const struct requirement *req2)
1526{
1527 return (are_universals_equal(&req1->source, &req2->source)
1528 && req1->range == req2->range
1529 && req1->survives == req2->survives
1530 && req1->present != req2->present);
1531}
1532
1533/**********************************************************************/
1537static bool impr_contra_genus(const struct requirement *impr_req,
1538 const struct requirement *genus_req)
1539{
1540 /* The input is sane. */
1542 || impr_req->source.kind == VUT_SITE, FALSE);
1544
1545 if (impr_req->range == REQ_RANGE_LOCAL
1546 && genus_req->range == REQ_RANGE_LOCAL) {
1547 /* Applies to the same target building. */
1548
1549 if (impr_req->present && !genus_req->present) {
1550 /* The target building can't not have the genus it has. */
1551 return (impr_req->source.value.building->genus
1552 == genus_req->source.value.impr_genus);
1553 }
1554
1555 if (impr_req->present && genus_req->present) {
1556 /* The target building can't have another genus than it has. */
1557 return (impr_req->source.value.building->genus
1558 != genus_req->source.value.impr_genus);
1559 }
1560 }
1561
1562 /* No special knowledge. */
1563 return FALSE;
1564}
1565
1566/**********************************************************************/
1570static bool impr_contra_flag(const struct requirement *impr_req,
1571 const struct requirement *flag_req)
1572{
1573 /* The input is sane. */
1575 || impr_req->source.kind == VUT_SITE, FALSE);
1577
1578 if (impr_req->range == REQ_RANGE_LOCAL
1579 && flag_req->range == REQ_RANGE_LOCAL) {
1580 /* Applies to the same target building. */
1581
1582 if (impr_req->present && !flag_req->present) {
1583 /* The target building can't not have the flag it has. */
1584 return improvement_has_flag(impr_req->source.value.building,
1585 flag_req->source.value.impr_flag);
1586 }
1587
1588 if (impr_req->present && flag_req->present) {
1589 /* The target building can't have another flag than it has. */
1590 return !improvement_has_flag(impr_req->source.value.building,
1591 flag_req->source.value.impr_flag);
1592 }
1593 }
1594
1595 /* No special knowledge. */
1596 return FALSE;
1597}
1598
1599/**********************************************************************/
1604 const struct requirement *group_req)
1605{
1606 /* The input is sane. */
1607 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1609
1610 if (nation_req->range == REQ_RANGE_PLAYER
1611 && group_req->range == REQ_RANGE_PLAYER) {
1612 /* Applies to the same target building. */
1613
1614 if (nation_req->present && !group_req->present) {
1615 /* The target nation can't be in the group. */
1616 return nation_is_in_group(nation_req->source.value.nation,
1617 group_req->source.value.nationgroup);
1618 }
1619 }
1620
1621 /* No special knowledge. */
1622 return FALSE;
1623}
1624
1625/**********************************************************************/
1629static bool city_center_contra(const struct requirement *cc_req,
1630 const struct requirement *ct_req)
1631{
1632 /* The input is sane. */
1633 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1634 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1635
1636 if (cc_req->source.value.citytile == CITYT_CENTER
1637 && cc_req->present && cc_req->range <= ct_req->range) {
1638 switch (ct_req->source.value.citytile) {
1639 case CITYT_CENTER:
1640 case CITYT_CLAIMED:
1641 case CITYT_EXTRAS_OWNED:
1642 case CITYT_WORKED:
1644 /* Should be always on city center */
1645 return !ct_req->present;
1647 /* Handled later */
1648 break;
1649 case CITYT_LAST:
1650 /* Error */
1651 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1652 }
1653 }
1654 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1655 || cc_req->source.value.citytile == CITYT_CENTER)
1656 && ct_req->source.value.citytile
1658 && REQ_RANGE_TILE == cc_req->range
1659 && REQ_RANGE_TILE == ct_req->range) {
1660 /* Can't coexist */
1661 return cc_req->present ? ct_req->present : !ct_req->present;
1662 }
1663
1664 return FALSE;
1665}
1666
1667/**********************************************************************/
1672static bool present_implies_not_present(const struct requirement *req1,
1673 const struct requirement *req2)
1674{
1675 const struct requirement *absent, *present;
1676
1677 if (req1->present == req2->present) {
1678 /* Can't use the knowledge in universal_found_function when both are
1679 * required to be absent or when both are required to be present.
1680 * It is no contradiction to require !Spy unit and !Missile unit class.
1681 * It is no contradiction to require River and Irrigation at the same
1682 * tile. */
1683 return FALSE;
1684 }
1685
1686 if (req1->present) {
1687 absent = req2;
1688 present = req1;
1689 } else {
1690 absent = req1;
1691 present = req2;
1692 }
1693
1694 if (!universal_found_function[present->source.kind]) {
1695 /* No knowledge to exploit. */
1696 return FALSE;
1697 }
1698
1699 if (present->range != absent->range) {
1700 /* Larger ranges are not always strict supersets of smaller ranges.
1701 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1702 * but not in Trade Route. */
1703 return FALSE;
1704 }
1705
1707 &present->source);
1708}
1709
1710/**********************************************************************/
1713bool req_implies_req(const struct requirement *req1,
1714 const struct requirement *req2)
1715{
1716 struct requirement nreq2;
1717
1718 req_copy(&nreq2, req2);
1719 nreq2.present = !nreq2.present;
1721}
1722
1723/**********************************************************************/
1731 const struct requirement *req2)
1732{
1733 if (are_requirements_opposites(req1, req2)) {
1734 /* The exact opposite. */
1735 return TRUE;
1736 }
1737
1738 if (present_implies_not_present(req1, req2)) {
1739 return TRUE;
1740 }
1741
1742 switch (req1->source.kind) {
1743 case VUT_IMPROVEMENT:
1744 case VUT_SITE:
1745 if (req2->source.kind == VUT_IMPR_GENUS) {
1746 return impr_contra_genus(req1, req2);
1747 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1748 return impr_contra_flag(req1, req2);
1749 } else if (req2->source.kind == VUT_CITYTILE
1750 && req2->source.value.citytile == CITYT_CENTER
1751 && REQ_RANGE_TILE == req2->range
1752 && REQ_RANGE_TILE == req1->range
1753 && req1->present) {
1754 /* A building must be in a city */
1755 return !req2->present;
1756 }
1757
1758 /* No special knowledge. */
1759 return FALSE;
1760 case VUT_IMPR_GENUS:
1761 if (req2->source.kind == VUT_IMPROVEMENT
1762 || req2->source.kind == VUT_SITE) {
1763 return impr_contra_genus(req2, req1);
1764 }
1765
1766 /* No special knowledge. */
1767 return FALSE;
1768 case VUT_IMPR_FLAG:
1769 if (req2->source.kind == VUT_IMPROVEMENT
1770 || req2->source.kind == VUT_SITE) {
1771 return impr_contra_flag(req2, req1);
1772 }
1773
1774 /* No special knowledge. */
1775 return FALSE;
1776 case VUT_DIPLREL:
1777 case VUT_DIPLREL_TILE:
1778 case VUT_DIPLREL_TILE_O:
1781 if (req2->source.kind != req1->source.kind) {
1782 /* Finding contradictions across requirement kinds aren't supported
1783 * for DiplRel requirements. */
1784 return FALSE;
1785 } else {
1786 /* Use the special knowledge about DiplRel requirements to find
1787 * contradictions. */
1788
1790 int req2_pos;
1791
1794 req2->range,
1795 req2->present);
1796
1797 return BV_ISSET(req1_contra, req2_pos);
1798 }
1799 break;
1800 case VUT_MINMOVES:
1801 if (req2->source.kind != VUT_MINMOVES) {
1802 /* Finding contradictions across requirement kinds aren't supported
1803 * for MinMoveFrags requirements. */
1804 return FALSE;
1805 } else if (req1->present == req2->present) {
1806 /* No contradiction possible. */
1807 return FALSE;
1808 } else {
1809 /* Number of move fragments left can't be larger than the number
1810 * required to be present and smaller than the number required to not
1811 * be present when the number required to be present is smaller than
1812 * the number required to not be present. */
1813 if (req1->present) {
1814 return req1->source.value.minmoves >= req2->source.value.minmoves;
1815 } else {
1816 return req1->source.value.minmoves <= req2->source.value.minmoves;
1817 }
1818 }
1819 break;
1820 case VUT_MINLATITUDE:
1821 case VUT_MAXLATITUDE:
1822 if (req2->source.kind != VUT_MINLATITUDE
1823 && req2->source.kind != VUT_MAXLATITUDE) {
1824 /* Finding contradictions across requirement kinds other than each
1825 * other is not supported for MinLatitude and MaxLatitude. */
1826 return FALSE;
1827 } else {
1828 /* For a contradiction, we need
1829 * - a minimum (present MinLatitude or negated MaxLatitude)
1830 * - a maximum (negated MinLatitude or present MaxLatitude)
1831 * - the maximum to be less than the minimum
1832 * - a requirement at the larger range that applies to the entire
1833 * range (i.e. a negated requirement, unless the range is Tile)
1834 * Otherwise, the two requirements could still be fulfilled
1835 * simultaneously by different tiles in the range */
1836
1837 /* Initial values beyond the boundaries to avoid edge cases */
1838 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
1840
1841#define EXTRACT_INFO(req) \
1842 if (req->present) { \
1843 if (req->source.kind == VUT_MINLATITUDE) { \
1844 /* present MinLatitude */ \
1845 minimum = MAX(minimum, req->source.value.latitude); \
1846 } else { \
1847 /* present MaxLatitude */ \
1848 maximum = MIN(maximum, req->source.value.latitude); \
1849 } \
1850 } else { \
1851 covered_range = MAX(covered_range, req->range); \
1852 if (req->source.kind == VUT_MINLATITUDE) { \
1853 /* negated MinLatitude */ \
1854 maximum = MIN(maximum, req->source.value.latitude - 1); \
1855 } else { \
1856 /* negated MaxLatitude */ \
1857 minimum = MAX(minimum, req->source.value.latitude + 1); \
1858 } \
1859 }
1860
1861 EXTRACT_INFO(req1);
1862 EXTRACT_INFO(req2);
1863
1864#undef EXTRACT_INFO
1865
1866 return (maximum < minimum
1867 && covered_range >= req1->range
1868 && covered_range >= req2->range);
1869 }
1870 break;
1871 case VUT_NATION:
1872 if (req2->source.kind == VUT_NATIONGROUP) {
1873 return nation_contra_group(req1, req2);
1874 }
1875
1876 /* No special knowledge. */
1877 return FALSE;
1878 break;
1879 case VUT_NATIONGROUP:
1880 if (req2->source.kind == VUT_NATION) {
1881 return nation_contra_group(req2, req1);
1882 }
1883
1884 /* No special knowledge. */
1885 return FALSE;
1886 break;
1887 case VUT_CITYTILE:
1888 if (req2->source.kind == VUT_CITYTILE) {
1889 return city_center_contra(req1, req2)
1890 || city_center_contra(req2, req1);
1891 } else if (req1->source.value.citytile == CITYT_CENTER
1892 && (req2->source.kind == VUT_IMPROVEMENT
1893 || req2->source.kind == VUT_SITE)
1894 && REQ_RANGE_TILE == req2->range
1895 && REQ_RANGE_TILE == req1->range
1896 && req2->present) {
1897 /* A building must be in a city */
1898 return !req1->present;
1899 }
1900
1901 return FALSE;
1902 default:
1903 /* No special knowledge exists. The requirements aren't the exact
1904 * opposite of each other per the initial check. */
1905 return FALSE;
1906 }
1907}
1908
1909/**********************************************************************/
1914 const struct requirement_vector *vec)
1915{
1916 /* If the requirement is contradicted by any requirement in the vector it
1917 * contradicts the entire requirement vector. */
1920 return TRUE;
1921 }
1923
1924 /* Not a singe requirement in the requirement vector is contradicted be
1925 * the specified requirement. */
1926 return FALSE;
1927}
1928
1929/**********************************************************************/
1932static inline bool are_tiles_in_range(const struct tile *tile1,
1933 const struct tile *tile2,
1934 enum req_range range)
1935{
1936 switch (range) {
1937 case REQ_RANGE_ADJACENT:
1939 return TRUE;
1940 }
1942 case REQ_RANGE_TILE:
1943 return same_pos(tile1, tile2);
1945 return map_distance(tile1, tile2) <= 1;
1946 case REQ_RANGE_CITY:
1948 case REQ_RANGE_LOCAL:
1950 case REQ_RANGE_PLAYER:
1951 case REQ_RANGE_TEAM:
1952 case REQ_RANGE_ALLIANCE:
1953 case REQ_RANGE_WORLD:
1954 case REQ_RANGE_COUNT:
1955 /* Invalid */
1957 }
1958 return FALSE;
1959}
1960
1961/**********************************************************************/
1964static inline bool players_in_same_range(const struct player *pplayer1,
1965 const struct player *pplayer2,
1966 enum req_range range)
1967{
1968 switch (range) {
1969 case REQ_RANGE_WORLD:
1970 return TRUE;
1971 case REQ_RANGE_ALLIANCE:
1973 case REQ_RANGE_TEAM:
1975 case REQ_RANGE_PLAYER:
1976 return pplayer1 == pplayer2;
1979 case REQ_RANGE_CITY:
1980 case REQ_RANGE_ADJACENT:
1982 case REQ_RANGE_TILE:
1983 case REQ_RANGE_LOCAL:
1984 case REQ_RANGE_COUNT:
1985 break;
1986 }
1987
1988 fc_assert_msg(FALSE, "Invalid range %d.", range);
1989 return FALSE;
1990}
1991
1992#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
1993{ \
1994 fc_assert_ret_val(req != NULL, TRI_MAYBE); \
1995 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
1996 fc_assert(context != NULL); \
1997}
1998
1999/**********************************************************************/
2006static enum fc_tristate
2008 const struct req_context *context,
2009 const struct player *other_player,
2010 const struct requirement *req)
2011{
2013
2014 return TRI_YES;
2015}
2016
2017/**********************************************************************/
2021static int num_world_buildings_total(const struct impr_type *building)
2022{
2023 if (is_great_wonder(building)) {
2024 return (great_wonder_is_built(building)
2025 || great_wonder_is_destroyed(building) ? 1 : 0);
2026 } else {
2027 log_error("World-ranged requirements are only supported for wonders.");
2028 return 0;
2029 }
2030}
2031
2032/**********************************************************************/
2035static int num_world_buildings(const struct impr_type *building)
2036{
2037 if (is_great_wonder(building)) {
2038 return (great_wonder_is_built(building) ? 1 : 0);
2039 } else {
2040 log_error("World-ranged requirements are only supported for wonders.");
2041 return 0;
2042 }
2043}
2044
2045/**********************************************************************/
2056static bool player_has_ever_built(const struct player *pplayer,
2057 const struct impr_type *building)
2058{
2059 if (is_wonder(building)) {
2060 return (wonder_is_built(pplayer, building)
2061 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2062 } else {
2063 log_error("Player-ranged requirements are only supported for wonders.");
2064 return FALSE;
2065 }
2066}
2067
2068/**********************************************************************/
2071static int num_player_buildings(const struct player *pplayer,
2072 const struct impr_type *building)
2073{
2074 if (is_wonder(building)) {
2075 return (wonder_is_built(pplayer, building) ? 1 : 0);
2076 } else {
2077 log_error("Player-ranged requirements are only supported for wonders.");
2078 return 0;
2079 }
2080}
2081
2082/**********************************************************************/
2085static int num_continent_buildings(const struct player *pplayer,
2086 int continent,
2087 const struct impr_type *building)
2088{
2089 if (is_wonder(building)) {
2090 const struct city *pcity;
2091
2092 pcity = city_from_wonder(pplayer, building);
2093 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2094 return 1;
2095 }
2096 } else {
2097 log_error("Island-ranged requirements are only supported for wonders.");
2098 }
2099 return 0;
2100}
2101
2102/**********************************************************************/
2105static int num_city_buildings(const struct city *pcity,
2106 const struct impr_type *building)
2107{
2108 return (city_has_building(pcity, building) ? 1 : 0);
2109}
2110
2111/**********************************************************************/
2118static enum fc_tristate
2120 const struct req_context *context,
2121 const struct player *other_player,
2122 const struct requirement *req)
2123{
2124 const struct impr_type *building;
2125
2126 /* Can't use this assertion, as both VUT_IMPROVEMENT and VUT_SITE
2127 * are handled here. */
2128 /* IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT); */
2129
2130 building = req->source.value.building;
2131
2132 /* Check if it's certain that the building is obsolete given the
2133 * specification we have */
2134 if (req->source.kind == VUT_IMPROVEMENT
2135 && improvement_obsolete(context->player, building, context->city)) {
2136 return TRI_NO;
2137 }
2138
2139 if (req->survives) {
2140
2141 /* Check whether condition has ever held, using cached information. */
2142 switch (req->range) {
2143 case REQ_RANGE_WORLD:
2144 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2145 case REQ_RANGE_ALLIANCE:
2146 case REQ_RANGE_TEAM:
2147 if (context->player == NULL) {
2148 return TRI_MAYBE;
2149 }
2150 players_iterate_alive(plr2) {
2151 if (players_in_same_range(context->player, plr2, req->range)
2152 && player_has_ever_built(plr2, building)) {
2153 return TRI_YES;
2154 }
2156 return TRI_NO;
2157 case REQ_RANGE_PLAYER:
2158 if (context->player == NULL) {
2159 return TRI_MAYBE;
2160 }
2162 building));
2165 case REQ_RANGE_CITY:
2166 case REQ_RANGE_LOCAL:
2167 case REQ_RANGE_TILE:
2169 case REQ_RANGE_ADJACENT:
2170 /* There is no sources cache for this. */
2171 log_error("Surviving requirements are only supported at "
2172 "World/Alliance/Team/Player ranges.");
2173 return TRI_NO;
2174 case REQ_RANGE_COUNT:
2175 break;
2176 }
2177
2178 } else {
2179
2180 /* Non-surviving requirement. */
2181 switch (req->range) {
2182 case REQ_RANGE_WORLD:
2183 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2184 case REQ_RANGE_ALLIANCE:
2185 case REQ_RANGE_TEAM:
2186 if (context->player == NULL) {
2187 return TRI_MAYBE;
2188 }
2189 players_iterate_alive(plr2) {
2190 if (players_in_same_range(context->player, plr2, req->range)
2191 && num_player_buildings(plr2, building) > 0) {
2192 return TRI_YES;
2193 }
2195 return TRI_NO;
2196 case REQ_RANGE_PLAYER:
2197 if (context->player == NULL) {
2198 return TRI_MAYBE;
2199 }
2201 building)
2202 > 0);
2204 /* At present, "Continent" effects can affect only
2205 * cities and units in cities. */
2206 if (context->player && context->city) {
2207 int continent = tile_continent(context->city->tile);
2209 continent, building)
2210 > 0);
2211 } else {
2212 return TRI_MAYBE;
2213 }
2215 if (context->city) {
2216 if (num_city_buildings(context->city, building) > 0) {
2217 return TRI_YES;
2218 } else {
2219 enum fc_tristate ret = TRI_NO;
2220
2222 if (trade_partner == NULL) {
2223 ret = TRI_MAYBE;
2224 } else if (num_city_buildings(trade_partner, building) > 0) {
2225 return TRI_YES;
2226 }
2228
2229 return ret;
2230 }
2231 } else {
2232 return TRI_MAYBE;
2233 }
2234 case REQ_RANGE_CITY:
2235 if (context->city) {
2236 return BOOL_TO_TRISTATE(num_city_buildings(context->city, building)
2237 > 0);
2238 } else {
2239 return TRI_MAYBE;
2240 }
2241 case REQ_RANGE_LOCAL:
2242 if (context->building) {
2243 if (context->building == building) {
2244 return TRI_YES;
2245 } else {
2246 return TRI_NO;
2247 }
2248 } else {
2249 /* TODO: other local targets */
2250 return TRI_MAYBE;
2251 }
2252 case REQ_RANGE_TILE:
2253 if (context->tile) {
2254 const struct city *pcity = tile_city(context->tile);
2255
2256 if (pcity) {
2257 return BOOL_TO_TRISTATE(num_city_buildings(pcity, building) > 0);
2258 } else {
2259 return TRI_NO;
2260 }
2261 } else {
2262 return TRI_MAYBE;
2263 }
2265 case REQ_RANGE_ADJACENT:
2266 case REQ_RANGE_COUNT:
2267 break;
2268 }
2269
2270 }
2271
2272 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2273 return TRI_NO;
2274}
2275
2276/**********************************************************************/
2284static enum fc_tristate
2286 const struct req_context *context,
2287 const struct player *other_player,
2288 const struct requirement *req)
2289{
2291
2292 return (context->building ? BOOL_TO_TRISTATE(
2293 context->building->genus
2294 == req->source.value.impr_genus)
2295 : TRI_MAYBE);
2296}
2297
2298/**********************************************************************/
2301static enum fc_tristate is_buildingflag_in_city(const struct city *pcity,
2302 enum impr_flag_id flag)
2303{
2304 struct player *owner;
2305
2306 if (pcity == NULL) {
2307 return TRI_MAYBE;
2308 }
2309
2310 owner = city_owner(pcity);
2311 city_built_iterate(pcity, impr) {
2312 if (improvement_has_flag(impr, flag)
2313 && !improvement_obsolete(owner, impr, pcity)) {
2314 return TRI_YES;
2315 }
2317
2318 return TRI_NO;
2319}
2320
2321/**********************************************************************/
2329static enum fc_tristate
2331 const struct req_context *context,
2332 const struct player *other_player,
2333 const struct requirement *req)
2334{
2336
2337 switch (req->range) {
2338 case REQ_RANGE_LOCAL:
2339 return (context->building
2341 req->source.value.impr_flag))
2342 : TRI_MAYBE);
2343 case REQ_RANGE_CITY:
2345 case REQ_RANGE_TILE:
2346 if (context->tile == NULL) {
2347 return TRI_MAYBE;
2348 }
2350 req->source.value.impr_flag);
2352 case REQ_RANGE_ADJACENT:
2355 case REQ_RANGE_PLAYER:
2356 case REQ_RANGE_ALLIANCE:
2357 case REQ_RANGE_TEAM:
2358 case REQ_RANGE_WORLD:
2359 case REQ_RANGE_COUNT:
2360 break;
2361 }
2362
2363 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2364
2365 return TRI_MAYBE;
2366}
2367
2368/**********************************************************************/
2376static enum fc_tristate
2378 const struct req_context *context,
2379 const struct player *other_player,
2380 const struct requirement *req)
2381{
2383
2384 switch (req->range) {
2385 case REQ_RANGE_PLAYER:
2386 return (context->player != NULL
2388 req->source.value.plr_flag))
2389 : TRI_MAYBE);
2390 case REQ_RANGE_LOCAL:
2391 case REQ_RANGE_CITY:
2392 case REQ_RANGE_TILE:
2394 case REQ_RANGE_ADJACENT:
2397 case REQ_RANGE_ALLIANCE:
2398 case REQ_RANGE_TEAM:
2399 case REQ_RANGE_WORLD:
2400 case REQ_RANGE_COUNT:
2401 break;
2402 }
2403
2404 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2405
2406 return TRI_MAYBE;
2407}
2408
2409/**********************************************************************/
2417static enum fc_tristate
2419 const struct req_context *context,
2420 const struct player *other_player,
2421 const struct requirement *req)
2422{
2424
2425 switch (req->range) {
2426 case REQ_RANGE_PLAYER:
2427 return (context->player != NULL
2429 req->source.value.plrstate))
2430 : TRI_MAYBE);
2431 case REQ_RANGE_LOCAL:
2432 case REQ_RANGE_CITY:
2433 case REQ_RANGE_TILE:
2435 case REQ_RANGE_ADJACENT:
2438 case REQ_RANGE_ALLIANCE:
2439 case REQ_RANGE_TEAM:
2440 case REQ_RANGE_WORLD:
2441 case REQ_RANGE_COUNT:
2442 break;
2443 }
2444
2445 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2446
2447 return TRI_MAYBE;
2448}
2449
2450/**********************************************************************/
2457static enum fc_tristate
2459 const struct req_context *context,
2460 const struct player *other_player,
2461 const struct requirement *req)
2462{
2463 Tech_type_id tech;
2464
2466
2467 tech = advance_number(req->source.value.advance);
2468
2469 if (req->survives) {
2472 }
2473
2474 /* Not a 'surviving' requirement. */
2475 switch (req->range) {
2476 case REQ_RANGE_PLAYER:
2477 if (NULL != context->player) {
2479 (research_get(context->player), tech));
2480 } else {
2481 return TRI_MAYBE;
2482 }
2483 case REQ_RANGE_TEAM:
2484 case REQ_RANGE_ALLIANCE:
2485 case REQ_RANGE_WORLD:
2486 if (NULL == context->player) {
2487 return TRI_MAYBE;
2488 }
2489 players_iterate_alive(plr2) {
2490 if (players_in_same_range(context->player, plr2, req->range)) {
2491 if (research_invention_state(research_get(plr2), tech)
2492 == TECH_KNOWN) {
2493 return TRI_YES;
2494 }
2495 }
2497
2498 return TRI_NO;
2499 case REQ_RANGE_LOCAL:
2500 case REQ_RANGE_TILE:
2502 case REQ_RANGE_ADJACENT:
2503 case REQ_RANGE_CITY:
2506 case REQ_RANGE_COUNT:
2507 break;
2508 }
2509
2510 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2511
2512 return TRI_MAYBE;
2513}
2514
2515/**********************************************************************/
2522static enum fc_tristate
2524 const struct req_context *context,
2525 const struct player *other_player,
2526 const struct requirement *req)
2527{
2528 enum tech_flag_id techflag;
2529
2531
2532 techflag = req->source.value.techflag;
2533
2534 switch (req->range) {
2535 case REQ_RANGE_PLAYER:
2536 if (NULL != context->player) {
2538 techflag));
2539 } else {
2540 return TRI_MAYBE;
2541 }
2542 break;
2543 case REQ_RANGE_TEAM:
2544 case REQ_RANGE_ALLIANCE:
2545 if (NULL == context->player) {
2546 return TRI_MAYBE;
2547 }
2548 players_iterate_alive(plr2) {
2549 if (players_in_same_range(context->player, plr2, req->range)
2550 && player_knows_techs_with_flag(plr2, techflag)) {
2551 return TRI_YES;
2552 }
2554 return TRI_NO;
2555 case REQ_RANGE_WORLD:
2556 players_iterate(pplayer) {
2557 if (player_knows_techs_with_flag(pplayer, techflag)) {
2558 return TRI_YES;
2559 }
2561
2562 return TRI_NO;
2563 case REQ_RANGE_LOCAL:
2564 case REQ_RANGE_TILE:
2566 case REQ_RANGE_ADJACENT:
2567 case REQ_RANGE_CITY:
2570 case REQ_RANGE_COUNT:
2571 break;
2572 }
2573
2574 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2575
2576 return TRI_MAYBE;
2577}
2578
2579/**********************************************************************/
2586static enum fc_tristate
2588 const struct req_context *context,
2589 const struct player *other_player,
2590 const struct requirement *req)
2591{
2592 int minculture;
2593
2595
2596 minculture = req->source.value.minculture;
2597
2598 switch (req->range) {
2599 case REQ_RANGE_CITY:
2600 if (!context->city) {
2601 return TRI_MAYBE;
2602 }
2603 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2605 if (!context->city) {
2606 return TRI_MAYBE;
2607 }
2608 if (city_culture(context->city) >= minculture) {
2609 return TRI_YES;
2610 } else {
2611 enum fc_tristate ret = TRI_NO;
2612
2614 if (trade_partner == NULL) {
2615 ret = TRI_MAYBE;
2616 } else if (city_culture(trade_partner) >= minculture) {
2617 return TRI_YES;
2618 }
2620
2621 return ret;
2622 }
2623 case REQ_RANGE_PLAYER:
2624 case REQ_RANGE_TEAM:
2625 case REQ_RANGE_ALLIANCE:
2626 case REQ_RANGE_WORLD:
2627 if (NULL == context->player) {
2628 return TRI_MAYBE;
2629 }
2630 players_iterate_alive(plr2) {
2631 if (players_in_same_range(context->player, plr2, req->range)) {
2632 if (player_culture(plr2) >= minculture) {
2633 return TRI_YES;
2634 }
2635 }
2637 return TRI_NO;
2638 case REQ_RANGE_LOCAL:
2639 case REQ_RANGE_TILE:
2641 case REQ_RANGE_ADJACENT:
2643 case REQ_RANGE_COUNT:
2644 break;
2645 }
2646
2647 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2648
2649 return TRI_MAYBE;
2650}
2651
2652/**********************************************************************/
2660static enum fc_tristate
2662 const struct req_context *context,
2663 const struct player *other_player,
2664 const struct requirement *req)
2665{
2667
2669
2671
2672 switch (req->range) {
2673 case REQ_RANGE_CITY:
2674 if (!context->city) {
2675 return TRI_MAYBE;
2676 }
2678 / city_size_get(context->city);
2681 if (!context->city) {
2682 return TRI_MAYBE;
2683 }
2685 / city_size_get(context->city);
2687 return TRI_YES;
2688 } else {
2689 enum fc_tristate ret = TRI_NO;
2690
2692 if (trade_partner == NULL) {
2693 ret = TRI_MAYBE;
2694 } else {
2698 return TRI_YES;
2699 }
2700 }
2702
2703 return ret;
2704 }
2705 case REQ_RANGE_PLAYER:
2706 case REQ_RANGE_TEAM:
2707 case REQ_RANGE_ALLIANCE:
2708 case REQ_RANGE_WORLD:
2709 case REQ_RANGE_LOCAL:
2710 case REQ_RANGE_TILE:
2712 case REQ_RANGE_ADJACENT:
2714 case REQ_RANGE_COUNT:
2715 break;
2716 }
2717
2718 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2719
2720 return TRI_MAYBE;
2721}
2722
2723/**********************************************************************/
2731static enum fc_tristate
2733 const struct req_context *context,
2734 const struct player *other_player,
2735 const struct requirement *req)
2736{
2737 int max_units;
2738
2740
2742
2743 /* TODO: if can't see V_INVIS -> TRI_MAYBE */
2744 switch (req->range) {
2745 case REQ_RANGE_TILE:
2746 if (!context->tile) {
2747 return TRI_MAYBE;
2748 }
2749 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
2751 if (!context->tile) {
2752 return TRI_MAYBE;
2753 }
2754 if (unit_list_size(context->tile->units) <= max_units) {
2755 return TRI_YES;
2756 }
2758 if (unit_list_size(adjc_tile->units) <= max_units) {
2759 return TRI_YES;
2760 }
2762 return TRI_NO;
2763 case REQ_RANGE_ADJACENT:
2764 if (!context->tile) {
2765 return TRI_MAYBE;
2766 }
2767 if (unit_list_size(context->tile->units) <= max_units) {
2768 return TRI_YES;
2769 }
2771 if (unit_list_size(adjc_tile->units) <= max_units) {
2772 return TRI_YES;
2773 }
2775 return TRI_NO;
2776 case REQ_RANGE_CITY:
2779 case REQ_RANGE_PLAYER:
2780 case REQ_RANGE_TEAM:
2781 case REQ_RANGE_ALLIANCE:
2782 case REQ_RANGE_WORLD:
2783 case REQ_RANGE_LOCAL:
2784 case REQ_RANGE_COUNT:
2785 break;
2786 }
2787
2788 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2789
2790 return TRI_MAYBE;
2791}
2792
2793/**********************************************************************/
2800static enum fc_tristate
2802 const struct req_context *context,
2803 const struct player *other_player,
2804 const struct requirement *req)
2805{
2806 const struct extra_type *pextra;
2807 enum fc_tristate ret;
2808
2810
2811 pextra = req->source.value.extra;
2812
2813 switch (req->range) {
2814 case REQ_RANGE_LOCAL:
2815 if (!context->extra) {
2816 return TRI_MAYBE;
2817 }
2818 return BOOL_TO_TRISTATE(context->extra == pextra);
2819 case REQ_RANGE_TILE:
2820 /* The requirement is filled if the tile has extra of requested type. */
2821 if (!context->tile) {
2822 return TRI_MAYBE;
2823 }
2824 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
2826 if (!context->tile) {
2827 return TRI_MAYBE;
2828 }
2829 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2830 || is_extra_card_near(nmap, context->tile, pextra));
2831 case REQ_RANGE_ADJACENT:
2832 if (!context->tile) {
2833 return TRI_MAYBE;
2834 }
2835 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2836 || is_extra_near_tile(nmap, context->tile, pextra));
2837 case REQ_RANGE_CITY:
2838 if (!context->city) {
2839 return TRI_MAYBE;
2840 }
2842 city_tile(context->city), ptile) {
2843 if (tile_has_extra(ptile, pextra)) {
2844 return TRI_YES;
2845 }
2847
2848 return TRI_NO;
2849
2851 if (!context->city) {
2852 return TRI_MAYBE;
2853 }
2855 city_tile(context->city), ptile) {
2856 if (tile_has_extra(ptile, pextra)) {
2857 return TRI_YES;
2858 }
2860
2861 ret = TRI_NO;
2863 if (trade_partner == NULL) {
2864 ret = TRI_MAYBE;
2865 } else {
2867 city_tile(trade_partner), ptile) {
2868 if (tile_has_extra(ptile, pextra)) {
2869 return TRI_YES;
2870 }
2872 }
2874
2875 return ret;
2876
2878 case REQ_RANGE_PLAYER:
2879 case REQ_RANGE_TEAM:
2880 case REQ_RANGE_ALLIANCE:
2881 case REQ_RANGE_WORLD:
2882 case REQ_RANGE_COUNT:
2883 break;
2884 }
2885
2886 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2887
2888 return TRI_MAYBE;
2889}
2890
2891/**********************************************************************/
2898static enum fc_tristate
2900 const struct req_context *context,
2901 const struct player *other_player,
2902 const struct requirement *req)
2903{
2904 const struct goods_type *pgood;
2905
2907
2908 pgood = req->source.value.good;
2909
2910 switch (req->range) {
2911 case REQ_RANGE_LOCAL:
2912 case REQ_RANGE_CITY:
2913 /* The requirement is filled if the city imports good of requested type. */
2914 if (!context->city) {
2915 return TRI_MAYBE;
2916 }
2920 case REQ_RANGE_TILE:
2922 case REQ_RANGE_ADJACENT:
2925 case REQ_RANGE_PLAYER:
2926 case REQ_RANGE_TEAM:
2927 case REQ_RANGE_ALLIANCE:
2928 case REQ_RANGE_WORLD:
2929 case REQ_RANGE_COUNT:
2930 break;
2931 }
2932
2933 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2934
2935 return TRI_MAYBE;
2936}
2937
2938/**********************************************************************/
2945static enum fc_tristate
2947 const struct req_context *context,
2948 const struct player *other_player,
2949 const struct requirement *req)
2950{
2952
2953 return BOOL_TO_TRISTATE(context->action
2954 && action_number(context->action)
2955 == action_number(req->source.value.action));
2956}
2957
2958/**********************************************************************/
2966static enum fc_tristate
2968 const struct req_context *context,
2969 const struct player *other_player,
2970 const struct requirement *req)
2971{
2973
2974 return BOOL_TO_TRISTATE(context->output
2975 && context->output->index
2976 == req->source.value.outputtype);
2977}
2978
2979/**********************************************************************/
2986static enum fc_tristate
2988 const struct req_context *context,
2989 const struct player *other_player,
2990 const struct requirement *req)
2991{
2993
2994 return BOOL_TO_TRISTATE(context->specialist
2995 && context->specialist
2996 == req->source.value.specialist);
2997}
2998
2999/**********************************************************************/
3006static enum fc_tristate
3008 const struct req_context *context,
3009 const struct player *other_player,
3010 const struct requirement *req)
3011{
3012 const struct terrain *pterrain;
3013
3015
3016 pterrain = req->source.value.terrain;
3017
3018 switch (req->range) {
3019 case REQ_RANGE_TILE:
3020 /* The requirement is filled if the tile has the terrain. */
3021 if (!context->tile) {
3022 return TRI_MAYBE;
3023 }
3024 return pterrain && tile_terrain(context->tile) == pterrain;
3026 if (!context->tile) {
3027 return TRI_MAYBE;
3028 }
3029 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
3030 case REQ_RANGE_ADJACENT:
3031 if (!context->tile) {
3032 return TRI_MAYBE;
3033 }
3034 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
3035 case REQ_RANGE_CITY:
3036 if (!context->city) {
3037 return TRI_MAYBE;
3038 }
3039 if (pterrain != NULL) {
3041 city_tile(context->city), ptile) {
3042 if (tile_terrain(ptile) == pterrain) {
3043 return TRI_YES;
3044 }
3046 }
3047 return TRI_NO;
3049 if (!context->city) {
3050 return TRI_MAYBE;
3051 }
3052 if (pterrain != NULL) {
3053 enum fc_tristate ret;
3054
3056 city_tile(context->city), ptile) {
3057 if (tile_terrain(ptile) == pterrain) {
3058 return TRI_YES;
3059 }
3061
3062 ret = TRI_NO;
3064 if (trade_partner == NULL) {
3065 ret = TRI_MAYBE;
3066 } else {
3068 city_tile(trade_partner), ptile) {
3069 if (tile_terrain(ptile) == pterrain) {
3070 return TRI_YES;
3071 }
3073 }
3075
3076 return ret;
3077 }
3078
3079 return TRI_MAYBE;
3081 case REQ_RANGE_PLAYER:
3082 case REQ_RANGE_TEAM:
3083 case REQ_RANGE_ALLIANCE:
3084 case REQ_RANGE_WORLD:
3085 case REQ_RANGE_LOCAL:
3086 case REQ_RANGE_COUNT:
3087 break;
3088 }
3089
3090 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3091
3092 return TRI_MAYBE;
3093}
3094
3095/**********************************************************************/
3103static enum fc_tristate
3105 const struct req_context *context,
3106 const struct player *other_player,
3107 const struct requirement *req)
3108{
3109 enum terrain_class pclass;
3110 enum fc_tristate ret;
3111
3113
3115
3116 switch (req->range) {
3117 case REQ_RANGE_TILE:
3118 /* The requirement is filled if the tile has the terrain of correct class. */
3119 if (!context->tile) {
3120 return TRI_MAYBE;
3121 }
3124 if (!context->tile) {
3125 return TRI_MAYBE;
3126 }
3129 case REQ_RANGE_ADJACENT:
3130 if (!context->tile) {
3131 return TRI_MAYBE;
3132 }
3135 case REQ_RANGE_CITY:
3136 if (!context->city) {
3137 return TRI_MAYBE;
3138 }
3140 city_tile(context->city), ptile) {
3141 const struct terrain *pterrain = tile_terrain(ptile);
3142
3143 if (pterrain != T_UNKNOWN
3144 && terrain_type_terrain_class(pterrain) == pclass) {
3145 return TRI_YES;
3146 }
3148
3149 return TRI_NO;
3151 if (!context->city) {
3152 return TRI_MAYBE;
3153 }
3155 city_tile(context->city), ptile) {
3156 const struct terrain *pterrain = tile_terrain(ptile);
3157
3158 if (pterrain != T_UNKNOWN
3159 && terrain_type_terrain_class(pterrain) == pclass) {
3160 return TRI_YES;
3161 }
3163
3164 ret = TRI_NO;
3166 if (trade_partner == NULL) {
3167 ret = TRI_MAYBE;
3168 } else {
3170 city_tile(trade_partner), ptile) {
3171 const struct terrain *pterrain = tile_terrain(ptile);
3172
3173 if (pterrain != T_UNKNOWN
3174 && terrain_type_terrain_class(pterrain) == pclass) {
3175 return TRI_YES;
3176 }
3178 }
3180
3181 return ret;
3183 case REQ_RANGE_PLAYER:
3184 case REQ_RANGE_TEAM:
3185 case REQ_RANGE_ALLIANCE:
3186 case REQ_RANGE_WORLD:
3187 case REQ_RANGE_LOCAL:
3188 case REQ_RANGE_COUNT:
3189 break;
3190 }
3191
3192 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3193
3194 return TRI_MAYBE;
3195}
3196
3197/**********************************************************************/
3205static enum fc_tristate
3207 const struct req_context *context,
3208 const struct player *other_player,
3209 const struct requirement *req)
3210{
3212 enum fc_tristate ret;
3213
3215
3217
3218 switch (req->range) {
3219 case REQ_RANGE_TILE:
3220 /* The requirement is fulfilled if the tile has a terrain with
3221 * correct flag. */
3222 if (!context->tile) {
3223 return TRI_MAYBE;
3224 }
3226 terrflag));
3228 if (!context->tile) {
3229 return TRI_MAYBE;
3230 }
3232 terrflag)
3234 terrflag));
3235 case REQ_RANGE_ADJACENT:
3236 if (!context->tile) {
3237 return TRI_MAYBE;
3238 }
3240 terrflag)
3242 terrflag));
3243 case REQ_RANGE_CITY:
3244 if (!context->city) {
3245 return TRI_MAYBE;
3246 }
3248 city_tile(context->city), ptile) {
3249 const struct terrain *pterrain = tile_terrain(ptile);
3250
3251 if (pterrain != T_UNKNOWN
3252 && terrain_has_flag(pterrain, terrflag)) {
3253 return TRI_YES;
3254 }
3256
3257 return TRI_NO;
3259 if (!context->city) {
3260 return TRI_MAYBE;
3261 }
3263 city_tile(context->city), ptile) {
3264 const struct terrain *pterrain = tile_terrain(ptile);
3265
3266 if (pterrain != T_UNKNOWN
3267 && terrain_has_flag(pterrain, terrflag)) {
3268 return TRI_YES;
3269 }
3271
3272 ret = TRI_NO;
3274 if (trade_partner == NULL) {
3275 ret = TRI_MAYBE;
3276 } else {
3278 city_tile(trade_partner), ptile) {
3279 const struct terrain *pterrain = tile_terrain(ptile);
3280
3281 if (pterrain != T_UNKNOWN
3282 && terrain_has_flag(pterrain, terrflag)) {
3283 return TRI_YES;
3284 }
3286 }
3288
3289 return ret;
3291 case REQ_RANGE_PLAYER:
3292 case REQ_RANGE_TEAM:
3293 case REQ_RANGE_ALLIANCE:
3294 case REQ_RANGE_WORLD:
3295 case REQ_RANGE_LOCAL:
3296 case REQ_RANGE_COUNT:
3297 break;
3298 }
3299
3300 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3301
3302 return TRI_MAYBE;
3303}
3304
3305/**********************************************************************/
3312static enum fc_tristate
3314 const struct req_context *context,
3315 const struct player *other_player,
3316 const struct requirement *req)
3317{
3318 enum road_flag_id roadflag;
3319 enum fc_tristate ret;
3320
3322
3323 roadflag = req->source.value.roadflag;
3324
3325 switch (req->range) {
3326 case REQ_RANGE_LOCAL:
3327 {
3328 if (!context->extra) {
3329 return TRI_MAYBE;
3330 }
3331 struct road_type *r = extra_road_get(context->extra);
3332
3333 return BOOL_TO_TRISTATE(
3334 r && road_has_flag(r, roadflag)
3335 );
3336 }
3337 case REQ_RANGE_TILE:
3338 /* The requirement is filled if the tile has a road with correct flag. */
3339 if (!context->tile) {
3340 return TRI_MAYBE;
3341 }
3342 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3344 if (!context->tile) {
3345 return TRI_MAYBE;
3346 }
3347 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3349 roadflag));
3350 case REQ_RANGE_ADJACENT:
3351 if (!context->tile) {
3352 return TRI_MAYBE;
3353 }
3354 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3356 roadflag));
3357 case REQ_RANGE_CITY:
3358 if (!context->city) {
3359 return TRI_MAYBE;
3360 }
3362 city_tile(context->city), ptile) {
3363 if (tile_has_road_flag(ptile, roadflag)) {
3364 return TRI_YES;
3365 }
3367
3368 return TRI_NO;
3370 if (!context->city) {
3371 return TRI_MAYBE;
3372 }
3374 city_tile(context->city), ptile) {
3375 if (tile_has_road_flag(ptile, roadflag)) {
3376 return TRI_YES;
3377 }
3379
3380 ret = TRI_NO;
3382 if (trade_partner == NULL) {
3383 ret = TRI_MAYBE;
3384 } else {
3386 city_tile(trade_partner), ptile) {
3387 if (tile_has_road_flag(ptile, roadflag)) {
3388 return TRI_YES;
3389 }
3391 }
3393
3394 return ret;
3396 case REQ_RANGE_PLAYER:
3397 case REQ_RANGE_TEAM:
3398 case REQ_RANGE_ALLIANCE:
3399 case REQ_RANGE_WORLD:
3400 case REQ_RANGE_COUNT:
3401 break;
3402 }
3403
3404 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3405
3406 return TRI_MAYBE;
3407}
3408
3409/**********************************************************************/
3416static enum fc_tristate
3418 const struct req_context *context,
3419 const struct player *other_player,
3420 const struct requirement *req)
3421{
3422 enum extra_flag_id extraflag;
3423 enum fc_tristate ret;
3424
3426
3427 extraflag = req->source.value.extraflag;
3428
3429 switch (req->range) {
3430 case REQ_RANGE_LOCAL:
3431 if (!context->extra) {
3432 return TRI_MAYBE;
3433 }
3434 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3435 case REQ_RANGE_TILE:
3436 /* The requirement is filled if the tile has an extra with correct flag. */
3437 if (!context->tile) {
3438 return TRI_MAYBE;
3439 }
3440 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3442 if (!context->tile) {
3443 return TRI_MAYBE;
3444 }
3445 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3446 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3447 case REQ_RANGE_ADJACENT:
3448 if (!context->tile) {
3449 return TRI_MAYBE;
3450 }
3451 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3452 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3453 case REQ_RANGE_CITY:
3454 if (!context->city) {
3455 return TRI_MAYBE;
3456 }
3458 city_tile(context->city), ptile) {
3459 if (tile_has_extra_flag(ptile, extraflag)) {
3460 return TRI_YES;
3461 }
3463
3464 return TRI_NO;
3466 if (!context->city) {
3467 return TRI_MAYBE;
3468 }
3470 city_tile(context->city), ptile) {
3471 if (tile_has_extra_flag(ptile, extraflag)) {
3472 return TRI_YES;
3473 }
3475
3476 ret = TRI_NO;
3478 if (trade_partner == NULL) {
3479 ret = TRI_MAYBE;
3480 } else {
3482 city_tile(trade_partner), ptile) {
3483 if (tile_has_extra_flag(ptile, extraflag)) {
3484 return TRI_YES;
3485 }
3487 }
3489
3490 return ret;
3492 case REQ_RANGE_PLAYER:
3493 case REQ_RANGE_TEAM:
3494 case REQ_RANGE_ALLIANCE:
3495 case REQ_RANGE_WORLD:
3496 case REQ_RANGE_COUNT:
3497 break;
3498 }
3499
3500 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3501
3502 return TRI_MAYBE;
3503}
3504
3505/**********************************************************************/
3513static enum fc_tristate
3515 const struct req_context *context,
3516 const struct player *other_player,
3517 const struct requirement *req)
3518{
3520
3522
3524
3525 if (!context->tile) {
3526 return TRI_MAYBE;
3527 }
3528
3529 switch (req->range) {
3530 case REQ_RANGE_TILE:
3534 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
3535 case REQ_RANGE_CITY:
3538 case REQ_RANGE_PLAYER:
3539 case REQ_RANGE_TEAM:
3540 case REQ_RANGE_ALLIANCE:
3541 case REQ_RANGE_WORLD:
3542 case REQ_RANGE_LOCAL:
3543 case REQ_RANGE_COUNT:
3544 break;
3545 }
3546
3547 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3548
3549 return TRI_MAYBE;
3550}
3551
3552/**********************************************************************/
3559static enum fc_tristate
3561 const struct req_context *context,
3562 const struct player *other_player,
3563 const struct requirement *req)
3564{
3566
3567 if (context->player == NULL) {
3568 return TRI_MAYBE;
3569 } else {
3571 == req->source.value.govern);
3572 }
3573}
3574
3575/**********************************************************************/
3582static enum fc_tristate
3584 const struct req_context *context,
3585 const struct player *other_player,
3586 const struct requirement *req)
3587{
3589
3590 if (context->player == NULL) {
3591 return TRI_MAYBE;
3592 } else {
3593 return BOOL_TO_TRISTATE(context->player->style
3594 == req->source.value.style);
3595 }
3596}
3597
3598/**********************************************************************/
3605static enum fc_tristate
3607 const struct req_context *context,
3608 const struct player *other_player,
3609 const struct requirement *req)
3610{
3612
3613 switch (req->range) {
3614 case REQ_RANGE_WORLD:
3615 /* "None" does not count */
3616 return ((game.info.global_advance_count - 1)
3617 >= req->source.value.min_techs);
3618 case REQ_RANGE_PLAYER:
3619 if (context->player == NULL) {
3620 return TRI_MAYBE;
3621 } else {
3622 /* "None" does not count */
3623 return BOOL_TO_TRISTATE(
3624 (research_get(context->player)->techs_researched - 1)
3625 >= req->source.value.min_techs
3626 );
3627 }
3628 default:
3629 return TRI_MAYBE;
3630 }
3631}
3632
3633/**********************************************************************/
3640static enum fc_tristate
3642 const struct req_context *context,
3643 const struct player *other_player,
3644 const struct requirement *req)
3645{
3647
3648 if (context->player == NULL) {
3649 return TRI_MAYBE;
3650 } else {
3651 return BOOL_TO_TRISTATE(is_ai(context->player)
3652 && context->player->ai_common.skill_level
3653 == req->source.value.ai_level);
3654 }
3655}
3656
3657/**********************************************************************/
3664static enum fc_tristate
3666 const struct req_context *context,
3667 const struct player *other_player,
3668 const struct requirement *req)
3669{
3670 const struct nation_type *nation;
3671
3673
3674 nation = req->source.value.nation;
3675
3676 switch (req->range) {
3677 case REQ_RANGE_PLAYER:
3678 if (context->player == NULL) {
3679 return TRI_MAYBE;
3680 }
3681 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
3682 case REQ_RANGE_TEAM:
3683 case REQ_RANGE_ALLIANCE:
3684 if (context->player == NULL) {
3685 return TRI_MAYBE;
3686 }
3687 players_iterate_alive(plr2) {
3688 if (players_in_same_range(context->player, plr2, req->range)) {
3689 if (nation_of_player(plr2) == nation) {
3690 return TRI_YES;
3691 }
3692 }
3694 return TRI_NO;
3695 case REQ_RANGE_WORLD:
3696 /* NB: if a player is ever removed outright from the game
3697 * (e.g. via /remove), rather than just dying, this 'survives'
3698 * requirement will stop being true for their nation.
3699 * create_command_newcomer() can also cause this to happen. */
3700 return BOOL_TO_TRISTATE(NULL != nation->player
3701 && (req->survives || nation->player->is_alive));
3702 case REQ_RANGE_LOCAL:
3703 case REQ_RANGE_TILE:
3705 case REQ_RANGE_ADJACENT:
3706 case REQ_RANGE_CITY:
3709 case REQ_RANGE_COUNT:
3710 break;
3711 }
3712
3713 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3714
3715 return TRI_MAYBE;
3716}
3717
3718/**********************************************************************/
3726static enum fc_tristate
3728 const struct req_context *context,
3729 const struct player *other_player,
3730 const struct requirement *req)
3731{
3732 const struct nation_group *ngroup;
3733
3735
3737
3738 switch (req->range) {
3739 case REQ_RANGE_PLAYER:
3740 if (context->player == NULL) {
3741 return TRI_MAYBE;
3742 }
3744 nation_of_player(context->player), ngroup));
3745 case REQ_RANGE_TEAM:
3746 case REQ_RANGE_ALLIANCE:
3747 case REQ_RANGE_WORLD:
3748 if (context->player == NULL) {
3749 return TRI_MAYBE;
3750 }
3751 players_iterate_alive(plr2) {
3752 if (players_in_same_range(context->player, plr2, req->range)) {
3754 return TRI_YES;
3755 }
3756 }
3758 return TRI_NO;
3759 case REQ_RANGE_LOCAL:
3760 case REQ_RANGE_TILE:
3762 case REQ_RANGE_ADJACENT:
3763 case REQ_RANGE_CITY:
3766 case REQ_RANGE_COUNT:
3767 break;
3768 }
3769
3770 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3771
3772 return TRI_MAYBE;
3773}
3774
3775/**********************************************************************/
3783static enum fc_tristate
3785 const struct req_context *context,
3786 const struct player *other_player,
3787 const struct requirement *req)
3788{
3789 const struct nation_type *nationality;
3790 enum fc_tristate ret;
3791
3793
3794 nationality = req->source.value.nationality;
3795
3796 switch (req->range) {
3797 case REQ_RANGE_CITY:
3798 if (context->city == NULL) {
3799 return TRI_MAYBE;
3800 }
3801 citizens_iterate(context->city, slot, count) {
3802 if (player_slot_get_player(slot)->nation == nationality) {
3803 return TRI_YES;
3804 }
3806
3807 return TRI_NO;
3809 if (context->city == NULL) {
3810 return TRI_MAYBE;
3811 }
3812 citizens_iterate(context->city, slot, count) {
3813 if (player_slot_get_player(slot)->nation == nationality) {
3814 return TRI_YES;
3815 }
3817
3818 ret = TRI_NO;
3820 if (trade_partner == NULL) {
3821 ret = TRI_MAYBE;
3822 } else {
3823 citizens_iterate(trade_partner, slot, count) {
3824 if (player_slot_get_player(slot)->nation == nationality) {
3825 return TRI_YES;
3826 }
3828 }
3830
3831 return ret;
3832 case REQ_RANGE_PLAYER:
3833 case REQ_RANGE_TEAM:
3834 case REQ_RANGE_ALLIANCE:
3835 case REQ_RANGE_WORLD:
3836 case REQ_RANGE_LOCAL:
3837 case REQ_RANGE_TILE:
3839 case REQ_RANGE_ADJACENT:
3841 case REQ_RANGE_COUNT:
3842 break;
3843 }
3844
3845 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3846
3847 return TRI_MAYBE;
3848}
3849
3850/**********************************************************************/
3858static enum fc_tristate
3860 const struct req_context *context,
3861 const struct player *other_player,
3862 const struct requirement *req)
3863{
3864 const struct nation_type *nation;
3865
3867
3868 nation = req->source.value.origowner;
3869
3870 switch (req->range) {
3871 case REQ_RANGE_CITY:
3872 if (context->city == NULL || context->city->original == NULL) {
3873 return TRI_MAYBE;
3874 }
3875 if (player_nation(context->city->original) == nation) {
3876 return TRI_YES;
3877 }
3878
3879 return TRI_NO;
3881 case REQ_RANGE_PLAYER:
3882 case REQ_RANGE_TEAM:
3883 case REQ_RANGE_ALLIANCE:
3884 case REQ_RANGE_WORLD:
3885 case REQ_RANGE_LOCAL:
3886 case REQ_RANGE_TILE:
3888 case REQ_RANGE_ADJACENT:
3890 case REQ_RANGE_COUNT:
3891 break;
3892 }
3893
3894 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3895
3896 return TRI_MAYBE;
3897}
3898
3899/**********************************************************************/
3903 const struct player *other_player,
3904 enum req_range range,
3905 int diplrel)
3906{
3907 switch (range) {
3908 case REQ_RANGE_PLAYER:
3909 if (target_player == NULL) {
3910 return TRI_MAYBE;
3911 }
3913 case REQ_RANGE_TEAM:
3914 case REQ_RANGE_ALLIANCE:
3915 case REQ_RANGE_WORLD:
3916 if (target_player == NULL) {
3917 return TRI_MAYBE;
3918 }
3919 players_iterate_alive(plr2) {
3921 if (is_diplrel_to_other(plr2, diplrel)) {
3922 return TRI_YES;
3923 }
3924 }
3926 return TRI_NO;
3927 case REQ_RANGE_LOCAL:
3928 if (target_player == NULL || other_player == NULL) {
3929 return TRI_MAYBE;
3930 }
3931 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
3932 case REQ_RANGE_TILE:
3934 case REQ_RANGE_ADJACENT:
3935 case REQ_RANGE_CITY:
3938 case REQ_RANGE_COUNT:
3939 break;
3940 }
3941
3942 fc_assert_msg(FALSE, "Invalid range %d.", range);
3943
3944 return TRI_MAYBE;
3945}
3946
3947/**********************************************************************/
3954static enum fc_tristate
3956 const struct req_context *context,
3957 const struct player *other_player,
3958 const struct requirement *req)
3959{
3961
3962 return is_diplrel_in_range(context->player, other_player, req->range,
3963 req->source.value.diplrel);
3964}
3965
3966/**********************************************************************/
3974static enum fc_tristate
3976 const struct req_context *context,
3977 const struct player *other_player,
3978 const struct requirement *req)
3979{
3981
3982 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
3983 : NULL,
3984 context->player,
3985 req->range,
3986 req->source.value.diplrel);
3987}
3988
3989/**********************************************************************/
3998static enum fc_tristate
4000 const struct req_context *context,
4001 const struct player *other_player,
4002 const struct requirement *req)
4003{
4005
4006 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4007 : NULL,
4008 other_player,
4009 req->range,
4010 req->source.value.diplrel);
4011}
4012
4013/**********************************************************************/
4016static enum fc_tristate
4018 const struct player *other_player,
4019 enum req_range range,
4020 int diplrel)
4021{
4022 enum fc_tristate out = TRI_NO;
4023
4024 if (target_tile == NULL) {
4025 return TRI_MAYBE;
4026 }
4027
4030 unit_owner(target_unit), other_player, range, diplrel);
4031
4034
4035 return out;
4036}
4037
4038/**********************************************************************/
4047static enum fc_tristate
4049 const struct req_context *context,
4050 const struct player *other_player,
4051 const struct requirement *req)
4052{
4054
4055 return is_diplrel_unitany_in_range(context->tile, context->player,
4056 req->range,
4057 req->source.value.diplrel);
4058}
4059
4060/**********************************************************************/
4069static enum fc_tristate
4071 const struct req_context *context,
4072 const struct player *other_player,
4073 const struct requirement *req)
4074{
4076
4077 return is_diplrel_unitany_in_range(context->tile, other_player,
4078 req->range,
4079 req->source.value.diplrel);
4080}
4081
4082/**********************************************************************/
4089static enum fc_tristate
4091 const struct req_context *context,
4092 const struct player *other_player,
4093 const struct requirement *req)
4094{
4095 const struct unit_type *punittype;
4096
4098
4099 punittype = req->source.value.utype;
4100
4101 if (req->range != REQ_RANGE_LOCAL) {
4102 return TRI_NO;
4103 }
4104 if (!context->unittype) {
4105 return TRI_MAYBE;
4106 }
4107
4108 return BOOL_TO_TRISTATE(context->unittype == punittype);
4109}
4110
4111/**********************************************************************/
4118static enum fc_tristate
4120 const struct req_context *context,
4121 const struct player *other_player,
4122 const struct requirement *req)
4123{
4124 enum unit_type_flag_id unitflag;
4125
4127
4128 unitflag = req->source.value.unitflag;
4129
4130 if (req->range != REQ_RANGE_LOCAL) {
4131 return TRI_NO;
4132 }
4133 if (!context->unittype) {
4134 return TRI_MAYBE;
4135 }
4136
4137 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4138}
4139
4140/**********************************************************************/
4147static enum fc_tristate
4149 const struct req_context *context,
4150 const struct player *other_player,
4151 const struct requirement *req)
4152{
4153 const struct unit_class *pclass;
4154
4156
4157 pclass = req->source.value.uclass;
4158
4159 if (req->range != REQ_RANGE_LOCAL) {
4160 return TRI_NO;
4161 }
4162 if (!context->unittype) {
4163 return TRI_MAYBE;
4164 }
4165
4166 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4167}
4168
4169/**********************************************************************/
4177static enum fc_tristate
4179 const struct req_context *context,
4180 const struct player *other_player,
4181 const struct requirement *req)
4182{
4184
4186
4188
4189 if (req->range != REQ_RANGE_LOCAL) {
4190 return TRI_NO;
4191 }
4192 if (!context->unittype) {
4193 return TRI_MAYBE;
4194 }
4195
4197}
4198
4199/**********************************************************************/
4206static enum fc_tristate
4208 const struct req_context *context,
4209 const struct player *other_player,
4210 const struct requirement *req)
4211{
4212 enum ustate_prop uprop;
4213
4215
4217
4219 "Unsupported range \"%s\"",
4220 req_range_name(req->range));
4221
4222 /* Could be asked with incomplete data.
4223 * is_req_active() will handle it based on prob_type. */
4224 if (context->unit == NULL) {
4225 return TRI_MAYBE;
4226 }
4227
4228 switch (uprop) {
4229 case USP_TRANSPORTED:
4230 return BOOL_TO_TRISTATE(context->unit->transporter != NULL);
4231 case USP_LIVABLE_TILE:
4232 return BOOL_TO_TRISTATE(
4234 unit_tile(context->unit)));
4235 break;
4236 case USP_TRANSPORTING:
4238 case USP_HAS_HOME_CITY:
4239 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
4240 case USP_NATIVE_TILE:
4241 return BOOL_TO_TRISTATE(
4243 unit_tile(context->unit)));
4244 break;
4245 case USP_NATIVE_EXTRA:
4246 return BOOL_TO_TRISTATE(
4248 unit_type_get(context->unit)));
4249 break;
4251 return BOOL_TO_TRISTATE(context->unit->moved);
4252 case USP_COUNT:
4253 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
4254 /* Invalid property is unknowable. */
4255 return TRI_NO;
4256 }
4257
4258 /* Should never be reached */
4259 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
4260
4261 return TRI_NO;
4262}
4263
4264/**********************************************************************/
4271static enum fc_tristate
4273 const struct req_context *context,
4274 const struct player *other_player,
4275 const struct requirement *req)
4276{
4277 enum unit_activity activity;
4278
4280
4281 activity = req->source.value.activity;
4282
4284 "Unsupported range \"%s\"",
4285 req_range_name(req->range));
4286
4287 if (context->unit == NULL) {
4288 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
4289 * it's the zero value that context has by default - so many callers
4290 * who meant not to set specific activity actually have ACTIVITY_IDLE
4291 * instead of ACTIVITY_LAST */
4292 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
4293 return BOOL_TO_TRISTATE(activity == context->activity);
4294 }
4295
4296 /* Could be asked with incomplete data.
4297 * is_req_active() will handle it based on prob_type. */
4298 return TRI_MAYBE;
4299 }
4300
4301 switch (context->unit->activity) {
4302 case ACTIVITY_IDLE:
4303 case ACTIVITY_SENTRY:
4304 case ACTIVITY_GOTO:
4305 case ACTIVITY_EXPLORE:
4306 /* Seen as idle. */
4307 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
4308 default:
4309 /* Handled below. */
4310 break;
4311 }
4312
4313 return BOOL_TO_TRISTATE(context->unit->activity == activity);
4314}
4315
4316/**********************************************************************/
4323static enum fc_tristate
4325 const struct req_context *context,
4326 const struct player *other_player,
4327 const struct requirement *req)
4328{
4330
4331 if (context->unit == NULL) {
4332 return TRI_MAYBE;
4333 } else {
4334 return BOOL_TO_TRISTATE(context->unit->veteran
4335 >= req->source.value.minveteran);
4336 }
4337}
4338
4339/**********************************************************************/
4347static enum fc_tristate
4349 const struct req_context *context,
4350 const struct player *other_player,
4351 const struct requirement *req)
4352{
4354
4355 if (context->unit == NULL) {
4356 return TRI_MAYBE;
4357 } else {
4359 <= context->unit->moves_left);
4360 }
4361}
4362
4363/**********************************************************************/
4371static enum fc_tristate
4373 const struct req_context *context,
4374 const struct player *other_player,
4375 const struct requirement *req)
4376{
4378
4379 if (context->unit == NULL) {
4380 return TRI_MAYBE;
4381 } else {
4383 <= context->unit->hp);
4384 }
4385}
4386
4387/**********************************************************************/
4394static enum fc_tristate
4396 const struct req_context *context,
4397 const struct player *other_player,
4398 const struct requirement *req)
4399{
4401
4402 switch (req->range) {
4403 case REQ_RANGE_LOCAL:
4404 if (context->unit == NULL || !is_server()) {
4405 return TRI_MAYBE;
4406 } else {
4407 return BOOL_TO_TRISTATE(
4408 req->source.value.age <=
4409 game.info.turn - context->unit->birth_turn);
4410 }
4411 break;
4412 case REQ_RANGE_CITY:
4413 if (context->city == NULL) {
4414 return TRI_MAYBE;
4415 } else {
4416 return BOOL_TO_TRISTATE(
4417 req->source.value.age <=
4418 game.info.turn - context->city->turn_founded);
4419 }
4420 break;
4421 case REQ_RANGE_PLAYER:
4422 if (context->player == NULL) {
4423 return TRI_MAYBE;
4424 } else {
4425 return BOOL_TO_TRISTATE(req->source.value.age
4426 <= player_age(context->player));
4427 }
4428 break;
4429 default:
4430 return TRI_MAYBE;
4431 break;
4432 }
4433}
4434
4435/**********************************************************************/
4442static enum fc_tristate
4444 const struct req_context *context,
4445 const struct player *other_player,
4446 const struct requirement *req)
4447{
4449
4450 switch (req->range) {
4451 case REQ_RANGE_LOCAL:
4452 if (context->unit == NULL || !is_server()) {
4453 return TRI_MAYBE;
4454 } else {
4455 return BOOL_TO_TRISTATE(
4456 req->source.value.form_age <=
4457 game.info.turn - context->unit->current_form_turn);
4458 }
4459 break;
4460 default:
4461 return TRI_MAYBE;
4462 break;
4463 }
4464}
4465
4466/**********************************************************************/
4469static bool is_city_in_tile(const struct tile *ptile,
4470 const struct city *pcity)
4471{
4472 if (pcity == NULL) {
4473 return tile_city(ptile) != NULL;
4474 } else {
4475 return is_city_center(pcity, ptile);
4476 }
4477}
4478
4479/**********************************************************************/
4486static enum fc_tristate
4488 const struct req_context *context,
4489 const struct player *other_player,
4490 const struct requirement *req)
4491{
4492 enum citytile_type citytile;
4493
4495
4496 citytile = req->source.value.citytile;
4497
4499 if (context->tile == NULL) {
4500 return TRI_MAYBE;
4501 }
4502
4503 switch (citytile) {
4504 case CITYT_CENTER:
4505 switch (req->range) {
4506 case REQ_RANGE_TILE:
4508 context->city));
4510 if (is_city_in_tile(context->tile, context->city)) {
4511 return TRI_YES;
4512 }
4514 if (is_city_in_tile(adjc_tile, context->city)) {
4515 return TRI_YES;
4516 }
4518
4519 return TRI_NO;
4520 case REQ_RANGE_ADJACENT:
4521 if (is_city_in_tile(context->tile, context->city)) {
4522 return TRI_YES;
4523 }
4525 if (is_city_in_tile(adjc_tile, context->city)) {
4526 return TRI_YES;
4527 }
4529
4530 return TRI_NO;
4531 case REQ_RANGE_CITY:
4534 case REQ_RANGE_PLAYER:
4535 case REQ_RANGE_TEAM:
4536 case REQ_RANGE_ALLIANCE:
4537 case REQ_RANGE_WORLD:
4538 case REQ_RANGE_LOCAL:
4539 case REQ_RANGE_COUNT:
4540 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4541 break;
4542 }
4543
4544 return TRI_MAYBE;
4545 case CITYT_CLAIMED:
4546 switch (req->range) {
4547 case REQ_RANGE_TILE:
4548 return BOOL_TO_TRISTATE(context->tile->owner != NULL);
4550 if (context->tile->owner != NULL) {
4551 return TRI_YES;
4552 }
4554 if (adjc_tile->owner != NULL) {
4555 return TRI_YES;
4556 }
4558
4559 return TRI_NO;
4560 case REQ_RANGE_ADJACENT:
4561 if (context->tile->owner != NULL) {
4562 return TRI_YES;
4563 }
4565 if (adjc_tile->owner != NULL) {
4566 return TRI_YES;
4567 }
4569
4570 return TRI_NO;
4571 case REQ_RANGE_CITY:
4574 case REQ_RANGE_PLAYER:
4575 case REQ_RANGE_TEAM:
4576 case REQ_RANGE_ALLIANCE:
4577 case REQ_RANGE_WORLD:
4578 case REQ_RANGE_LOCAL:
4579 case REQ_RANGE_COUNT:
4580 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4581 break;
4582 }
4583
4584 return TRI_MAYBE;
4585 case CITYT_EXTRAS_OWNED:
4586 switch (req->range) {
4587 case REQ_RANGE_TILE:
4588 return BOOL_TO_TRISTATE(context->tile->extras_owner != NULL);
4590 if (context->tile->extras_owner != NULL) {
4591 return TRI_YES;
4592 }
4594 if (adjc_tile->extras_owner != NULL) {
4595 return TRI_YES;
4596 }
4598
4599 return TRI_NO;
4600 case REQ_RANGE_ADJACENT:
4601 if (context->tile->extras_owner != NULL) {
4602 return TRI_YES;
4603 }
4605 if (adjc_tile->extras_owner != NULL) {
4606 return TRI_YES;
4607 }
4609
4610 return TRI_NO;
4611 case REQ_RANGE_CITY:
4614 case REQ_RANGE_PLAYER:
4615 case REQ_RANGE_TEAM:
4616 case REQ_RANGE_ALLIANCE:
4617 case REQ_RANGE_WORLD:
4618 case REQ_RANGE_LOCAL:
4619 case REQ_RANGE_COUNT:
4620 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4621 break;
4622 }
4623
4624 return TRI_MAYBE;
4625 case CITYT_WORKED:
4626 switch (req->range) {
4627 case REQ_RANGE_TILE:
4628 return BOOL_TO_TRISTATE(context->tile->worked != NULL);
4630 if (context->tile->worked != NULL) {
4631 return TRI_YES;
4632 }
4634 if (adjc_tile->worked != NULL) {
4635 return TRI_YES;
4636 }
4638
4639 return TRI_NO;
4640 case REQ_RANGE_ADJACENT:
4641 if (context->tile->worked != NULL) {
4642 return TRI_YES;
4643 }
4645 if (adjc_tile->worked != NULL) {
4646 return TRI_YES;
4647 }
4649
4650 return TRI_NO;
4651 case REQ_RANGE_CITY:
4654 case REQ_RANGE_PLAYER:
4655 case REQ_RANGE_TEAM:
4656 case REQ_RANGE_ALLIANCE:
4657 case REQ_RANGE_WORLD:
4658 case REQ_RANGE_LOCAL:
4659 case REQ_RANGE_COUNT:
4660 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4661 break;
4662 }
4663
4664 return TRI_MAYBE;
4666 {
4668 const struct tile *target_tile = context->tile, *cc_tile;
4669
4670 if (!context->city) {
4671 return TRI_MAYBE;
4672 }
4673 cc_tile = city_tile(context->city);
4674 if (!cc_tile) {
4675 /* Unplaced virtual city */
4676 return TRI_MAYBE;
4677 }
4679 /* Note: No special treatment of 0 == cc here*/
4680 switch (req->range) {
4681 case REQ_RANGE_TILE:
4684 if (tile_continent(target_tile) == cc) {
4685 return TRI_YES;
4686 }
4688 if (tile_continent(adjc_tile) == cc) {
4689 return TRI_YES;
4690 }
4692
4693 return TRI_NO;
4694 case REQ_RANGE_ADJACENT:
4695 if (tile_continent(target_tile) == cc) {
4696 return TRI_YES;
4697 }
4699 if (tile_continent(adjc_tile) == cc) {
4700 return TRI_YES;
4701 }
4703
4704 return TRI_NO;
4705 case REQ_RANGE_CITY:
4708 case REQ_RANGE_PLAYER:
4709 case REQ_RANGE_TEAM:
4710 case REQ_RANGE_ALLIANCE:
4711 case REQ_RANGE_WORLD:
4712 case REQ_RANGE_LOCAL:
4713 case REQ_RANGE_COUNT:
4714 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4715 break;
4716 }
4717 }
4718
4719 return TRI_MAYBE;
4721 {
4722 int n = 0;
4724 bool ukt = FALSE;
4725 const struct tile *target_tile = context->tile, *cc_tile;
4726
4727 if (!context->city) {
4728 return TRI_MAYBE;
4729 }
4730 cc_tile = city_tile(context->city);
4731 if (!cc_tile) {
4732 /* Unplaced virtual city */
4733 return TRI_MAYBE;
4734 }
4736 if (!cc) {
4737 /* Don't know the city center terrain class.
4738 * Maybe, the city floats? Even if the rules prohibit it... */
4739 return TRI_MAYBE;
4740 }
4743
4744 if (0 != tc) {
4745 bool seen = FALSE;
4746 int i = n;
4747
4748 if (tc == cc) {
4749 continue;
4750 }
4751 while (--i >= 0) {
4752 if (adjc_cont[i] == tc) {
4753 seen = TRUE;
4754 break;
4755 }
4756 }
4757 if (seen) {
4758 continue;
4759 }
4761 } else {
4762 /* Likely, it's a black tile in client and we don't know
4763 * We possibly can calculate, but keep it simple. */
4764 ukt = TRUE;
4765 }
4767 if (0 == n) {
4768 return ukt ? TRI_MAYBE : TRI_NO;
4769 }
4770
4771 switch (req->range) {
4772 case REQ_RANGE_TILE:
4773 {
4775
4776 if (cc == tc) {
4777 return TRI_NO;
4778 }
4779 if (0 == tc || ukt) {
4780 return TRI_MAYBE;
4781 }
4782 for (int i = 0; i < n; i++) {
4783 if (tc == adjc_cont[i]) {
4784 return TRI_YES;
4785 }
4786 }
4787 }
4788
4789 return TRI_NO;
4790 case REQ_RANGE_ADJACENT:
4791 if (ukt) {
4792 /* If ALL the tiles in range are on cc, we can say it's false */
4794 if (tile_continent(adjc_tile) != cc) {
4795 return TRI_MAYBE;
4796 }
4798
4799 return TRI_NO;
4800 } else {
4803
4804 if (0 == tc) {
4805 return TRI_MAYBE;
4806 }
4807 for (int i = 0; i < n; i++) {
4808 if (tc == adjc_cont[i]) {
4809 return TRI_YES;
4810 }
4811 }
4813 }
4814
4815 return TRI_NO;
4817 if (ukt) {
4818 /* If ALL the tiles in range are on cc, we can say it's false */
4820 if (tile_continent(cadjc_tile) != cc) {
4821 return TRI_MAYBE;
4822 }
4824 } else {
4827
4828 if (0 == tc) {
4829 return TRI_MAYBE;
4830 }
4831 for (int i = 0; i < n; i++) {
4832 if (tc == adjc_cont[i]) {
4833 return TRI_YES;
4834 }
4835 }
4837 }
4838
4839 return TRI_NO;
4840 case REQ_RANGE_CITY:
4843 case REQ_RANGE_PLAYER:
4844 case REQ_RANGE_TEAM:
4845 case REQ_RANGE_ALLIANCE:
4846 case REQ_RANGE_WORLD:
4847 case REQ_RANGE_LOCAL:
4848 case REQ_RANGE_COUNT:
4849 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4850 break;
4851 }
4852 }
4853
4854 return TRI_MAYBE;
4855 case CITYT_LAST:
4856 /* Handled below */
4857 break;
4858 }
4859
4860 /* Not implemented */
4861 log_error("is_req_active(): citytile %d not supported.",
4862 citytile);
4863 return TRI_MAYBE;
4864}
4865
4866/**********************************************************************/
4874static enum fc_tristate
4876 const struct req_context *context,
4877 const struct player *other_player,
4878 const struct requirement *req)
4879{
4880 enum citystatus_type citystatus;
4881
4883
4884 citystatus = req->source.value.citystatus;
4885
4886 if (context->city == NULL) {
4887 return TRI_MAYBE;
4888 }
4889
4890 switch (citystatus) {
4892 switch (req->range) {
4893 case REQ_RANGE_CITY:
4894 if (context->city->original == NULL) {
4895 return TRI_MAYBE;
4896 }
4897 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
4899 {
4900 enum fc_tristate ret;
4901
4902 if (city_owner(context->city) == context->city->original) {
4903 return TRI_YES;
4904 }
4905
4906 ret = TRI_NO;
4908 if (trade_partner == NULL || trade_partner->original == NULL) {
4909 ret = TRI_MAYBE;
4910 } else if (city_owner(trade_partner) == trade_partner->original) {
4911 return TRI_YES;
4912 }
4914
4915 return ret;
4916 }
4917 case REQ_RANGE_LOCAL:
4918 case REQ_RANGE_TILE:
4920 case REQ_RANGE_ADJACENT:
4922 case REQ_RANGE_PLAYER:
4923 case REQ_RANGE_TEAM:
4924 case REQ_RANGE_ALLIANCE:
4925 case REQ_RANGE_WORLD:
4926 case REQ_RANGE_COUNT:
4927 break;
4928 }
4929
4930 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
4931 req->range);
4932
4933 return TRI_MAYBE;
4934
4935 case CITYS_STARVED:
4936 switch (req->range) {
4937 case REQ_RANGE_CITY:
4938 return BOOL_TO_TRISTATE(context->city->had_famine);
4940 {
4941 enum fc_tristate ret;
4942
4943 if (context->city->had_famine) {
4944 return TRI_YES;
4945 }
4946
4947 ret = TRI_NO;
4949 if (trade_partner == NULL) {
4950 ret = TRI_MAYBE;
4951 } else if (trade_partner->had_famine) {
4952 return TRI_YES;
4953 }
4955
4956 return ret;
4957 }
4958 case REQ_RANGE_LOCAL:
4959 case REQ_RANGE_TILE:
4961 case REQ_RANGE_ADJACENT:
4963 case REQ_RANGE_PLAYER:
4964 case REQ_RANGE_TEAM:
4965 case REQ_RANGE_ALLIANCE:
4966 case REQ_RANGE_WORLD:
4967 case REQ_RANGE_COUNT:
4968 break;
4969 }
4970
4971 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
4972 req->range);
4973
4974 return TRI_MAYBE;
4975
4976 case CITYS_DISORDER:
4977 switch (req->range) {
4978 case REQ_RANGE_CITY:
4979 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
4981 {
4982 enum fc_tristate ret;
4983
4984 if (context->city->anarchy > 0) {
4985 return TRI_YES;
4986 }
4987
4988 ret = TRI_NO;
4990 if (trade_partner == NULL) {
4991 ret = TRI_MAYBE;
4992 } else if (trade_partner->anarchy > 0) {
4993 return TRI_YES;
4994 }
4996
4997 return ret;
4998 }
4999 case REQ_RANGE_LOCAL:
5000 case REQ_RANGE_TILE:
5002 case REQ_RANGE_ADJACENT:
5004 case REQ_RANGE_PLAYER:
5005 case REQ_RANGE_TEAM:
5006 case REQ_RANGE_ALLIANCE:
5007 case REQ_RANGE_WORLD:
5008 case REQ_RANGE_COUNT:
5009 break;
5010 }
5011
5012 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
5013 req->range);
5014
5015 return TRI_MAYBE;
5016
5017 case CITYS_CELEBRATION:
5018 switch (req->range) {
5019 case REQ_RANGE_CITY:
5020 return BOOL_TO_TRISTATE(context->city->rapture > 0);
5022 {
5023 enum fc_tristate ret;
5024
5025 if (context->city->rapture > 0) {
5026 return TRI_YES;
5027 }
5028
5029 ret = TRI_NO;
5031 if (trade_partner == NULL) {
5032 ret = TRI_MAYBE;
5033 } else if (trade_partner->rapture > 0) {
5034 return TRI_YES;
5035 }
5037
5038 return ret;
5039 }
5040 case REQ_RANGE_LOCAL:
5041 case REQ_RANGE_TILE:
5043 case REQ_RANGE_ADJACENT:
5045 case REQ_RANGE_PLAYER:
5046 case REQ_RANGE_TEAM:
5047 case REQ_RANGE_ALLIANCE:
5048 case REQ_RANGE_WORLD:
5049 case REQ_RANGE_COUNT:
5050 break;
5051 }
5052
5053 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
5054 req->range);
5055
5056 return TRI_MAYBE;
5057
5058 case CITYS_TRANSFERRED:
5059 switch (req->range) {
5060 case REQ_RANGE_CITY:
5061 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
5063 {
5064 enum fc_tristate ret;
5065
5066 if (context->city->acquire_t != CACQ_FOUNDED) {
5067 return TRI_YES;
5068 }
5069
5070 ret = TRI_NO;
5072 if (trade_partner == NULL) {
5073 ret = TRI_MAYBE;
5074 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
5075 return TRI_YES;
5076 }
5078
5079 return ret;
5080 }
5081 case REQ_RANGE_LOCAL:
5082 case REQ_RANGE_TILE:
5084 case REQ_RANGE_ADJACENT:
5086 case REQ_RANGE_PLAYER:
5087 case REQ_RANGE_TEAM:
5088 case REQ_RANGE_ALLIANCE:
5089 case REQ_RANGE_WORLD:
5090 case REQ_RANGE_COUNT:
5091 break;
5092 }
5093
5094 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
5095 req->range);
5096
5097 return TRI_MAYBE;
5098
5099 case CITYS_LAST:
5100 break;
5101 }
5102
5103 /* Not implemented */
5104 log_error("is_req_active(): citystatus %d not supported.",
5105 citystatus);
5106
5107 return TRI_MAYBE;
5108}
5109
5110/**********************************************************************/
5117static enum fc_tristate
5119 const struct req_context *context,
5120 const struct player *other_player,
5121 const struct requirement *req)
5122{
5124
5125 if (context->city == NULL) {
5126 return TRI_MAYBE;
5127 } else {
5128 if (req->range == REQ_RANGE_TRADE_ROUTE) {
5129 enum fc_tristate ret;
5130
5131 if (city_size_get(context->city) >= req->source.value.minsize) {
5132 return TRI_YES;
5133 }
5134
5135 ret = TRI_NO;
5137 if (trade_partner == NULL) {
5138 ret = TRI_MAYBE;
5139 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
5140 return TRI_YES;
5141 }
5143
5144 return ret;
5145 } else {
5147 >= req->source.value.minsize);
5148 }
5149 }
5150}
5151
5152/**********************************************************************/
5159static enum fc_tristate
5161 const struct req_context *context,
5162 const struct player *other_player,
5163 const struct requirement *req)
5164{
5165 const struct counter *count;
5166
5168
5169 count = req->source.value.counter;
5170
5171 if (NULL == context->city) {
5172 return TRI_MAYBE;
5173 }
5174 return BOOL_TO_TRISTATE(count->checkpoint <=
5175 context->city->counter_values[
5176 counter_index(count)]);
5177}
5178
5179/**********************************************************************/
5187static enum fc_tristate
5189 const struct req_context *context,
5190 const struct player *other_player,
5191 const struct requirement *req)
5192{
5193 const struct achievement *achievement;
5194
5196
5198
5199 if (req->range == REQ_RANGE_WORLD) {
5201 } else if (context->player == NULL) {
5202 return TRI_MAYBE;
5203 } else if (req->range == REQ_RANGE_ALLIANCE
5204 || req->range == REQ_RANGE_TEAM) {
5205 players_iterate_alive(plr2) {
5206 if (players_in_same_range(context->player, plr2, req->range)
5208 return TRI_YES;
5209 }
5211 return TRI_NO;
5212 } else if (req->range == REQ_RANGE_PLAYER) {
5214 return TRI_YES;
5215 } else {
5216 return TRI_NO;
5217 }
5218 }
5219
5220 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
5221
5222 return TRI_MAYBE;
5223}
5224
5225/**********************************************************************/
5233static enum fc_tristate
5235 const struct req_context *context,
5236 const struct player *other_player,
5237 const struct requirement *req)
5238{
5239 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
5240
5243
5244 switch (req->source.kind) {
5245 case VUT_MINLATITUDE:
5246 min = req->source.value.latitude;
5247 break;
5248 case VUT_MAXLATITUDE:
5249 max = req->source.value.latitude;
5250 break;
5251 default:
5253 || req->source.kind == VUT_MAXLATITUDE);
5254 break;
5255 }
5256
5257 switch (req->range) {
5258 case REQ_RANGE_WORLD:
5260 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
5261
5262 case REQ_RANGE_TILE:
5263 if (context->tile == NULL) {
5264 return TRI_MAYBE;
5265 } else {
5267
5269 }
5270
5272 if (context->tile == NULL) {
5273 return TRI_MAYBE;
5274 }
5275
5278
5280 return TRI_YES;
5281 }
5283 return TRI_NO;
5284
5285 case REQ_RANGE_ADJACENT:
5286 if (!context->tile) {
5287 return TRI_MAYBE;
5288 }
5289
5292
5294 return TRI_YES;
5295 }
5297 return TRI_NO;
5298
5299 case REQ_RANGE_CITY:
5302 case REQ_RANGE_PLAYER:
5303 case REQ_RANGE_TEAM:
5304 case REQ_RANGE_ALLIANCE:
5305 case REQ_RANGE_LOCAL:
5306 case REQ_RANGE_COUNT:
5307 break;
5308 }
5309
5311 "Illegal range %d for latitude requirement.", req->range);
5312
5313 return TRI_MAYBE;
5314}
5315
5316/**********************************************************************/
5323static enum fc_tristate
5325 const struct req_context *context,
5326 const struct player *other_player,
5327 const struct requirement *req)
5328{
5330
5332}
5333
5334/**********************************************************************/
5341static enum fc_tristate
5343 const struct req_context *context,
5344 const struct player *other_player,
5345 const struct requirement *req)
5346{
5348
5350 >= req->source.value.mincalfrag);
5351}
5352
5353/**********************************************************************/
5360static enum fc_tristate
5362 const struct req_context *context,
5363 const struct player *other_player,
5364 const struct requirement *req)
5365{
5367
5368 return BOOL_TO_TRISTATE(
5370}
5371
5372/**********************************************************************/
5379static enum fc_tristate
5381 const struct req_context *context,
5382 const struct player *other_player,
5383 const struct requirement *req)
5384{
5386
5387 return BOOL_TO_TRISTATE(
5389}
5390
5391/**********************************************************************/
5399static enum fc_tristate
5401 const struct req_context *context,
5402 const struct player *other_player,
5403 const struct requirement *req)
5404{
5406
5408 req->source.value.ssetval));
5409}
5410
5411/* Not const for potential ruleset-related adjustment */
5414
5415 /* Alphabetical order of enum constant */
5474};
5475
5476/**********************************************************************/
5489 const struct player *other_player,
5490 const struct requirement *req,
5491 const enum req_problem_type prob_type)
5492{
5493 const struct civ_map *nmap = &(wld.map);
5494 enum fc_tristate eval;
5496 struct thr_req_data *trdata = NULL;
5497
5500 if (fc_threads_equal(self, data->thr_id)) {
5501 trdata = data;
5502 }
5504
5505 if (trdata == NULL) {
5506 trdata = fc_malloc(sizeof(struct thr_req_data));
5507 trdata->thr_id = self;
5509 }
5511
5512 eval = tri_req_present(nmap, context, other_player, req);
5513
5514 if (eval == TRI_MAYBE) {
5515 if (prob_type == RPT_POSSIBLE) {
5516 return TRUE;
5517 } else {
5518 return FALSE;
5519 }
5520 }
5521
5522 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
5523}
5524
5525/**********************************************************************/
5533static
5535 const struct req_context *context,
5536 const struct player *other_player,
5537 const struct requirement *req)
5538{
5539 if (context == NULL) {
5541 }
5542
5543 if (req->source.kind >= VUT_COUNT) {
5544 log_error("tri_req_present(): invalid source kind %d.",
5545 req->source.kind);
5546 return TRI_NO;
5547 }
5548
5550
5551 return req_definitions[req->source.kind].cb(nmap, context,
5552 other_player, req);
5553}
5554
5555/**********************************************************************/
5564 const struct player *other_player,
5565 const struct requirement *req)
5566{
5567 const struct civ_map *nmap = &(wld.map);
5568 enum fc_tristate eval = tri_req_present(nmap, context, other_player, req);
5569
5570 if (!req->present) {
5571 if (TRI_NO == eval) {
5572 return TRI_YES;
5573 }
5574 if (TRI_YES == eval) {
5575 return TRI_NO;
5576 }
5577 }
5578
5579 return eval;
5580}
5581
5582/**********************************************************************/
5597 const struct player *other_player,
5598 const struct requirement_vector *reqs,
5599 const enum req_problem_type prob_type)
5600{
5602 if (!is_req_active(context, other_player, preq, prob_type)) {
5603 return FALSE;
5604 }
5606
5607 return TRUE;
5608}
5609
5610/**********************************************************************/
5615 const enum req_range max_range,
5616 const struct req_context *context,
5617 const struct player *other_player,
5618 const struct requirement_vector *reqs,
5619 const enum req_problem_type prob_type)
5620{
5622 if (preq->range >= min_range && preq->range <= max_range) {
5623 if (!is_req_active(context, other_player, preq, prob_type)) {
5624 return FALSE;
5625 }
5626 }
5628
5629 return TRUE;
5630}
5631
5632/**********************************************************************/
5638enum fc_tristate
5640 const struct req_context *context,
5641 const struct player *other_player,
5642 const struct requirement *req)
5643{
5644 /* FIXME: doubles code from calendar.c */
5648 int fragment1 = fragment; /* if fragments don't advance */
5649 int year_inc, year_inc1;
5652 bool present, present1;
5653
5654 fc_assert(pass >= 0 && period >= 0);
5655 if (slowdown >= 3) {
5656 if (ypt > 1) {
5657 ypt = 1;
5658 }
5659 } else if (slowdown >= 2) {
5660 if (ypt > 2) {
5661 ypt = 2;
5662 }
5663 } else if (slowdown >= 1) {
5664 if (ypt > 5) {
5665 ypt = 5;
5666 }
5667 }
5668 year_inc = ypt * pass;
5671 int fragment_years;
5672
5673 fragment += fpt * pass;
5681 }
5683 if (year_inc + game.info.year >= 0) {
5684 year_inc++;
5685 year_inc1++;
5686 } else if (year_inc1 + game.info.year >= 0) {
5687 year_inc1++;
5688 }
5689 }
5690
5691 switch (req->source.kind) {
5692 case VUT_AGE:
5693 switch (req->range) {
5694 case REQ_RANGE_LOCAL:
5695 if (context->unit == NULL || !is_server()) {
5696 return TRI_MAYBE;
5697 } else {
5698 int ua = game.info.turn + pass - context->unit->birth_turn;
5699
5700 present = req->source.value.age <= ua;
5701 present1 = req->source.value.age <= ua + period;
5702 }
5703 break;
5704 case REQ_RANGE_CITY:
5705 if (context->city == NULL) {
5706 return TRI_MAYBE;
5707 } else {
5708 int ca = game.info.turn + pass - context->city->turn_founded;
5709
5710 present = req->source.value.age <= ca;
5711 present1 = req->source.value.age <= ca + period;
5712 }
5713 break;
5714 case REQ_RANGE_PLAYER:
5715 if (context->player == NULL) {
5716 return TRI_MAYBE;
5717 } else {
5718 present = req->source.value.age
5719 <= player_age(context->player) + pass;
5720 present1 = req->source.value.age
5721 <= player_age(context->player) + pass + period;
5722 }
5723 break;
5724 default:
5725 return TRI_MAYBE;
5726 }
5727 break;
5728 case VUT_FORM_AGE:
5729 if (context->unit == NULL || !is_server()) {
5730 return TRI_MAYBE;
5731 } else {
5732 int ua = game.info.turn + pass - context->unit->current_form_turn;
5733
5734 present = req->source.value.form_age <= ua;
5735 present1 = req->source.value.form_age <= ua + period;
5736 }
5737 break;
5738 case VUT_MINYEAR:
5739 present = game.info.year + year_inc >= req->source.value.minyear;
5741 break;
5742 case VUT_MINCALFRAG:
5744 /* Hope that the requirement is valid and fragments advance fine */
5745 return TRI_YES;
5746 }
5747 present = fragment >= req->source.value.mincalfrag;
5749 break;
5750 default:
5751 /* No special handling invented */
5752 return tri_req_active(context, other_player, req);
5753 }
5754 return BOOL_TO_TRISTATE(req->present
5755 ? present || present1 : !(present && present1));
5756}
5757
5758/**********************************************************************/
5764 (const struct req_context *context,
5765 const struct player *other_player,
5766 const struct requirement *req,
5767 void *data, int n_data)
5768{
5769 int i;
5770
5771 fc_assert_ret_val(data || n_data == 0, TRI_NO);
5772
5773 for (i = 0; i < n_data; i++) {
5774 if (are_requirements_contradictions(&((struct requirement *) data)[i],
5775 req)) {
5776 return TRI_NO;
5777 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
5778 return TRI_YES;
5779 }
5780 }
5781
5782 return tri_req_active(context, other_player, req);
5783}
5784
5785/**********************************************************************/
5791enum fc_tristate
5793 const struct player *other_player,
5794 const struct requirement_vector *reqs,
5797 void *data, int n_data)
5798{
5799 bool active = TRUE;
5800 bool certain = TRUE;
5801
5804 switch(tester(context, other_player, preq,
5805 data, n_data)) {
5806 case TRI_NO:
5807 active = FALSE;
5808 certain = TRUE;
5809 break;
5810 case TRI_YES:
5811 break;
5812 case TRI_MAYBE:
5813 certain = FALSE;
5814 if (maybe_reqs) {
5816 }
5817 break;
5818 default:
5820 active = FALSE;
5821 }
5822 if (!active) {
5823 break;
5824 }
5826
5827 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
5828}
5829
5830/**********************************************************************/
5840 const struct requirement *req)
5841{
5842 enum req_unchanging_status s;
5843 const struct civ_map *nmap = &(wld.map);
5844
5847 "Invalid source kind %d.", req->source.kind);
5849
5850 if (req->survives) {
5851 /* Special case for surviving requirements */
5852 /* Buildings may obsolete even here */
5853 if (VUT_IMPROVEMENT == req->source.kind) {
5854 const struct impr_type *b = req->source.value.building;
5855
5857 if (improvement_obsolete(context->player, b, context->city)) {
5858 /* FIXME: sometimes can unobsolete, but considering it
5859 * may sometimes put the function on endless recursion */
5860 return REQUCH_ACT; /* Mostly about techs */
5861 } else {
5862 /* NOTE: may obsoletion reqs be unchanging? Hardly but why not. */
5863 return REQUCH_NO;
5864 }
5865 }
5866 }
5867 s = unchanging_present(nmap, s, context, req);
5868 if (s != REQUCH_NO) {
5869 return unchanging_noally(nmap, s, context, req);
5870 }
5871 } else {
5874
5875 if (cond) {
5876 return cond(nmap, s, context, req);
5877 }
5878 }
5879
5880 return s;
5881}
5882
5883/**********************************************************************/
5888 const struct player *other_player,
5889 const struct requirement *req,
5891{
5893
5894 if (REQUCH_NO != u) {
5895 /* Presence is precalculated */
5896 bool auto_present = (req->survives
5897 && !(VUT_IMPROVEMENT == req->source.kind
5901
5902 if (auto_present ? req->present
5903 : is_req_active(context, other_player, req, RPT_POSSIBLE)) {
5904 /* Unchanging but does not block */
5905 return REQUCH_NO;
5906 }
5907 }
5908
5909 return u;
5910}
5911
5912/**********************************************************************/
5916bool is_req_in_vec(const struct requirement *req,
5917 const struct requirement_vector *vec)
5918{
5920 if (are_requirements_equal(req, preq)) {
5921 return TRUE;
5922 }
5924
5925 return FALSE;
5926}
5927
5928/**********************************************************************/
5935 enum universals_n kind)
5936{
5938 if (preq->present && preq->source.kind == kind) {
5939 return TRUE;
5940 }
5942 return FALSE;
5943}
5944
5945/**********************************************************************/
5954{
5955 switch (source->kind) {
5956 case VUT_ACTION:
5957 return !action_is_in_use(source->value.action);
5958 case VUT_UTFLAG:
5959 return !utype_flag_is_in_use(source->value.unitflag);
5960 case VUT_UCFLAG:
5961 return !uclass_flag_is_in_use(source->value.unitclassflag);
5962 case VUT_EXTRAFLAG:
5963 return !extra_flag_is_in_use(source->value.extraflag);
5964 case VUT_MINLATITUDE:
5965 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
5966 case VUT_MAXLATITUDE:
5967 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
5968 case VUT_COUNTER:
5969 case VUT_OTYPE:
5970 case VUT_SPECIALIST:
5971 case VUT_AI_LEVEL:
5972 case VUT_CITYTILE:
5973 case VUT_CITYSTATUS:
5974 case VUT_STYLE:
5975 case VUT_TOPO:
5976 case VUT_WRAP:
5977 case VUT_SERVERSETTING:
5978 case VUT_NATION:
5979 case VUT_NATIONGROUP:
5980 case VUT_ADVANCE:
5981 case VUT_TECHFLAG:
5982 case VUT_GOVERNMENT:
5983 case VUT_ACHIEVEMENT:
5984 case VUT_IMPROVEMENT:
5985 case VUT_SITE:
5986 case VUT_IMPR_GENUS:
5987 case VUT_IMPR_FLAG:
5988 case VUT_PLAYER_FLAG:
5989 case VUT_PLAYER_STATE:
5990 case VUT_MINSIZE:
5991 case VUT_MINCULTURE:
5992 case VUT_MINFOREIGNPCT:
5993 case VUT_MINTECHS:
5994 case VUT_NATIONALITY:
5995 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
5996 case VUT_DIPLREL:
5997 case VUT_DIPLREL_TILE:
5998 case VUT_DIPLREL_TILE_O:
6001 case VUT_MAXTILEUNITS:
6002 case VUT_UTYPE:
6003 case VUT_UCLASS:
6004 case VUT_MINVETERAN:
6005 case VUT_UNITSTATE:
6006 case VUT_ACTIVITY:
6007 case VUT_MINMOVES:
6008 case VUT_MINHP:
6009 case VUT_AGE:
6010 case VUT_FORM_AGE:
6011 case VUT_ROADFLAG:
6012 case VUT_MINCALFRAG:
6013 case VUT_TERRAIN:
6014 case VUT_EXTRA:
6015 case VUT_GOOD:
6016 case VUT_TERRAINCLASS:
6017 case VUT_TERRFLAG:
6018 case VUT_TERRAINALTER:
6019 case VUT_MINYEAR:
6020 case VUT_NONE:
6021 case VUT_COUNT:
6022 /* Not implemented. */
6023 break;
6024 }
6025
6026 return FALSE;
6027}
6028
6029/**********************************************************************/
6037{
6038 /* Not known to be impossible to fulfill */
6039 return req->present && universal_never_there(&req->source);
6040}
6041
6042/**********************************************************************/
6050{
6053 return TRUE;
6054 }
6056
6057 /* Not known to be impossible to fulfill */
6058 return FALSE;
6059}
6060
6061/**********************************************************************/
6070 const struct requirement_vector *vec)
6071{
6072 if (vec) {
6073 return 0;
6074 } else {
6075 return -1;
6076 }
6077}
6078
6079/********************************************************************/
6087struct requirement_vector *
6089{
6090 fc_assert_ret_val(number == 0, NULL);
6091 return (struct requirement_vector *)parent_item;
6092}
6093
6094/**********************************************************************/
6104const char *req_vec_change_translation(const struct req_vec_change *change,
6106{
6107 const char *req_vec_description;
6108 static char buf[MAX_LEN_NAME * 3];
6109 struct astring astr;
6110
6111 fc_assert_ret_val(change, NULL);
6113 NULL);
6114
6115 /* Get rid of the previous. */
6116 buf[0] = '\0';
6117
6118 if (namer == NULL) {
6119 /* TRANS: default description of a requirement vector
6120 * (used in ruledit) */
6121 req_vec_description = _("the requirement vector");
6122 } else {
6124 }
6125
6126 switch (change->operation) {
6127 case RVCO_REMOVE:
6128 fc_snprintf(buf, sizeof(buf),
6129 /* TRANS: remove a requirement from a requirement vector
6130 * (in ruledit).
6131 * The first %s is the operation.
6132 * The second %s is the requirement.
6133 * The third %s is a description of the requirement vector,
6134 * like "actor_reqs" */
6135 _("%s %s from %s"),
6137 req_to_fstring(&change->req, &astr),
6139 astr_free(&astr);
6140 break;
6141 case RVCO_APPEND:
6142 fc_snprintf(buf, sizeof(buf),
6143 /* TRANS: append a requirement to a requirement vector
6144 * (in ruledit).
6145 * The first %s is the operation.
6146 * The second %s is the requirement.
6147 * The third %s is a description of the requirement vector,
6148 * like "actor_reqs" */
6149 _("%s %s to %s"),
6151 req_to_fstring(&change->req, &astr),
6153 astr_free(&astr);
6154 break;
6155 case RVCO_NOOP:
6156 fc_snprintf(buf, sizeof(buf),
6157 /* TRANS: do nothing to a requirement vector (in ruledit).
6158 * The first %s is a description of the requirement vector,
6159 * like "actor_reqs" */
6160 _("Do nothing to %s"), req_vec_description);
6161 break;
6162 }
6163
6164 return buf;
6165}
6166
6167/**********************************************************************/
6179 const void *parent_item)
6180{
6181 struct requirement_vector *target
6182 = getter(parent_item, modification->vector_number);
6183 int i = 0;
6184
6185 switch (modification->operation) {
6186 case RVCO_APPEND:
6188 return TRUE;
6189 case RVCO_REMOVE:
6193 return TRUE;
6194 }
6195 i++;
6197 return FALSE;
6198 case RVCO_NOOP:
6199 return FALSE;
6200 }
6201
6202 return FALSE;
6203}
6204
6205/**********************************************************************/
6214struct req_vec_problem *
6216 const char *description,
6217 const char *description_translated)
6218{
6219 struct req_vec_problem *out;
6220 int i;
6221
6222 out = fc_malloc(sizeof(*out));
6223
6224 fc_strlcpy(out->description, description, sizeof(out->description));
6225 fc_strlcpy(out->description_translated, _(description_translated),
6226 sizeof(out->description_translated));
6227
6228 out->num_suggested_solutions = num_suggested_solutions;
6229 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
6230 * sizeof(struct req_vec_change));
6231 for (i = 0; i < out->num_suggested_solutions; i++) {
6232 /* No suggestions are ready yet. */
6233 out->suggested_solutions[i].operation = RVCO_NOOP;
6234 out->suggested_solutions[i].vector_number = -1;
6235 out->suggested_solutions[i].req.source.kind = VUT_NONE;
6236 }
6237
6238 return out;
6239}
6240
6241/**********************************************************************/
6250 const char *descr, ...)
6251{
6252 char description[500];
6253 char description_translated[500];
6254 va_list ap;
6255
6256 va_start(ap, descr);
6257 fc_vsnprintf(description, sizeof(description), descr, ap);
6258 va_end(ap);
6259
6260 va_start(ap, descr);
6262 _(descr), ap);
6263 va_end(ap);
6264
6267}
6268
6269/**********************************************************************/
6275{
6276 FC_FREE(issue->suggested_solutions);
6277 issue->num_suggested_solutions = 0;
6278
6279 FC_FREE(issue);
6280}
6281
6282/**********************************************************************/
6293struct req_vec_problem *
6296 const void *parent_item)
6297{
6298 int i, j;
6300
6301 if (vec == NULL || requirement_vector_size(vec) == 0) {
6302 /* No vector. */
6303 return NULL;
6304 }
6305
6306 if (get_num == NULL || parent_item == NULL) {
6307 vec_num = 0;
6308 } else {
6309 vec_num = get_num(parent_item, vec);
6310 }
6311
6312 /* Look for contradictions */
6313 for (i = 0; i < requirement_vector_size(vec); i++) {
6314 struct requirement *preq = requirement_vector_get(vec, i);
6315 for (j = 0; j < requirement_vector_size(vec); j++) {
6316 struct requirement *nreq = requirement_vector_get(vec, j);
6317
6319 struct req_vec_problem *problem;
6320 struct astring astr;
6321 struct astring nastr;
6322
6324 N_("Requirements {%s} and {%s} contradict each other."),
6326
6327 astr_free(&astr);
6328 astr_free(&nastr);
6329
6330 /* The solution is to remove one of the contradictions. */
6331 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6332 problem->suggested_solutions[0].vector_number = vec_num;
6333 problem->suggested_solutions[0].req = *preq;
6334
6335 problem->suggested_solutions[1].operation = RVCO_REMOVE;
6336 problem->suggested_solutions[1].vector_number = vec_num;
6337 problem->suggested_solutions[1].req = *nreq;
6338
6339 /* Only the first contradiction is reported. */
6340 return problem;
6341 }
6342 }
6343 }
6344
6345 return NULL;
6346}
6347
6348/**********************************************************************/
6358struct req_vec_problem *
6361 const void *parent_item)
6362{
6363 /* Check for self contradictins. */
6365}
6366
6367/**********************************************************************/
6379struct req_vec_problem *
6382 const void *parent_item)
6383{
6384 int i;
6386 struct req_vec_problem *problem = NULL;
6387
6388 if (vec == NULL || requirement_vector_size(vec) == 0) {
6389 /* No vector. */
6390 return NULL;
6391 }
6392
6393 if (get_num == NULL || parent_item == NULL) {
6394 vec_num = 0;
6395 } else {
6396 vec_num = get_num(parent_item, vec);
6397 }
6398
6399 /* Look for contradictions */
6400 for (i = 0; i < requirement_vector_size(vec); i++) {
6401 struct requirement *preq = requirement_vector_get(vec, i);
6402
6403 if (universal_never_there(&preq->source)) {
6404 struct astring astr;
6405
6406 if (preq->present) {
6407 /* The requirement vector can never be fulfilled. Removing the
6408 * requirement makes it possible to fulfill it. This is a rule
6409 * change and shouldn't be "fixed" without thinking. Don't offer any
6410 * automatic solution to prevent mindless "fixes". */
6411 /* TRANS: ruledit warns a user about an unused requirement vector
6412 * that never can be fulfilled because it asks for something that
6413 * never will be there. */
6414 if (problem == NULL) {
6416 N_("Requirement {%s} requires %s but it will never be"
6417 " there."),
6419 astr_free(&astr);
6420 }
6421
6422 /* Continue to check if other problems have a solution proposal,
6423 * and prefer to return those. */
6424 continue;
6425 }
6426
6427 if (problem != NULL) {
6428 /* Free previous one (one with no solution proposals) */
6430 }
6431
6433 N_("Requirement {%s} mentions %s but it will never be there."),
6435
6436 astr_free(&astr);
6437
6438 /* The solution is to remove the reference to the missing
6439 * universal. */
6440 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6441 problem->suggested_solutions[0].vector_number = vec_num;
6442 problem->suggested_solutions[0].req = *preq;
6443
6444 /* Only the first missing universal is reported. */
6445 return problem;
6446 }
6447 }
6448
6449 return problem;
6450}
6451
6452/**********************************************************************/
6464struct req_vec_problem *
6467 const void *parent_item)
6468{
6469 int i, j;
6471
6472 if (vec == NULL || requirement_vector_size(vec) == 0) {
6473 /* No vector. */
6474 return NULL;
6475 }
6476
6477 if (get_num == NULL || parent_item == NULL) {
6478 vec_num = 0;
6479 } else {
6480 vec_num = get_num(parent_item, vec);
6481 }
6482
6483 /* Look for repeated requirements */
6484 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
6485 struct requirement *preq = requirement_vector_get(vec, i);
6486 for (j = i + 1; j < requirement_vector_size(vec); j++) {
6487 struct requirement *nreq = requirement_vector_get(vec, j);
6488
6490 struct req_vec_problem *problem;
6491 struct astring astr;
6492 struct astring nastr;
6493
6495 N_("Requirements {%s} and {%s} are the same."),
6497
6498 astr_free(&astr);
6499 astr_free(&nastr);
6500
6501 /* The solution is to remove one of the redundant requirements. */
6502 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6503 problem->suggested_solutions[0].vector_number = vec_num;
6504 problem->suggested_solutions[0].req = *preq;
6505
6506 problem->suggested_solutions[1].operation = RVCO_REMOVE;
6507 problem->suggested_solutions[1].vector_number = vec_num;
6508 problem->suggested_solutions[1].req = *nreq;
6509
6510 /* Only the first redundancy is reported. */
6511 return problem;
6512 }
6513 }
6514 }
6515
6516 return NULL;
6517}
6518
6519/**********************************************************************/
6530struct req_vec_problem *
6533 const void *parent_item)
6534{
6535 struct req_vec_problem *out;
6536
6538 if (out != NULL) {
6539 /* A bug, not just a potential improvement */
6540 return out;
6541 }
6542
6543 /* Check if a universal that never will appear in the game is checked. */
6545 if (out != NULL) {
6546 return out;
6547 }
6548
6549 /* Check if a requirement is redundant. */
6551 return out;
6552}
6553
6554/**********************************************************************/
6559 const struct universal *psource2)
6560{
6561 if (psource1->kind != psource2->kind) {
6562 return FALSE;
6563 }
6564 switch (psource1->kind) {
6565 case VUT_NONE:
6566 return TRUE;
6567 case VUT_COUNTER:
6568 return psource1->value.counter == psource2->value.counter;
6569 case VUT_ADVANCE:
6570 return psource1->value.advance == psource2->value.advance;
6571 case VUT_TECHFLAG:
6572 return psource1->value.techflag == psource2->value.techflag;
6573 case VUT_GOVERNMENT:
6574 return psource1->value.govern == psource2->value.govern;
6575 case VUT_ACHIEVEMENT:
6576 return psource1->value.achievement == psource2->value.achievement;
6577 case VUT_STYLE:
6578 return psource1->value.style == psource2->value.style;
6579 case VUT_IMPROVEMENT:
6580 case VUT_SITE:
6581 return psource1->value.building == psource2->value.building;
6582 case VUT_IMPR_GENUS:
6583 return psource1->value.impr_genus == psource2->value.impr_genus;
6584 case VUT_IMPR_FLAG:
6585 return psource1->value.impr_flag == psource2->value.impr_flag;
6586 case VUT_PLAYER_FLAG:
6587 return psource1->value.plr_flag == psource2->value.plr_flag;
6588 case VUT_PLAYER_STATE:
6589 return psource1->value.plrstate == psource2->value.plrstate;
6590 case VUT_EXTRA:
6591 return psource1->value.extra == psource2->value.extra;
6592 case VUT_GOOD:
6593 return psource1->value.good == psource2->value.good;
6594 case VUT_TERRAIN:
6595 return psource1->value.terrain == psource2->value.terrain;
6596 case VUT_TERRFLAG:
6597 return psource1->value.terrainflag == psource2->value.terrainflag;
6598 case VUT_NATION:
6599 return psource1->value.nation == psource2->value.nation;
6600 case VUT_NATIONGROUP:
6601 return psource1->value.nationgroup == psource2->value.nationgroup;
6602 case VUT_NATIONALITY:
6603 return psource1->value.nationality == psource2->value.nationality;
6604 case VUT_ORIGINAL_OWNER:
6605 return psource1->value.origowner == psource2->value.origowner;
6606 case VUT_DIPLREL:
6607 case VUT_DIPLREL_TILE:
6608 case VUT_DIPLREL_TILE_O:
6611 return psource1->value.diplrel == psource2->value.diplrel;
6612 case VUT_UTYPE:
6613 return psource1->value.utype == psource2->value.utype;
6614 case VUT_UTFLAG:
6615 return psource1->value.unitflag == psource2->value.unitflag;
6616 case VUT_UCLASS:
6617 return psource1->value.uclass == psource2->value.uclass;
6618 case VUT_UCFLAG:
6619 return psource1->value.unitclassflag == psource2->value.unitclassflag;
6620 case VUT_MINVETERAN:
6621 return psource1->value.minveteran == psource2->value.minveteran;
6622 case VUT_UNITSTATE:
6623 return psource1->value.unit_state == psource2->value.unit_state;
6624 case VUT_ACTIVITY:
6625 return psource1->value.activity == psource2->value.activity;
6626 case VUT_MINMOVES:
6627 return psource1->value.minmoves == psource2->value.minmoves;
6628 case VUT_MINHP:
6629 return psource1->value.min_hit_points == psource2->value.min_hit_points;
6630 case VUT_AGE:
6631 return psource1->value.age == psource2->value.age;
6632 case VUT_FORM_AGE:
6633 return psource1->value.form_age == psource2->value.form_age;
6634 case VUT_MINTECHS:
6635 return psource1->value.min_techs == psource2->value.min_techs;
6636 case VUT_ACTION:
6637 return (action_number(psource1->value.action)
6638 == action_number(psource2->value.action));
6639 case VUT_OTYPE:
6640 return psource1->value.outputtype == psource2->value.outputtype;
6641 case VUT_SPECIALIST:
6642 return psource1->value.specialist == psource2->value.specialist;
6643 case VUT_MINSIZE:
6644 return psource1->value.minsize == psource2->value.minsize;
6645 case VUT_MINCULTURE:
6646 return psource1->value.minculture == psource2->value.minculture;
6647 case VUT_MINFOREIGNPCT:
6648 return psource1->value.minforeignpct == psource2->value.minforeignpct;
6649 case VUT_AI_LEVEL:
6650 return psource1->value.ai_level == psource2->value.ai_level;
6651 case VUT_MAXTILEUNITS:
6652 return psource1->value.max_tile_units == psource2->value.max_tile_units;
6653 case VUT_TERRAINCLASS:
6654 return psource1->value.terrainclass == psource2->value.terrainclass;
6655 case VUT_ROADFLAG:
6656 return psource1->value.roadflag == psource2->value.roadflag;
6657 case VUT_EXTRAFLAG:
6658 return psource1->value.extraflag == psource2->value.extraflag;
6659 case VUT_MINYEAR:
6660 return psource1->value.minyear == psource2->value.minyear;
6661 case VUT_MINCALFRAG:
6662 return psource1->value.mincalfrag == psource2->value.mincalfrag;
6663 case VUT_TOPO:
6664 return psource1->value.topo_property == psource2->value.topo_property;
6665 case VUT_WRAP:
6666 return psource1->value.wrap_property == psource2->value.wrap_property;
6667 case VUT_SERVERSETTING:
6668 return psource1->value.ssetval == psource2->value.ssetval;
6669 case VUT_TERRAINALTER:
6670 return psource1->value.terrainalter == psource2->value.terrainalter;
6671 case VUT_CITYTILE:
6672 return psource1->value.citytile == psource2->value.citytile;
6673 case VUT_CITYSTATUS:
6674 return psource1->value.citystatus == psource2->value.citystatus;
6675 case VUT_MINLATITUDE:
6676 case VUT_MAXLATITUDE:
6677 return psource1->value.latitude == psource2->value.latitude;
6678 case VUT_COUNT:
6679 break;
6680 }
6681
6682 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
6683 return FALSE;
6684}
6685
6686/**********************************************************************/
6690const char *universal_rule_name(const struct universal *psource)
6691{
6692 static char buffer[10];
6693
6694 switch (psource->kind) {
6695 case VUT_NONE:
6696 return "(none)";
6697 case VUT_COUNTER:
6698 return counter_rule_name(psource->value.counter);
6699 case VUT_CITYTILE:
6700 return citytile_type_name(psource->value.citytile);
6701 case VUT_CITYSTATUS:
6702 return citystatus_type_name(psource->value.citystatus);
6703 case VUT_MINYEAR:
6704 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
6705
6706 return buffer;
6707 case VUT_MINCALFRAG:
6708 /* Rule name is 0-based number, not pretty name from ruleset */
6709 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
6710
6711 return buffer;
6712 case VUT_TOPO:
6713 return topo_flag_name(psource->value.topo_property);
6714 case VUT_WRAP:
6715 return wrap_flag_name(psource->value.wrap_property);
6716 case VUT_SERVERSETTING:
6717 return ssetv_rule_name(psource->value.ssetval);
6718 case VUT_ADVANCE:
6719 return advance_rule_name(psource->value.advance);
6720 case VUT_TECHFLAG:
6721 return tech_flag_id_name(psource->value.techflag);
6722 case VUT_GOVERNMENT:
6723 return government_rule_name(psource->value.govern);
6724 case VUT_ACHIEVEMENT:
6725 return achievement_rule_name(psource->value.achievement);
6726 case VUT_STYLE:
6727 return style_rule_name(psource->value.style);
6728 case VUT_IMPROVEMENT:
6729 case VUT_SITE:
6730 return improvement_rule_name(psource->value.building);
6731 case VUT_IMPR_GENUS:
6732 return impr_genus_id_name(psource->value.impr_genus);
6733 case VUT_IMPR_FLAG:
6734 return impr_flag_id_name(psource->value.impr_flag);
6735 case VUT_PLAYER_FLAG:
6736 return plr_flag_id_name(psource->value.plr_flag);
6737 case VUT_PLAYER_STATE:
6738 return plrstate_type_name(psource->value.plrstate);
6739 case VUT_EXTRA:
6740 return extra_rule_name(psource->value.extra);
6741 case VUT_GOOD:
6742 return goods_rule_name(psource->value.good);
6743 case VUT_TERRAIN:
6744 return terrain_rule_name(psource->value.terrain);
6745 case VUT_TERRFLAG:
6746 return terrain_flag_id_name(psource->value.terrainflag);
6747 case VUT_NATION:
6748 return nation_rule_name(psource->value.nation);
6749 case VUT_NATIONGROUP:
6750 return nation_group_rule_name(psource->value.nationgroup);
6751 case VUT_DIPLREL:
6752 case VUT_DIPLREL_TILE:
6753 case VUT_DIPLREL_TILE_O:
6756 return diplrel_rule_name(psource->value.diplrel);
6757 case VUT_NATIONALITY:
6758 return nation_rule_name(psource->value.nationality);
6759 case VUT_ORIGINAL_OWNER:
6760 return nation_rule_name(psource->value.origowner);
6761 case VUT_UTYPE:
6762 return utype_rule_name(psource->value.utype);
6763 case VUT_UTFLAG:
6764 return unit_type_flag_id_name(psource->value.unitflag);
6765 case VUT_UCLASS:
6766 return uclass_rule_name(psource->value.uclass);
6767 case VUT_UCFLAG:
6768 return unit_class_flag_id_name(psource->value.unitclassflag);
6769 case VUT_MINVETERAN:
6770 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
6771
6772 return buffer;
6773 case VUT_UNITSTATE:
6774 return ustate_prop_name(psource->value.unit_state);
6775 case VUT_ACTIVITY:
6776 return unit_activity_name(psource->value.activity);
6777 case VUT_MINMOVES:
6778 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
6779
6780 return buffer;
6781 case VUT_MINHP:
6782 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
6783
6784 return buffer;
6785 case VUT_AGE:
6786 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
6787
6788 return buffer;
6789 case VUT_FORM_AGE:
6790 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
6791
6792 return buffer;
6793 case VUT_MINTECHS:
6794 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
6795
6796 return buffer;
6797 case VUT_ACTION:
6798 return action_rule_name(psource->value.action);
6799 case VUT_OTYPE:
6800 return get_output_identifier(psource->value.outputtype);
6801 case VUT_SPECIALIST:
6802 return specialist_rule_name(psource->value.specialist);
6803 case VUT_MINSIZE:
6804 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
6805
6806 return buffer;
6807 case VUT_MINCULTURE:
6808 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
6809
6810 return buffer;
6811 case VUT_MINFOREIGNPCT:
6812 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
6813
6814 return buffer;
6815 case VUT_AI_LEVEL:
6816 return ai_level_name(psource->value.ai_level);
6817 case VUT_MAXTILEUNITS:
6818 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_units);
6819 return buffer;
6820 case VUT_TERRAINCLASS:
6821 return terrain_class_name(psource->value.terrainclass);
6822 case VUT_ROADFLAG:
6823 return road_flag_id_name(psource->value.roadflag);
6824 case VUT_EXTRAFLAG:
6825 return extra_flag_id_name(psource->value.extraflag);
6826 case VUT_TERRAINALTER:
6827 return terrain_alteration_name(psource->value.terrainalter);
6828 case VUT_MINLATITUDE:
6829 case VUT_MAXLATITUDE:
6830 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
6831
6832 return buffer;
6833 case VUT_COUNT:
6834 break;
6835 }
6836
6837 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
6838 return NULL;
6839}
6840
6841/**********************************************************************/
6850 char *buf, size_t bufsz)
6851{
6852 buf[0] = '\0'; /* to be safe. */
6853 switch (psource->kind) {
6854 case VUT_NONE:
6855 /* TRANS: missing value */
6856 fc_strlcat(buf, _("(none)"), bufsz);
6857 return buf;
6858 case VUT_ADVANCE:
6860 return buf;
6861 case VUT_COUNTER:
6863 return buf;
6864 case VUT_TECHFLAG:
6865 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
6866 tech_flag_id_translated_name(psource->value.techflag));
6867 return buf;
6868 case VUT_GOVERNMENT:
6870 bufsz);
6871 return buf;
6872 case VUT_ACHIEVEMENT:
6874 bufsz);
6875 return buf;
6876 case VUT_STYLE:
6878 bufsz);
6879 return buf;
6880 case VUT_IMPROVEMENT:
6882 bufsz);
6883 return buf;
6884 case VUT_SITE:
6885 {
6886 char local_buf[1024];
6887
6888 fc_snprintf(local_buf, sizeof(local_buf), _("%s site"),
6889 improvement_name_translation(psource->value.building));
6891 }
6892
6893 return buf;
6894 case VUT_IMPR_GENUS:
6896 impr_genus_id_translated_name(psource->value.impr_genus),
6897 bufsz);
6898 return buf;
6899 case VUT_IMPR_FLAG:
6901 impr_flag_id_translated_name(psource->value.impr_flag),
6902 bufsz);
6903 return buf;
6904 case VUT_PLAYER_FLAG:
6906 plr_flag_id_translated_name(psource->value.plr_flag),
6907 bufsz);
6908 return buf;
6909 case VUT_PLAYER_STATE:
6911 plrstate_type_translated_name(psource->value.plrstate),
6912 bufsz);
6913 return buf;
6914 case VUT_EXTRA:
6916 return buf;
6917 case VUT_GOOD:
6919 return buf;
6920 case VUT_TERRAIN:
6922 return buf;
6923 case VUT_NATION:
6925 bufsz);
6926 return buf;
6927 case VUT_NATIONGROUP:
6929 bufsz);
6930 return buf;
6931 case VUT_NATIONALITY:
6932 cat_snprintf(buf, bufsz, _("%s citizens"),
6933 nation_adjective_translation(psource->value.nationality));
6934 return buf;
6935 case VUT_ORIGINAL_OWNER:
6936 /* TRANS: Keep short. City founding nation. */
6937 cat_snprintf(buf, bufsz, _("%s original owner"),
6938 nation_adjective_translation(psource->value.origowner));
6939 return buf;
6940 case VUT_DIPLREL:
6941 case VUT_DIPLREL_TILE:
6942 case VUT_DIPLREL_TILE_O:
6946 bufsz);
6947 return buf;
6948 case VUT_UTYPE:
6950 return buf;
6951 case VUT_UTFLAG:
6953 /* TRANS: Unit type flag */
6954 Q_("?utflag:\"%s\" units"),
6956 psource->value.unitflag));
6957 return buf;
6958 case VUT_UCLASS:
6960 /* TRANS: Unit class */
6961 _("%s units"),
6962 uclass_name_translation(psource->value.uclass));
6963 return buf;
6964 case VUT_UCFLAG:
6966 /* TRANS: Unit class flag */
6967 Q_("?ucflag:\"%s\" units"),
6969 psource->value.unitclassflag));
6970 return buf;
6971 case VUT_MINVETERAN:
6972 /* FIXME */
6973 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
6974 psource->value.minveteran);
6975 return buf;
6976 case VUT_UNITSTATE:
6977 switch (psource->value.unit_state) {
6978 case USP_TRANSPORTED:
6979 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
6980 cat_snprintf(buf, bufsz, _("Transported"));
6981 break;
6982 case USP_LIVABLE_TILE:
6984 /* TRANS: unit state. (appears in strings like
6985 * "Missile+On livable tile") */
6986 _("On livable tile"));
6987 break;
6988 case USP_TRANSPORTING:
6989 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
6990 cat_snprintf(buf, bufsz, _("Transporting"));
6991 break;
6992 case USP_HAS_HOME_CITY:
6993 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
6994 cat_snprintf(buf, bufsz, _("Has a home city"));
6995 break;
6996 case USP_NATIVE_TILE:
6998 /* TRANS: unit state. (appears in strings like
6999 * "Missile+On native tile") */
7000 _("On native tile"));
7001 break;
7002 case USP_NATIVE_EXTRA:
7004 /* TRANS: unit state. (appears in strings like
7005 * "Missile+In native extra") */
7006 _("In native extra"));
7007 break;
7009 /* TRANS: unit state. (appears in strings like
7010 * "Missile+Has moved this turn") */
7011 cat_snprintf(buf, bufsz, _("Has moved this turn"));
7012 break;
7013 case USP_COUNT:
7014 fc_assert_msg(psource->value.unit_state != USP_COUNT,
7015 "Invalid unit state property.");
7016 break;
7017 }
7018 return buf;
7019 case VUT_ACTIVITY:
7020 cat_snprintf(buf, bufsz, _("%s activity"),
7021 Q_(unit_activity_name(psource->value.activity)));
7022 return buf;
7023 case VUT_MINMOVES:
7024 /* TRANS: Minimum unit movement points left for requirement to be met
7025 * (%s is a string like "1" or "2 1/3") */
7026 cat_snprintf(buf, bufsz, _("%s MP"),
7027 move_points_text(psource->value.minmoves, TRUE));
7028 return buf;
7029 case VUT_MINHP:
7030 /* TRANS: HP = hit points */
7031 cat_snprintf(buf, bufsz, _("%d HP"),
7032 psource->value.min_hit_points);
7033 return buf;
7034 case VUT_AGE:
7035 cat_snprintf(buf, bufsz, _("Age %d"),
7036 psource->value.age);
7037 return buf;
7038 case VUT_FORM_AGE:
7039 cat_snprintf(buf, bufsz, _("Form age %d"),
7040 psource->value.form_age);
7041 return buf;
7042 case VUT_MINTECHS:
7043 cat_snprintf(buf, bufsz, _("%d Techs"),
7044 psource->value.min_techs);
7045 return buf;
7046 case VUT_ACTION:
7048 bufsz);
7049 return buf;
7050 case VUT_OTYPE:
7051 /* FIXME */
7052 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
7053 return buf;
7054 case VUT_SPECIALIST:
7056 bufsz);
7057 return buf;
7058 case VUT_MINSIZE:
7059 cat_snprintf(buf, bufsz, _("Size %d"),
7060 psource->value.minsize);
7061 return buf;
7062 case VUT_MINCULTURE:
7063 cat_snprintf(buf, bufsz, _("Culture %d"),
7064 psource->value.minculture);
7065 return buf;
7066 case VUT_MINFOREIGNPCT:
7067 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
7068 psource->value.minforeignpct);
7069 return buf;
7070 case VUT_AI_LEVEL:
7071 /* TRANS: "Hard AI" */
7072 cat_snprintf(buf, bufsz, _("%s AI"),
7073 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
7074 return buf;
7075 case VUT_MAXTILEUNITS:
7076 /* TRANS: here <= means 'less than or equal' */
7077 cat_snprintf(buf, bufsz, PL_("<=%d unit",
7078 "<=%d units", psource->value.max_tile_units),
7079 psource->value.max_tile_units);
7080 return buf;
7081 case VUT_TERRAINCLASS:
7082 /* TRANS: Terrain class: "Land terrain" */
7083 cat_snprintf(buf, bufsz, _("%s terrain"),
7084 terrain_class_name_translation(psource->value.terrainclass));
7085 return buf;
7086 case VUT_TERRFLAG:
7088 /* TRANS: Terrain flag */
7089 Q_("?terrflag:\"%s\" terrain"),
7091 psource->value.terrainflag));
7092 return buf;
7093 case VUT_ROADFLAG:
7095 /* TRANS: Road flag */
7096 Q_("?roadflag:\"%s\" road"),
7097 road_flag_id_translated_name(psource->value.roadflag));
7098 return buf;
7099 case VUT_EXTRAFLAG:
7101 /* TRANS: Extra flag */
7102 Q_("?extraflag:\"%s\" extra"),
7103 extra_flag_id_translated_name(psource->value.extraflag));
7104 return buf;
7105 case VUT_MINYEAR:
7106 cat_snprintf(buf, bufsz, _("After %s"),
7107 textyear(psource->value.minyear));
7108 return buf;
7109 case VUT_MINCALFRAG:
7110 /* TRANS: here >= means 'greater than or equal'.
7111 * %s identifies a calendar fragment (may be bare number). */
7112 cat_snprintf(buf, bufsz, _(">=%s"),
7113 textcalfrag(psource->value.mincalfrag));
7114 return buf;
7115 case VUT_TOPO:
7116 /* TRANS: topology flag name ("Hex", "ISO") */
7117 cat_snprintf(buf, bufsz, _("%s map"),
7118 _(topo_flag_name(psource->value.topo_property)));
7119 return buf;
7120 case VUT_WRAP:
7121 /* TRANS: wrap flag name ("WrapX", "WrapY") */
7122 cat_snprintf(buf, bufsz, _("%s map"),
7123 _(wrap_flag_name(psource->value.wrap_property)));
7124 return buf;
7125 case VUT_SERVERSETTING:
7127 bufsz);
7128 return buf;
7129 case VUT_TERRAINALTER:
7130 /* TRANS: "Irrigation possible" */
7131 cat_snprintf(buf, bufsz, _("%s possible"),
7132 Q_(terrain_alteration_name(psource->value.terrainalter)));
7133 return buf;
7134 case VUT_CITYTILE:
7135 switch (psource->value.citytile) {
7136 case CITYT_CENTER:
7137 fc_strlcat(buf, _("City center"), bufsz);
7138 break;
7139 case CITYT_CLAIMED:
7140 fc_strlcat(buf, _("Tile claimed"), bufsz);
7141 break;
7142 case CITYT_EXTRAS_OWNED:
7143 fc_strlcat(buf, _("Extras owned"), bufsz);
7144 break;
7145 case CITYT_WORKED:
7146 fc_strlcat(buf, _("Worked tile"), bufsz);
7147 break;
7149 fc_strlcat(buf, _("Same continent tile"), bufsz);
7150 break;
7152 /* TRANS: Short for "a tile of other terrain class mass near city" */
7153 fc_strlcat(buf, _("Port reachable tile"), bufsz);
7154 break;
7155 case CITYT_LAST:
7156 fc_assert(psource->value.citytile != CITYT_LAST);
7157 fc_strlcat(buf, "error", bufsz);
7158 break;
7159 }
7160 return buf;
7161 case VUT_CITYSTATUS:
7162 switch (psource->value.citystatus) {
7164 fc_strlcat(buf, _("Owned by original"), bufsz);
7165 break;
7166 case CITYS_STARVED:
7167 fc_strlcat(buf, _("Starved"), bufsz);
7168 break;
7169 case CITYS_DISORDER:
7170 fc_strlcat(buf, _("Disorder"), bufsz);
7171 break;
7172 case CITYS_CELEBRATION:
7173 fc_strlcat(buf, _("Celebration"), bufsz);
7174 break;
7175 case CITYS_TRANSFERRED:
7176 /* TRANS: CityStatus value - city has changed hands */
7177 fc_strlcat(buf, _("Transferred"), bufsz);
7178 break;
7179 case CITYS_LAST:
7180 fc_assert(psource->value.citystatus != CITYS_LAST);
7181 fc_strlcat(buf, "error", bufsz);
7182 break;
7183 }
7184 return buf;
7185 case VUT_MINLATITUDE:
7186 /* TRANS: here >= means 'greater than or equal'. */
7187 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
7188 psource->value.latitude);
7189 return buf;
7190 case VUT_MAXLATITUDE:
7191 /* TRANS: here <= means 'less than or equal'. */
7192 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
7193 psource->value.latitude);
7194 return buf;
7195 case VUT_COUNT:
7196 break;
7197 }
7198
7199 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
7200 return buf;
7201}
7202
7203/**********************************************************************/
7207{
7208 return universals_n_name(psource->kind);
7209}
7210
7211/**********************************************************************/
7214int universal_build_shield_cost(const struct city *pcity,
7215 const struct universal *target)
7216{
7217 switch (target->kind) {
7218 case VUT_IMPROVEMENT:
7219 case VUT_SITE:
7220 return impr_build_shield_cost(pcity, target->value.building);
7221 case VUT_UTYPE:
7222 return utype_build_shield_cost(pcity, NULL, target->value.utype);
7223 default:
7224 break;
7225 }
7226 return FC_INFINITY;
7227}
7228
7229/**********************************************************************/
7235 const struct universal *to_replace,
7236 const struct universal *replacement)
7237{
7238 bool changed = FALSE;
7239
7242 preq->source = *replacement;
7243 changed = TRUE;
7244 }
7246
7247 return changed;
7248}
7249
7250/**********************************************************************/
7255 const struct requirement_vector *reqs,
7256 const struct universal *psource)
7257{
7260 return TRUE;
7261 }
7263
7264 return FALSE;
7265}
7266
7267/**********************************************************************/
7277 struct universal *unis,
7278 size_t n_unis)
7279{
7280 int i;
7281
7282 for (i = 0; i < n_unis; i++) {
7284 /* This universal makes it impossible to fulfill the specified
7285 * requirement vector */
7286 return TRUE;
7287 }
7288 }
7289
7290 /* No specified universal is known to guarantee that the requirement
7291 * vector never will be fulfilled. */
7292 return FALSE;
7293}
7294
7295/**********************************************************************/
7310 struct universal *unis,
7311 size_t n_unis)
7312{
7314 int i;
7316
7317 for (i = 0; i < n_unis; i++) {
7318 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
7319 case ITF_NO:
7320 case ITF_YES:
7321 /* this req matched this source */
7323 break;
7324 case ITF_NOT_APPLICABLE:
7325 /* Not a mention. */
7326 break;
7327 }
7328 }
7329
7331 /* A requirement not relevant to any of the specified universals was
7332 * found in the requirement vector. */
7333 return FALSE;
7334 }
7336
7337 /* No requirement not relevant to any of the specified universals was
7338 * found in the requirement vector. */
7339 return TRUE;
7340}
7341
7342/**********************************************************************/
7345enum req_item_found
7347 const struct universal *source)
7348{
7351 "No req item found function for %s",
7353
7354 return (*universal_found_function[source->kind])(preq, source);
7355}
7356
7357/**********************************************************************/
7368 const struct requirement_vector *reqs,
7369 const struct universal *source)
7370{
7371 bool necessary = FALSE;
7372
7375 "No req item found function for %s",
7377
7379 switch ((*universal_found_function[source->kind])(preq, source)) {
7380 case ITF_NOT_APPLICABLE:
7381 continue;
7382 case ITF_NO:
7383 if (preq->present) {
7384 return FALSE;
7385 }
7386 break;
7387 case ITF_YES:
7388 if (preq->present) {
7389 necessary = TRUE;
7390 } else {
7391 return FALSE;
7392 }
7393 break;
7394 }
7396
7397 return (!check_necessary || necessary);
7398}
7399
7400/**********************************************************************/
7405 const struct universal *source)
7406{
7407 switch (universal_fulfills_requirement(req, source)) {
7408 case ITF_NOT_APPLICABLE:
7409 return FALSE;
7410 case ITF_NO:
7411 case ITF_YES:
7412 return TRUE;
7413 }
7414
7415 log_error("Unhandled item_found value");
7416 return FALSE;
7417}
7418
7419/**********************************************************************/
7423 const struct universal *source)
7424{
7425 fc_assert(source->value.nation);
7426
7427 switch (preq->source.kind) {
7428 case VUT_NATION:
7429 return preq->source.value.nation == source->value.nation ? ITF_YES
7430 : ITF_NO;
7431 case VUT_NATIONGROUP:
7432 return nation_is_in_group(source->value.nation,
7433 preq->source.value.nationgroup) ? ITF_YES
7434 : ITF_NO;
7435 default:
7436 break;
7437 }
7438
7439 return ITF_NOT_APPLICABLE;
7440}
7441
7442/**********************************************************************/
7446 const struct universal *source)
7447{
7448 fc_assert(source->value.govern);
7449
7450 if (preq->source.kind == VUT_GOVERNMENT) {
7451 return preq->source.value.govern == source->value.govern ? ITF_YES
7452 : ITF_NO;
7453 }
7454
7455 return ITF_NOT_APPLICABLE;
7456}
7457
7458/**********************************************************************/
7462 const struct universal *source)
7463{
7464 fc_assert(source->value.building);
7465
7466 /* We only ever return ITF_YES, because requiring a different
7467 * improvement does not mean that the improvement under consideration
7468 * cannot fulfill the requirements. This is necessary to allow
7469 * requirement vectors to specify multiple required improvements. */
7470
7471 switch (preq->source.kind) {
7472 case VUT_IMPROVEMENT:
7473 case VUT_SITE:
7474 if (source->value.building == preq->source.value.building) {
7475 return ITF_YES;
7476 }
7477 break;
7478 case VUT_IMPR_GENUS:
7479 if (source->value.building->genus == preq->source.value.impr_genus) {
7480 return ITF_YES;
7481 }
7482 break;
7483 case VUT_IMPR_FLAG:
7484 if (improvement_has_flag(source->value.building,
7485 preq->source.value.impr_flag)) {
7486 return ITF_YES;
7487 }
7488 break;
7489 default:
7490 break;
7491 }
7492
7493 return ITF_NOT_APPLICABLE;
7494}
7495
7496/**********************************************************************/
7500 const struct universal *source)
7501{
7502 fc_assert(source->value.uclass);
7503
7504 switch (preq->source.kind) {
7505 case VUT_UCLASS:
7506 return source->value.uclass == preq->source.value.uclass ? ITF_YES
7507 : ITF_NO;
7508 case VUT_UCFLAG:
7509 return uclass_has_flag(source->value.uclass,
7510 preq->source.value.unitclassflag) ? ITF_YES
7511 : ITF_NO;
7512
7513 default:
7514 /* Not found and not relevant. */
7515 return ITF_NOT_APPLICABLE;
7516 };
7517}
7518
7519/**********************************************************************/
7523 const struct universal *source)
7524{
7525 fc_assert(source->value.utype);
7526
7527 switch (preq->source.kind) {
7528 case VUT_UTYPE:
7529 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
7530 case VUT_UCLASS:
7531 return utype_class(source->value.utype) == preq->source.value.uclass
7532 ? ITF_YES : ITF_NO;
7533 case VUT_UTFLAG:
7534 return utype_has_flag(source->value.utype,
7535 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
7536 case VUT_UCFLAG:
7537 return uclass_has_flag(utype_class(source->value.utype),
7538 preq->source.value.unitclassflag) ? ITF_YES
7539 : ITF_NO;
7540 default:
7541 /* Not found and not relevant. */
7542 return ITF_NOT_APPLICABLE;
7543 };
7544}
7545
7546/**********************************************************************/
7549static enum req_item_found
7551 const struct universal *source)
7552{
7555
7556 switch (preq->source.kind) {
7557 case VUT_ACTIVITY:
7558 return source->value.activity == preq->source.value.activity ? ITF_YES
7559 : ITF_NO;
7560 default:
7561 /* Not found and not relevant. */
7562 return ITF_NOT_APPLICABLE;
7563 };
7564}
7565
7566/**********************************************************************/
7570 const struct universal *source)
7571{
7572 fc_assert(source->value.terrain);
7573
7574 switch (preq->source.kind) {
7575 case VUT_TERRAIN:
7576 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
7577 case VUT_TERRAINCLASS:
7578 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
7579 ? ITF_YES : ITF_NO;
7580 case VUT_TERRFLAG:
7581 return terrain_has_flag(source->value.terrain,
7582 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
7583 case VUT_TERRAINALTER:
7584 return (terrain_can_support_alteration(source->value.terrain,
7585 preq->source.value.terrainalter)
7586 ? ITF_YES : ITF_NO);
7587 default:
7588 /* Not found and not relevant. */
7589 return ITF_NOT_APPLICABLE;
7590 };
7591}
7592
7593/**********************************************************************/
7597 const struct universal *source)
7598{
7601
7602 switch (preq->source.kind) {
7603 case VUT_CITYTILE:
7604 return (source->value.citytile == preq->source.value.citytile
7605 ? ITF_YES
7606 /* The presence of one tile state doesn't block another */
7608 default:
7609 /* Not found and not relevant. */
7610 return ITF_NOT_APPLICABLE;
7611 };
7612}
7613
7614/**********************************************************************/
7618 const struct universal *source)
7619{
7620 fc_assert(source->value.extra);
7621
7622 switch (preq->source.kind) {
7623 case VUT_EXTRA:
7624 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
7625 case VUT_EXTRAFLAG:
7626 return extra_has_flag(source->value.extra,
7627 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
7628 case VUT_ROADFLAG:
7629 {
7630 struct road_type *r = extra_road_get(source->value.extra);
7631 return r && road_has_flag(r, preq->source.value.roadflag)
7632 ? ITF_YES : ITF_NO;
7633 }
7634 default:
7635 /* Not found and not relevant. */
7636 return ITF_NOT_APPLICABLE;
7637 }
7638}
7639
7640/**********************************************************************/
7644 const struct universal *source)
7645{
7646 fc_assert(source->value.action);
7647
7648 if (preq->source.kind == VUT_ACTION) {
7649 return preq->source.value.action == source->value.action ? ITF_YES
7650 : ITF_NO;
7651 }
7652
7653 return ITF_NOT_APPLICABLE;
7654}
7655
7656/**********************************************************************/
7660 const struct universal *source)
7661{
7663 || source->kind == VUT_DIPLREL_TILE
7664 || source->kind == VUT_DIPLREL_TILE_O
7665 || source->kind == VUT_DIPLREL_UNITANY
7666 || source->kind == VUT_DIPLREL_UNITANY_O),
7668
7669 if (preq->source.kind == source->kind) {
7670 if (preq->source.value.diplrel == source->value.diplrel) {
7671 /* The diplrel itself. */
7672 return ITF_YES;
7673 }
7674 if (preq->source.value.diplrel == DRO_FOREIGN
7675 && source->value.diplrel < DS_LAST) {
7676 /* All diplstate_type values are to foreigners. */
7677 return ITF_YES;
7678 }
7679 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
7680 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
7681 /* A real embassy is an embassy. */
7682 return ITF_YES;
7683 }
7684 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
7685 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
7686 /* A real embassy is an embassy. */
7687 return ITF_YES;
7688 }
7689 if (preq->source.value.diplrel < DS_LAST
7690 && source->value.diplrel < DS_LAST
7691 && preq->range == REQ_RANGE_LOCAL) {
7692 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
7693 ITF_YES);
7694 /* Can only have one diplstate_type to a specific player. */
7695 return ITF_NO;
7696 }
7697 /* Can't say this diplrel blocks the other diplrel. */
7698 return ITF_NOT_APPLICABLE;
7699 }
7700
7701 /* Not relevant. */
7702 return ITF_NOT_APPLICABLE;
7703}
7704
7705/**********************************************************************/
7709 const struct universal *source)
7710{
7711 switch (preq->source.kind) {
7712 case VUT_OTYPE:
7713 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
7714 : ITF_NO;
7715 default:
7716 /* Not found and not relevant. */
7717 return ITF_NOT_APPLICABLE;
7718 }
7719}
7720
7721/**********************************************************************/
7725 const struct universal *source)
7726{
7727 if (preq->range != REQ_RANGE_LOCAL) {
7728 return ITF_NOT_APPLICABLE;
7729 }
7730
7731 if (preq->source.kind == VUT_UNITSTATE) {
7732 switch (source->value.unit_state) {
7733 case USP_TRANSPORTED:
7734 case USP_TRANSPORTING:
7735 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
7736 case USP_LIVABLE_TILE:
7737 case USP_NATIVE_TILE:
7738 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
7739 * UTYF_COAST_STRICT. */
7740 case USP_HAS_HOME_CITY:
7741 case USP_NATIVE_EXTRA:
7743 if (source->value.unit_state == preq->source.value.unit_state) {
7744 /* The other unit states doesn't contradict */
7745 return ITF_YES;
7746 }
7747 break;
7748 case USP_COUNT:
7749 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
7751 }
7752 }
7753
7754 /* Not found and not relevant. */
7755 return ITF_NOT_APPLICABLE;
7756}
7757
7758/**********************************************************************/
7782
7783/**********************************************************************/
7791int requirement_kind_ereq(const int value,
7792 const enum req_range range,
7793 const bool present,
7794 const int max_value)
7795{
7796 /* The enumerators in each range starts with present for every possible
7797 * value followed by !present for every possible value. */
7798 const int pres_start = (present ? 0 : max_value);
7799
7800 /* The enumerators for every range follows all the positions of the
7801 * previous range(s). */
7802 const int range_start = ((max_value - 1) * 2) * range;
7803
7804 return range_start + pres_start + value;
7805}
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 *action)
Definition actions.c:1991
bool action_is_in_use(struct action *paction)
Definition actions.c:6398
struct action * action_by_rule_name(const char *name)
Definition actions.c:1840
const char * action_rule_name(const struct action *action)
Definition actions.c:1977
int action_number(const struct action *action)
Definition actions.c:1969
static struct action * action_by_number(action_id act_id)
Definition actions.h:635
void astr_free(struct astring *astr)
Definition astring.c:153
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:267
void astr_init(struct astring *astr)
Definition astring.c:144
#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:1240
Output_type_id output_type_by_identifier(const char *id)
Definition city.c:647
const char * get_output_identifier(Output_type_id output)
Definition city.c:619
const char * get_output_name(Output_type_id output)
Definition city.c:629
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
#define city_tile(_pcity_)
Definition city.h:564
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
#define city_owner(_pcity_)
Definition city.h:563
static bool is_city_center(const struct city *pcity, const struct tile *ptile)
Definition city.h:868
#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:834
#define city_built_iterate_end
Definition city.h:840
static struct ai_type * self
Definition classicai.c:45
char * incite_cost
Definition comments.c:75
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:46
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 @21::@22 reqs
int get_world_bonus(enum effect_type effect_type)
Definition effects.c:816
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:987
bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:890
bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:870
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:861
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:377
req_problem_type
Definition fc_types.h:699
@ RPT_POSSIBLE
Definition fc_types.h:700
#define MAX_LEN_NAME
Definition fc_types.h:66
@ VC_SPACERACE
Definition fc_types.h:1271
@ O_LAST
Definition fc_types.h:101
signed short Continent_id
Definition fc_types.h:372
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
bool register_at_thread_exit_callback(at_thread_exit_cb *cb)
Definition fcthread.c:32
void fc_mutex_allocate(fc_mutex *mutex)
void fc_mutex_init(fc_mutex *mutex)
void fc_mutex_release(fc_mutex *mutex)
fc_thread_id fc_thread_self(void)
bool fc_threads_equal(fc_thread_id thr1, fc_thread_id thr2)
void fc_mutex_destroy(fc_mutex *mutex)
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
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_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:931
int map_signed_latitude(const struct tile *ptile)
Definition map.c:1550
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:940
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:654
#define current_topo_has_flag(flag)
Definition map.h:48
#define MAP_MAX_LATITUDE
Definition map.h:574
#define adjc_iterate_end
Definition map.h:433
#define MAP_MAX_REAL_LATITUDE(_nmap)
Definition map.h:586
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:391
#define cardinal_adjc_iterate_end
Definition map.h:459
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:428
#define square_iterate_end
Definition map.h:394
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:455
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:401
#define current_wrap_has_flag(flag)
Definition map.h:51
#define MAP_MIN_REAL_LATITUDE(_nmap)
Definition map.h:588
#define circle_iterate_end
Definition map.h:404
#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:1047
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:351
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:363
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:1998
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Definition player.c:1823
int diplrel_by_rule_name(const char *value)
Definition player.c:1581
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1476
bool is_diplrel_to_other(const struct player *pplayer, int diplrel)
Definition player.c:1562
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1990
const char * diplrel_name_translation(int value)
Definition player.c:1627
bool is_diplrel_between(const struct player *player1, const struct player *player2, int diplrel)
Definition player.c:1512
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:1405
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:1615
#define players_iterate_end
Definition player.h:537
#define players_iterate(_pplayer)
Definition player.h:532
#define player_nation(_plr_)
Definition player.h:406
#define is_ai(plr)
Definition player.h:230
#define players_iterate_alive_end
Definition player.h:547
#define players_iterate_alive(_pplayer)
Definition player.h:542
static enum fc_tristate is_latitude_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
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_topology_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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 player *other_player, 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)
static int num_city_buildings(const struct city *pcity, const struct impr_type *building)
int universal_build_shield_cost(const struct city *pcity, const struct universal *target)
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 req_item_found unit_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_mincalfrag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
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_extraflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_minforeignpct_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static int num_continent_buildings(const struct player *pplayer, int continent, const struct impr_type *building)
static enum fc_tristate tri_req_present(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
const char * req_to_fstring(const struct requirement *req, struct astring *astr)
static enum fc_tristate is_style_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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)
static enum fc_tristate is_roadflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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)
static enum fc_tristate is_specialist_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum req_unchanging_status unchanging_noally(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_minveteran_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_unitstate_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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 req_unchanging_status unchanging_building(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
bool are_requirements_equal(const struct requirement *req1, const struct requirement *req2)
static enum req_item_found extra_type_found(const struct requirement *preq, const struct universal *source)
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)
bool are_reqs_active_ranges(const enum req_range min_range, const enum req_range max_range, const struct req_context *context, const struct player *other_player, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
static enum fc_tristate is_buildingflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_nation_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
bool is_req_active(const struct req_context *context, const struct player *other_player, const struct requirement *req, const enum req_problem_type prob_type)
static enum fc_tristate is_buildinggenus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
static enum fc_tristate is_diplrel_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
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)
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)
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)
bool are_reqs_active(const struct req_context *context, const struct player *other_player, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
const char * universal_rule_name(const struct universal *psource)
static enum fc_tristate is_ai_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
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)
static enum fc_tristate is_plr_flag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_citytile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_nationality_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_activity_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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 fc_tristate is_wrap_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum req_item_found action_found(const struct requirement *preq, const struct universal *source)
enum fc_tristate default_tester_cb(const struct req_context *context, const struct player *other_player, const struct requirement *req, void *data, int n_data)
bool are_requirements_contradictions(const struct requirement *req1, const struct requirement *req2)
enum fc_tristate tri_req_active_turns(int pass, int period, const struct req_context *context, const struct player *other_player, 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 player *other_player, const struct requirement *req)
#define REQUC_IMPR
struct req_vec_problem * req_vec_problem_new(int num_suggested_solutions, const char *descr,...)
static enum fc_tristate is_form_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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_counter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_none_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
bool universal_is_legal_in_requirement(const struct universal *univ)
static enum fc_tristate is_maxunitsontile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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_terrain_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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)
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_gov_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_terrainalter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_tech_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_good_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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 *)
struct universal universal_by_number(const enum universals_n kind, const int value)
static enum fc_tristate is_achievement_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
enum req_item_found universal_fulfills_requirement(const struct requirement *preq, const struct universal *source)
void requirements_free(void)
static enum fc_tristate is_building_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static bool city_center_contra(const struct requirement *cc_req, const struct requirement *ct_req)
static enum fc_tristate is_unitclassflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum req_item_found ustate_found(const struct requirement *preq, const struct universal *source)
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)
enum fc_tristate tri_reqs_cb_active(const struct req_context *context, const struct player *other_player, const struct requirement_vector *reqs, struct requirement_vector *maybe_reqs, req_tester_cb tester, void *data, int n_data)
static enum req_item_found output_type_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 player *other_player, 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_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_nationgroup_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static bool is_city_in_tile(const struct tile *ptile, const struct city *pcity)
enum fc_tristate(* is_req_active_cb)(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_originalowner_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_plr_state_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
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 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_serversetting_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_action_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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)
#define REQUC_NALLY
static enum req_item_found unit_activity_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_mintechs_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_unitclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
enum fc_tristate tri_req_active(const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_terrainflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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_extra_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
#define thr_req_data_list_iterate(trlist, ptrdata)
static enum req_item_found nation_found(const struct requirement *preq, const struct universal *source)
#define REQUC_WORLD
const char * universal_type_rule_name(const struct universal *psource)
#define REQUC_PRESENT
void universal_found_functions_init(void)
static enum 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_outputtype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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_minsize_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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 player *other_player, 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)
static enum fc_tristate is_unitflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
void requirements_init(void)
bool req_implies_req(const struct requirement *req1, const struct requirement *req2)
#define thr_req_data_list_iterate_end
void req_copy(struct requirement *dst, const struct requirement *src)
enum req_unchanging_status is_req_unchanging(const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_techflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static bool player_has_ever_built(const struct player *pplayer, const struct impr_type *building)
static enum fc_tristate is_terrainclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
enum req_unchanging_status is_req_preventing(const struct req_context *context, const struct player *other_player, const struct requirement *req, enum req_problem_type prob_type)
static bool nation_contra_group(const struct requirement *nation_req, const struct requirement *group_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 enum fc_tristate is_minyear_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static fc_mutex trmutex
static struct thr_req_data_list * trdatas
static bool are_requirements_opposites(const struct requirement *req1, const struct requirement *req2)
static int num_world_buildings(const struct impr_type *building)
static enum fc_tristate is_minmovefrags_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, 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 player *other_player, const struct requirement *req)
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_minculture_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
static void thr_exit_cb(void)
struct universal universal_by_rule_name(const char *kind, const char *value)
static enum fc_tristate is_citystatus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
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)
static enum fc_tristate is_unittype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
#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)
enum fc_tristate(* req_tester_cb)(const struct req_context *context, const struct player *other_player, const struct requirement *req, void *data, int n_data)
#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:410
bool is_road_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:440
bool is_road_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:419
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:140
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:266
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
int techs_researched
Definition research.h:42
fc_thread_id thr_id
Definition tile.h:50
struct tile * tile
Definition unit.h:140
enum universals_n kind
Definition fc_types.h:902
universals_u value
Definition fc_types.h:901
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:974
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:791
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:836
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:900
#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:290
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:299
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:57
#define terrain_has_flag(terr, flag)
Definition terrain.h:283
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:114
#define tile_continent(_tile)
Definition tile.h:92
#define tile_has_extra(ptile, pextra)
Definition tile.h:151
#define tile_owner(_tile)
Definition tile.h:96
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 goods_can_be_provided(const struct city *pcity, const struct goods_type *pgood, struct unit *punit)
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:721
struct nation_style * style
Definition fc_types.h:725
enum ai_level ai_level
Definition fc_types.h:729
struct specialist * specialist
Definition fc_types.h:718
enum impr_genus_id impr_genus
Definition fc_types.h:751
enum citytile_type citytile
Definition fc_types.h:730
struct nation_group * nationgroup
Definition fc_types.h:724
struct extra_type * extra
Definition fc_types.h:722
enum wrap_flag wrap_property
Definition fc_types.h:764
enum plrstate_type plrstate
Definition fc_types.h:732
struct nation_type * nation
Definition fc_types.h:715
int terrainclass
Definition fc_types.h:739
int unitclassflag
Definition fc_types.h:741
struct government * govern
Definition fc_types.h:713
struct nation_type * origowner
Definition fc_types.h:717
enum impr_flag_id impr_flag
Definition fc_types.h:752
int max_tile_units
Definition fc_types.h:755
int terrainalter
Definition fc_types.h:740
enum citystatus_type citystatus
Definition fc_types.h:731
int minforeignpct
Definition fc_types.h:735
const struct impr_type * building
Definition fc_types.h:714
struct achievement * achievement
Definition fc_types.h:723
ssetv ssetval
Definition fc_types.h:765
struct advance * advance
Definition fc_types.h:711
enum unit_activity activity
Definition fc_types.h:750
struct goods_type * good
Definition fc_types.h:727
struct terrain * terrain
Definition fc_types.h:719
int terrainflag
Definition fc_types.h:743
enum ustate_prop unit_state
Definition fc_types.h:749
Output_type_id outputtype
Definition fc_types.h:738
enum topo_flag topo_property
Definition fc_types.h:763
struct counter * counter
Definition fc_types.h:712
int min_hit_points
Definition fc_types.h:757
struct unit_class * uclass
Definition fc_types.h:720
struct nation_type * nationality
Definition fc_types.h:716
struct action * action
Definition fc_types.h:726
enum plr_flag_id plr_flag
Definition fc_types.h:753
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1791
#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
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:2981
struct unit_class * uclass_by_number(const Unit_Class_id id)
Definition unittype.c:2477
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1578
struct unit_type * utype_by_number(const Unit_type_id id)
Definition unittype.c:112
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:3000
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:2468
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:766
#define utype_class(_t_)
Definition unittype.h:749
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:617
bool victory_enabled(enum victory_condition_type victory)
Definition victory.c:26