Freeciv-3.3
Loading...
Searching...
No Matches
requirements.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2004 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17#include <stdarg.h>
18
19/* utility */
20#include "astring.h"
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "achievements.h"
27#include "calendar.h"
28#include "citizens.h"
29#include "counters.h"
30#include "culture.h"
31#include "game.h"
32#include "government.h"
33#include "improvement.h"
34#include "movement.h"
35#include "nation.h"
36#include "player.h"
37#include "map.h"
38#include "research.h"
39#include "road.h"
40#include "server_settings.h"
41#include "specialist.h"
42#include "style.h"
43#include "victory.h" /* victory_enabled() */
44
45#include "requirements.h"
46
47/************************************************************************
48 Container for req_item_found functions
49************************************************************************/
50typedef enum req_item_found (*universal_found)(const struct requirement *,
51 const struct universal *);
53
54static
56 const struct req_context *context,
57 const struct req_context *other_context,
58 const struct requirement *req);
59
60/* Function pointer for requirement-type-specific is_req_active handlers */
61typedef enum fc_tristate
62(*is_req_active_cb)(const struct civ_map *nmap,
63 const struct req_context *context,
64 const struct req_context *other_context,
65 const struct requirement *req);
66
67static inline bool are_tiles_in_range(const struct tile *tile1,
68 const struct tile *tile2,
69 enum req_range range);
70
71/**********************************************************************/
76static enum req_unchanging_status
78 enum req_unchanging_status def,
79 const struct req_context *context,
80 const struct requirement *req)
81{
82 return req->range == REQ_RANGE_LOCAL ? REQUCH_YES : def;
83}
84#define REQUC_LOCAL unchanging_local
85
86/**********************************************************************/
89static enum req_unchanging_status
91 enum req_unchanging_status def,
92 const struct req_context *context,
93 const struct requirement *req)
94{
95 if (TRI_YES != tri_req_present(nmap, context, NULL, req)) {
96 return REQUCH_NO;
97 }
98 return def;
99}
100#define REQUC_PRESENT unchanging_present
101
102/**********************************************************************/
105static enum req_unchanging_status
107 enum req_unchanging_status def,
108 const struct req_context *context,
109 const struct requirement *req)
110{
111 return
113 context, req);
114}
115#define REQUC_WORLD unchanging_world
116
117/**********************************************************************/
121static enum req_unchanging_status
123 enum req_unchanging_status def,
124 const struct req_context *context,
125 const struct requirement *req)
126{
127 if (REQ_RANGE_ALLIANCE == req->range
128 || REQ_RANGE_TEAM == req->range) {
129 struct requirement preq;
130
131 req_copy(&preq, req);
132 preq.range = REQ_RANGE_PLAYER;
134 return REQ_RANGE_TEAM == req->range ? REQUCH_ACT : REQUCH_NO;
135 }
136 }
137 return def;
138}
139#define REQUC_NALLY unchanging_noally
140
141/**********************************************************************/
144static enum req_unchanging_status
146 enum req_unchanging_status def,
147 const struct req_context *context,
148 const struct requirement *req)
149{
153 && NULL != context->city && NULL != context->tile
154 && NULL != city_tile(context->city)
156 req->range))){
157 /* Cities don't move, and most reqs are present on city center */
158 return REQUCH_YES;
159 }
160 return def;
161}
162#define REQUC_CITYTILE unchanging_citytile
163
164/**********************************************************************/
167static enum req_unchanging_status
169 enum req_unchanging_status def,
170 const struct req_context *context,
171 const struct requirement *req)
172{
174
175 if (REQ_RANGE_CITY == req->range
178 return REQUCH_CTRL;
179 }
180
181 return def;
182}
183#define REQUC_CITYSTATUS unchanging_citystatus
184
185/**********************************************************************/
190static enum req_unchanging_status
192 enum req_unchanging_status def,
193 const struct req_context *context,
194 const struct requirement *req)
195{
196 const struct impr_type *b = req->source.value.building;
197
199 || VUT_SITE == req->source.kind, REQUCH_NO);
200 if (REQ_RANGE_LOCAL == req->range) {
201 /* Likely, won't be questioned for an obsolete building */
202 return REQUCH_YES;
203 }
204
205 if (req->source.kind == VUT_IMPROVEMENT
206 && improvement_obsolete(context->player, b, context->city)) {
207 /* FIXME: sometimes can unobsolete, but considering it
208 * may sometimes put the function on endless recursion */
209 return REQUCH_ACT; /* Mostly about techs */
210 }
211 if (is_great_wonder(b)) {
214 && (req->range <= REQ_RANGE_CITY && TRI_YES
215 == tri_req_present(nmap, context, NULL, req)))) {
216 /* If the wonder stays somewhere, it may either remain there
217 * or be destroyed. If it is destroyed, it is nowhere. */
218 return REQUCH_SCRIPTS;
219 }
220 }
221 return def;
222}
223#define REQUC_IMPR unchanging_building
224
230
231/**********************************************************************/
239 const char *value)
240{
241 struct universal source;
242
244 if (!universals_n_is_valid(source.kind)) {
245 return source;
246 }
247
249
250 return source;
251}
252
253/**********************************************************************/
258{
259 return unit_activity_is_valid(act)
260 && act != ACTIVITY_SENTRY
261 && act != ACTIVITY_GOTO
262 && act != ACTIVITY_EXPLORE;
263}
264
265/**********************************************************************/
270{
271 if (univ->kind == VUT_ACTIVITY) {
273 }
274
275 return TRUE;
276}
277
278/**********************************************************************/
283{
284 /* Finally scan the value string based on the type of the source. */
285 switch (source->kind) {
286 case VUT_NONE:
287 return;
288 case VUT_ADVANCE:
289 source->value.advance = advance_by_rule_name(value);
290 if (source->value.advance != NULL) {
291 return;
292 }
293 break;
294 case VUT_TECHFLAG:
295 source->value.techflag
297 if (tech_flag_id_is_valid(source->value.techflag)) {
298 return;
299 }
300 break;
301 case VUT_GOVERNMENT:
302 source->value.govern = government_by_rule_name(value);
303 if (source->value.govern != NULL) {
304 return;
305 }
306 break;
307 case VUT_ACHIEVEMENT:
308 source->value.achievement = achievement_by_rule_name(value);
309 if (source->value.achievement != NULL) {
310 return;
311 }
312 break;
313 case VUT_STYLE:
314 source->value.style = style_by_rule_name(value);
315 if (source->value.style != NULL) {
316 return;
317 }
318 break;
319 case VUT_IMPROVEMENT:
320 case VUT_SITE:
321 source->value.building = improvement_by_rule_name(value);
322 if (source->value.building != NULL) {
323 return;
324 }
325 break;
326 case VUT_IMPR_GENUS:
327 source->value.impr_genus = impr_genus_id_by_name(value, fc_strcasecmp);
328 if (impr_genus_id_is_valid(source->value.impr_genus)) {
329 return;
330 }
331 break;
332 case VUT_IMPR_FLAG:
333 source->value.impr_flag = impr_flag_id_by_name(value, fc_strcasecmp);
334 if (impr_flag_id_is_valid(source->value.impr_flag)) {
335 return;
336 }
337 break;
338 case VUT_PLAYER_FLAG:
339 source->value.plr_flag = plr_flag_id_by_name(value, fc_strcasecmp);
340 if (plr_flag_id_is_valid(source->value.plr_flag)) {
341 return;
342 }
343 break;
344 case VUT_EXTRA:
345 source->value.extra = extra_type_by_rule_name(value);
346 if (source->value.extra != NULL) {
347 return;
348 }
349 break;
350 case VUT_GOOD:
351 source->value.good = goods_by_rule_name(value);
352 if (source->value.good != NULL) {
353 return;
354 }
355 break;
356 case VUT_TERRAIN:
357 source->value.terrain = terrain_by_rule_name(value);
358 if (source->value.terrain != T_UNKNOWN) {
359 return;
360 }
361 break;
362 case VUT_TERRFLAG:
363 source->value.terrainflag
365 if (terrain_flag_id_is_valid(source->value.terrainflag)) {
366 return;
367 }
368 break;
369 case VUT_NATION:
370 source->value.nation = nation_by_rule_name(value);
371 if (source->value.nation != NO_NATION_SELECTED) {
372 return;
373 }
374 break;
375 case VUT_NATIONGROUP:
376 source->value.nationgroup = nation_group_by_rule_name(value);
377 if (source->value.nationgroup != NULL) {
378 return;
379 }
380 break;
381 case VUT_NATIONALITY:
382 source->value.nationality = nation_by_rule_name(value);
383 if (source->value.nationality != NO_NATION_SELECTED) {
384 return;
385 }
386 break;
388 source->value.origowner = nation_by_rule_name(value);
389 if (source->value.origowner != NO_NATION_SELECTED) {
390 return;
391 }
392 break;
393 case VUT_DIPLREL:
394 case VUT_DIPLREL_TILE:
398 source->value.diplrel = diplrel_by_rule_name(value);
399 if (source->value.diplrel != diplrel_other_invalid()) {
400 return;
401 }
402 break;
403 case VUT_UTYPE:
404 source->value.utype = unit_type_by_rule_name(value);
405 if (source->value.utype) {
406 return;
407 }
408 break;
409 case VUT_UTFLAG:
411 if (unit_type_flag_id_is_valid(source->value.unitflag)) {
412 return;
413 }
414 break;
415 case VUT_UCLASS:
416 source->value.uclass = unit_class_by_rule_name(value);
417 if (source->value.uclass) {
418 return;
419 }
420 break;
421 case VUT_UCFLAG:
422 source->value.unitclassflag
424 if (unit_class_flag_id_is_valid(source->value.unitclassflag)) {
425 return;
426 }
427 break;
428 case VUT_MINVETERAN:
429 source->value.minveteran = atoi(value);
430 if (source->value.minveteran > 0) {
431 return;
432 }
433 break;
434 case VUT_UNITSTATE:
435 source->value.unit_state = ustate_prop_by_name(value, fc_strcasecmp);
436 if (ustate_prop_is_valid(source->value.unit_state)) {
437 return;
438 }
439 break;
440 case VUT_ACTIVITY:
442 if (activity_is_valid_in_requirement(source->value.activity)) {
443 return;
444 }
445 break;
446 case VUT_MINMOVES:
447 source->value.minmoves = atoi(value);
448 if (source->value.minmoves > 0) {
449 return;
450 }
451 break;
452 case VUT_MINHP:
453 source->value.min_hit_points = atoi(value);
454 if (source->value.min_hit_points > 0) {
455 return;
456 }
457 break;
458 case VUT_AGE:
459 source->value.age = atoi(value);
460 if (source->value.age > 0) {
461 return;
462 }
463 break;
464 case VUT_FORM_AGE:
465 source->value.form_age = atoi(value);
466 if (source->value.form_age > 0) {
467 return;
468 }
469 break;
470 case VUT_MINTECHS:
471 source->value.min_techs = atoi(value);
472 if (source->value.min_techs > 0) {
473 return;
474 }
475 break;
476 case VUT_MINCITIES:
477 source->value.min_cities = atoi(value);
478 if (source->value.min_cities > 0) {
479 return;
480 }
481 break;
482 case VUT_ACTION:
483 source->value.action = action_by_rule_name(value);
484 if (source->value.action != NULL) {
485 return;
486 }
487 break;
488 case VUT_OTYPE:
489 source->value.outputtype = output_type_by_identifier(value);
490 if (source->value.outputtype != O_LAST) {
491 return;
492 }
493 break;
494 case VUT_SPECIALIST:
495 source->value.specialist = specialist_by_rule_name(value);
496 if (source->value.specialist) {
497 return;
498 }
499 break;
500 case VUT_MINSIZE:
501 source->value.minsize = atoi(value);
502 if (source->value.minsize > 0) {
503 return;
504 }
505 break;
506 case VUT_MINCULTURE:
507 source->value.minculture = atoi(value);
508 if (source->value.minculture > 0) {
509 return;
510 }
511 break;
513 source->value.minforeignpct = atoi(value);
514 if (source->value.minforeignpct > 0) {
515 return;
516 }
517 break;
518 case VUT_AI_LEVEL:
519 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
520 if (ai_level_is_valid(source->value.ai_level)) {
521 return;
522 }
523 break;
524 case VUT_MAXTILEUNITS:
525 source->value.max_tile_units = atoi(value);
526 if (0 <= source->value.max_tile_units) {
527 return;
528 }
529 break;
530 case VUT_TERRAINCLASS:
531 source->value.terrainclass
533 if (terrain_class_is_valid(source->value.terrainclass)) {
534 return;
535 }
536 break;
537 case VUT_ROADFLAG:
539 if (road_flag_id_is_valid(source->value.roadflag)) {
540 return;
541 }
542 break;
543 case VUT_EXTRAFLAG:
544 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
545 if (extra_flag_id_is_valid(source->value.extraflag)) {
546 return;
547 }
548 break;
549 case VUT_MINYEAR:
550 source->value.minyear = atoi(value);
551 return;
552 case VUT_MINCALFRAG:
553 /* Rule names are 0-based numbers, not pretty names from ruleset */
554 source->value.mincalfrag = atoi(value);
555 if (source->value.mincalfrag >= 0) {
556 /* More range checking done later, in sanity_check_req_individual() */
557 return;
558 }
559 break;
560 case VUT_TOPO:
561 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
562 if (topo_flag_is_valid(source->value.topo_property)) {
563 return;
564 }
565 break;
566 case VUT_WRAP:
567 source->value.wrap_property = wrap_flag_by_name(value, fc_strcasecmp);
568 if (wrap_flag_is_valid(source->value.wrap_property)) {
569 return;
570 }
571 break;
573 source->value.ssetval = ssetv_by_rule_name(value);
574 if (source->value.ssetval != SSETV_NONE) {
575 return;
576 }
577 break;
578 case VUT_TERRAINALTER:
579 source->value.terrainalter
581 if (terrain_alteration_is_valid(source->value.terrainalter)) {
582 return;
583 }
584 break;
585 case VUT_CITYTILE:
587 if (source->value.citytile != CITYT_LAST) {
588 return;
589 }
590 break;
591 case VUT_CITYSTATUS:
593 if (source->value.citystatus != CITYS_LAST) {
594 return;
595 }
596 break;
597 case VUT_PLAYER_STATE:
599 if (source->value.plrstate != PLRS_LAST) {
600 return;
601 }
602 break;
603 case VUT_MINLATITUDE:
604 case VUT_MAXLATITUDE:
605 source->value.latitude = atoi(value);
606 if (source->value.latitude >= -MAP_MAX_LATITUDE
607 && source->value.latitude <= MAP_MAX_LATITUDE) {
608 return;
609 }
610 break;
611 case VUT_COUNTER:
612 source->value.counter = counter_by_rule_name(value);
613 if (source->value.counter != NULL) {
614 return;
615 }
616 break;
618 source->value.distance_sq = atoi(value);
619 if (0 <= source->value.distance_sq) {
620 return;
621 }
622 break;
624 source->value.region_tiles = atoi(value);
625 if (0 < source->value.region_tiles) {
626 return;
627 }
628 break;
629 case VUT_TILE_REL:
631 if (source->value.tilerel != TREL_COUNT) {
632 return;
633 }
634 break;
635 case VUT_COUNT:
636 break;
637 }
638
639 /* If we reach here there's been an error. */
641}
642
643/**********************************************************************/
650{
651 struct universal source;
652
653 source.kind = kind;
654
655 switch (source.kind) {
656 case VUT_NONE:
657 /* Avoid compiler warning about unitialized source.value */
658 source.value.advance = NULL;
659
660 return source;
661 case VUT_ADVANCE:
662 source.value.advance = advance_by_number(value);
663 if (source.value.advance != NULL) {
664 return source;
665 }
666 break;
667 case VUT_TECHFLAG:
668 source.value.techflag = value;
669 return source;
670 case VUT_GOVERNMENT:
672 if (source.value.govern != NULL) {
673 return source;
674 }
675 break;
676 case VUT_ACHIEVEMENT:
677 source.value.achievement = achievement_by_number(value);
678 if (source.value.achievement != NULL) {
679 return source;
680 }
681 break;
682 case VUT_STYLE:
683 source.value.style = style_by_number(value);
684 if (source.value.style != NULL) {
685 return source;
686 }
687 break;
688 case VUT_IMPROVEMENT:
689 case VUT_SITE:
690 source.value.building = improvement_by_number(value);
691 if (source.value.building != NULL) {
692 return source;
693 }
694 break;
695 case VUT_IMPR_GENUS:
696 source.value.impr_genus = value;
697 return source;
698 case VUT_IMPR_FLAG:
699 source.value.impr_flag = value;
700 return source;
701 case VUT_PLAYER_FLAG:
702 source.value.plr_flag = value;
703 return source;
704 case VUT_EXTRA:
706 return source;
707 case VUT_GOOD:
708 source.value.good = goods_by_number(value);
709 return source;
710 case VUT_TERRAIN:
711 source.value.terrain = terrain_by_number(value);
712 if (source.value.terrain != NULL) {
713 return source;
714 }
715 break;
716 case VUT_TERRFLAG:
717 source.value.terrainflag = value;
718 return source;
719 case VUT_NATION:
721 if (source.value.nation != NULL) {
722 return source;
723 }
724 break;
725 case VUT_NATIONGROUP:
726 source.value.nationgroup = nation_group_by_number(value);
727 if (source.value.nationgroup != NULL) {
728 return source;
729 }
730 break;
731 case VUT_DIPLREL:
732 case VUT_DIPLREL_TILE:
736 source.value.diplrel = value;
737 if (source.value.diplrel != diplrel_other_invalid()) {
738 return source;
739 }
740 break;
741 case VUT_NATIONALITY:
743 if (source.value.nationality != NULL) {
744 return source;
745 }
746 break;
748 source.value.origowner = nation_by_number(value);
749 if (source.value.origowner != NULL) {
750 return source;
751 }
752 break;
753 case VUT_UTYPE:
754 source.value.utype = utype_by_number(value);
755 if (source.value.utype != NULL) {
756 return source;
757 }
758 break;
759 case VUT_UTFLAG:
760 source.value.unitflag = value;
761 return source;
762 case VUT_UCLASS:
764 if (source.value.uclass != NULL) {
765 return source;
766 }
767 break;
768 case VUT_UCFLAG:
769 source.value.unitclassflag = value;
770 return source;
771 case VUT_MINVETERAN:
772 source.value.minveteran = value;
773 return source;
774 case VUT_UNITSTATE:
775 source.value.unit_state = value;
776 return source;
777 case VUT_ACTIVITY:
778 source.value.activity = value;
779 return source;
780 case VUT_MINMOVES:
781 source.value.minmoves = value;
782 return source;
783 case VUT_MINHP:
785 return source;
786 case VUT_AGE:
787 source.value.age = value;
788 return source;
789 case VUT_FORM_AGE:
790 source.value.form_age = value;
791 return source;
792 case VUT_MINTECHS:
793 source.value.min_techs = value;
794 return source;
795 case VUT_MINCITIES:
796 source.value.min_cities = value;
797 return source;
798 case VUT_ACTION:
800 if (source.value.action != NULL) {
801 return source;
802 }
803 break;
804 case VUT_OTYPE:
805 source.value.outputtype = value;
806 return source;
807 case VUT_SPECIALIST:
809 return source;
810 case VUT_MINSIZE:
811 source.value.minsize = value;
812 return source;
813 case VUT_MINCULTURE:
814 source.value.minculture = value;
815 return source;
817 source.value.minforeignpct = value;
818 return source;
819 case VUT_AI_LEVEL:
820 source.value.ai_level = value;
821 return source;
822 case VUT_MAXTILEUNITS:
824 return source;
825 case VUT_TERRAINCLASS:
826 source.value.terrainclass = value;
827 return source;
828 case VUT_ROADFLAG:
829 source.value.roadflag = value;
830 return source;
831 case VUT_EXTRAFLAG:
832 source.value.extraflag = value;
833 return source;
834 case VUT_MINYEAR:
835 source.value.minyear = value;
836 return source;
837 case VUT_MINCALFRAG:
838 source.value.mincalfrag = value;
839 return source;
840 case VUT_TOPO:
841 source.value.topo_property = value;
842 return source;
843 case VUT_WRAP:
844 source.value.wrap_property = value;
845 return source;
847 source.value.ssetval = value;
848 return source;
849 case VUT_TERRAINALTER:
850 source.value.terrainalter = value;
851 return source;
852 case VUT_CITYTILE:
853 source.value.citytile = value;
854 return source;
855 case VUT_CITYSTATUS:
856 source.value.citystatus = value;
857 return source;
858 case VUT_PLAYER_STATE:
859 source.value.plrstate = value;
860 return source;
861 case VUT_COUNTER:
863 return source;
864 case VUT_MINLATITUDE:
865 case VUT_MAXLATITUDE:
866 source.value.latitude = value;
867 return source;
869 source.value.distance_sq = value;
870 return source;
872 source.value.region_tiles = value;
873 return source;
874 case VUT_TILE_REL:
875 source.value.tilerel = value;
876 return source;
877 case VUT_COUNT:
878 break;
879 }
880
881 /* If we reach here there's been an error. */
883 /* Avoid compiler warning about unitialized source.value */
884 source.value.advance = NULL;
885
886 return source;
887}
888
889/**********************************************************************/
892void universal_copy(struct universal *dst, const struct universal *src)
893{
894 dst->value = src->value;
895 dst->kind = src->kind;
896}
897
898/**********************************************************************/
903 int *kind, int *value)
904{
905 *kind = source->kind;
907}
908
909/**********************************************************************/
913{
914 switch (source->kind) {
915 case VUT_NONE:
916 return 0;
917 case VUT_ADVANCE:
918 return advance_number(source->value.advance);
919 case VUT_TECHFLAG:
920 return source->value.techflag;
921 case VUT_GOVERNMENT:
922 return government_number(source->value.govern);
923 case VUT_ACHIEVEMENT:
924 return achievement_number(source->value.achievement);
925 case VUT_STYLE:
926 return style_number(source->value.style);
927 case VUT_IMPROVEMENT:
928 case VUT_SITE:
929 return improvement_number(source->value.building);
930 case VUT_IMPR_GENUS:
931 return source->value.impr_genus;
932 case VUT_IMPR_FLAG:
933 return source->value.impr_flag;
934 case VUT_PLAYER_FLAG:
935 return source->value.plr_flag;
936 case VUT_EXTRA:
937 return extra_number(source->value.extra);
938 case VUT_GOOD:
939 return goods_number(source->value.good);
940 case VUT_TERRAIN:
941 return terrain_number(source->value.terrain);
942 case VUT_TERRFLAG:
943 return source->value.terrainflag;
944 case VUT_NATION:
945 return nation_number(source->value.nation);
946 case VUT_NATIONGROUP:
947 return nation_group_number(source->value.nationgroup);
948 case VUT_NATIONALITY:
949 return nation_number(source->value.nationality);
951 return nation_number(source->value.origowner);
952 case VUT_DIPLREL:
953 case VUT_DIPLREL_TILE:
957 return source->value.diplrel;
958 case VUT_UTYPE:
959 return utype_number(source->value.utype);
960 case VUT_UTFLAG:
961 return source->value.unitflag;
962 case VUT_UCLASS:
963 return uclass_number(source->value.uclass);
964 case VUT_UCFLAG:
965 return source->value.unitclassflag;
966 case VUT_MINVETERAN:
967 return source->value.minveteran;
968 case VUT_UNITSTATE:
969 return source->value.unit_state;
970 case VUT_ACTIVITY:
971 return source->value.activity;
972 case VUT_MINMOVES:
973 return source->value.minmoves;
974 case VUT_MINHP:
975 return source->value.min_hit_points;
976 case VUT_AGE:
977 return source->value.age;
978 case VUT_FORM_AGE:
979 return source->value.form_age;
980 case VUT_MINTECHS:
981 return source->value.min_techs;
982 case VUT_MINCITIES:
983 return source->value.min_cities;
984 case VUT_ACTION:
985 return action_number(source->value.action);
986 case VUT_OTYPE:
987 return source->value.outputtype;
988 case VUT_SPECIALIST:
989 return specialist_number(source->value.specialist);
990 case VUT_MINSIZE:
991 return source->value.minsize;
992 case VUT_MINCULTURE:
993 return source->value.minculture;
995 return source->value.minforeignpct;
996 case VUT_AI_LEVEL:
997 return source->value.ai_level;
998 case VUT_MAXTILEUNITS:
999 return source->value.max_tile_units;
1000 case VUT_TERRAINCLASS:
1001 return source->value.terrainclass;
1002 case VUT_ROADFLAG:
1003 return source->value.roadflag;
1004 case VUT_EXTRAFLAG:
1005 return source->value.extraflag;
1006 case VUT_MINYEAR:
1007 return source->value.minyear;
1008 case VUT_MINCALFRAG:
1009 return source->value.mincalfrag;
1010 case VUT_TOPO:
1011 return source->value.topo_property;
1012 case VUT_WRAP:
1013 return source->value.wrap_property;
1014 case VUT_SERVERSETTING:
1015 return source->value.ssetval;
1016 case VUT_TERRAINALTER:
1017 return source->value.terrainalter;
1018 case VUT_CITYTILE:
1019 return source->value.citytile;
1020 case VUT_CITYSTATUS:
1021 return source->value.citystatus;
1022 case VUT_PLAYER_STATE:
1023 return source->value.plrstate;
1024 case VUT_COUNTER:
1025 return counter_id(source->value.counter);
1026 case VUT_MINLATITUDE:
1027 case VUT_MAXLATITUDE:
1028 return source->value.latitude;
1030 return source->value.distance_sq;
1032 return source->value.region_tiles;
1033 case VUT_TILE_REL:
1034 return source->value.tilerel;
1035 case VUT_COUNT:
1036 break;
1037 }
1038
1039 /* If we reach here there's been an error. */
1040 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
1041 source->kind);
1042 return 0;
1043}
1044
1045
1046/**********************************************************************/
1050{
1051 static const struct req_context empty = {};
1052 return &empty;
1053}
1054
1055
1056/**********************************************************************/
1064const char *req_to_fstring(const struct requirement *req,
1065 struct astring *astr)
1066{
1067 astr_init(astr);
1068
1069 astr_set(astr, "%s%s %s %s%s",
1070 req->survives ? "surviving " : "",
1071 req_range_name(req->range),
1073 req->present ? "" : "!",
1075
1076 return astr_str(astr);
1077}
1078
1079/**********************************************************************/
1087 bool survives, bool present, bool quiet,
1088 const char *value)
1089{
1090 struct requirement req;
1091 bool invalid;
1092 const char *error = NULL;
1093
1094 req.source = universal_by_rule_name(type, value);
1095
1097 if (invalid) {
1098 error = "bad type or name";
1099 } else {
1100 /* Scan the range string to find the range. If no range is given a
1101 * default fallback is used rather than giving an error. */
1102 if (range != NULL) {
1104 if (!req_range_is_valid(req.range)) {
1105 invalid = TRUE;
1106 }
1107 } else {
1108 switch (req.source.kind) {
1109 case VUT_NONE:
1110 case VUT_COUNT:
1111 break;
1112 case VUT_IMPROVEMENT:
1113 case VUT_SITE:
1114 case VUT_IMPR_GENUS:
1115 case VUT_IMPR_FLAG:
1116 case VUT_UTYPE:
1117 case VUT_UTFLAG:
1118 case VUT_UCLASS:
1119 case VUT_UCFLAG:
1120 case VUT_MINVETERAN:
1121 case VUT_UNITSTATE:
1122 case VUT_ACTIVITY:
1123 case VUT_MINMOVES:
1124 case VUT_MINHP:
1125 case VUT_AGE:
1126 case VUT_FORM_AGE:
1127 case VUT_ACTION:
1128 case VUT_OTYPE:
1129 case VUT_SPECIALIST:
1130 case VUT_DIPLREL_TILE_O:
1132 req.range = REQ_RANGE_LOCAL;
1133 break;
1134 case VUT_EXTRA:
1135 case VUT_ROADFLAG:
1136 case VUT_EXTRAFLAG:
1137 /* Keep old behavior */
1138 req.range = REQ_RANGE_TILE;
1139 break;
1140 case VUT_TERRAIN:
1141 case VUT_TERRFLAG:
1142 case VUT_TERRAINCLASS:
1143 case VUT_TERRAINALTER:
1144 case VUT_CITYTILE:
1145 case VUT_MAXTILEUNITS:
1146 case VUT_MINLATITUDE:
1147 case VUT_MAXLATITUDE:
1149 req.range = REQ_RANGE_TILE;
1150 break;
1151 case VUT_COUNTER:
1152 case VUT_MINSIZE:
1153 case VUT_MINCULTURE:
1154 case VUT_MINFOREIGNPCT:
1155 case VUT_NATIONALITY:
1156 case VUT_ORIGINAL_OWNER:
1157 case VUT_CITYSTATUS:
1158 case VUT_GOOD:
1159 req.range = REQ_RANGE_CITY;
1160 break;
1161 case VUT_GOVERNMENT:
1162 case VUT_ACHIEVEMENT:
1163 case VUT_STYLE:
1164 case VUT_ADVANCE:
1165 case VUT_TECHFLAG:
1166 case VUT_NATION:
1167 case VUT_NATIONGROUP:
1168 case VUT_DIPLREL:
1169 case VUT_DIPLREL_TILE:
1171 case VUT_AI_LEVEL:
1172 case VUT_PLAYER_FLAG:
1173 case VUT_PLAYER_STATE:
1174 case VUT_MINCITIES:
1175 req.range = REQ_RANGE_PLAYER;
1176 break;
1177 case VUT_MINYEAR:
1178 case VUT_MINCALFRAG:
1179 case VUT_TOPO:
1180 case VUT_WRAP:
1181 case VUT_MINTECHS:
1182 case VUT_SERVERSETTING:
1183 req.range = REQ_RANGE_WORLD;
1184 break;
1187 break;
1188 case VUT_TILE_REL:
1189 req.range = REQ_RANGE_TILE;
1191 /* Not available at Tile range */
1193 }
1194 break;
1195 }
1196 }
1197
1198 req.survives = survives;
1199 req.present = present;
1200 req.quiet = quiet;
1201
1202 /* These checks match what combinations are supported inside
1203 * is_req_active(). However, it's only possible to do basic checks,
1204 * not anything that might depend on the rest of the ruleset which
1205 * might not have been loaded yet. */
1206 switch (req.source.kind) {
1207 case VUT_TERRAIN:
1208 case VUT_TERRAINCLASS:
1209 case VUT_TERRFLAG:
1210 invalid = (req.range != REQ_RANGE_TILE
1211 && req.range != REQ_RANGE_CADJACENT
1212 && req.range != REQ_RANGE_ADJACENT
1213 && req.range != REQ_RANGE_CITY
1214 && req.range != REQ_RANGE_TRADE_ROUTE);
1215 break;
1216 case VUT_EXTRA:
1217 case VUT_ROADFLAG:
1218 case VUT_EXTRAFLAG:
1220 break;
1221 case VUT_ACHIEVEMENT:
1222 case VUT_MINTECHS:
1223 invalid = (req.range < REQ_RANGE_PLAYER);
1224 break;
1225 case VUT_ADVANCE:
1226 case VUT_TECHFLAG:
1228 && req.range != REQ_RANGE_LOCAL);
1229 break;
1230 case VUT_GOVERNMENT:
1231 case VUT_AI_LEVEL:
1232 case VUT_STYLE:
1233 case VUT_MINCITIES:
1234 invalid = (req.range != REQ_RANGE_PLAYER);
1235 break;
1236 case VUT_MINSIZE:
1237 case VUT_MINFOREIGNPCT:
1238 case VUT_NATIONALITY:
1239 case VUT_CITYSTATUS:
1240 invalid = (req.range != REQ_RANGE_CITY
1241 && req.range != REQ_RANGE_TRADE_ROUTE);
1242 break;
1243 case VUT_GOOD:
1244 case VUT_ORIGINAL_OWNER:
1245 invalid = (req.range != REQ_RANGE_CITY);
1246 break;
1247 case VUT_MINCULTURE:
1248 invalid = (req.range != REQ_RANGE_CITY
1250 && req.range != REQ_RANGE_PLAYER
1251 && req.range != REQ_RANGE_TEAM
1252 && req.range != REQ_RANGE_ALLIANCE
1253 && req.range != REQ_RANGE_WORLD);
1254 break;
1255 case VUT_DIPLREL:
1256 invalid = (req.range != REQ_RANGE_LOCAL
1257 && req.range != REQ_RANGE_PLAYER
1258 && req.range != REQ_RANGE_TEAM
1259 && req.range != REQ_RANGE_ALLIANCE
1260 && req.range != REQ_RANGE_WORLD)
1261 /* Non local foreign makes no sense. */
1262 || (req.source.value.diplrel == DRO_FOREIGN
1263 && req.range != REQ_RANGE_LOCAL);
1264 break;
1265 case VUT_DIPLREL_TILE:
1266 invalid = (req.range != REQ_RANGE_LOCAL
1267 && req.range != REQ_RANGE_PLAYER
1268 && req.range != REQ_RANGE_TEAM
1269 && req.range != REQ_RANGE_ALLIANCE)
1270 /* Non local foreign makes no sense. */
1271 || (req.source.value.diplrel == DRO_FOREIGN
1272 && req.range != REQ_RANGE_LOCAL);
1273 break;
1274 case VUT_DIPLREL_TILE_O:
1275 invalid = (req.range != REQ_RANGE_LOCAL);
1276 break;
1278 invalid = (req.range != REQ_RANGE_LOCAL
1279 && req.range != REQ_RANGE_PLAYER
1280 && req.range != REQ_RANGE_TEAM
1281 && req.range != REQ_RANGE_ALLIANCE)
1282 /* Non local foreign makes no sense. */
1283 || (req.source.value.diplrel == DRO_FOREIGN
1284 && req.range != REQ_RANGE_LOCAL);
1285 break;
1287 invalid = (req.range != REQ_RANGE_LOCAL);
1288 break;
1289 case VUT_NATION:
1290 case VUT_NATIONGROUP:
1292 && req.range != REQ_RANGE_TEAM
1293 && req.range != REQ_RANGE_ALLIANCE
1294 && req.range != REQ_RANGE_WORLD);
1295 break;
1296 case VUT_MINVETERAN:
1297 case VUT_UNITSTATE:
1298 case VUT_ACTIVITY:
1299 case VUT_MINMOVES:
1300 case VUT_MINHP:
1301 case VUT_ACTION:
1302 case VUT_OTYPE:
1303 case VUT_SPECIALIST:
1304 invalid = (req.range != REQ_RANGE_LOCAL);
1305 break;
1306 case VUT_UTYPE:
1307 case VUT_UTFLAG:
1308 case VUT_UCLASS:
1309 case VUT_UCFLAG:
1310 invalid = (req.range != REQ_RANGE_LOCAL
1311 && req.range != REQ_RANGE_TILE
1312 && req.range != REQ_RANGE_CADJACENT
1313 && req.range != REQ_RANGE_ADJACENT);
1314 break;
1315 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1317 invalid = (req.range != REQ_RANGE_TILE);
1318 break;
1319 case VUT_CITYTILE:
1320 case VUT_MAXTILEUNITS:
1321 invalid = (req.range != REQ_RANGE_TILE
1322 && req.range != REQ_RANGE_CADJACENT
1323 && req.range != REQ_RANGE_ADJACENT);
1324 break;
1325 case VUT_MINLATITUDE:
1326 case VUT_MAXLATITUDE:
1327 invalid = (req.range != REQ_RANGE_TILE
1328 && req.range != REQ_RANGE_CADJACENT
1329 && req.range != REQ_RANGE_ADJACENT
1330 && req.range != REQ_RANGE_WORLD)
1331 /* Avoid redundancy at tile range: no negated requirements
1332 * that could be emulated by a present requirement of the
1333 * other type */
1334 || (req.range == REQ_RANGE_TILE && !req.present);
1335 break;
1336 case VUT_MINYEAR:
1337 case VUT_MINCALFRAG:
1338 case VUT_TOPO:
1339 case VUT_WRAP:
1340 case VUT_SERVERSETTING:
1341 invalid = (req.range != REQ_RANGE_WORLD);
1342 break;
1343 case VUT_AGE:
1344 /* FIXME: could support TRADE_ROUTE, TEAM, etc */
1345 invalid = (req.range != REQ_RANGE_LOCAL
1346 && req.range != REQ_RANGE_CITY
1347 && req.range != REQ_RANGE_PLAYER);
1348 break;
1349 case VUT_FORM_AGE:
1350 invalid = (req.range != REQ_RANGE_LOCAL);
1351 break;
1352 case VUT_IMPR_GENUS:
1353 /* TODO: Support other ranges too. */
1354 invalid = (req.range != REQ_RANGE_LOCAL);
1355 break;
1356 case VUT_IMPR_FLAG:
1357 invalid = (req.range != REQ_RANGE_LOCAL
1358 && req.range != REQ_RANGE_TILE
1359 && req.range != REQ_RANGE_CITY);
1360 break;
1361 case VUT_COUNTER:
1362 invalid = req.range != REQ_RANGE_CITY;
1363 break;
1364 case VUT_PLAYER_FLAG:
1365 case VUT_PLAYER_STATE:
1366 invalid = (req.range != REQ_RANGE_PLAYER);
1367 break;
1370 && req.range != REQ_RANGE_CADJACENT
1371 && req.range != REQ_RANGE_ADJACENT);
1372 break;
1373 case VUT_TILE_REL:
1375 && req.range != REQ_RANGE_CADJACENT
1376 && req.range != REQ_RANGE_TILE)
1377 /* TREL_ONLY_OTHER_REGION not supported at Tile range */
1379 && req.range == REQ_RANGE_TILE);
1380 break;
1381 case VUT_IMPROVEMENT:
1382 case VUT_SITE:
1383 /* Valid ranges depend on the building genus (wonder/improvement),
1384 * which might not have been loaded from the ruleset yet.
1385 * So we allow anything here, and do a proper check once ruleset
1386 * loading is complete, in sanity_check_req_individual(). */
1387 case VUT_NONE:
1388 invalid = FALSE;
1389 break;
1390 case VUT_COUNT:
1391 break;
1392 }
1393 if (invalid) {
1394 error = "bad range";
1395 }
1396 }
1397
1398 if (!invalid) {
1399 /* Check 'survives'. */
1400 switch (req.source.kind) {
1401 case VUT_IMPROVEMENT:
1402 case VUT_SITE:
1403 /* See buildings_in_range(). */
1405 break;
1406 case VUT_NATION:
1407 case VUT_ADVANCE:
1409 break;
1410 case VUT_COUNTER:
1411 case VUT_IMPR_GENUS:
1412 case VUT_IMPR_FLAG:
1413 case VUT_PLAYER_FLAG:
1414 case VUT_PLAYER_STATE:
1415 case VUT_GOVERNMENT:
1416 case VUT_TERRAIN:
1417 case VUT_UTYPE:
1418 case VUT_UTFLAG:
1419 case VUT_UCLASS:
1420 case VUT_UCFLAG:
1421 case VUT_MINVETERAN:
1422 case VUT_UNITSTATE:
1423 case VUT_ACTIVITY:
1424 case VUT_MINMOVES:
1425 case VUT_MINHP:
1426 case VUT_AGE:
1427 case VUT_FORM_AGE:
1428 case VUT_ACTION:
1429 case VUT_OTYPE:
1430 case VUT_SPECIALIST:
1431 case VUT_MINSIZE:
1432 case VUT_MINCULTURE:
1433 case VUT_MINFOREIGNPCT:
1434 case VUT_AI_LEVEL:
1435 case VUT_TERRAINCLASS:
1436 case VUT_MINYEAR:
1437 case VUT_MINCALFRAG:
1438 case VUT_TOPO:
1439 case VUT_WRAP:
1440 case VUT_SERVERSETTING:
1441 case VUT_TERRAINALTER:
1442 case VUT_CITYTILE:
1443 case VUT_CITYSTATUS:
1444 case VUT_TERRFLAG:
1445 case VUT_NATIONALITY:
1446 case VUT_ORIGINAL_OWNER:
1447 case VUT_ROADFLAG:
1448 case VUT_EXTRAFLAG:
1449 case VUT_EXTRA:
1450 case VUT_GOOD:
1451 case VUT_TECHFLAG:
1452 case VUT_ACHIEVEMENT:
1453 case VUT_NATIONGROUP:
1454 case VUT_STYLE:
1455 case VUT_DIPLREL:
1456 case VUT_DIPLREL_TILE:
1457 case VUT_DIPLREL_TILE_O:
1460 case VUT_MAXTILEUNITS:
1461 case VUT_MINTECHS:
1462 case VUT_MINCITIES:
1463 case VUT_MINLATITUDE:
1464 case VUT_MAXLATITUDE:
1467 case VUT_TILE_REL:
1468 /* Most requirements don't support 'survives'. */
1469 invalid = survives;
1470 break;
1471 case VUT_NONE:
1472 case VUT_COUNT:
1473 break;
1474 }
1475 if (invalid) {
1476 error = "bad 'survives'";
1477 }
1478 }
1479
1480 if (invalid) {
1481 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1482 type, range, survives ? "survives" : "",
1483 present ? "present" : "", value, error);
1485 }
1486
1487 return req;
1488}
1489
1490/**********************************************************************/
1496 int value)
1497{
1498 struct requirement req;
1499
1500 req.source = universal_by_number(type, value);
1501 req.range = range;
1502 req.survives = survives;
1503 req.present = present;
1504 req.quiet = quiet;
1505
1506 return req;
1507}
1508
1509/**********************************************************************/
1513void req_get_values(const struct requirement *req,
1514 int *type, int *range,
1515 bool *survives, bool *present, bool *quiet,
1516 int *value)
1517{
1518 universal_extraction(&req->source, type, value);
1519 *range = req->range;
1520 *survives = req->survives;
1521 *present = req->present;
1522 *quiet = req->quiet;
1523}
1524
1525/**********************************************************************/
1528void req_copy(struct requirement *dst, const struct requirement *src)
1529{
1530 universal_copy(&(dst->source), &(src->source));
1531 dst->range = src->range;
1532 dst->survives = src->survives;
1533 dst->present = src->present;
1534 dst->quiet = src->quiet;
1535}
1536
1537/**********************************************************************/
1541bool are_requirements_equal(const struct requirement *req1,
1542 const struct requirement *req2)
1543{
1544 return (are_universals_equal(&req1->source, &req2->source)
1545 && req1->range == req2->range
1546 && req1->survives == req2->survives
1547 && req1->present == req2->present);
1548}
1549
1550/**********************************************************************/
1553static bool are_requirements_opposites(const struct requirement *req1,
1554 const struct requirement *req2)
1555{
1556 return (are_universals_equal(&req1->source, &req2->source)
1557 && req1->range == req2->range
1558 && req1->survives == req2->survives
1559 && req1->present != req2->present);
1560}
1561
1562/**********************************************************************/
1566static bool impr_contra_genus(const struct requirement *impr_req,
1567 const struct requirement *genus_req)
1568{
1569 /* The input is sane. */
1571 || impr_req->source.kind == VUT_SITE, FALSE);
1573
1574 if (impr_req->range == REQ_RANGE_LOCAL
1575 && genus_req->range == REQ_RANGE_LOCAL) {
1576 /* Applies to the same target building. */
1577
1578 if (impr_req->present && !genus_req->present) {
1579 /* The target building can't not have the genus it has. */
1580 return (impr_req->source.value.building->genus
1581 == genus_req->source.value.impr_genus);
1582 }
1583
1584 if (impr_req->present && genus_req->present) {
1585 /* The target building can't have another genus than it has. */
1586 return (impr_req->source.value.building->genus
1587 != genus_req->source.value.impr_genus);
1588 }
1589 }
1590
1591 /* No special knowledge. */
1592 return FALSE;
1593}
1594
1595/**********************************************************************/
1599static bool impr_contra_flag(const struct requirement *impr_req,
1600 const struct requirement *flag_req)
1601{
1602 /* The input is sane. */
1604 || impr_req->source.kind == VUT_SITE, FALSE);
1606
1607 if (impr_req->range == REQ_RANGE_LOCAL
1608 && flag_req->range == REQ_RANGE_LOCAL) {
1609 /* Applies to the same target building. */
1610
1611 if (impr_req->present && !flag_req->present) {
1612 /* The target building can't not have the flag it has. */
1613 return improvement_has_flag(impr_req->source.value.building,
1614 flag_req->source.value.impr_flag);
1615 }
1616
1617 if (impr_req->present && flag_req->present) {
1618 /* The target building can't have another flag than it has. */
1619 return !improvement_has_flag(impr_req->source.value.building,
1620 flag_req->source.value.impr_flag);
1621 }
1622 }
1623
1624 /* No special knowledge. */
1625 return FALSE;
1626}
1627
1628/**********************************************************************/
1633 const struct requirement *group_req)
1634{
1635 /* The input is sane. */
1636 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1638
1639 if (nation_req->range == REQ_RANGE_PLAYER
1640 && group_req->range == REQ_RANGE_PLAYER) {
1641 /* Applies to the same target building. */
1642
1643 if (nation_req->present && !group_req->present) {
1644 /* The target nation can't be in the group. */
1645 return nation_is_in_group(nation_req->source.value.nation,
1646 group_req->source.value.nationgroup);
1647 }
1648 }
1649
1650 /* No special knowledge. */
1651 return FALSE;
1652}
1653
1654/**********************************************************************/
1658static bool city_center_contra(const struct requirement *cc_req,
1659 const struct requirement *ct_req)
1660{
1661 /* The input is sane. */
1662 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1663 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1664
1665 if (cc_req->source.value.citytile == CITYT_CENTER
1666 && cc_req->present && cc_req->range <= ct_req->range) {
1667 switch (ct_req->source.value.citytile) {
1668 case CITYT_CENTER:
1669 case CITYT_CLAIMED:
1670 case CITYT_EXTRAS_OWNED:
1671 case CITYT_WORKED:
1673 /* Should be always on city center */
1674 return !ct_req->present;
1676 /* Handled later */
1677 break;
1678 case CITYT_LAST:
1679 /* Error */
1680 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1681 }
1682 }
1683 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1684 || cc_req->source.value.citytile == CITYT_CENTER)
1685 && ct_req->source.value.citytile
1687 && REQ_RANGE_TILE == cc_req->range
1688 && REQ_RANGE_TILE == ct_req->range) {
1689 /* Can't coexist */
1690 return cc_req->present ? ct_req->present : !ct_req->present;
1691 }
1692
1693 return FALSE;
1694}
1695
1696/**********************************************************************/
1701static bool present_implies_not_present(const struct requirement *req1,
1702 const struct requirement *req2)
1703{
1704 const struct requirement *absent, *present;
1705
1706 if (req1->present == req2->present) {
1707 /* Can't use the knowledge in universal_found_function when both are
1708 * required to be absent or when both are required to be present.
1709 * It is no contradiction to require !Spy unit and !Missile unit class.
1710 * It is no contradiction to require River and Irrigation at the same
1711 * tile. */
1712 return FALSE;
1713 }
1714
1715 if (req1->present) {
1716 absent = req2;
1717 present = req1;
1718 } else {
1719 absent = req1;
1720 present = req2;
1721 }
1722
1723 if (!universal_found_function[present->source.kind]) {
1724 /* No knowledge to exploit. */
1725 return FALSE;
1726 }
1727
1728 if (present->range != absent->range) {
1729 /* Larger ranges are not always strict supersets of smaller ranges.
1730 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1731 * but not in Trade Route. */
1732 return FALSE;
1733 }
1734
1736 &present->source);
1737}
1738
1739/**********************************************************************/
1742bool req_implies_req(const struct requirement *req1,
1743 const struct requirement *req2)
1744{
1745 struct requirement nreq2;
1746
1747 req_copy(&nreq2, req2);
1748 nreq2.present = !nreq2.present;
1750}
1751
1752/**********************************************************************/
1757static inline bool are_bounds_contradictions(int bound1, bool is_upper1,
1758 int bound2, bool is_upper2)
1759{
1760 /* If the bounds are on opposite sides, and one is inclusive, the other
1761 * exclusive, the number of values that satisfy both bounds is exactly
1762 * their difference, (upper bound) - (lower bound).
1763 * The bounds contradict each other iff this difference is 0 or less,
1764 * i.e. iff (upper bound) <= (lower bound) */
1765 if (is_upper1 && !is_upper2) {
1766 return bound1 <= bound2;
1767 } else if (!is_upper1 && is_upper2) {
1768 return bound1 >= bound2;
1769 }
1770 /* Both are upper or both are lower ~> no contradiction possible */
1771 return FALSE;
1772}
1773
1774/**********************************************************************/
1782 const struct requirement *req2)
1783{
1784 if (are_requirements_opposites(req1, req2)) {
1785 /* The exact opposite. */
1786 return TRUE;
1787 }
1788
1789 if (present_implies_not_present(req1, req2)) {
1790 return TRUE;
1791 }
1792
1793 switch (req1->source.kind) {
1794 case VUT_IMPROVEMENT:
1795 case VUT_SITE:
1796 if (req2->source.kind == VUT_IMPR_GENUS) {
1797 return impr_contra_genus(req1, req2);
1798 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1799 return impr_contra_flag(req1, req2);
1800 } else if (req2->source.kind == VUT_CITYTILE
1801 && req2->source.value.citytile == CITYT_CENTER
1802 && REQ_RANGE_TILE == req2->range
1803 && REQ_RANGE_TILE == req1->range
1804 && req1->present) {
1805 /* A building must be in a city */
1806 return !req2->present;
1807 }
1808
1809 /* No special knowledge. */
1810 return FALSE;
1811 case VUT_IMPR_GENUS:
1812 if (req2->source.kind == VUT_IMPROVEMENT
1813 || req2->source.kind == VUT_SITE) {
1814 return impr_contra_genus(req2, req1);
1815 }
1816
1817 /* No special knowledge. */
1818 return FALSE;
1819 case VUT_IMPR_FLAG:
1820 if (req2->source.kind == VUT_IMPROVEMENT
1821 || req2->source.kind == VUT_SITE) {
1822 return impr_contra_flag(req2, req1);
1823 }
1824
1825 /* No special knowledge. */
1826 return FALSE;
1827 case VUT_DIPLREL:
1828 case VUT_DIPLREL_TILE:
1829 case VUT_DIPLREL_TILE_O:
1832 if (req2->source.kind != req1->source.kind) {
1833 /* Finding contradictions across requirement kinds aren't supported
1834 * for DiplRel requirements. */
1835 return FALSE;
1836 } else {
1837 /* Use the special knowledge about DiplRel requirements to find
1838 * contradictions. */
1839
1841 int req2_pos;
1842
1845 req2->range,
1846 req2->present);
1847
1848 return BV_ISSET(req1_contra, req2_pos);
1849 }
1850 break;
1851 case VUT_MINMOVES:
1852 if (req2->source.kind != VUT_MINMOVES) {
1853 /* Finding contradictions across requirement kinds aren't supported
1854 * for MinMoveFrags requirements. */
1855 return FALSE;
1856 }
1858 req1->source.value.minmoves, !req1->present,
1859 req2->source.value.minmoves, !req2->present);
1860 case VUT_MINLATITUDE:
1861 case VUT_MAXLATITUDE:
1862 if (req2->source.kind != VUT_MINLATITUDE
1863 && req2->source.kind != VUT_MAXLATITUDE) {
1864 /* Finding contradictions across requirement kinds other than each
1865 * other is not supported for MinLatitude and MaxLatitude. */
1866 return FALSE;
1867 } else {
1868 /* For a contradiction, we need
1869 * - a minimum (present MinLatitude or negated MaxLatitude)
1870 * - a maximum (negated MinLatitude or present MaxLatitude)
1871 * - the maximum to be less than the minimum
1872 * - a requirement at the larger range that applies to the entire
1873 * range (i.e. a negated requirement, unless the range is Tile)
1874 * Otherwise, the two requirements could still be fulfilled
1875 * simultaneously by different tiles in the range */
1876
1877 /* Initial values beyond the boundaries to avoid edge cases */
1878 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
1880
1881#define EXTRACT_INFO(req) \
1882 if (req->present) { \
1883 if (req->source.kind == VUT_MINLATITUDE) { \
1884 /* present MinLatitude */ \
1885 minimum = MAX(minimum, req->source.value.latitude); \
1886 } else { \
1887 /* present MaxLatitude */ \
1888 maximum = MIN(maximum, req->source.value.latitude); \
1889 } \
1890 } else { \
1891 covered_range = MAX(covered_range, req->range); \
1892 if (req->source.kind == VUT_MINLATITUDE) { \
1893 /* negated MinLatitude */ \
1894 maximum = MIN(maximum, req->source.value.latitude - 1); \
1895 } else { \
1896 /* negated MaxLatitude */ \
1897 minimum = MAX(minimum, req->source.value.latitude + 1); \
1898 } \
1899 }
1900
1901 EXTRACT_INFO(req1);
1902 EXTRACT_INFO(req2);
1903
1904#undef EXTRACT_INFO
1905
1906 return (maximum < minimum
1907 && covered_range >= req1->range
1908 && covered_range >= req2->range);
1909 }
1910 break;
1911 case VUT_NATION:
1912 if (req2->source.kind == VUT_NATIONGROUP) {
1913 return nation_contra_group(req1, req2);
1914 }
1915
1916 /* No special knowledge. */
1917 return FALSE;
1918 break;
1919 case VUT_NATIONGROUP:
1920 if (req2->source.kind == VUT_NATION) {
1921 return nation_contra_group(req2, req1);
1922 }
1923
1924 /* No special knowledge. */
1925 return FALSE;
1926 break;
1927 case VUT_CITYTILE:
1928 if (req2->source.kind == VUT_CITYTILE) {
1929 return city_center_contra(req1, req2)
1930 || city_center_contra(req2, req1);
1931 } else if (req1->source.value.citytile == CITYT_CENTER
1932 && (req2->source.kind == VUT_IMPROVEMENT
1933 || req2->source.kind == VUT_SITE)
1934 && REQ_RANGE_TILE == req2->range
1935 && REQ_RANGE_TILE == req1->range
1936 && req2->present) {
1937 /* A building must be in a city */
1938 return !req1->present;
1939 }
1940
1941 return FALSE;
1943 if (req2->source.kind != VUT_MAX_DISTANCE_SQ) {
1944 /* Finding contradictions across requirement kinds isn't supported
1945 * for MaxDistanceSq requirements. */
1946 return FALSE;
1947 }
1949 req1->source.value.distance_sq, req1->present,
1950 req2->source.value.distance_sq, req2->present);
1952 if (req2->source.kind != VUT_MAX_REGION_TILES) {
1953 /* Finding contradictions across requirement kinds isn't supported
1954 * for MaxRegionTiles requirements. */
1955 return FALSE;
1956 } else if (req1->range != req2->range) {
1957 /* FIXME: Finding contradictions across ranges not yet supported.
1958 * In particular, a max at a small range and a min at a larger range
1959 * needs extra work to figure out. */
1960 return FALSE;
1961 }
1963 req1->source.value.region_tiles, req1->present,
1964 req2->source.value.region_tiles, req2->present);
1965 case VUT_TILE_REL:
1966 if (req2->source.kind != VUT_TILE_REL) {
1967 /* Finding contradictions across requirement kinds isn't supported
1968 * for TileRel requirements. */
1969 return FALSE;
1970 }
1971 if (req1->source.value.tilerel == req2->source.value.tilerel) {
1972 /* Same requirement at different ranges. Note that same range is
1973 * already covered by are_requirements_opposites() above. */
1974 switch (req1->source.value.tilerel) {
1975 case TREL_SAME_TCLASS:
1976 case TREL_SAME_REGION:
1978 /* Negated req at larger range contradicts present req at
1979 * smaller range. */
1980 if (req1->range > req2->range) {
1981 return !req1->present && req2->present;
1982 } else {
1983 return req1->present && !req2->present;
1984 }
1985 break;
1987 /* Present req at larger range contradicts negated req at
1988 * smaller range */
1989 if (req1->range > req2->range) {
1990 return req1->present && !req2->present;
1991 } else {
1992 return !req1->present && req2->present;
1993 }
1994 break;
1995 default:
1996 return FALSE;
1997 }
1998 }
2000 && req2->source.value.tilerel == TREL_SAME_REGION) {
2001 /* Same region at any range implies same terrain class at that range
2002 * and any larger range ~> contradicts negated */
2003 return (!req1->present && req2->present
2004 && (req1->range >= req2->range));
2005 } else if (req2->source.value.tilerel == TREL_SAME_TCLASS
2006 && req1->source.value.tilerel == TREL_SAME_REGION) {
2007 /* Same as above */
2008 return (req1->present && !req2->present
2009 && (req1->range <= req2->range));
2010 } else if (req1->source.value.tilerel == TREL_REGION_SURROUNDED
2012 const struct requirement *surr, *other;
2014 surr = req1;
2015 other = req2;
2016 } else {
2017 surr = req2;
2018 other = req1;
2019 }
2020 if (surr->present && surr->range == REQ_RANGE_TILE) {
2021 /* Target tile must be part of a surrounded region
2022 * ~> not the same terrain class
2023 * ~> not the same region
2024 * ~> not touched by a third region */
2025 switch (other->source.value.tilerel) {
2026 case TREL_SAME_TCLASS:
2027 case TREL_SAME_REGION:
2028 return (other->present && other->range == REQ_RANGE_TILE);
2030 return (!other->present);
2031 default:
2032 break;
2033 }
2034 }
2035 }
2036 /* No further contradictions we can detect */
2037 return FALSE;
2038 default:
2039 /* No special knowledge exists. The requirements aren't the exact
2040 * opposite of each other per the initial check. */
2041 return FALSE;
2042 }
2043}
2044
2045/**********************************************************************/
2050 const struct requirement_vector *vec)
2051{
2052 /* If the requirement is contradicted by any requirement in the vector it
2053 * contradicts the entire requirement vector. */
2056 return TRUE;
2057 }
2059
2060 /* Not a singe requirement in the requirement vector is contradicted be
2061 * the specified requirement. */
2062 return FALSE;
2063}
2064
2065/**********************************************************************/
2068static inline bool are_tiles_in_range(const struct tile *tile1,
2069 const struct tile *tile2,
2070 enum req_range range)
2071{
2072 switch (range) {
2073 case REQ_RANGE_ADJACENT:
2075 return TRUE;
2076 }
2078 case REQ_RANGE_TILE:
2079 return same_pos(tile1, tile2);
2081 return map_distance(tile1, tile2) <= 1;
2082 case REQ_RANGE_CITY:
2084 case REQ_RANGE_LOCAL:
2086 case REQ_RANGE_PLAYER:
2087 case REQ_RANGE_TEAM:
2088 case REQ_RANGE_ALLIANCE:
2089 case REQ_RANGE_WORLD:
2090 case REQ_RANGE_COUNT:
2091 /* Invalid */
2093 }
2094 return FALSE;
2095}
2096
2097/**********************************************************************/
2100static inline bool players_in_same_range(const struct player *pplayer1,
2101 const struct player *pplayer2,
2102 enum req_range range)
2103{
2104 switch (range) {
2105 case REQ_RANGE_WORLD:
2106 return TRUE;
2107 case REQ_RANGE_ALLIANCE:
2109 case REQ_RANGE_TEAM:
2111 case REQ_RANGE_PLAYER:
2112 return pplayer1 == pplayer2;
2115 case REQ_RANGE_CITY:
2116 case REQ_RANGE_ADJACENT:
2118 case REQ_RANGE_TILE:
2119 case REQ_RANGE_LOCAL:
2120 case REQ_RANGE_COUNT:
2121 break;
2122 }
2123
2124 fc_assert_msg(FALSE, "Invalid range %d.", range);
2125 return FALSE;
2126}
2127
2128#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
2129{ \
2130 fc_assert_ret_val(req != nullptr, TRI_MAYBE); \
2131 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
2132 fc_assert(context != nullptr); \
2133 fc_assert(other_context != nullptr); \
2134}
2135
2136/**********************************************************************/
2144static enum fc_tristate
2146 const struct req_context *context,
2147 const struct req_context *other_context,
2148 const struct requirement *req)
2149{
2151
2152 return TRI_YES;
2153}
2154
2155/**********************************************************************/
2159static int num_world_buildings_total(const struct impr_type *building)
2160{
2161 if (is_great_wonder(building)) {
2162 return (great_wonder_is_built(building)
2163 || great_wonder_is_destroyed(building) ? 1 : 0);
2164 } else {
2165 log_error("World-ranged requirements are only supported for wonders.");
2166 return 0;
2167 }
2168}
2169
2170/**********************************************************************/
2173static int num_world_buildings(const struct impr_type *building)
2174{
2175 if (is_great_wonder(building)) {
2176 return (great_wonder_is_built(building) ? 1 : 0);
2177 } else {
2178 log_error("World-ranged requirements are only supported for wonders.");
2179 return 0;
2180 }
2181}
2182
2183/**********************************************************************/
2194static bool player_has_ever_built(const struct player *pplayer,
2195 const struct impr_type *building)
2196{
2197 if (is_wonder(building)) {
2198 return (wonder_is_built(pplayer, building)
2199 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2200 } else {
2201 log_error("Player-ranged requirements are only supported for wonders.");
2202 return FALSE;
2203 }
2204}
2205
2206/**********************************************************************/
2209static int num_player_buildings(const struct player *pplayer,
2210 const struct impr_type *building)
2211{
2212 if (is_wonder(building)) {
2213 return (wonder_is_built(pplayer, building) ? 1 : 0);
2214 } else {
2215 log_error("Player-ranged requirements are only supported for wonders.");
2216 return 0;
2217 }
2218}
2219
2220/**********************************************************************/
2223static int num_continent_buildings(const struct player *pplayer,
2224 int continent,
2225 const struct impr_type *building)
2226{
2227 if (is_wonder(building)) {
2228 const struct city *pcity;
2229
2230 pcity = city_from_wonder(pplayer, building);
2231 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2232 return 1;
2233 }
2234 } else {
2235 log_error("Island-ranged requirements are only supported for wonders.");
2236 }
2237 return 0;
2238}
2239
2240/**********************************************************************/
2248static enum fc_tristate
2250 const struct req_context *context,
2251 const struct req_context *other_context,
2252 const struct requirement *req)
2253{
2254 const struct impr_type *building;
2255
2256 /* Can't use this assertion, as both VUT_IMPROVEMENT and VUT_SITE
2257 * are handled here. */
2258 /* IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT); */
2259
2260 building = req->source.value.building;
2261
2262 /* Check if it's certain that the building is obsolete given the
2263 * specification we have */
2264 if (req->source.kind == VUT_IMPROVEMENT
2265 && improvement_obsolete(context->player, building, context->city)) {
2266 return TRI_NO;
2267 }
2268
2269 if (req->survives) {
2270
2271 /* Check whether condition has ever held, using cached information. */
2272 switch (req->range) {
2273 case REQ_RANGE_WORLD:
2274 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2275 case REQ_RANGE_ALLIANCE:
2276 case REQ_RANGE_TEAM:
2277 if (context->player == NULL) {
2278 return TRI_MAYBE;
2279 }
2280 players_iterate_alive(plr2) {
2281 if (players_in_same_range(context->player, plr2, req->range)
2282 && player_has_ever_built(plr2, building)) {
2283 return TRI_YES;
2284 }
2286 return TRI_NO;
2287 case REQ_RANGE_PLAYER:
2288 if (context->player == NULL) {
2289 return TRI_MAYBE;
2290 }
2292 building));
2295 case REQ_RANGE_CITY:
2296 case REQ_RANGE_LOCAL:
2297 case REQ_RANGE_TILE:
2299 case REQ_RANGE_ADJACENT:
2300 /* There is no sources cache for this. */
2301 log_error("Surviving requirements are only supported at "
2302 "World/Alliance/Team/Player ranges.");
2303 return TRI_NO;
2304 case REQ_RANGE_COUNT:
2305 break;
2306 }
2307
2308 } else {
2309
2310 /* Non-surviving requirement. */
2311 switch (req->range) {
2312 case REQ_RANGE_WORLD:
2313 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2314 case REQ_RANGE_ALLIANCE:
2315 case REQ_RANGE_TEAM:
2316 if (context->player == NULL) {
2317 return TRI_MAYBE;
2318 }
2319 players_iterate_alive(plr2) {
2320 if (players_in_same_range(context->player, plr2, req->range)
2321 && num_player_buildings(plr2, building) > 0) {
2322 return TRI_YES;
2323 }
2325 return TRI_NO;
2326 case REQ_RANGE_PLAYER:
2327 if (context->player == NULL) {
2328 return TRI_MAYBE;
2329 }
2331 building)
2332 > 0);
2334 /* At present, "Continent" effects can affect only
2335 * cities and units in cities. */
2336 if (context->player && context->city) {
2337 int continent = tile_continent(context->city->tile);
2339 continent, building)
2340 > 0);
2341 } else {
2342 return TRI_MAYBE;
2343 }
2345 if (context->city) {
2346 if (city_has_building(context->city, building)) {
2347 return TRI_YES;
2348 } else {
2349 enum fc_tristate ret = TRI_NO;
2350
2352 if (trade_partner == NULL) {
2353 ret = TRI_MAYBE;
2354 } else if (city_has_building(trade_partner, building)) {
2355 return TRI_YES;
2356 }
2358
2359 return ret;
2360 }
2361 } else {
2362 return TRI_MAYBE;
2363 }
2364 case REQ_RANGE_CITY:
2365 if (context->city) {
2366 return BOOL_TO_TRISTATE(city_has_building(context->city, building));
2367 } else {
2368 return TRI_MAYBE;
2369 }
2370 case REQ_RANGE_LOCAL:
2371 if (context->building) {
2372 if (context->building == building) {
2373 return TRI_YES;
2374 } else {
2375 return TRI_NO;
2376 }
2377 } else {
2378 /* TODO: other local targets */
2379 return TRI_MAYBE;
2380 }
2381 case REQ_RANGE_TILE:
2382 if (context->tile) {
2383 const struct city *pcity = tile_city(context->tile);
2384
2385 if (pcity) {
2386 return BOOL_TO_TRISTATE(city_has_building(pcity, building));
2387 } else {
2388 return TRI_NO;
2389 }
2390 } else {
2391 return TRI_MAYBE;
2392 }
2394 case REQ_RANGE_ADJACENT:
2395 case REQ_RANGE_COUNT:
2396 break;
2397 }
2398
2399 }
2400
2401 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2402 return TRI_NO;
2403}
2404
2405/**********************************************************************/
2413static enum fc_tristate
2415 const struct req_context *context,
2416 const struct req_context *other_context,
2417 const struct requirement *req)
2418{
2420
2421 return (context->building ? BOOL_TO_TRISTATE(
2422 context->building->genus
2423 == req->source.value.impr_genus)
2424 : TRI_MAYBE);
2425}
2426
2427/**********************************************************************/
2431 enum impr_flag_id flag)
2432{
2433 struct player *owner;
2434
2435 if (pcity == NULL) {
2436 return TRI_MAYBE;
2437 }
2438
2440 city_built_iterate(pcity, impr) {
2441 if (improvement_has_flag(impr, flag)
2442 && !improvement_obsolete(owner, impr, pcity)) {
2443 return TRI_YES;
2444 }
2446
2447 return TRI_NO;
2448}
2449
2450/**********************************************************************/
2458static enum fc_tristate
2460 const struct req_context *context,
2461 const struct req_context *other_context,
2462 const struct requirement *req)
2463{
2465
2466 switch (req->range) {
2467 case REQ_RANGE_LOCAL:
2468 return (context->building
2470 req->source.value.impr_flag))
2471 : TRI_MAYBE);
2472 case REQ_RANGE_CITY:
2474 case REQ_RANGE_TILE:
2475 if (context->tile == NULL) {
2476 return TRI_MAYBE;
2477 }
2479 req->source.value.impr_flag);
2481 case REQ_RANGE_ADJACENT:
2484 case REQ_RANGE_PLAYER:
2485 case REQ_RANGE_ALLIANCE:
2486 case REQ_RANGE_TEAM:
2487 case REQ_RANGE_WORLD:
2488 case REQ_RANGE_COUNT:
2489 break;
2490 }
2491
2492 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2493
2494 return TRI_MAYBE;
2495}
2496
2497/**********************************************************************/
2505static enum fc_tristate
2507 const struct req_context *context,
2508 const struct req_context *other_context,
2509 const struct requirement *req)
2510{
2512
2513 switch (req->range) {
2514 case REQ_RANGE_PLAYER:
2515 return (context->player != NULL
2517 req->source.value.plr_flag))
2518 : TRI_MAYBE);
2519 case REQ_RANGE_LOCAL:
2520 case REQ_RANGE_CITY:
2521 case REQ_RANGE_TILE:
2523 case REQ_RANGE_ADJACENT:
2526 case REQ_RANGE_ALLIANCE:
2527 case REQ_RANGE_TEAM:
2528 case REQ_RANGE_WORLD:
2529 case REQ_RANGE_COUNT:
2530 break;
2531 }
2532
2533 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2534
2535 return TRI_MAYBE;
2536}
2537
2538/**********************************************************************/
2546static enum fc_tristate
2548 const struct req_context *context,
2549 const struct req_context *other_context,
2550 const struct requirement *req)
2551{
2553
2554 switch (req->range) {
2555 case REQ_RANGE_PLAYER:
2556 return (context->player != NULL
2558 req->source.value.plrstate))
2559 : TRI_MAYBE);
2560 case REQ_RANGE_LOCAL:
2561 case REQ_RANGE_CITY:
2562 case REQ_RANGE_TILE:
2564 case REQ_RANGE_ADJACENT:
2567 case REQ_RANGE_ALLIANCE:
2568 case REQ_RANGE_TEAM:
2569 case REQ_RANGE_WORLD:
2570 case REQ_RANGE_COUNT:
2571 break;
2572 }
2573
2574 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2575
2576 return TRI_MAYBE;
2577}
2578
2579/**********************************************************************/
2587static enum fc_tristate
2589 const struct req_context *context,
2590 const struct req_context *other_context,
2591 const struct requirement *req)
2592{
2593 Tech_type_id tech;
2594
2596
2597 tech = advance_number(req->source.value.advance);
2598
2599 if (req->survives) {
2602 }
2603
2604 /* Not a 'surviving' requirement. */
2605 switch (req->range) {
2606 case REQ_RANGE_PLAYER:
2607 if (context->player != nullptr) {
2609 (research_get(context->player), tech));
2610 } else {
2611 return TRI_MAYBE;
2612 }
2613 case REQ_RANGE_TEAM:
2614 case REQ_RANGE_ALLIANCE:
2615 case REQ_RANGE_WORLD:
2616 if (context->player == nullptr) {
2617 return TRI_MAYBE;
2618 }
2619 players_iterate_alive(plr2) {
2620 if (players_in_same_range(context->player, plr2, req->range)) {
2621 if (research_invention_state(research_get(plr2), tech)
2622 == TECH_KNOWN) {
2623 return TRI_YES;
2624 }
2625 }
2627
2628 return TRI_NO;
2629 case REQ_RANGE_LOCAL:
2630 if (context->player == nullptr) {
2631 return TRI_MAYBE;
2632 }
2633 if (research_get(context->player)->researching == tech) {
2634 return TRI_YES;
2635 }
2636 return TRI_NO;
2637 case REQ_RANGE_TILE:
2639 case REQ_RANGE_ADJACENT:
2640 case REQ_RANGE_CITY:
2643 case REQ_RANGE_COUNT:
2644 break;
2645 }
2646
2647 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2648
2649 return TRI_MAYBE;
2650}
2651
2652/**********************************************************************/
2660static enum fc_tristate
2662 const struct req_context *context,
2663 const struct req_context *other_context,
2664 const struct requirement *req)
2665{
2666 enum tech_flag_id techflag;
2667
2669
2670 techflag = req->source.value.techflag;
2671
2672 switch (req->range) {
2673 case REQ_RANGE_PLAYER:
2674 if (context->player != nullptr) {
2676 techflag));
2677 } else {
2678 return TRI_MAYBE;
2679 }
2680 break;
2681 case REQ_RANGE_TEAM:
2682 case REQ_RANGE_ALLIANCE:
2683 if (context->player == nullptr) {
2684 return TRI_MAYBE;
2685 }
2686 players_iterate_alive(plr2) {
2687 if (players_in_same_range(context->player, plr2, req->range)
2688 && player_knows_techs_with_flag(plr2, techflag)) {
2689 return TRI_YES;
2690 }
2692 return TRI_NO;
2693 case REQ_RANGE_WORLD:
2694 players_iterate(pplayer) {
2695 if (player_knows_techs_with_flag(pplayer, techflag)) {
2696 return TRI_YES;
2697 }
2699
2700 return TRI_NO;
2701 case REQ_RANGE_LOCAL:
2702 if (context->player == nullptr) {
2703 return TRI_MAYBE;
2704 }
2705 if (advance_has_flag(research_get(context->player)->researching, techflag)) {
2706 return TRI_YES;
2707 }
2708 return TRI_NO;
2709 case REQ_RANGE_TILE:
2711 case REQ_RANGE_ADJACENT:
2712 case REQ_RANGE_CITY:
2715 case REQ_RANGE_COUNT:
2716 break;
2717 }
2718
2719 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2720
2721 return TRI_MAYBE;
2722}
2723
2724/**********************************************************************/
2732static enum fc_tristate
2734 const struct req_context *context,
2735 const struct req_context *other_context,
2736 const struct requirement *req)
2737{
2738 int minculture;
2739
2741
2742 minculture = req->source.value.minculture;
2743
2744 switch (req->range) {
2745 case REQ_RANGE_CITY:
2746 if (!context->city) {
2747 return TRI_MAYBE;
2748 }
2749 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2751 if (!context->city) {
2752 return TRI_MAYBE;
2753 }
2754 if (city_culture(context->city) >= minculture) {
2755 return TRI_YES;
2756 } else {
2757 enum fc_tristate ret = TRI_NO;
2758
2760 if (trade_partner == NULL) {
2761 ret = TRI_MAYBE;
2762 } else if (city_culture(trade_partner) >= minculture) {
2763 return TRI_YES;
2764 }
2766
2767 return ret;
2768 }
2769 case REQ_RANGE_PLAYER:
2770 case REQ_RANGE_TEAM:
2771 case REQ_RANGE_ALLIANCE:
2772 case REQ_RANGE_WORLD:
2773 if (NULL == context->player) {
2774 return TRI_MAYBE;
2775 }
2776 players_iterate_alive(plr2) {
2777 if (players_in_same_range(context->player, plr2, req->range)) {
2778 if (player_culture(plr2) >= minculture) {
2779 return TRI_YES;
2780 }
2781 }
2783 return TRI_NO;
2784 case REQ_RANGE_LOCAL:
2785 case REQ_RANGE_TILE:
2787 case REQ_RANGE_ADJACENT:
2789 case REQ_RANGE_COUNT:
2790 break;
2791 }
2792
2793 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2794
2795 return TRI_MAYBE;
2796}
2797
2798/**********************************************************************/
2806static enum fc_tristate
2808 const struct req_context *context,
2809 const struct req_context *other_context,
2810 const struct requirement *req)
2811{
2813
2815
2817
2818 switch (req->range) {
2819 case REQ_RANGE_CITY:
2820 if (!context->city) {
2821 return TRI_MAYBE;
2822 }
2824 / city_size_get(context->city);
2827 if (!context->city) {
2828 return TRI_MAYBE;
2829 }
2831 / city_size_get(context->city);
2833 return TRI_YES;
2834 } else {
2835 enum fc_tristate ret = TRI_NO;
2836
2838 if (trade_partner == NULL) {
2839 ret = TRI_MAYBE;
2840 } else {
2844 return TRI_YES;
2845 }
2846 }
2848
2849 return ret;
2850 }
2851 case REQ_RANGE_PLAYER:
2852 case REQ_RANGE_TEAM:
2853 case REQ_RANGE_ALLIANCE:
2854 case REQ_RANGE_WORLD:
2855 case REQ_RANGE_LOCAL:
2856 case REQ_RANGE_TILE:
2858 case REQ_RANGE_ADJACENT:
2860 case REQ_RANGE_COUNT:
2861 break;
2862 }
2863
2864 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2865
2866 return TRI_MAYBE;
2867}
2868
2869/**********************************************************************/
2877static enum fc_tristate
2879 const struct req_context *context,
2880 const struct req_context *other_context,
2881 const struct requirement *req)
2882{
2883 int max_units;
2884
2886
2888
2889 /* TODO: if can't see V_INVIS -> TRI_MAYBE */
2890 switch (req->range) {
2891 case REQ_RANGE_TILE:
2892 if (!context->tile) {
2893 return TRI_MAYBE;
2894 }
2895 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
2897 if (!context->tile) {
2898 return TRI_MAYBE;
2899 }
2900 if (unit_list_size(context->tile->units) <= max_units) {
2901 return TRI_YES;
2902 }
2904 if (unit_list_size(adjc_tile->units) <= max_units) {
2905 return TRI_YES;
2906 }
2908 return TRI_NO;
2909 case REQ_RANGE_ADJACENT:
2910 if (!context->tile) {
2911 return TRI_MAYBE;
2912 }
2913 if (unit_list_size(context->tile->units) <= max_units) {
2914 return TRI_YES;
2915 }
2917 if (unit_list_size(adjc_tile->units) <= max_units) {
2918 return TRI_YES;
2919 }
2921 return TRI_NO;
2922 case REQ_RANGE_CITY:
2925 case REQ_RANGE_PLAYER:
2926 case REQ_RANGE_TEAM:
2927 case REQ_RANGE_ALLIANCE:
2928 case REQ_RANGE_WORLD:
2929 case REQ_RANGE_LOCAL:
2930 case REQ_RANGE_COUNT:
2931 break;
2932 }
2933
2934 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2935
2936 return TRI_MAYBE;
2937}
2938
2939/**********************************************************************/
2947static enum fc_tristate
2949 const struct req_context *context,
2950 const struct req_context *other_context,
2951 const struct requirement *req)
2952{
2953 const struct extra_type *pextra;
2954 enum fc_tristate ret;
2955
2957
2958 pextra = req->source.value.extra;
2959
2960 switch (req->range) {
2961 case REQ_RANGE_LOCAL:
2962 if (!context->extra) {
2963 return TRI_MAYBE;
2964 }
2965 return BOOL_TO_TRISTATE(context->extra == pextra);
2966 case REQ_RANGE_TILE:
2967 /* The requirement is filled if the tile has extra of requested type. */
2968 if (!context->tile) {
2969 return TRI_MAYBE;
2970 }
2971 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
2973 if (!context->tile) {
2974 return TRI_MAYBE;
2975 }
2976 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2977 || is_extra_card_near(nmap, context->tile, pextra));
2978 case REQ_RANGE_ADJACENT:
2979 if (!context->tile) {
2980 return TRI_MAYBE;
2981 }
2982 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2983 || is_extra_near_tile(nmap, context->tile, pextra));
2984 case REQ_RANGE_CITY:
2985 if (!context->city) {
2986 return TRI_MAYBE;
2987 }
2989 city_tile(context->city), ptile) {
2990 if (tile_has_extra(ptile, pextra)) {
2991 return TRI_YES;
2992 }
2994
2995 return TRI_NO;
2996
2998 if (!context->city) {
2999 return TRI_MAYBE;
3000 }
3002 city_tile(context->city), ptile) {
3003 if (tile_has_extra(ptile, pextra)) {
3004 return TRI_YES;
3005 }
3007
3008 ret = TRI_NO;
3010 if (trade_partner == NULL) {
3011 ret = TRI_MAYBE;
3012 } else {
3014 city_tile(trade_partner), ptile) {
3015 if (tile_has_extra(ptile, pextra)) {
3016 return TRI_YES;
3017 }
3019 }
3021
3022 return ret;
3023
3025 case REQ_RANGE_PLAYER:
3026 case REQ_RANGE_TEAM:
3027 case REQ_RANGE_ALLIANCE:
3028 case REQ_RANGE_WORLD:
3029 case REQ_RANGE_COUNT:
3030 break;
3031 }
3032
3033 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3034
3035 return TRI_MAYBE;
3036}
3037
3038/**********************************************************************/
3046static enum fc_tristate
3048 const struct req_context *context,
3049 const struct req_context *other_context,
3050 const struct requirement *req)
3051{
3052 const struct goods_type *pgood;
3053
3055
3056 pgood = req->source.value.good;
3057
3058 switch (req->range) {
3059 case REQ_RANGE_LOCAL:
3060 case REQ_RANGE_CITY:
3061 /* The requirement is filled if the city imports good of requested type. */
3062 if (!context->city) {
3063 return TRI_MAYBE;
3064 }
3068 case REQ_RANGE_TILE:
3070 case REQ_RANGE_ADJACENT:
3073 case REQ_RANGE_PLAYER:
3074 case REQ_RANGE_TEAM:
3075 case REQ_RANGE_ALLIANCE:
3076 case REQ_RANGE_WORLD:
3077 case REQ_RANGE_COUNT:
3078 break;
3079 }
3080
3081 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3082
3083 return TRI_MAYBE;
3084}
3085
3086/**********************************************************************/
3094static enum fc_tristate
3096 const struct req_context *context,
3097 const struct req_context *other_context,
3098 const struct requirement *req)
3099{
3101
3102 if (context->action) {
3103 return BOOL_TO_TRISTATE(action_number(context->action)
3104 == action_number(req->source.value.action));
3105 }
3106
3107 if (context->unit != nullptr && context->unit->action != ACTION_NONE) {
3108 log_normal("Unit action %s", action_id_rule_name(context->unit->action));
3109 return BOOL_TO_TRISTATE(context->unit->action
3110 == action_number(req->source.value.action));
3111 }
3112
3113 return TRI_NO;
3114}
3115
3116/**********************************************************************/
3124static enum fc_tristate
3126 const struct req_context *context,
3127 const struct req_context *other_context,
3128 const struct requirement *req)
3129{
3131
3132 return BOOL_TO_TRISTATE(context->output
3133 && context->output->index
3134 == req->source.value.outputtype);
3135}
3136
3137/**********************************************************************/
3145static enum fc_tristate
3147 const struct req_context *context,
3148 const struct req_context *other_context,
3149 const struct requirement *req)
3150{
3152
3153 return BOOL_TO_TRISTATE(context->specialist
3154 && context->specialist
3155 == req->source.value.specialist);
3156}
3157
3158/**********************************************************************/
3166static enum fc_tristate
3168 const struct req_context *context,
3169 const struct req_context *other_context,
3170 const struct requirement *req)
3171{
3172 const struct terrain *pterrain;
3173
3175
3176 pterrain = req->source.value.terrain;
3177
3178 switch (req->range) {
3179 case REQ_RANGE_TILE:
3180 /* The requirement is filled if the tile has the terrain. */
3181 if (!context->tile) {
3182 return TRI_MAYBE;
3183 }
3184 return pterrain && tile_terrain(context->tile) == pterrain;
3186 if (!context->tile) {
3187 return TRI_MAYBE;
3188 }
3189 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
3190 case REQ_RANGE_ADJACENT:
3191 if (!context->tile) {
3192 return TRI_MAYBE;
3193 }
3194 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
3195 case REQ_RANGE_CITY:
3196 if (!context->city) {
3197 return TRI_MAYBE;
3198 }
3199 if (pterrain != NULL) {
3201 city_tile(context->city), ptile) {
3202 if (tile_terrain(ptile) == pterrain) {
3203 return TRI_YES;
3204 }
3206 }
3207 return TRI_NO;
3209 if (!context->city) {
3210 return TRI_MAYBE;
3211 }
3212 if (pterrain != NULL) {
3213 enum fc_tristate ret;
3214
3216 city_tile(context->city), ptile) {
3217 if (tile_terrain(ptile) == pterrain) {
3218 return TRI_YES;
3219 }
3221
3222 ret = TRI_NO;
3224 if (trade_partner == NULL) {
3225 ret = TRI_MAYBE;
3226 } else {
3228 city_tile(trade_partner), ptile) {
3229 if (tile_terrain(ptile) == pterrain) {
3230 return TRI_YES;
3231 }
3233 }
3235
3236 return ret;
3237 }
3238
3239 return TRI_MAYBE;
3241 case REQ_RANGE_PLAYER:
3242 case REQ_RANGE_TEAM:
3243 case REQ_RANGE_ALLIANCE:
3244 case REQ_RANGE_WORLD:
3245 case REQ_RANGE_LOCAL:
3246 case REQ_RANGE_COUNT:
3247 break;
3248 }
3249
3250 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3251
3252 return TRI_MAYBE;
3253}
3254
3255/**********************************************************************/
3263static enum fc_tristate
3265 const struct req_context *context,
3266 const struct req_context *other_context,
3267 const struct requirement *req)
3268{
3269 enum terrain_class pclass;
3270 enum fc_tristate ret;
3271
3273
3275
3276 switch (req->range) {
3277 case REQ_RANGE_TILE:
3278 /* The requirement is filled if the tile has the terrain of correct class. */
3279 if (!context->tile) {
3280 return TRI_MAYBE;
3281 }
3284 if (!context->tile) {
3285 return TRI_MAYBE;
3286 }
3289 case REQ_RANGE_ADJACENT:
3290 if (!context->tile) {
3291 return TRI_MAYBE;
3292 }
3295 case REQ_RANGE_CITY:
3296 if (!context->city) {
3297 return TRI_MAYBE;
3298 }
3300 city_tile(context->city), ptile) {
3301 const struct terrain *pterrain = tile_terrain(ptile);
3302
3303 if (pterrain != T_UNKNOWN
3304 && terrain_type_terrain_class(pterrain) == pclass) {
3305 return TRI_YES;
3306 }
3308
3309 return TRI_NO;
3311 if (!context->city) {
3312 return TRI_MAYBE;
3313 }
3315 city_tile(context->city), ptile) {
3316 const struct terrain *pterrain = tile_terrain(ptile);
3317
3318 if (pterrain != T_UNKNOWN
3319 && terrain_type_terrain_class(pterrain) == pclass) {
3320 return TRI_YES;
3321 }
3323
3324 ret = TRI_NO;
3326 if (trade_partner == NULL) {
3327 ret = TRI_MAYBE;
3328 } else {
3330 city_tile(trade_partner), ptile) {
3331 const struct terrain *pterrain = tile_terrain(ptile);
3332
3333 if (pterrain != T_UNKNOWN
3334 && terrain_type_terrain_class(pterrain) == pclass) {
3335 return TRI_YES;
3336 }
3338 }
3340
3341 return ret;
3343 case REQ_RANGE_PLAYER:
3344 case REQ_RANGE_TEAM:
3345 case REQ_RANGE_ALLIANCE:
3346 case REQ_RANGE_WORLD:
3347 case REQ_RANGE_LOCAL:
3348 case REQ_RANGE_COUNT:
3349 break;
3350 }
3351
3352 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3353
3354 return TRI_MAYBE;
3355}
3356
3357/**********************************************************************/
3365static enum fc_tristate
3367 const struct req_context *context,
3368 const struct req_context *other_context,
3369 const struct requirement *req)
3370{
3372 enum fc_tristate ret;
3373
3375
3377
3378 switch (req->range) {
3379 case REQ_RANGE_TILE:
3380 /* The requirement is fulfilled if the tile has a terrain with
3381 * correct flag. */
3382 if (!context->tile) {
3383 return TRI_MAYBE;
3384 }
3386 terrflag));
3388 if (!context->tile) {
3389 return TRI_MAYBE;
3390 }
3392 terrflag)
3394 terrflag));
3395 case REQ_RANGE_ADJACENT:
3396 if (!context->tile) {
3397 return TRI_MAYBE;
3398 }
3400 terrflag)
3402 terrflag));
3403 case REQ_RANGE_CITY:
3404 if (!context->city) {
3405 return TRI_MAYBE;
3406 }
3408 city_tile(context->city), ptile) {
3409 const struct terrain *pterrain = tile_terrain(ptile);
3410
3411 if (pterrain != T_UNKNOWN
3412 && terrain_has_flag(pterrain, terrflag)) {
3413 return TRI_YES;
3414 }
3416
3417 return TRI_NO;
3419 if (!context->city) {
3420 return TRI_MAYBE;
3421 }
3423 city_tile(context->city), ptile) {
3424 const struct terrain *pterrain = tile_terrain(ptile);
3425
3426 if (pterrain != T_UNKNOWN
3427 && terrain_has_flag(pterrain, terrflag)) {
3428 return TRI_YES;
3429 }
3431
3432 ret = TRI_NO;
3434 if (trade_partner == NULL) {
3435 ret = TRI_MAYBE;
3436 } else {
3438 city_tile(trade_partner), ptile) {
3439 const struct terrain *pterrain = tile_terrain(ptile);
3440
3441 if (pterrain != T_UNKNOWN
3442 && terrain_has_flag(pterrain, terrflag)) {
3443 return TRI_YES;
3444 }
3446 }
3448
3449 return ret;
3451 case REQ_RANGE_PLAYER:
3452 case REQ_RANGE_TEAM:
3453 case REQ_RANGE_ALLIANCE:
3454 case REQ_RANGE_WORLD:
3455 case REQ_RANGE_LOCAL:
3456 case REQ_RANGE_COUNT:
3457 break;
3458 }
3459
3460 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3461
3462 return TRI_MAYBE;
3463}
3464
3465/**********************************************************************/
3473static enum fc_tristate
3475 const struct req_context *context,
3476 const struct req_context *other_context,
3477 const struct requirement *req)
3478{
3479 enum road_flag_id roadflag;
3480 enum fc_tristate ret;
3481
3483
3484 roadflag = req->source.value.roadflag;
3485
3486 switch (req->range) {
3487 case REQ_RANGE_LOCAL:
3488 {
3489 if (!context->extra) {
3490 return TRI_MAYBE;
3491 }
3492 struct road_type *r = extra_road_get(context->extra);
3493
3494 return BOOL_TO_TRISTATE(
3495 r && road_has_flag(r, roadflag)
3496 );
3497 }
3498 case REQ_RANGE_TILE:
3499 /* The requirement is filled if the tile has a road with correct flag. */
3500 if (!context->tile) {
3501 return TRI_MAYBE;
3502 }
3503 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3505 if (!context->tile) {
3506 return TRI_MAYBE;
3507 }
3508 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3510 roadflag));
3511 case REQ_RANGE_ADJACENT:
3512 if (!context->tile) {
3513 return TRI_MAYBE;
3514 }
3515 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3517 roadflag));
3518 case REQ_RANGE_CITY:
3519 if (!context->city) {
3520 return TRI_MAYBE;
3521 }
3523 city_tile(context->city), ptile) {
3524 if (tile_has_road_flag(ptile, roadflag)) {
3525 return TRI_YES;
3526 }
3528
3529 return TRI_NO;
3531 if (!context->city) {
3532 return TRI_MAYBE;
3533 }
3535 city_tile(context->city), ptile) {
3536 if (tile_has_road_flag(ptile, roadflag)) {
3537 return TRI_YES;
3538 }
3540
3541 ret = TRI_NO;
3543 if (trade_partner == NULL) {
3544 ret = TRI_MAYBE;
3545 } else {
3547 city_tile(trade_partner), ptile) {
3548 if (tile_has_road_flag(ptile, roadflag)) {
3549 return TRI_YES;
3550 }
3552 }
3554
3555 return ret;
3557 case REQ_RANGE_PLAYER:
3558 case REQ_RANGE_TEAM:
3559 case REQ_RANGE_ALLIANCE:
3560 case REQ_RANGE_WORLD:
3561 case REQ_RANGE_COUNT:
3562 break;
3563 }
3564
3565 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3566
3567 return TRI_MAYBE;
3568}
3569
3570/**********************************************************************/
3578static enum fc_tristate
3580 const struct req_context *context,
3581 const struct req_context *other_context,
3582 const struct requirement *req)
3583{
3584 enum extra_flag_id extraflag;
3585 enum fc_tristate ret;
3586
3588
3589 extraflag = req->source.value.extraflag;
3590
3591 switch (req->range) {
3592 case REQ_RANGE_LOCAL:
3593 if (!context->extra) {
3594 return TRI_MAYBE;
3595 }
3596 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3597 case REQ_RANGE_TILE:
3598 /* The requirement is filled if the tile has an extra with correct flag. */
3599 if (!context->tile) {
3600 return TRI_MAYBE;
3601 }
3602 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3604 if (!context->tile) {
3605 return TRI_MAYBE;
3606 }
3607 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3608 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3609 case REQ_RANGE_ADJACENT:
3610 if (!context->tile) {
3611 return TRI_MAYBE;
3612 }
3613 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3614 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3615 case REQ_RANGE_CITY:
3616 if (!context->city) {
3617 return TRI_MAYBE;
3618 }
3620 city_tile(context->city), ptile) {
3621 if (tile_has_extra_flag(ptile, extraflag)) {
3622 return TRI_YES;
3623 }
3625
3626 return TRI_NO;
3628 if (!context->city) {
3629 return TRI_MAYBE;
3630 }
3632 city_tile(context->city), ptile) {
3633 if (tile_has_extra_flag(ptile, extraflag)) {
3634 return TRI_YES;
3635 }
3637
3638 ret = TRI_NO;
3640 if (trade_partner == NULL) {
3641 ret = TRI_MAYBE;
3642 } else {
3644 city_tile(trade_partner), ptile) {
3645 if (tile_has_extra_flag(ptile, extraflag)) {
3646 return TRI_YES;
3647 }
3649 }
3651
3652 return ret;
3654 case REQ_RANGE_PLAYER:
3655 case REQ_RANGE_TEAM:
3656 case REQ_RANGE_ALLIANCE:
3657 case REQ_RANGE_WORLD:
3658 case REQ_RANGE_COUNT:
3659 break;
3660 }
3661
3662 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3663
3664 return TRI_MAYBE;
3665}
3666
3667/**********************************************************************/
3675static enum fc_tristate
3677 const struct req_context *context,
3678 const struct req_context *other_context,
3679 const struct requirement *req)
3680{
3682
3684
3686
3687 if (!context->tile) {
3688 return TRI_MAYBE;
3689 }
3690
3691 switch (req->range) {
3692 case REQ_RANGE_TILE:
3696 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
3697 case REQ_RANGE_CITY:
3700 case REQ_RANGE_PLAYER:
3701 case REQ_RANGE_TEAM:
3702 case REQ_RANGE_ALLIANCE:
3703 case REQ_RANGE_WORLD:
3704 case REQ_RANGE_LOCAL:
3705 case REQ_RANGE_COUNT:
3706 break;
3707 }
3708
3709 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3710
3711 return TRI_MAYBE;
3712}
3713
3714/**********************************************************************/
3722static enum fc_tristate
3724 const struct req_context *context,
3725 const struct req_context *other_context,
3726 const struct requirement *req)
3727{
3729
3730 if (context->player == NULL) {
3731 return TRI_MAYBE;
3732 } else {
3734 == req->source.value.govern);
3735 }
3736}
3737
3738/**********************************************************************/
3746static enum fc_tristate
3748 const struct req_context *context,
3749 const struct req_context *other_context,
3750 const struct requirement *req)
3751{
3753
3754 if (context->player == NULL) {
3755 return TRI_MAYBE;
3756 } else {
3757 return BOOL_TO_TRISTATE(context->player->style
3758 == req->source.value.style);
3759 }
3760}
3761
3762/**********************************************************************/
3770static enum fc_tristate
3772 const struct req_context *context,
3773 const struct req_context *other_context,
3774 const struct requirement *req)
3775{
3777
3778 switch (req->range) {
3779 case REQ_RANGE_WORLD:
3780 /* "None" does not count */
3781 return ((game.info.global_advance_count - 1)
3782 >= req->source.value.min_techs);
3783 case REQ_RANGE_PLAYER:
3784 if (context->player == NULL) {
3785 return TRI_MAYBE;
3786 } else {
3787 /* "None" does not count */
3788 return BOOL_TO_TRISTATE(
3789 (research_get(context->player)->techs_researched - 1)
3790 >= req->source.value.min_techs
3791 );
3792 }
3793 default:
3794 return TRI_MAYBE;
3795 }
3796}
3797
3798/**********************************************************************/
3806static enum fc_tristate
3808 const struct req_context *context,
3809 const struct req_context *other_context,
3810 const struct requirement *req)
3811{
3813
3814 switch (req->range) {
3815 case REQ_RANGE_PLAYER:
3816 if (context->player == NULL) {
3817 return TRI_MAYBE;
3818 } else {
3819 /* "None" does not count */
3820 return BOOL_TO_TRISTATE(
3821 city_list_size(context->player->cities)
3822 >= req->source.value.min_cities
3823 );
3824 }
3825 default:
3826 return TRI_MAYBE;
3827 }
3828}
3829
3830/**********************************************************************/
3838static enum fc_tristate
3840 const struct req_context *context,
3841 const struct req_context *other_context,
3842 const struct requirement *req)
3843{
3845
3846 if (context->player == NULL) {
3847 return TRI_MAYBE;
3848 } else {
3849 return BOOL_TO_TRISTATE(is_ai(context->player)
3850 && context->player->ai_common.skill_level
3851 == req->source.value.ai_level);
3852 }
3853}
3854
3855/**********************************************************************/
3863static enum fc_tristate
3865 const struct req_context *context,
3866 const struct req_context *other_context,
3867 const struct requirement *req)
3868{
3869 const struct nation_type *nation;
3870
3872
3873 nation = req->source.value.nation;
3874
3875 switch (req->range) {
3876 case REQ_RANGE_PLAYER:
3877 if (context->player == NULL) {
3878 return TRI_MAYBE;
3879 }
3880 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
3881 case REQ_RANGE_TEAM:
3882 case REQ_RANGE_ALLIANCE:
3883 if (context->player == NULL) {
3884 return TRI_MAYBE;
3885 }
3886 players_iterate_alive(plr2) {
3887 if (players_in_same_range(context->player, plr2, req->range)) {
3888 if (nation_of_player(plr2) == nation) {
3889 return TRI_YES;
3890 }
3891 }
3893 return TRI_NO;
3894 case REQ_RANGE_WORLD:
3895 /* NB: if a player is ever removed outright from the game
3896 * (e.g. via /remove), rather than just dying, this 'survives'
3897 * requirement will stop being true for their nation.
3898 * create_command_newcomer() can also cause this to happen. */
3899 return BOOL_TO_TRISTATE(NULL != nation->player
3900 && (req->survives || nation->player->is_alive));
3901 case REQ_RANGE_LOCAL:
3902 case REQ_RANGE_TILE:
3904 case REQ_RANGE_ADJACENT:
3905 case REQ_RANGE_CITY:
3908 case REQ_RANGE_COUNT:
3909 break;
3910 }
3911
3912 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3913
3914 return TRI_MAYBE;
3915}
3916
3917/**********************************************************************/
3925static enum fc_tristate
3927 const struct req_context *context,
3928 const struct req_context *other_context,
3929 const struct requirement *req)
3930{
3931 const struct nation_group *ngroup;
3932
3934
3936
3937 switch (req->range) {
3938 case REQ_RANGE_PLAYER:
3939 if (context->player == NULL) {
3940 return TRI_MAYBE;
3941 }
3943 nation_of_player(context->player), ngroup));
3944 case REQ_RANGE_TEAM:
3945 case REQ_RANGE_ALLIANCE:
3946 case REQ_RANGE_WORLD:
3947 if (context->player == NULL) {
3948 return TRI_MAYBE;
3949 }
3950 players_iterate_alive(plr2) {
3951 if (players_in_same_range(context->player, plr2, req->range)) {
3953 return TRI_YES;
3954 }
3955 }
3957 return TRI_NO;
3958 case REQ_RANGE_LOCAL:
3959 case REQ_RANGE_TILE:
3961 case REQ_RANGE_ADJACENT:
3962 case REQ_RANGE_CITY:
3965 case REQ_RANGE_COUNT:
3966 break;
3967 }
3968
3969 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3970
3971 return TRI_MAYBE;
3972}
3973
3974/**********************************************************************/
3982static enum fc_tristate
3984 const struct req_context *context,
3985 const struct req_context *other_context,
3986 const struct requirement *req)
3987{
3988 const struct nation_type *nationality;
3989 enum fc_tristate ret;
3990
3992
3993 nationality = req->source.value.nationality;
3994
3995 switch (req->range) {
3996 case REQ_RANGE_CITY:
3997 if (context->city == NULL) {
3998 return TRI_MAYBE;
3999 }
4000 citizens_iterate(context->city, slot, count) {
4001 if (player_slot_get_player(slot)->nation == nationality) {
4002 return TRI_YES;
4003 }
4005
4006 return TRI_NO;
4008 if (context->city == NULL) {
4009 return TRI_MAYBE;
4010 }
4011 citizens_iterate(context->city, slot, count) {
4012 if (player_slot_get_player(slot)->nation == nationality) {
4013 return TRI_YES;
4014 }
4016
4017 ret = TRI_NO;
4019 if (trade_partner == NULL) {
4020 ret = TRI_MAYBE;
4021 } else {
4022 citizens_iterate(trade_partner, slot, count) {
4023 if (player_slot_get_player(slot)->nation == nationality) {
4024 return TRI_YES;
4025 }
4027 }
4029
4030 return ret;
4031 case REQ_RANGE_PLAYER:
4032 case REQ_RANGE_TEAM:
4033 case REQ_RANGE_ALLIANCE:
4034 case REQ_RANGE_WORLD:
4035 case REQ_RANGE_LOCAL:
4036 case REQ_RANGE_TILE:
4038 case REQ_RANGE_ADJACENT:
4040 case REQ_RANGE_COUNT:
4041 break;
4042 }
4043
4044 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4045
4046 return TRI_MAYBE;
4047}
4048
4049/**********************************************************************/
4057static enum fc_tristate
4059 const struct req_context *context,
4060 const struct req_context *other_context,
4061 const struct requirement *req)
4062{
4063 const struct nation_type *nation;
4064
4066
4067 nation = req->source.value.origowner;
4068
4069 switch (req->range) {
4070 case REQ_RANGE_CITY:
4071 if (context->city == NULL || context->city->original == NULL) {
4072 return TRI_MAYBE;
4073 }
4074 if (player_nation(context->city->original) == nation) {
4075 return TRI_YES;
4076 }
4077
4078 return TRI_NO;
4080 case REQ_RANGE_PLAYER:
4081 case REQ_RANGE_TEAM:
4082 case REQ_RANGE_ALLIANCE:
4083 case REQ_RANGE_WORLD:
4084 case REQ_RANGE_LOCAL:
4085 case REQ_RANGE_TILE:
4087 case REQ_RANGE_ADJACENT:
4089 case REQ_RANGE_COUNT:
4090 break;
4091 }
4092
4093 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4094
4095 return TRI_MAYBE;
4096}
4097
4098/**********************************************************************/
4102 const struct player *other_player,
4103 enum req_range range,
4104 int diplrel)
4105{
4106 switch (range) {
4107 case REQ_RANGE_PLAYER:
4108 if (target_player == NULL) {
4109 return TRI_MAYBE;
4110 }
4112 case REQ_RANGE_TEAM:
4113 case REQ_RANGE_ALLIANCE:
4114 case REQ_RANGE_WORLD:
4115 if (target_player == NULL) {
4116 return TRI_MAYBE;
4117 }
4118 players_iterate_alive(plr2) {
4120 if (is_diplrel_to_other(plr2, diplrel)) {
4121 return TRI_YES;
4122 }
4123 }
4125 return TRI_NO;
4126 case REQ_RANGE_LOCAL:
4127 if (target_player == NULL || other_player == NULL) {
4128 return TRI_MAYBE;
4129 }
4130 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
4131 case REQ_RANGE_TILE:
4133 case REQ_RANGE_ADJACENT:
4134 case REQ_RANGE_CITY:
4137 case REQ_RANGE_COUNT:
4138 break;
4139 }
4140
4141 fc_assert_msg(FALSE, "Invalid range %d.", range);
4142
4143 return TRI_MAYBE;
4144}
4145
4146/**********************************************************************/
4154static enum fc_tristate
4156 const struct req_context *context,
4157 const struct req_context *other_context,
4158 const struct requirement *req)
4159{
4161
4162 return is_diplrel_in_range(context->player, other_context->player,
4163 req->range, req->source.value.diplrel);
4164}
4165
4166/**********************************************************************/
4174static enum fc_tristate
4176 const struct req_context *context,
4177 const struct req_context *other_context,
4178 const struct requirement *req)
4179{
4181
4182 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4183 : NULL,
4184 context->player,
4185 req->range,
4186 req->source.value.diplrel);
4187}
4188
4189/**********************************************************************/
4198static enum fc_tristate
4200 const struct req_context *context,
4201 const struct req_context *other_context,
4202 const struct requirement *req)
4203{
4205
4206 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4207 : NULL,
4208 other_context->player,
4209 req->range,
4210 req->source.value.diplrel);
4211}
4212
4213/**********************************************************************/
4216static enum fc_tristate
4218 const struct player *other_player,
4219 enum req_range range,
4220 int diplrel)
4221{
4222 enum fc_tristate out = TRI_NO;
4223
4224 if (target_tile == NULL) {
4225 return TRI_MAYBE;
4226 }
4227
4230 unit_owner(target_unit), other_player, range, diplrel);
4231
4234
4235 return out;
4236}
4237
4238/**********************************************************************/
4247static enum fc_tristate
4249 const struct req_context *context,
4250 const struct req_context *other_context,
4251 const struct requirement *req)
4252{
4254
4255 return is_diplrel_unitany_in_range(context->tile, context->player,
4256 req->range,
4257 req->source.value.diplrel);
4258}
4259
4260/**********************************************************************/
4269static enum fc_tristate
4271 const struct req_context *context,
4272 const struct req_context *other_context,
4273 const struct requirement *req)
4274{
4276
4278 req->range,
4279 req->source.value.diplrel);
4280}
4281
4282/**********************************************************************/
4290static enum fc_tristate
4292 const struct req_context *context,
4293 const struct req_context *other_context,
4294 const struct requirement *req)
4295{
4296 const struct unit_type *punittype;
4297
4299
4300 punittype = req->source.value.utype;
4301
4302 switch (req->range) {
4303 case REQ_RANGE_LOCAL:
4304 if (!context->unittype) {
4305 return TRI_MAYBE;
4306 }
4307 return BOOL_TO_TRISTATE(context->unittype == punittype);
4308 case REQ_RANGE_TILE:
4310 case REQ_RANGE_ADJACENT:
4311 if (context->tile == nullptr) {
4312 return TRI_MAYBE;
4313 }
4314
4315 unit_list_iterate(context->tile->units, punit) {
4316 if (punit->utype == punittype) {
4317 return TRI_YES;
4318 }
4320
4321 if (req->range == REQ_RANGE_TILE) {
4322 return TRI_NO;
4323 }
4324
4325 if (req->range == REQ_RANGE_CADJACENT) {
4328 if (punit->utype == punittype) {
4329 return TRI_YES;
4330 }
4333 } else {
4335
4338 if (punit->utype == punittype) {
4339 return TRI_YES;
4340 }
4343 }
4344
4345 return TRI_NO;
4346
4347 case REQ_RANGE_CITY:
4350 case REQ_RANGE_PLAYER:
4351 case REQ_RANGE_TEAM:
4352 case REQ_RANGE_ALLIANCE:
4353 case REQ_RANGE_WORLD:
4354 case REQ_RANGE_COUNT:
4356 break;
4357 }
4358
4359 return TRI_NO;
4360}
4361
4362/**********************************************************************/
4370static enum fc_tristate
4372 const struct req_context *context,
4373 const struct req_context *other_context,
4374 const struct requirement *req)
4375{
4376 enum unit_type_flag_id unitflag;
4377
4379
4380 unitflag = req->source.value.unitflag;
4381
4382 switch (req->range) {
4383 case REQ_RANGE_LOCAL:
4384 if (!context->unittype) {
4385 return TRI_MAYBE;
4386 }
4387 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4388 case REQ_RANGE_TILE:
4390 case REQ_RANGE_ADJACENT:
4391 if (context->tile == nullptr) {
4392 return TRI_MAYBE;
4393 }
4394
4395 unit_list_iterate(context->tile->units, punit) {
4396 if (unit_has_type_flag(punit, unitflag)) {
4397 return TRI_YES;
4398 }
4400
4401 if (req->range == REQ_RANGE_TILE) {
4402 return TRI_NO;
4403 }
4404
4405 if (req->range == REQ_RANGE_CADJACENT) {
4408 if (unit_has_type_flag(punit, unitflag)) {
4409 return TRI_YES;
4410 }
4413 } else {
4415
4418 if (unit_has_type_flag(punit, unitflag)) {
4419 return TRI_YES;
4420 }
4423 }
4424
4425 return TRI_NO;
4426
4427 case REQ_RANGE_CITY:
4430 case REQ_RANGE_PLAYER:
4431 case REQ_RANGE_TEAM:
4432 case REQ_RANGE_ALLIANCE:
4433 case REQ_RANGE_WORLD:
4434 case REQ_RANGE_COUNT:
4436 break;
4437 }
4438
4439 return TRI_NO;
4440}
4441
4442/**********************************************************************/
4450static enum fc_tristate
4452 const struct req_context *context,
4453 const struct req_context *other_context,
4454 const struct requirement *req)
4455{
4456 const struct unit_class *pclass;
4457
4459
4460 pclass = req->source.value.uclass;
4461
4462 switch (req->range) {
4463 case REQ_RANGE_LOCAL:
4464 if (!context->unittype) {
4465 return TRI_MAYBE;
4466 }
4467 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4468 case REQ_RANGE_TILE:
4470 case REQ_RANGE_ADJACENT:
4471 if (context->tile == nullptr) {
4472 return TRI_MAYBE;
4473 }
4474
4475 unit_list_iterate(context->tile->units, punit) {
4476 if (unit_class_get(punit) == pclass) {
4477 return TRI_YES;
4478 }
4480
4481 if (req->range == REQ_RANGE_TILE) {
4482 return TRI_NO;
4483 }
4484
4485 if (req->range == REQ_RANGE_CADJACENT) {
4488 if (unit_class_get(punit) == pclass) {
4489 return TRI_YES;
4490 }
4493 } else {
4495
4498 if (unit_class_get(punit) == pclass) {
4499 return TRI_YES;
4500 }
4503 }
4504
4505 return TRI_NO;
4506
4507 case REQ_RANGE_CITY:
4510 case REQ_RANGE_PLAYER:
4511 case REQ_RANGE_TEAM:
4512 case REQ_RANGE_ALLIANCE:
4513 case REQ_RANGE_WORLD:
4514 case REQ_RANGE_COUNT:
4516 break;
4517 }
4518
4519 return TRI_NO;
4520}
4521
4522/**********************************************************************/
4530static enum fc_tristate
4532 const struct req_context *context,
4533 const struct req_context *other_context,
4534 const struct requirement *req)
4535{
4537
4539
4541
4542 switch (req->range) {
4543 case REQ_RANGE_LOCAL:
4544 if (!context->unittype) {
4545 return TRI_MAYBE;
4546 }
4548 case REQ_RANGE_TILE:
4550 case REQ_RANGE_ADJACENT:
4551 if (context->tile == nullptr) {
4552 return TRI_MAYBE;
4553 }
4554
4555 unit_list_iterate(context->tile->units, punit) {
4557 return TRI_YES;
4558 }
4560
4561 if (req->range == REQ_RANGE_TILE) {
4562 return TRI_NO;
4563 }
4564
4565 if (req->range == REQ_RANGE_CADJACENT) {
4569 return TRI_YES;
4570 }
4573 } else {
4575
4579 return TRI_YES;
4580 }
4583 }
4584
4585 return TRI_NO;
4586
4587 case REQ_RANGE_CITY:
4590 case REQ_RANGE_PLAYER:
4591 case REQ_RANGE_TEAM:
4592 case REQ_RANGE_ALLIANCE:
4593 case REQ_RANGE_WORLD:
4594 case REQ_RANGE_COUNT:
4596 break;
4597 }
4598
4599 return TRI_NO;
4600}
4601
4602/**********************************************************************/
4610static enum fc_tristate
4612 const struct req_context *context,
4613 const struct req_context *other_context,
4614 const struct requirement *req)
4615{
4616 enum ustate_prop uprop;
4617
4619
4621
4623 "Unsupported range \"%s\"",
4624 req_range_name(req->range));
4625
4626 /* Could be asked with incomplete data.
4627 * is_req_active() will handle it based on prob_type. */
4628 if (context->unit == NULL) {
4629 return TRI_MAYBE;
4630 }
4631
4632 switch (uprop) {
4633 case USP_TRANSPORTED:
4634 return BOOL_TO_TRISTATE(context->unit->transporter != NULL);
4635 case USP_LIVABLE_TILE:
4636 return BOOL_TO_TRISTATE(
4638 unit_tile(context->unit)));
4639 break;
4640 case USP_TRANSPORTING:
4642 case USP_HAS_HOME_CITY:
4643 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
4644 case USP_NATIVE_TILE:
4645 return BOOL_TO_TRISTATE(
4647 unit_tile(context->unit)));
4648 break;
4649 case USP_NATIVE_EXTRA:
4650 return BOOL_TO_TRISTATE(
4652 unit_type_get(context->unit)));
4653 break;
4655 return BOOL_TO_TRISTATE(context->unit->moved);
4656 case USP_COUNT:
4657 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
4658 /* Invalid property is unknowable. */
4659 return TRI_NO;
4660 }
4661
4662 /* Should never be reached */
4663 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
4664
4665 return TRI_NO;
4666}
4667
4668/**********************************************************************/
4676static enum fc_tristate
4678 const struct req_context *context,
4679 const struct req_context *other_context,
4680 const struct requirement *req)
4681{
4682 enum unit_activity activity;
4683
4685
4686 activity = req->source.value.activity;
4687
4689 "Unsupported range \"%s\"",
4690 req_range_name(req->range));
4691
4692 if (context->unit == NULL) {
4693 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
4694 * it's the zero value that context has by default - so many callers
4695 * who meant not to set specific activity actually have ACTIVITY_IDLE
4696 * instead of ACTIVITY_LAST */
4697 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
4698 return BOOL_TO_TRISTATE(activity == context->activity);
4699 }
4700
4701 /* Could be asked with incomplete data.
4702 * is_req_active() will handle it based on prob_type. */
4703 return TRI_MAYBE;
4704 }
4705
4706 switch (context->unit->activity) {
4707 case ACTIVITY_IDLE:
4708 case ACTIVITY_SENTRY:
4709 case ACTIVITY_GOTO:
4710 case ACTIVITY_EXPLORE:
4711 /* Seen as idle. */
4712 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
4713 default:
4714 /* Handled below. */
4715 break;
4716 }
4717
4718 return BOOL_TO_TRISTATE(context->unit->activity == activity);
4719}
4720
4721/**********************************************************************/
4729static enum fc_tristate
4731 const struct req_context *context,
4732 const struct req_context *other_context,
4733 const struct requirement *req)
4734{
4736
4737 if (context->unit == NULL) {
4738 return TRI_MAYBE;
4739 } else {
4740 return BOOL_TO_TRISTATE(context->unit->veteran
4741 >= req->source.value.minveteran);
4742 }
4743}
4744
4745/**********************************************************************/
4753static enum fc_tristate
4755 const struct req_context *context,
4756 const struct req_context *other_context,
4757 const struct requirement *req)
4758{
4760
4761 if (context->unit == NULL) {
4762 return TRI_MAYBE;
4763 } else {
4765 <= context->unit->moves_left);
4766 }
4767}
4768
4769/**********************************************************************/
4777static enum fc_tristate
4779 const struct req_context *context,
4780 const struct req_context *other_context,
4781 const struct requirement *req)
4782{
4784
4785 if (context->unit == NULL) {
4786 return TRI_MAYBE;
4787 } else {
4789 <= context->unit->hp);
4790 }
4791}
4792
4793/**********************************************************************/
4801static enum fc_tristate
4803 const struct req_context *context,
4804 const struct req_context *other_context,
4805 const struct requirement *req)
4806{
4808
4809 switch (req->range) {
4810 case REQ_RANGE_LOCAL:
4811 if (context->unit == NULL || !is_server()) {
4812 return TRI_MAYBE;
4813 } else {
4814 return BOOL_TO_TRISTATE(
4815 req->source.value.age <=
4816 game.info.turn - context->unit->birth_turn);
4817 }
4818 break;
4819 case REQ_RANGE_CITY:
4820 if (context->city == NULL) {
4821 return TRI_MAYBE;
4822 } else {
4823 return BOOL_TO_TRISTATE(
4824 req->source.value.age <=
4825 game.info.turn - context->city->turn_founded);
4826 }
4827 break;
4828 case REQ_RANGE_PLAYER:
4829 if (context->player == NULL) {
4830 return TRI_MAYBE;
4831 } else {
4832 return BOOL_TO_TRISTATE(req->source.value.age
4833 <= player_age(context->player));
4834 }
4835 break;
4836 default:
4837 return TRI_MAYBE;
4838 break;
4839 }
4840}
4841
4842/**********************************************************************/
4850static enum fc_tristate
4852 const struct req_context *context,
4853 const struct req_context *other_context,
4854 const struct requirement *req)
4855{
4857
4858 switch (req->range) {
4859 case REQ_RANGE_LOCAL:
4860 if (context->unit == NULL || !is_server()) {
4861 return TRI_MAYBE;
4862 } else {
4863 return BOOL_TO_TRISTATE(
4864 req->source.value.form_age <=
4865 game.info.turn - context->unit->current_form_turn);
4866 }
4867 break;
4868 default:
4869 return TRI_MAYBE;
4870 break;
4871 }
4872}
4873
4874/**********************************************************************/
4878static inline enum fc_tristate
4880{
4882 bool whole_known;
4883
4884 if (cont > 0) {
4887
4888 if (actual_surrounder > 0) {
4889 return TRI_NO;
4890 }
4891 } else if (cont < 0) {
4894
4895 if (actual_surrounder < 0) {
4896 return TRI_NO;
4897 }
4898 } else {
4899 return TRI_MAYBE;
4900 }
4901
4902 if (actual_surrounder == 0 || surrounder == 0) {
4903 return TRI_MAYBE;
4904 } else if (actual_surrounder != surrounder) {
4905 return TRI_NO;
4906 } else if (!whole_known) {
4907 return TRI_MAYBE;
4908 } else {
4909 return TRI_YES;
4910 }
4911}
4912
4913/**********************************************************************/
4921static enum fc_tristate
4923 const struct req_context *context,
4924 const struct req_context *other_context,
4925 const struct requirement *req)
4926{
4928
4929 if (context->tile == nullptr || other_context->tile == nullptr) {
4930 /* Note: For some values, we might be able to give a definitive
4931 * TRI_NO answer even if one of the tiles is missing, but that's
4932 * probably not worth the added effort. */
4933 return TRI_MAYBE;
4934 }
4935
4936 switch (req->source.value.tilerel) {
4937 case TREL_SAME_TCLASS:
4938 if (tile_terrain(other_context->tile) == T_UNKNOWN) {
4939 return TRI_MAYBE;
4940 }
4942 || req->range == REQ_RANGE_CADJACENT
4943 || req->range == REQ_RANGE_ADJACENT),
4944 TRI_MAYBE,
4945 "Invalid range %d for tile relation \"%s\" req",
4947 {
4950 bool seen_unknown = FALSE;
4951 const struct terrain *terr;
4952
4953 if ((terr = tile_terrain(context->tile)) == T_UNKNOWN) {
4955 } else if (terrain_type_terrain_class(terr) == cls) {
4956 return TRUE;
4957 }
4958
4960 if ((terr = tile_terrain(adj_tile)) == T_UNKNOWN) {
4962 } else if (terrain_type_terrain_class(terr) == cls) {
4963 return TRUE;
4964 }
4966
4967 if (seen_unknown) {
4968 return TRI_MAYBE;
4969 } else {
4970 return TRI_NO;
4971 }
4972 }
4973 break;
4974 case TREL_SAME_REGION:
4975 if (tile_continent(other_context->tile) == 0) {
4976 return TRI_MAYBE;
4977 }
4979 || req->range == REQ_RANGE_CADJACENT
4980 || req->range == REQ_RANGE_ADJACENT),
4981 TRI_MAYBE,
4982 "Invalid range %d for tile relation \"%s\" req",
4984
4985 if (tile_continent(context->tile)
4986 == tile_continent(other_context->tile)) {
4987 return TRI_YES;
4988 } else {
4989 bool seen_unknown = (tile_continent(context->tile) == 0);
4991
4994
4995 if (adj_cont == cont) {
4996 return TRI_YES;
4997 } else if (adj_cont == 0) {
4999 }
5001
5002 if (seen_unknown) {
5003 return TRI_MAYBE;
5004 } else {
5005 return TRI_NO;
5006 }
5007 }
5008 break;
5010 if (tile_continent(context->tile) == 0
5011 || tile_continent(other_context->tile) == 0) {
5012 /* Note: We could still give a definitive TRI_NO answer if there are
5013 * too many different adjacent continents, but that's probably not
5014 * worth the added effort. */
5015 return TRI_MAYBE;
5016 }
5018 || req->range == REQ_RANGE_ADJACENT),
5019 TRI_MAYBE,
5020 "Invalid range %d for tile relation \"%s\" req",
5021 req->range,
5023
5024 {
5025 bool seen_unknown = FALSE;
5026 Continent_id cont = tile_continent(context->tile);
5028
5031
5032 if (adj_cont == 0) {
5034 } else if (adj_cont != cont && adj_cont != other_cont) {
5035 return TRI_NO;
5036 }
5038
5039 if (seen_unknown) {
5040 return TRI_MAYBE;
5041 } else {
5042 return TRI_YES;
5043 }
5044 }
5045 break;
5048 || req->range == REQ_RANGE_CADJACENT
5049 || req->range == REQ_RANGE_ADJACENT),
5050 TRI_MAYBE,
5051 "Invalid range %d for tile relation \"%s\" req",
5052 req->range,
5054
5055 {
5056 bool seen_maybe = FALSE;
5058
5060 wanted)) {
5061 case TRI_YES:
5062 return TRI_YES;
5063 case TRI_MAYBE:
5064 seen_maybe = TRUE;
5065 break;
5066 default:
5067 break;
5068 }
5069
5072 wanted)) {
5073 case TRI_YES:
5074 return TRI_YES;
5075 case TRI_MAYBE:
5076 seen_maybe = TRUE;
5077 break;
5078 default:
5079 break;
5080 }
5082
5083 if (seen_maybe) {
5084 return TRI_MAYBE;
5085 } else {
5086 return TRI_NO;
5087 }
5088 }
5089 break;
5090 default:
5091 break;
5092 }
5093
5095 "Illegal value %d for tile relationship requirement.",
5096 req->source.value.tilerel);
5097 return TRI_MAYBE;
5098}
5099
5100/**********************************************************************/
5103static bool is_city_in_tile(const struct tile *ptile,
5104 const struct city *pcity)
5105{
5106 if (pcity == NULL) {
5107 return tile_city(ptile) != NULL;
5108 } else {
5109 return is_city_center(pcity, ptile);
5110 }
5111}
5112
5113/**********************************************************************/
5121static enum fc_tristate
5123 const struct req_context *context,
5124 const struct req_context *other_context,
5125 const struct requirement *req)
5126{
5127 enum citytile_type citytile;
5128
5130
5131 citytile = req->source.value.citytile;
5132
5134 if (context->tile == NULL) {
5135 return TRI_MAYBE;
5136 }
5137
5138 switch (citytile) {
5139 case CITYT_CENTER:
5140 switch (req->range) {
5141 case REQ_RANGE_TILE:
5143 context->city));
5145 if (is_city_in_tile(context->tile, context->city)) {
5146 return TRI_YES;
5147 }
5149 if (is_city_in_tile(adjc_tile, context->city)) {
5150 return TRI_YES;
5151 }
5153
5154 return TRI_NO;
5155 case REQ_RANGE_ADJACENT:
5156 if (is_city_in_tile(context->tile, context->city)) {
5157 return TRI_YES;
5158 }
5160 if (is_city_in_tile(adjc_tile, context->city)) {
5161 return TRI_YES;
5162 }
5164
5165 return TRI_NO;
5166 case REQ_RANGE_CITY:
5169 case REQ_RANGE_PLAYER:
5170 case REQ_RANGE_TEAM:
5171 case REQ_RANGE_ALLIANCE:
5172 case REQ_RANGE_WORLD:
5173 case REQ_RANGE_LOCAL:
5174 case REQ_RANGE_COUNT:
5175 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5176 break;
5177 }
5178
5179 return TRI_MAYBE;
5180 case CITYT_CLAIMED:
5181 switch (req->range) {
5182 case REQ_RANGE_TILE:
5183 return BOOL_TO_TRISTATE(context->tile->owner != NULL);
5185 if (context->tile->owner != NULL) {
5186 return TRI_YES;
5187 }
5189 if (adjc_tile->owner != NULL) {
5190 return TRI_YES;
5191 }
5193
5194 return TRI_NO;
5195 case REQ_RANGE_ADJACENT:
5196 if (context->tile->owner != NULL) {
5197 return TRI_YES;
5198 }
5200 if (adjc_tile->owner != NULL) {
5201 return TRI_YES;
5202 }
5204
5205 return TRI_NO;
5206 case REQ_RANGE_CITY:
5209 case REQ_RANGE_PLAYER:
5210 case REQ_RANGE_TEAM:
5211 case REQ_RANGE_ALLIANCE:
5212 case REQ_RANGE_WORLD:
5213 case REQ_RANGE_LOCAL:
5214 case REQ_RANGE_COUNT:
5215 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5216 break;
5217 }
5218
5219 return TRI_MAYBE;
5220 case CITYT_EXTRAS_OWNED:
5221 switch (req->range) {
5222 case REQ_RANGE_TILE:
5223 return BOOL_TO_TRISTATE(context->tile->extras_owner != NULL);
5225 if (context->tile->extras_owner != NULL) {
5226 return TRI_YES;
5227 }
5229 if (adjc_tile->extras_owner != NULL) {
5230 return TRI_YES;
5231 }
5233
5234 return TRI_NO;
5235 case REQ_RANGE_ADJACENT:
5236 if (context->tile->extras_owner != NULL) {
5237 return TRI_YES;
5238 }
5240 if (adjc_tile->extras_owner != NULL) {
5241 return TRI_YES;
5242 }
5244
5245 return TRI_NO;
5246 case REQ_RANGE_CITY:
5249 case REQ_RANGE_PLAYER:
5250 case REQ_RANGE_TEAM:
5251 case REQ_RANGE_ALLIANCE:
5252 case REQ_RANGE_WORLD:
5253 case REQ_RANGE_LOCAL:
5254 case REQ_RANGE_COUNT:
5255 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5256 break;
5257 }
5258
5259 return TRI_MAYBE;
5260 case CITYT_WORKED:
5261 switch (req->range) {
5262 case REQ_RANGE_TILE:
5263 return BOOL_TO_TRISTATE(context->tile->worked != NULL);
5265 if (context->tile->worked != NULL) {
5266 return TRI_YES;
5267 }
5269 if (adjc_tile->worked != NULL) {
5270 return TRI_YES;
5271 }
5273
5274 return TRI_NO;
5275 case REQ_RANGE_ADJACENT:
5276 if (context->tile->worked != NULL) {
5277 return TRI_YES;
5278 }
5280 if (adjc_tile->worked != NULL) {
5281 return TRI_YES;
5282 }
5284
5285 return TRI_NO;
5286 case REQ_RANGE_CITY:
5289 case REQ_RANGE_PLAYER:
5290 case REQ_RANGE_TEAM:
5291 case REQ_RANGE_ALLIANCE:
5292 case REQ_RANGE_WORLD:
5293 case REQ_RANGE_LOCAL:
5294 case REQ_RANGE_COUNT:
5295 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5296 break;
5297 }
5298
5299 return TRI_MAYBE;
5301 {
5303 const struct tile *target_tile = context->tile, *cc_tile;
5304
5305 if (!context->city) {
5306 return TRI_MAYBE;
5307 }
5308 cc_tile = city_tile(context->city);
5309 if (!cc_tile) {
5310 /* Unplaced virtual city */
5311 return TRI_MAYBE;
5312 }
5314 /* Note: No special treatment of 0 == cc here*/
5315 switch (req->range) {
5316 case REQ_RANGE_TILE:
5319 if (tile_continent(target_tile) == cc) {
5320 return TRI_YES;
5321 }
5323 if (tile_continent(adjc_tile) == cc) {
5324 return TRI_YES;
5325 }
5327
5328 return TRI_NO;
5329 case REQ_RANGE_ADJACENT:
5330 if (tile_continent(target_tile) == cc) {
5331 return TRI_YES;
5332 }
5334 if (tile_continent(adjc_tile) == cc) {
5335 return TRI_YES;
5336 }
5338
5339 return TRI_NO;
5340 case REQ_RANGE_CITY:
5343 case REQ_RANGE_PLAYER:
5344 case REQ_RANGE_TEAM:
5345 case REQ_RANGE_ALLIANCE:
5346 case REQ_RANGE_WORLD:
5347 case REQ_RANGE_LOCAL:
5348 case REQ_RANGE_COUNT:
5349 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5350 break;
5351 }
5352 }
5353
5354 return TRI_MAYBE;
5356 {
5357 int n = 0;
5359 bool ukt = FALSE;
5360 const struct tile *target_tile = context->tile, *cc_tile;
5361
5362 if (!context->city) {
5363 return TRI_MAYBE;
5364 }
5365 cc_tile = city_tile(context->city);
5366 if (!cc_tile) {
5367 /* Unplaced virtual city */
5368 return TRI_MAYBE;
5369 }
5371 if (!cc) {
5372 /* Don't know the city center terrain class.
5373 * Maybe, the city floats? Even if the rules prohibit it... */
5374 return TRI_MAYBE;
5375 }
5378
5379 if (0 != tc) {
5380 bool seen = FALSE;
5381 int i = n;
5382
5383 if (tc == cc) {
5384 continue;
5385 }
5386 while (--i >= 0) {
5387 if (adjc_cont[i] == tc) {
5388 seen = TRUE;
5389 break;
5390 }
5391 }
5392 if (seen) {
5393 continue;
5394 }
5396 } else {
5397 /* Likely, it's a black tile in client and we don't know
5398 * We possibly can calculate, but keep it simple. */
5399 ukt = TRUE;
5400 }
5402 if (0 == n) {
5403 return ukt ? TRI_MAYBE : TRI_NO;
5404 }
5405
5406 switch (req->range) {
5407 case REQ_RANGE_TILE:
5408 {
5410
5411 if (cc == tc) {
5412 return TRI_NO;
5413 }
5414 if (0 == tc || ukt) {
5415 return TRI_MAYBE;
5416 }
5417 for (int i = 0; i < n; i++) {
5418 if (tc == adjc_cont[i]) {
5419 return TRI_YES;
5420 }
5421 }
5422 }
5423
5424 return TRI_NO;
5425 case REQ_RANGE_ADJACENT:
5426 if (ukt) {
5427 /* If ALL the tiles in range are on cc, we can say it's false */
5429 if (tile_continent(adjc_tile) != cc) {
5430 return TRI_MAYBE;
5431 }
5433
5434 return TRI_NO;
5435 } else {
5438
5439 if (0 == tc) {
5440 return TRI_MAYBE;
5441 }
5442 for (int i = 0; i < n; i++) {
5443 if (tc == adjc_cont[i]) {
5444 return TRI_YES;
5445 }
5446 }
5448 }
5449
5450 return TRI_NO;
5452 if (ukt) {
5453 /* If ALL the tiles in range are on cc, we can say it's false */
5455 if (tile_continent(cadjc_tile) != cc) {
5456 return TRI_MAYBE;
5457 }
5459 } else {
5462
5463 if (0 == tc) {
5464 return TRI_MAYBE;
5465 }
5466 for (int i = 0; i < n; i++) {
5467 if (tc == adjc_cont[i]) {
5468 return TRI_YES;
5469 }
5470 }
5472 }
5473
5474 return TRI_NO;
5475 case REQ_RANGE_CITY:
5478 case REQ_RANGE_PLAYER:
5479 case REQ_RANGE_TEAM:
5480 case REQ_RANGE_ALLIANCE:
5481 case REQ_RANGE_WORLD:
5482 case REQ_RANGE_LOCAL:
5483 case REQ_RANGE_COUNT:
5484 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5485 break;
5486 }
5487 }
5488
5489 return TRI_MAYBE;
5490 case CITYT_LAST:
5491 /* Handled below */
5492 break;
5493 }
5494
5495 /* Not implemented */
5496 log_error("is_req_active(): citytile %d not supported.",
5497 citytile);
5498 return TRI_MAYBE;
5499}
5500
5501/**********************************************************************/
5509static enum fc_tristate
5511 const struct req_context *context,
5512 const struct req_context *other_context,
5513 const struct requirement *req)
5514{
5515 enum citystatus_type citystatus;
5516
5518
5519 citystatus = req->source.value.citystatus;
5520
5521 if (context->city == NULL) {
5522 return TRI_MAYBE;
5523 }
5524
5525 switch (citystatus) {
5527 switch (req->range) {
5528 case REQ_RANGE_CITY:
5529 if (context->city->original == NULL) {
5530 return TRI_MAYBE;
5531 }
5532 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
5534 {
5535 enum fc_tristate ret;
5536
5537 if (city_owner(context->city) == context->city->original) {
5538 return TRI_YES;
5539 }
5540
5541 ret = TRI_NO;
5543 if (trade_partner == NULL || trade_partner->original == NULL) {
5544 ret = TRI_MAYBE;
5545 } else if (city_owner(trade_partner) == trade_partner->original) {
5546 return TRI_YES;
5547 }
5549
5550 return ret;
5551 }
5552 case REQ_RANGE_LOCAL:
5553 case REQ_RANGE_TILE:
5555 case REQ_RANGE_ADJACENT:
5557 case REQ_RANGE_PLAYER:
5558 case REQ_RANGE_TEAM:
5559 case REQ_RANGE_ALLIANCE:
5560 case REQ_RANGE_WORLD:
5561 case REQ_RANGE_COUNT:
5562 break;
5563 }
5564
5565 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
5566 req->range);
5567
5568 return TRI_MAYBE;
5569
5570 case CITYS_STARVED:
5571 switch (req->range) {
5572 case REQ_RANGE_CITY:
5573 return BOOL_TO_TRISTATE(context->city->had_famine);
5575 {
5576 enum fc_tristate ret;
5577
5578 if (context->city->had_famine) {
5579 return TRI_YES;
5580 }
5581
5582 ret = TRI_NO;
5584 if (trade_partner == NULL) {
5585 ret = TRI_MAYBE;
5586 } else if (trade_partner->had_famine) {
5587 return TRI_YES;
5588 }
5590
5591 return ret;
5592 }
5593 case REQ_RANGE_LOCAL:
5594 case REQ_RANGE_TILE:
5596 case REQ_RANGE_ADJACENT:
5598 case REQ_RANGE_PLAYER:
5599 case REQ_RANGE_TEAM:
5600 case REQ_RANGE_ALLIANCE:
5601 case REQ_RANGE_WORLD:
5602 case REQ_RANGE_COUNT:
5603 break;
5604 }
5605
5606 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
5607 req->range);
5608
5609 return TRI_MAYBE;
5610
5611 case CITYS_DISORDER:
5612 switch (req->range) {
5613 case REQ_RANGE_CITY:
5614 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
5616 {
5617 enum fc_tristate ret;
5618
5619 if (context->city->anarchy > 0) {
5620 return TRI_YES;
5621 }
5622
5623 ret = TRI_NO;
5625 if (trade_partner == NULL) {
5626 ret = TRI_MAYBE;
5627 } else if (trade_partner->anarchy > 0) {
5628 return TRI_YES;
5629 }
5631
5632 return ret;
5633 }
5634 case REQ_RANGE_LOCAL:
5635 case REQ_RANGE_TILE:
5637 case REQ_RANGE_ADJACENT:
5639 case REQ_RANGE_PLAYER:
5640 case REQ_RANGE_TEAM:
5641 case REQ_RANGE_ALLIANCE:
5642 case REQ_RANGE_WORLD:
5643 case REQ_RANGE_COUNT:
5644 break;
5645 }
5646
5647 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
5648 req->range);
5649
5650 return TRI_MAYBE;
5651
5652 case CITYS_CELEBRATION:
5653 switch (req->range) {
5654 case REQ_RANGE_CITY:
5655 return BOOL_TO_TRISTATE(context->city->rapture > 0);
5657 {
5658 enum fc_tristate ret;
5659
5660 if (context->city->rapture > 0) {
5661 return TRI_YES;
5662 }
5663
5664 ret = TRI_NO;
5666 if (trade_partner == NULL) {
5667 ret = TRI_MAYBE;
5668 } else if (trade_partner->rapture > 0) {
5669 return TRI_YES;
5670 }
5672
5673 return ret;
5674 }
5675 case REQ_RANGE_LOCAL:
5676 case REQ_RANGE_TILE:
5678 case REQ_RANGE_ADJACENT:
5680 case REQ_RANGE_PLAYER:
5681 case REQ_RANGE_TEAM:
5682 case REQ_RANGE_ALLIANCE:
5683 case REQ_RANGE_WORLD:
5684 case REQ_RANGE_COUNT:
5685 break;
5686 }
5687
5688 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
5689 req->range);
5690
5691 return TRI_MAYBE;
5692
5693 case CITYS_TRANSFERRED:
5694 switch (req->range) {
5695 case REQ_RANGE_CITY:
5696 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
5698 {
5699 enum fc_tristate ret;
5700
5701 if (context->city->acquire_t != CACQ_FOUNDED) {
5702 return TRI_YES;
5703 }
5704
5705 ret = TRI_NO;
5707 if (trade_partner == NULL) {
5708 ret = TRI_MAYBE;
5709 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
5710 return TRI_YES;
5711 }
5713
5714 return ret;
5715 }
5716 case REQ_RANGE_LOCAL:
5717 case REQ_RANGE_TILE:
5719 case REQ_RANGE_ADJACENT:
5721 case REQ_RANGE_PLAYER:
5722 case REQ_RANGE_TEAM:
5723 case REQ_RANGE_ALLIANCE:
5724 case REQ_RANGE_WORLD:
5725 case REQ_RANGE_COUNT:
5726 break;
5727 }
5728
5729 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
5730 req->range);
5731
5732 return TRI_MAYBE;
5733
5734 case CITYS_LAST:
5735 break;
5736 }
5737
5738 /* Not implemented */
5739 log_error("is_req_active(): citystatus %d not supported.",
5740 citystatus);
5741
5742 return TRI_MAYBE;
5743}
5744
5745/**********************************************************************/
5753static enum fc_tristate
5755 const struct req_context *context,
5756 const struct req_context *other_context,
5757 const struct requirement *req)
5758{
5760
5761 if (context->city == NULL) {
5762 return TRI_MAYBE;
5763 } else {
5764 if (req->range == REQ_RANGE_TRADE_ROUTE) {
5765 enum fc_tristate ret;
5766
5767 if (city_size_get(context->city) >= req->source.value.minsize) {
5768 return TRI_YES;
5769 }
5770
5771 ret = TRI_NO;
5773 if (trade_partner == NULL) {
5774 ret = TRI_MAYBE;
5775 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
5776 return TRI_YES;
5777 }
5779
5780 return ret;
5781 } else {
5783 >= req->source.value.minsize);
5784 }
5785 }
5786}
5787
5788/**********************************************************************/
5796static enum fc_tristate
5798 const struct req_context *context,
5799 const struct req_context *other_context,
5800 const struct requirement *req)
5801{
5802 const struct counter *count;
5803
5805
5806 count = req->source.value.counter;
5807
5808 if (NULL == context->city) {
5809 return TRI_MAYBE;
5810 }
5811 return BOOL_TO_TRISTATE(count->checkpoint <=
5812 context->city->counter_values[
5813 counter_index(count)]);
5814}
5815
5816/**********************************************************************/
5824static enum fc_tristate
5826 const struct req_context *context,
5827 const struct req_context *other_context,
5828 const struct requirement *req)
5829{
5830 const struct achievement *achievement;
5831
5833
5835
5836 if (req->range == REQ_RANGE_WORLD) {
5838 } else if (context->player == NULL) {
5839 return TRI_MAYBE;
5840 } else if (req->range == REQ_RANGE_ALLIANCE
5841 || req->range == REQ_RANGE_TEAM) {
5842 players_iterate_alive(plr2) {
5843 if (players_in_same_range(context->player, plr2, req->range)
5845 return TRI_YES;
5846 }
5848 return TRI_NO;
5849 } else if (req->range == REQ_RANGE_PLAYER) {
5851 return TRI_YES;
5852 } else {
5853 return TRI_NO;
5854 }
5855 }
5856
5857 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
5858
5859 return TRI_MAYBE;
5860}
5861
5862/**********************************************************************/
5870static enum fc_tristate
5872 const struct req_context *context,
5873 const struct req_context *other_context,
5874 const struct requirement *req)
5875{
5876 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
5877
5880
5881 switch (req->source.kind) {
5882 case VUT_MINLATITUDE:
5883 min = req->source.value.latitude;
5884 break;
5885 case VUT_MAXLATITUDE:
5886 max = req->source.value.latitude;
5887 break;
5888 default:
5890 || req->source.kind == VUT_MAXLATITUDE);
5891 break;
5892 }
5893
5894 switch (req->range) {
5895 case REQ_RANGE_WORLD:
5897 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
5898
5899 case REQ_RANGE_TILE:
5900 if (context->tile == NULL) {
5901 return TRI_MAYBE;
5902 } else {
5904
5906 }
5907
5909 if (context->tile == NULL) {
5910 return TRI_MAYBE;
5911 }
5912
5915
5917 return TRI_YES;
5918 }
5920 return TRI_NO;
5921
5922 case REQ_RANGE_ADJACENT:
5923 if (!context->tile) {
5924 return TRI_MAYBE;
5925 }
5926
5929
5931 return TRI_YES;
5932 }
5934 return TRI_NO;
5935
5936 case REQ_RANGE_CITY:
5939 case REQ_RANGE_PLAYER:
5940 case REQ_RANGE_TEAM:
5941 case REQ_RANGE_ALLIANCE:
5942 case REQ_RANGE_LOCAL:
5943 case REQ_RANGE_COUNT:
5944 break;
5945 }
5946
5948 "Illegal range %d for latitude requirement.", req->range);
5949
5950 return TRI_MAYBE;
5951}
5952
5953/**********************************************************************/
5961static enum fc_tristate
5963 const struct req_context *context,
5964 const struct req_context *other_context,
5965 const struct requirement *req)
5966{
5968
5969 switch (req->range) {
5970 case REQ_RANGE_TILE:
5971 if (context->tile == nullptr || other_context->tile == nullptr) {
5972 return TRI_MAYBE;
5973 }
5974 return BOOL_TO_TRISTATE(
5976 <= req->source.value.distance_sq
5977 );
5978 default:
5979 break;
5980 }
5981
5983 "Illegal range %d for max squared distance requirement.",
5984 req->range);
5985
5986 return TRI_MAYBE;
5987}
5988
5989/**********************************************************************/
5997static enum fc_tristate
5999 const struct req_context *context,
6000 const struct req_context *other_context,
6001 const struct requirement *req)
6002{
6003 int max_tiles, min_tiles = 1;
6004
6006
6007 switch (req->range) {
6009 case REQ_RANGE_ADJACENT:
6010 if (context->tile == nullptr) {
6011 /* The tile itself is included in the range */
6012 max_tiles = 1 + ((req->range == REQ_RANGE_CADJACENT)
6013 ? nmap->num_cardinal_dirs
6014 : nmap->num_valid_dirs);
6015
6016 break;
6017 } else {
6018 Continent_id cont = tile_continent(context->tile);
6019
6020 /* Count how many adjacent tiles there actually are as we go along */
6021 max_tiles = 1;
6022
6025
6026 if (adj_cont == 0 || cont == 0) {
6027 max_tiles++;
6028 } else if (adj_cont == cont) {
6029 min_tiles++;
6030 max_tiles++;
6031 }
6033 }
6034 break;
6036 {
6037 Continent_id cont = context->tile ? tile_continent(context->tile) : 0;
6038
6041
6042 /* Note: We could come up with a better upper bound by subtracting
6043 * all other continent/ocean sizes, or all except the largest if we
6044 * don't know the tile.
6045 * We could even do a flood-fill count of the unknown area bordered
6046 * by known tiles of the continent.
6047 * Probably not worth the effort though. */
6048 max_tiles = nmap->xsize * nmap->ysize;
6049
6050 if (cont > 0) {
6051 min_tiles = nmap->continent_sizes[cont];
6052 if (is_whole_continent_known(cont)) {
6054 }
6055 } else if (cont < 0) {
6056 min_tiles = nmap->ocean_sizes[-cont];
6057 if (is_whole_ocean_known(-cont)) {
6059 }
6060 }
6061 }
6062 break;
6063 default:
6065 "Illegal range %d for max region tiles requirement.",
6066 req->range);
6067 return TRI_MAYBE;
6068 }
6069
6070 if (min_tiles > req->source.value.region_tiles) {
6071 return TRI_NO;
6072 } else if (max_tiles <= req->source.value.region_tiles) {
6073 return TRI_YES;
6074 }
6075 return TRI_MAYBE;
6076}
6077
6078/**********************************************************************/
6086static enum fc_tristate
6088 const struct req_context *context,
6089 const struct req_context *other_context,
6090 const struct requirement *req)
6091{
6093
6095}
6096
6097/**********************************************************************/
6105static enum fc_tristate
6107 const struct req_context *context,
6108 const struct req_context *other_context,
6109 const struct requirement *req)
6110{
6112
6114 >= req->source.value.mincalfrag);
6115}
6116
6117/**********************************************************************/
6125static enum fc_tristate
6127 const struct req_context *context,
6128 const struct req_context *other_context,
6129 const struct requirement *req)
6130{
6132
6133 return BOOL_TO_TRISTATE(
6135}
6136
6137/**********************************************************************/
6145static enum fc_tristate
6147 const struct req_context *context,
6148 const struct req_context *other_context,
6149 const struct requirement *req)
6150{
6152
6153 return BOOL_TO_TRISTATE(
6155}
6156
6157/**********************************************************************/
6165static enum fc_tristate
6167 const struct req_context *context,
6168 const struct req_context *other_context,
6169 const struct requirement *req)
6170{
6172
6174 req->source.value.ssetval));
6175}
6176
6177/* Not const for potential ruleset-related adjustment */
6180
6181 /* Alphabetical order of enum constant */
6244};
6245
6246/**********************************************************************/
6260 const struct req_context *other_context,
6261 const struct requirement *req,
6262 const enum req_problem_type prob_type)
6263{
6264 const struct civ_map *nmap = &(wld.map);
6266 req);
6267
6268 if (eval == TRI_MAYBE) {
6269 if (prob_type == RPT_POSSIBLE) {
6270 return TRUE;
6271 } else {
6272 return FALSE;
6273 }
6274 }
6275 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
6276}
6277
6278/**********************************************************************/
6287static
6289 const struct req_context *context,
6290 const struct req_context *other_context,
6291 const struct requirement *req)
6292{
6293 if (!context) {
6295 }
6296 if (!other_context) {
6298 }
6299
6300 if (req->source.kind >= VUT_COUNT) {
6301 log_error("tri_req_present(): invalid source kind %d.",
6302 req->source.kind);
6303 return TRI_NO;
6304 }
6305
6307
6308 return req_definitions[req->source.kind].cb(nmap, context,
6309 other_context, req);
6310}
6311
6312/**********************************************************************/
6322 const struct req_context *other_context,
6323 const struct requirement *req)
6324{
6325 const struct civ_map *nmap = &(wld.map);
6327
6328 if (!req->present) {
6329 if (TRI_NO == eval) {
6330 return TRI_YES;
6331 }
6332 if (TRI_YES == eval) {
6333 return TRI_NO;
6334 }
6335 }
6336
6337 return eval;
6338}
6339
6340/**********************************************************************/
6356 const struct req_context *other_context,
6357 const struct requirement_vector *reqs,
6358 const enum req_problem_type prob_type)
6359{
6362 return FALSE;
6363 }
6365
6366 return TRUE;
6367}
6368
6369/**********************************************************************/
6374 const enum req_range max_range,
6375 const struct req_context *context,
6376 const struct req_context *other_context,
6377 const struct requirement_vector *reqs,
6378 const enum req_problem_type prob_type)
6379{
6381 if (preq->range >= min_range && preq->range <= max_range) {
6383 return FALSE;
6384 }
6385 }
6387
6388 return TRUE;
6389}
6390
6391/**********************************************************************/
6397enum fc_tristate
6399 const struct req_context *context,
6400 const struct req_context *other_context,
6401 const struct requirement *req)
6402{
6403 /* FIXME: doubles code from calendar.c */
6407 int fragment1 = fragment; /* if fragments don't advance */
6408 int year_inc, year_inc1;
6411 bool present, present1;
6412
6413 fc_assert(pass >= 0 && period >= 0);
6414 if (slowdown >= 3) {
6415 if (ypt > 1) {
6416 ypt = 1;
6417 }
6418 } else if (slowdown >= 2) {
6419 if (ypt > 2) {
6420 ypt = 2;
6421 }
6422 } else if (slowdown >= 1) {
6423 if (ypt > 5) {
6424 ypt = 5;
6425 }
6426 }
6427 year_inc = ypt * pass;
6430 int fragment_years;
6431
6432 fragment += fpt * pass;
6440 }
6442 if (year_inc + game.info.year >= 0) {
6443 year_inc++;
6444 year_inc1++;
6445 } else if (year_inc1 + game.info.year >= 0) {
6446 year_inc1++;
6447 }
6448 }
6449
6450 switch (req->source.kind) {
6451 case VUT_AGE:
6452 switch (req->range) {
6453 case REQ_RANGE_LOCAL:
6454 if (context->unit == NULL || !is_server()) {
6455 return TRI_MAYBE;
6456 } else {
6457 int ua = game.info.turn + pass - context->unit->birth_turn;
6458
6459 present = req->source.value.age <= ua;
6460 present1 = req->source.value.age <= ua + period;
6461 }
6462 break;
6463 case REQ_RANGE_CITY:
6464 if (context->city == NULL) {
6465 return TRI_MAYBE;
6466 } else {
6467 int ca = game.info.turn + pass - context->city->turn_founded;
6468
6469 present = req->source.value.age <= ca;
6470 present1 = req->source.value.age <= ca + period;
6471 }
6472 break;
6473 case REQ_RANGE_PLAYER:
6474 if (context->player == NULL) {
6475 return TRI_MAYBE;
6476 } else {
6477 present = req->source.value.age
6478 <= player_age(context->player) + pass;
6479 present1 = req->source.value.age
6480 <= player_age(context->player) + pass + period;
6481 }
6482 break;
6483 default:
6484 return TRI_MAYBE;
6485 }
6486 break;
6487 case VUT_FORM_AGE:
6488 if (context->unit == NULL || !is_server()) {
6489 return TRI_MAYBE;
6490 } else {
6491 int ua = game.info.turn + pass - context->unit->current_form_turn;
6492
6493 present = req->source.value.form_age <= ua;
6494 present1 = req->source.value.form_age <= ua + period;
6495 }
6496 break;
6497 case VUT_MINYEAR:
6498 present = game.info.year + year_inc >= req->source.value.minyear;
6500 break;
6501 case VUT_MINCALFRAG:
6503 /* Hope that the requirement is valid and fragments advance fine */
6504 return TRI_YES;
6505 }
6506 present = fragment >= req->source.value.mincalfrag;
6508 break;
6509 default:
6510 /* No special handling invented */
6511 return tri_req_active(context, other_context, req);
6512 }
6513 return BOOL_TO_TRISTATE(req->present
6514 ? present || present1 : !(present && present1));
6515}
6516
6517/**********************************************************************/
6523 (const struct req_context *context,
6524 const struct req_context *other_context,
6525 const struct requirement *req,
6526 void *data, int n_data)
6527{
6528 int i;
6529
6530 fc_assert_ret_val(data || n_data == 0, TRI_NO);
6531
6532 for (i = 0; i < n_data; i++) {
6533 if (are_requirements_contradictions(&((struct requirement *) data)[i],
6534 req)) {
6535 return TRI_NO;
6536 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
6537 return TRI_YES;
6538 }
6539 }
6540
6541 return tri_req_active(context, other_context, req);
6542}
6543
6544/**********************************************************************/
6550enum fc_tristate
6552 const struct req_context *other_context,
6553 const struct requirement_vector *reqs,
6556 void *data, int n_data)
6557{
6558 bool active = TRUE;
6559 bool certain = TRUE;
6560
6564 data, n_data)) {
6565 case TRI_NO:
6566 active = FALSE;
6567 certain = TRUE;
6568 break;
6569 case TRI_YES:
6570 break;
6571 case TRI_MAYBE:
6572 certain = FALSE;
6573 if (maybe_reqs) {
6575 }
6576 break;
6577 default:
6579 active = FALSE;
6580 }
6581 if (!active) {
6582 break;
6583 }
6585
6586 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
6587}
6588
6589/**********************************************************************/
6599 const struct requirement *req)
6600{
6601 enum req_unchanging_status s;
6602 const struct civ_map *nmap = &(wld.map);
6603
6606 "Invalid source kind %d.", req->source.kind);
6608
6609 if (req->survives) {
6610 /* Special case for surviving requirements */
6611 /* Buildings may obsolete even here */
6612 if (VUT_IMPROVEMENT == req->source.kind) {
6613 const struct impr_type *b = req->source.value.building;
6614
6616 if (improvement_obsolete(context->player, b, context->city)) {
6617 /* FIXME: sometimes can unobsolete, but considering it
6618 * may sometimes put the function on endless recursion */
6619 return REQUCH_ACT; /* Mostly about techs */
6620 } else {
6621 /* NOTE: may obsoletion reqs be unchanging? Hardly but why not. */
6622 return REQUCH_NO;
6623 }
6624 }
6625 }
6626 s = unchanging_present(nmap, s, context, req);
6627 if (s != REQUCH_NO) {
6628 return unchanging_noally(nmap, s, context, req);
6629 }
6630 } else {
6633
6634 if (cond) {
6635 return cond(nmap, s, context, req);
6636 }
6637 }
6638
6639 return s;
6640}
6641
6642/**********************************************************************/
6647 const struct req_context *other_context,
6648 const struct requirement *req,
6650{
6652
6653 if (REQUCH_NO != u) {
6654 /* Presence is precalculated */
6655 bool auto_present = (req->survives
6656 && !(VUT_IMPROVEMENT == req->source.kind
6660
6661 if (auto_present ? req->present
6663 /* Unchanging but does not block */
6664 return REQUCH_NO;
6665 }
6666 }
6667
6668 return u;
6669}
6670
6671/**********************************************************************/
6675bool is_req_in_vec(const struct requirement *req,
6676 const struct requirement_vector *vec)
6677{
6679 if (are_requirements_equal(req, preq)) {
6680 return TRUE;
6681 }
6683
6684 return FALSE;
6685}
6686
6687/**********************************************************************/
6694 enum universals_n kind)
6695{
6697 if (preq->present && preq->source.kind == kind) {
6698 return TRUE;
6699 }
6701 return FALSE;
6702}
6703
6704/**********************************************************************/
6713{
6714 switch (source->kind) {
6715 case VUT_ACTION:
6716 return !action_is_in_use(source->value.action);
6717 case VUT_UTFLAG:
6718 return !utype_flag_is_in_use(source->value.unitflag);
6719 case VUT_UCFLAG:
6720 return !uclass_flag_is_in_use(source->value.unitclassflag);
6721 case VUT_EXTRAFLAG:
6722 return !extra_flag_is_in_use(source->value.extraflag);
6723 case VUT_MINLATITUDE:
6724 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
6725 case VUT_MAXLATITUDE:
6726 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
6727 case VUT_COUNTER:
6728 case VUT_OTYPE:
6729 case VUT_SPECIALIST:
6730 case VUT_AI_LEVEL:
6731 case VUT_CITYTILE:
6732 case VUT_CITYSTATUS:
6733 case VUT_STYLE:
6734 case VUT_TOPO:
6735 case VUT_WRAP:
6736 case VUT_SERVERSETTING:
6737 case VUT_NATION:
6738 case VUT_NATIONGROUP:
6739 case VUT_ADVANCE:
6740 case VUT_TECHFLAG:
6741 case VUT_GOVERNMENT:
6742 case VUT_ACHIEVEMENT:
6743 case VUT_IMPROVEMENT:
6744 case VUT_SITE:
6745 case VUT_IMPR_GENUS:
6746 case VUT_IMPR_FLAG:
6747 case VUT_PLAYER_FLAG:
6748 case VUT_PLAYER_STATE:
6749 case VUT_MINSIZE:
6750 case VUT_MINCULTURE:
6751 case VUT_MINFOREIGNPCT:
6752 case VUT_MINTECHS:
6753 case VUT_MINCITIES:
6754 case VUT_NATIONALITY:
6755 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
6756 case VUT_DIPLREL:
6757 case VUT_DIPLREL_TILE:
6758 case VUT_DIPLREL_TILE_O:
6761 case VUT_MAXTILEUNITS:
6762 case VUT_UTYPE:
6763 case VUT_UCLASS:
6764 case VUT_MINVETERAN:
6765 case VUT_UNITSTATE:
6766 case VUT_ACTIVITY:
6767 case VUT_MINMOVES:
6768 case VUT_MINHP:
6769 case VUT_AGE:
6770 case VUT_FORM_AGE:
6771 case VUT_ROADFLAG:
6772 case VUT_MINCALFRAG:
6773 case VUT_TERRAIN:
6774 case VUT_EXTRA:
6775 case VUT_GOOD:
6776 case VUT_TERRAINCLASS:
6777 case VUT_TERRFLAG:
6778 case VUT_TERRAINALTER:
6779 case VUT_MINYEAR:
6782 case VUT_TILE_REL:
6783 case VUT_NONE:
6784 case VUT_COUNT:
6785 /* Not implemented. */
6786 break;
6787 }
6788
6789 return FALSE;
6790}
6791
6792/**********************************************************************/
6800{
6801 /* Not known to be impossible to fulfill */
6802 return req->present && universal_never_there(&req->source);
6803}
6804
6805/**********************************************************************/
6813{
6816 return TRUE;
6817 }
6819
6820 /* Not known to be impossible to fulfill */
6821 return FALSE;
6822}
6823
6824/**********************************************************************/
6833 const struct requirement_vector *vec)
6834{
6835 if (vec) {
6836 return 0;
6837 } else {
6838 return -1;
6839 }
6840}
6841
6842/********************************************************************/
6850struct requirement_vector *
6852{
6853 fc_assert_ret_val(number == 0, NULL);
6854 return (struct requirement_vector *)parent_item;
6855}
6856
6857/**********************************************************************/
6867const char *req_vec_change_translation(const struct req_vec_change *change,
6869{
6870 const char *req_vec_description;
6871 static char buf[MAX_LEN_NAME * 3];
6872 struct astring astr;
6873
6874 fc_assert_ret_val(change, NULL);
6876 NULL);
6877
6878 /* Get rid of the previous. */
6879 buf[0] = '\0';
6880
6881 if (namer == NULL) {
6882 /* TRANS: default description of a requirement vector
6883 * (used in ruledit) */
6884 req_vec_description = _("the requirement vector");
6885 } else {
6887 }
6888
6889 switch (change->operation) {
6890 case RVCO_REMOVE:
6891 fc_snprintf(buf, sizeof(buf),
6892 /* TRANS: remove a requirement from a requirement vector
6893 * (in ruledit).
6894 * The first %s is the operation.
6895 * The second %s is the requirement.
6896 * The third %s is a description of the requirement vector,
6897 * like "actor_reqs" */
6898 _("%s %s from %s"),
6900 req_to_fstring(&change->req, &astr),
6902 astr_free(&astr);
6903 break;
6904 case RVCO_APPEND:
6905 fc_snprintf(buf, sizeof(buf),
6906 /* TRANS: append a requirement to a requirement vector
6907 * (in ruledit).
6908 * The first %s is the operation.
6909 * The second %s is the requirement.
6910 * The third %s is a description of the requirement vector,
6911 * like "actor_reqs" */
6912 _("%s %s to %s"),
6914 req_to_fstring(&change->req, &astr),
6916 astr_free(&astr);
6917 break;
6918 case RVCO_NOOP:
6919 fc_snprintf(buf, sizeof(buf),
6920 /* TRANS: do nothing to a requirement vector (in ruledit).
6921 * The first %s is a description of the requirement vector,
6922 * like "actor_reqs" */
6923 _("Do nothing to %s"), req_vec_description);
6924 break;
6925 }
6926
6927 return buf;
6928}
6929
6930/**********************************************************************/
6942 const void *parent_item)
6943{
6944 struct requirement_vector *target
6945 = getter(parent_item, modification->vector_number);
6946 int i = 0;
6947
6948 switch (modification->operation) {
6949 case RVCO_APPEND:
6951 return TRUE;
6952 case RVCO_REMOVE:
6956 return TRUE;
6957 }
6958 i++;
6960 return FALSE;
6961 case RVCO_NOOP:
6962 return FALSE;
6963 }
6964
6965 return FALSE;
6966}
6967
6968/**********************************************************************/
6977struct req_vec_problem *
6979 const char *description,
6980 const char *description_translated)
6981{
6982 struct req_vec_problem *out;
6983 int i;
6984
6985 out = fc_malloc(sizeof(*out));
6986
6987 fc_strlcpy(out->description, description, sizeof(out->description));
6988 fc_strlcpy(out->description_translated, _(description_translated),
6989 sizeof(out->description_translated));
6990
6991 out->num_suggested_solutions = num_suggested_solutions;
6992 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
6993 * sizeof(struct req_vec_change));
6994 for (i = 0; i < out->num_suggested_solutions; i++) {
6995 /* No suggestions are ready yet. */
6996 out->suggested_solutions[i].operation = RVCO_NOOP;
6997 out->suggested_solutions[i].vector_number = -1;
6998 out->suggested_solutions[i].req.source.kind = VUT_NONE;
6999 }
7000
7001 return out;
7002}
7003
7004/**********************************************************************/
7013 const char *descr, ...)
7014{
7015 char description[500];
7016 char description_translated[500];
7017 va_list ap;
7018
7019 va_start(ap, descr);
7020 fc_vsnprintf(description, sizeof(description), descr, ap);
7021 va_end(ap);
7022
7023 va_start(ap, descr);
7025 _(descr), ap);
7026 va_end(ap);
7027
7030}
7031
7032/**********************************************************************/
7038{
7039 FC_FREE(issue->suggested_solutions);
7040 issue->num_suggested_solutions = 0;
7041
7042 FC_FREE(issue);
7043}
7044
7045/**********************************************************************/
7056struct req_vec_problem *
7059 const void *parent_item)
7060{
7061 int i, j;
7063
7064 if (vec == NULL || requirement_vector_size(vec) == 0) {
7065 /* No vector. */
7066 return NULL;
7067 }
7068
7069 if (get_num == NULL || parent_item == NULL) {
7070 vec_num = 0;
7071 } else {
7072 vec_num = get_num(parent_item, vec);
7073 }
7074
7075 /* Look for contradictions */
7076 for (i = 0; i < requirement_vector_size(vec); i++) {
7077 struct requirement *preq = requirement_vector_get(vec, i);
7078 for (j = 0; j < requirement_vector_size(vec); j++) {
7079 struct requirement *nreq = requirement_vector_get(vec, j);
7080
7082 struct req_vec_problem *problem;
7083 struct astring astr;
7084 struct astring nastr;
7085
7087 N_("Requirements {%s} and {%s} contradict each other."),
7089
7090 astr_free(&astr);
7091 astr_free(&nastr);
7092
7093 /* The solution is to remove one of the contradictions. */
7094 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7095 problem->suggested_solutions[0].vector_number = vec_num;
7096 problem->suggested_solutions[0].req = *preq;
7097
7098 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7099 problem->suggested_solutions[1].vector_number = vec_num;
7100 problem->suggested_solutions[1].req = *nreq;
7101
7102 /* Only the first contradiction is reported. */
7103 return problem;
7104 }
7105 }
7106 }
7107
7108 return NULL;
7109}
7110
7111/**********************************************************************/
7121struct req_vec_problem *
7124 const void *parent_item)
7125{
7126 /* Check for self contradictins. */
7128}
7129
7130/**********************************************************************/
7142struct req_vec_problem *
7145 const void *parent_item)
7146{
7147 int i;
7149 struct req_vec_problem *problem = NULL;
7150
7151 if (vec == NULL || requirement_vector_size(vec) == 0) {
7152 /* No vector. */
7153 return NULL;
7154 }
7155
7156 if (get_num == NULL || parent_item == NULL) {
7157 vec_num = 0;
7158 } else {
7159 vec_num = get_num(parent_item, vec);
7160 }
7161
7162 /* Look for contradictions */
7163 for (i = 0; i < requirement_vector_size(vec); i++) {
7164 struct requirement *preq = requirement_vector_get(vec, i);
7165
7166 if (universal_never_there(&preq->source)) {
7167 struct astring astr;
7168
7169 if (preq->present) {
7170 /* The requirement vector can never be fulfilled. Removing the
7171 * requirement makes it possible to fulfill it. This is a rule
7172 * change and shouldn't be "fixed" without thinking. Don't offer any
7173 * automatic solution to prevent mindless "fixes". */
7174 /* TRANS: ruledit warns a user about an unused requirement vector
7175 * that never can be fulfilled because it asks for something that
7176 * never will be there. */
7177 if (problem == NULL) {
7179 N_("Requirement {%s} requires %s but it will never be"
7180 " there."),
7182 astr_free(&astr);
7183 }
7184
7185 /* Continue to check if other problems have a solution proposal,
7186 * and prefer to return those. */
7187 continue;
7188 }
7189
7190 if (problem != NULL) {
7191 /* Free previous one (one with no solution proposals) */
7193 }
7194
7196 N_("Requirement {%s} mentions %s but it will never be there."),
7198
7199 astr_free(&astr);
7200
7201 /* The solution is to remove the reference to the missing
7202 * universal. */
7203 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7204 problem->suggested_solutions[0].vector_number = vec_num;
7205 problem->suggested_solutions[0].req = *preq;
7206
7207 /* Only the first missing universal is reported. */
7208 return problem;
7209 }
7210 }
7211
7212 return problem;
7213}
7214
7215/**********************************************************************/
7227struct req_vec_problem *
7230 const void *parent_item)
7231{
7232 int i, j;
7234
7235 if (vec == NULL || requirement_vector_size(vec) == 0) {
7236 /* No vector. */
7237 return NULL;
7238 }
7239
7240 if (get_num == NULL || parent_item == NULL) {
7241 vec_num = 0;
7242 } else {
7243 vec_num = get_num(parent_item, vec);
7244 }
7245
7246 /* Look for repeated requirements */
7247 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
7248 struct requirement *preq = requirement_vector_get(vec, i);
7249 for (j = i + 1; j < requirement_vector_size(vec); j++) {
7250 struct requirement *nreq = requirement_vector_get(vec, j);
7251
7253 struct req_vec_problem *problem;
7254 struct astring astr;
7255 struct astring nastr;
7256
7258 N_("Requirements {%s} and {%s} are the same."),
7260
7261 astr_free(&astr);
7262 astr_free(&nastr);
7263
7264 /* The solution is to remove one of the redundant requirements. */
7265 problem->suggested_solutions[0].operation = RVCO_REMOVE;
7266 problem->suggested_solutions[0].vector_number = vec_num;
7267 problem->suggested_solutions[0].req = *preq;
7268
7269 problem->suggested_solutions[1].operation = RVCO_REMOVE;
7270 problem->suggested_solutions[1].vector_number = vec_num;
7271 problem->suggested_solutions[1].req = *nreq;
7272
7273 /* Only the first redundancy is reported. */
7274 return problem;
7275 }
7276 }
7277 }
7278
7279 return NULL;
7280}
7281
7282/**********************************************************************/
7293struct req_vec_problem *
7296 const void *parent_item)
7297{
7298 struct req_vec_problem *out;
7299
7301 if (out != NULL) {
7302 /* A bug, not just a potential improvement */
7303 return out;
7304 }
7305
7306 /* Check if a universal that never will appear in the game is checked. */
7308 if (out != NULL) {
7309 return out;
7310 }
7311
7312 /* Check if a requirement is redundant. */
7314 return out;
7315}
7316
7317/**********************************************************************/
7322 const struct universal *psource2)
7323{
7324 if (psource1->kind != psource2->kind) {
7325 return FALSE;
7326 }
7327 switch (psource1->kind) {
7328 case VUT_NONE:
7329 return TRUE;
7330 case VUT_COUNTER:
7331 return psource1->value.counter == psource2->value.counter;
7332 case VUT_ADVANCE:
7333 return psource1->value.advance == psource2->value.advance;
7334 case VUT_TECHFLAG:
7335 return psource1->value.techflag == psource2->value.techflag;
7336 case VUT_GOVERNMENT:
7337 return psource1->value.govern == psource2->value.govern;
7338 case VUT_ACHIEVEMENT:
7339 return psource1->value.achievement == psource2->value.achievement;
7340 case VUT_STYLE:
7341 return psource1->value.style == psource2->value.style;
7342 case VUT_IMPROVEMENT:
7343 case VUT_SITE:
7344 return psource1->value.building == psource2->value.building;
7345 case VUT_IMPR_GENUS:
7346 return psource1->value.impr_genus == psource2->value.impr_genus;
7347 case VUT_IMPR_FLAG:
7348 return psource1->value.impr_flag == psource2->value.impr_flag;
7349 case VUT_PLAYER_FLAG:
7350 return psource1->value.plr_flag == psource2->value.plr_flag;
7351 case VUT_PLAYER_STATE:
7352 return psource1->value.plrstate == psource2->value.plrstate;
7353 case VUT_EXTRA:
7354 return psource1->value.extra == psource2->value.extra;
7355 case VUT_GOOD:
7356 return psource1->value.good == psource2->value.good;
7357 case VUT_TERRAIN:
7358 return psource1->value.terrain == psource2->value.terrain;
7359 case VUT_TERRFLAG:
7360 return psource1->value.terrainflag == psource2->value.terrainflag;
7361 case VUT_NATION:
7362 return psource1->value.nation == psource2->value.nation;
7363 case VUT_NATIONGROUP:
7364 return psource1->value.nationgroup == psource2->value.nationgroup;
7365 case VUT_NATIONALITY:
7366 return psource1->value.nationality == psource2->value.nationality;
7367 case VUT_ORIGINAL_OWNER:
7368 return psource1->value.origowner == psource2->value.origowner;
7369 case VUT_DIPLREL:
7370 case VUT_DIPLREL_TILE:
7371 case VUT_DIPLREL_TILE_O:
7374 return psource1->value.diplrel == psource2->value.diplrel;
7375 case VUT_UTYPE:
7376 return psource1->value.utype == psource2->value.utype;
7377 case VUT_UTFLAG:
7378 return psource1->value.unitflag == psource2->value.unitflag;
7379 case VUT_UCLASS:
7380 return psource1->value.uclass == psource2->value.uclass;
7381 case VUT_UCFLAG:
7382 return psource1->value.unitclassflag == psource2->value.unitclassflag;
7383 case VUT_MINVETERAN:
7384 return psource1->value.minveteran == psource2->value.minveteran;
7385 case VUT_UNITSTATE:
7386 return psource1->value.unit_state == psource2->value.unit_state;
7387 case VUT_ACTIVITY:
7388 return psource1->value.activity == psource2->value.activity;
7389 case VUT_MINMOVES:
7390 return psource1->value.minmoves == psource2->value.minmoves;
7391 case VUT_MINHP:
7392 return psource1->value.min_hit_points == psource2->value.min_hit_points;
7393 case VUT_AGE:
7394 return psource1->value.age == psource2->value.age;
7395 case VUT_FORM_AGE:
7396 return psource1->value.form_age == psource2->value.form_age;
7397 case VUT_MINTECHS:
7398 return psource1->value.min_techs == psource2->value.min_techs;
7399 case VUT_MINCITIES:
7400 return psource1->value.min_cities == psource2->value.min_cities;
7401 case VUT_ACTION:
7402 return (action_number(psource1->value.action)
7403 == action_number(psource2->value.action));
7404 case VUT_OTYPE:
7405 return psource1->value.outputtype == psource2->value.outputtype;
7406 case VUT_SPECIALIST:
7407 return psource1->value.specialist == psource2->value.specialist;
7408 case VUT_MINSIZE:
7409 return psource1->value.minsize == psource2->value.minsize;
7410 case VUT_MINCULTURE:
7411 return psource1->value.minculture == psource2->value.minculture;
7412 case VUT_MINFOREIGNPCT:
7413 return psource1->value.minforeignpct == psource2->value.minforeignpct;
7414 case VUT_AI_LEVEL:
7415 return psource1->value.ai_level == psource2->value.ai_level;
7416 case VUT_MAXTILEUNITS:
7417 return psource1->value.max_tile_units == psource2->value.max_tile_units;
7418 case VUT_TERRAINCLASS:
7419 return psource1->value.terrainclass == psource2->value.terrainclass;
7420 case VUT_ROADFLAG:
7421 return psource1->value.roadflag == psource2->value.roadflag;
7422 case VUT_EXTRAFLAG:
7423 return psource1->value.extraflag == psource2->value.extraflag;
7424 case VUT_MINYEAR:
7425 return psource1->value.minyear == psource2->value.minyear;
7426 case VUT_MINCALFRAG:
7427 return psource1->value.mincalfrag == psource2->value.mincalfrag;
7428 case VUT_TOPO:
7429 return psource1->value.topo_property == psource2->value.topo_property;
7430 case VUT_WRAP:
7431 return psource1->value.wrap_property == psource2->value.wrap_property;
7432 case VUT_SERVERSETTING:
7433 return psource1->value.ssetval == psource2->value.ssetval;
7434 case VUT_TERRAINALTER:
7435 return psource1->value.terrainalter == psource2->value.terrainalter;
7436 case VUT_CITYTILE:
7437 return psource1->value.citytile == psource2->value.citytile;
7438 case VUT_CITYSTATUS:
7439 return psource1->value.citystatus == psource2->value.citystatus;
7440 case VUT_TILE_REL:
7441 return psource1->value.tilerel == psource2->value.tilerel;
7442 case VUT_MINLATITUDE:
7443 case VUT_MAXLATITUDE:
7444 return psource1->value.latitude == psource2->value.latitude;
7446 return psource1->value.distance_sq == psource2->value.distance_sq;
7448 return psource1->value.region_tiles == psource2->value.region_tiles;
7449 case VUT_COUNT:
7450 break;
7451 }
7452
7453 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
7454 return FALSE;
7455}
7456
7457/**********************************************************************/
7461const char *universal_rule_name(const struct universal *psource)
7462{
7463 static char buffer[10];
7464
7465 switch (psource->kind) {
7466 case VUT_NONE:
7467 return "(none)";
7468 case VUT_COUNTER:
7469 return counter_rule_name(psource->value.counter);
7470 case VUT_CITYTILE:
7471 return citytile_type_name(psource->value.citytile);
7472 case VUT_CITYSTATUS:
7473 return citystatus_type_name(psource->value.citystatus);
7474 case VUT_TILE_REL:
7475 return tilerel_type_name(psource->value.tilerel);
7476 case VUT_MINYEAR:
7477 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
7478
7479 return buffer;
7480 case VUT_MINCALFRAG:
7481 /* Rule name is 0-based number, not pretty name from ruleset */
7482 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
7483
7484 return buffer;
7485 case VUT_TOPO:
7486 return topo_flag_name(psource->value.topo_property);
7487 case VUT_WRAP:
7488 return wrap_flag_name(psource->value.wrap_property);
7489 case VUT_SERVERSETTING:
7490 return ssetv_rule_name(psource->value.ssetval);
7491 case VUT_ADVANCE:
7492 return advance_rule_name(psource->value.advance);
7493 case VUT_TECHFLAG:
7494 return tech_flag_id_name(psource->value.techflag);
7495 case VUT_GOVERNMENT:
7496 return government_rule_name(psource->value.govern);
7497 case VUT_ACHIEVEMENT:
7498 return achievement_rule_name(psource->value.achievement);
7499 case VUT_STYLE:
7500 return style_rule_name(psource->value.style);
7501 case VUT_IMPROVEMENT:
7502 case VUT_SITE:
7503 return improvement_rule_name(psource->value.building);
7504 case VUT_IMPR_GENUS:
7505 return impr_genus_id_name(psource->value.impr_genus);
7506 case VUT_IMPR_FLAG:
7507 return impr_flag_id_name(psource->value.impr_flag);
7508 case VUT_PLAYER_FLAG:
7509 return plr_flag_id_name(psource->value.plr_flag);
7510 case VUT_PLAYER_STATE:
7511 return plrstate_type_name(psource->value.plrstate);
7512 case VUT_EXTRA:
7513 return extra_rule_name(psource->value.extra);
7514 case VUT_GOOD:
7515 return goods_rule_name(psource->value.good);
7516 case VUT_TERRAIN:
7517 return terrain_rule_name(psource->value.terrain);
7518 case VUT_TERRFLAG:
7519 return terrain_flag_id_name(psource->value.terrainflag);
7520 case VUT_NATION:
7521 return nation_rule_name(psource->value.nation);
7522 case VUT_NATIONGROUP:
7523 return nation_group_rule_name(psource->value.nationgroup);
7524 case VUT_DIPLREL:
7525 case VUT_DIPLREL_TILE:
7526 case VUT_DIPLREL_TILE_O:
7529 return diplrel_rule_name(psource->value.diplrel);
7530 case VUT_NATIONALITY:
7531 return nation_rule_name(psource->value.nationality);
7532 case VUT_ORIGINAL_OWNER:
7533 return nation_rule_name(psource->value.origowner);
7534 case VUT_UTYPE:
7535 return utype_rule_name(psource->value.utype);
7536 case VUT_UTFLAG:
7537 return unit_type_flag_id_name(psource->value.unitflag);
7538 case VUT_UCLASS:
7539 return uclass_rule_name(psource->value.uclass);
7540 case VUT_UCFLAG:
7541 return unit_class_flag_id_name(psource->value.unitclassflag);
7542 case VUT_MINVETERAN:
7543 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
7544
7545 return buffer;
7546 case VUT_UNITSTATE:
7547 return ustate_prop_name(psource->value.unit_state);
7548 case VUT_ACTIVITY:
7549 return unit_activity_name(psource->value.activity);
7550 case VUT_MINMOVES:
7551 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
7552
7553 return buffer;
7554 case VUT_MINHP:
7555 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
7556
7557 return buffer;
7558 case VUT_AGE:
7559 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
7560
7561 return buffer;
7562 case VUT_FORM_AGE:
7563 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
7564
7565 return buffer;
7566 case VUT_MINTECHS:
7567 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
7568
7569 return buffer;
7570 case VUT_MINCITIES:
7571 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_cities);
7572
7573 return buffer;
7574 case VUT_ACTION:
7575 return action_rule_name(psource->value.action);
7576 case VUT_OTYPE:
7577 return get_output_identifier(psource->value.outputtype);
7578 case VUT_SPECIALIST:
7579 return specialist_rule_name(psource->value.specialist);
7580 case VUT_MINSIZE:
7581 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
7582
7583 return buffer;
7584 case VUT_MINCULTURE:
7585 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
7586
7587 return buffer;
7588 case VUT_MINFOREIGNPCT:
7589 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
7590
7591 return buffer;
7592 case VUT_AI_LEVEL:
7593 return ai_level_name(psource->value.ai_level);
7594 case VUT_MAXTILEUNITS:
7595 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_units);
7596 return buffer;
7597 case VUT_TERRAINCLASS:
7598 return terrain_class_name(psource->value.terrainclass);
7599 case VUT_ROADFLAG:
7600 return road_flag_id_name(psource->value.roadflag);
7601 case VUT_EXTRAFLAG:
7602 return extra_flag_id_name(psource->value.extraflag);
7603 case VUT_TERRAINALTER:
7604 return terrain_alteration_name(psource->value.terrainalter);
7605 case VUT_MINLATITUDE:
7606 case VUT_MAXLATITUDE:
7607 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
7608
7609 return buffer;
7611 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.distance_sq);
7612
7613 return buffer;
7615 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.region_tiles);
7616
7617 return buffer;
7618 case VUT_COUNT:
7619 break;
7620 }
7621
7622 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
7623 return NULL;
7624}
7625
7626/**********************************************************************/
7635 char *buf, size_t bufsz)
7636{
7637 buf[0] = '\0'; /* to be safe. */
7638 switch (psource->kind) {
7639 case VUT_NONE:
7640 /* TRANS: missing value */
7641 fc_strlcat(buf, _("(none)"), bufsz);
7642 return buf;
7643 case VUT_ADVANCE:
7645 return buf;
7646 case VUT_COUNTER:
7648 return buf;
7649 case VUT_TECHFLAG:
7650 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
7651 tech_flag_id_translated_name(psource->value.techflag));
7652 return buf;
7653 case VUT_GOVERNMENT:
7655 bufsz);
7656 return buf;
7657 case VUT_ACHIEVEMENT:
7659 bufsz);
7660 return buf;
7661 case VUT_STYLE:
7663 bufsz);
7664 return buf;
7665 case VUT_IMPROVEMENT:
7667 bufsz);
7668 return buf;
7669 case VUT_SITE:
7670 {
7671 char local_buf[1024];
7672
7673 fc_snprintf(local_buf, sizeof(local_buf), _("%s site"),
7674 improvement_name_translation(psource->value.building));
7676 }
7677
7678 return buf;
7679 case VUT_IMPR_GENUS:
7681 impr_genus_id_translated_name(psource->value.impr_genus),
7682 bufsz);
7683 return buf;
7684 case VUT_IMPR_FLAG:
7686 impr_flag_id_translated_name(psource->value.impr_flag),
7687 bufsz);
7688 return buf;
7689 case VUT_PLAYER_FLAG:
7691 plr_flag_id_translated_name(psource->value.plr_flag),
7692 bufsz);
7693 return buf;
7694 case VUT_PLAYER_STATE:
7696 plrstate_type_translated_name(psource->value.plrstate),
7697 bufsz);
7698 return buf;
7699 case VUT_EXTRA:
7701 return buf;
7702 case VUT_GOOD:
7704 return buf;
7705 case VUT_TERRAIN:
7707 return buf;
7708 case VUT_NATION:
7710 bufsz);
7711 return buf;
7712 case VUT_NATIONGROUP:
7714 bufsz);
7715 return buf;
7716 case VUT_NATIONALITY:
7717 cat_snprintf(buf, bufsz, _("%s citizens"),
7718 nation_adjective_translation(psource->value.nationality));
7719 return buf;
7720 case VUT_ORIGINAL_OWNER:
7721 /* TRANS: Keep short. City founding nation. */
7722 cat_snprintf(buf, bufsz, _("%s original owner"),
7723 nation_adjective_translation(psource->value.origowner));
7724 return buf;
7725 case VUT_DIPLREL:
7726 case VUT_DIPLREL_TILE:
7727 case VUT_DIPLREL_TILE_O:
7731 bufsz);
7732 return buf;
7733 case VUT_UTYPE:
7735 return buf;
7736 case VUT_UTFLAG:
7738 /* TRANS: Unit type flag */
7739 Q_("?utflag:\"%s\" units"),
7741 psource->value.unitflag));
7742 return buf;
7743 case VUT_UCLASS:
7745 /* TRANS: Unit class */
7746 _("%s units"),
7747 uclass_name_translation(psource->value.uclass));
7748 return buf;
7749 case VUT_UCFLAG:
7751 /* TRANS: Unit class flag */
7752 Q_("?ucflag:\"%s\" units"),
7754 psource->value.unitclassflag));
7755 return buf;
7756 case VUT_MINVETERAN:
7757 /* FIXME */
7758 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
7759 psource->value.minveteran);
7760 return buf;
7761 case VUT_UNITSTATE:
7762 switch (psource->value.unit_state) {
7763 case USP_TRANSPORTED:
7764 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7765 cat_snprintf(buf, bufsz, _("Transported"));
7766 break;
7767 case USP_LIVABLE_TILE:
7769 /* TRANS: unit state. (appears in strings like
7770 * "Missile+On livable tile") */
7771 _("On livable tile"));
7772 break;
7773 case USP_TRANSPORTING:
7774 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7775 cat_snprintf(buf, bufsz, _("Transporting"));
7776 break;
7777 case USP_HAS_HOME_CITY:
7778 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
7779 cat_snprintf(buf, bufsz, _("Has a home city"));
7780 break;
7781 case USP_NATIVE_TILE:
7783 /* TRANS: unit state. (appears in strings like
7784 * "Missile+On native tile") */
7785 _("On native tile"));
7786 break;
7787 case USP_NATIVE_EXTRA:
7789 /* TRANS: unit state. (appears in strings like
7790 * "Missile+In native extra") */
7791 _("In native extra"));
7792 break;
7794 /* TRANS: unit state. (appears in strings like
7795 * "Missile+Has moved this turn") */
7796 cat_snprintf(buf, bufsz, _("Has moved this turn"));
7797 break;
7798 case USP_COUNT:
7799 fc_assert_msg(psource->value.unit_state != USP_COUNT,
7800 "Invalid unit state property.");
7801 break;
7802 }
7803 return buf;
7804 case VUT_ACTIVITY:
7805 cat_snprintf(buf, bufsz, _("%s activity"),
7806 Q_(unit_activity_name(psource->value.activity)));
7807 return buf;
7808 case VUT_MINMOVES:
7809 /* TRANS: Minimum unit movement points left for requirement to be met
7810 * (%s is a string like "1" or "2 1/3") */
7811 cat_snprintf(buf, bufsz, _("%s MP"),
7812 move_points_text(psource->value.minmoves, TRUE));
7813 return buf;
7814 case VUT_MINHP:
7815 /* TRANS: HP = hit points */
7816 cat_snprintf(buf, bufsz, _("%d HP"),
7817 psource->value.min_hit_points);
7818 return buf;
7819 case VUT_AGE:
7820 cat_snprintf(buf, bufsz, _("Age %d"),
7821 psource->value.age);
7822 return buf;
7823 case VUT_FORM_AGE:
7824 cat_snprintf(buf, bufsz, _("Form age %d"),
7825 psource->value.form_age);
7826 return buf;
7827 case VUT_MINTECHS:
7828 cat_snprintf(buf, bufsz, _("%d Techs"),
7829 psource->value.min_techs);
7830 return buf;
7831 case VUT_MINCITIES:
7832 cat_snprintf(buf, bufsz, _("%d Cities"),
7833 psource->value.min_cities);
7834 return buf;
7835 case VUT_ACTION:
7837 bufsz);
7838 return buf;
7839 case VUT_OTYPE:
7840 /* FIXME */
7841 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
7842 return buf;
7843 case VUT_SPECIALIST:
7845 bufsz);
7846 return buf;
7847 case VUT_MINSIZE:
7848 cat_snprintf(buf, bufsz, _("Size %d"),
7849 psource->value.minsize);
7850 return buf;
7851 case VUT_MINCULTURE:
7852 cat_snprintf(buf, bufsz, _("Culture %d"),
7853 psource->value.minculture);
7854 return buf;
7855 case VUT_MINFOREIGNPCT:
7856 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
7857 psource->value.minforeignpct);
7858 return buf;
7859 case VUT_AI_LEVEL:
7860 /* TRANS: "Hard AI" */
7861 cat_snprintf(buf, bufsz, _("%s AI"),
7862 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
7863 return buf;
7864 case VUT_MAXTILEUNITS:
7865 /* TRANS: here <= means 'less than or equal' */
7866 cat_snprintf(buf, bufsz, PL_("<=%d unit",
7867 "<=%d units", psource->value.max_tile_units),
7868 psource->value.max_tile_units);
7869 return buf;
7870 case VUT_TERRAINCLASS:
7871 /* TRANS: Terrain class: "Land terrain" */
7872 cat_snprintf(buf, bufsz, _("%s terrain"),
7873 terrain_class_name_translation(psource->value.terrainclass));
7874 return buf;
7875 case VUT_TERRFLAG:
7877 /* TRANS: Terrain flag */
7878 Q_("?terrflag:\"%s\" terrain"),
7880 psource->value.terrainflag));
7881 return buf;
7882 case VUT_ROADFLAG:
7884 /* TRANS: Road flag */
7885 Q_("?roadflag:\"%s\" road"),
7886 road_flag_id_translated_name(psource->value.roadflag));
7887 return buf;
7888 case VUT_EXTRAFLAG:
7890 /* TRANS: Extra flag */
7891 Q_("?extraflag:\"%s\" extra"),
7892 extra_flag_id_translated_name(psource->value.extraflag));
7893 return buf;
7894 case VUT_MINYEAR:
7895 cat_snprintf(buf, bufsz, _("After %s"),
7896 textyear(psource->value.minyear));
7897 return buf;
7898 case VUT_MINCALFRAG:
7899 /* TRANS: here >= means 'greater than or equal'.
7900 * %s identifies a calendar fragment (may be bare number). */
7901 cat_snprintf(buf, bufsz, _(">=%s"),
7902 textcalfrag(psource->value.mincalfrag));
7903 return buf;
7904 case VUT_TOPO:
7905 /* TRANS: topology flag name ("Hex", "ISO") */
7906 cat_snprintf(buf, bufsz, _("%s map"),
7907 _(topo_flag_name(psource->value.topo_property)));
7908 return buf;
7909 case VUT_WRAP:
7910 /* TRANS: wrap flag name ("WrapX", "WrapY") */
7911 cat_snprintf(buf, bufsz, _("%s map"),
7912 _(wrap_flag_name(psource->value.wrap_property)));
7913 return buf;
7914 case VUT_SERVERSETTING:
7916 bufsz);
7917 return buf;
7918 case VUT_TERRAINALTER:
7919 /* TRANS: "Irrigation possible" */
7920 cat_snprintf(buf, bufsz, _("%s possible"),
7921 Q_(terrain_alteration_name(psource->value.terrainalter)));
7922 return buf;
7923 case VUT_CITYTILE:
7924 switch (psource->value.citytile) {
7925 case CITYT_CENTER:
7926 fc_strlcat(buf, _("City center"), bufsz);
7927 break;
7928 case CITYT_CLAIMED:
7929 fc_strlcat(buf, _("Tile claimed"), bufsz);
7930 break;
7931 case CITYT_EXTRAS_OWNED:
7932 fc_strlcat(buf, _("Extras owned"), bufsz);
7933 break;
7934 case CITYT_WORKED:
7935 fc_strlcat(buf, _("Worked tile"), bufsz);
7936 break;
7938 fc_strlcat(buf, _("Same continent tile"), bufsz);
7939 break;
7941 /* TRANS: Short for "a tile of other terrain class mass near city" */
7942 fc_strlcat(buf, _("Port reachable tile"), bufsz);
7943 break;
7944 case CITYT_LAST:
7945 fc_assert(psource->value.citytile != CITYT_LAST);
7946 fc_strlcat(buf, "error", bufsz);
7947 break;
7948 }
7949 return buf;
7950 case VUT_CITYSTATUS:
7951 switch (psource->value.citystatus) {
7953 fc_strlcat(buf, _("Owned by original"), bufsz);
7954 break;
7955 case CITYS_STARVED:
7956 fc_strlcat(buf, _("Starved"), bufsz);
7957 break;
7958 case CITYS_DISORDER:
7959 fc_strlcat(buf, _("Disorder"), bufsz);
7960 break;
7961 case CITYS_CELEBRATION:
7962 fc_strlcat(buf, _("Celebration"), bufsz);
7963 break;
7964 case CITYS_TRANSFERRED:
7965 /* TRANS: CityStatus value - city has changed hands */
7966 fc_strlcat(buf, _("Transferred"), bufsz);
7967 break;
7968 case CITYS_LAST:
7969 fc_assert(psource->value.citystatus != CITYS_LAST);
7970 fc_strlcat(buf, "error", bufsz);
7971 break;
7972 }
7973 return buf;
7974 case VUT_TILE_REL:
7975 switch (psource->value.tilerel) {
7976 case TREL_SAME_TCLASS:
7977 fc_strlcat(buf, _("Same terrain class"), bufsz);
7978 break;
7979 case TREL_SAME_REGION:
7980 fc_strlcat(buf, _("Same continent/ocean"), bufsz);
7981 break;
7983 fc_strlcat(buf, _("Only other continent/ocean"), bufsz);
7984 break;
7986 fc_strlcat(buf, _("Lake/island surrounded"), bufsz);
7987 break;
7988 case TREL_COUNT:
7989 fc_assert(psource->value.tilerel != TREL_COUNT);
7990 fc_strlcat(buf, "error", bufsz);
7991 break;
7992 }
7993 return buf;
7994 case VUT_MINLATITUDE:
7995 /* TRANS: here >= means 'greater than or equal'. */
7996 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
7997 psource->value.latitude);
7998 return buf;
7999 case VUT_MAXLATITUDE:
8000 /* TRANS: here <= means 'less than or equal'. */
8001 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
8002 psource->value.latitude);
8003 return buf;
8005 /* TRANS: here <= means 'less than or equal'. */
8006 cat_snprintf(buf, bufsz, _("Squared distance <= %d"),
8007 psource->value.distance_sq);
8008 return buf;
8010 cat_snprintf(buf, bufsz, _("%d or fewer region tiles"),
8011 psource->value.region_tiles);
8012 return buf;
8013 case VUT_COUNT:
8014 break;
8015 }
8016
8017 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
8018 return buf;
8019}
8020
8021/**********************************************************************/
8025{
8026 return universals_n_name(psource->kind);
8027}
8028
8029/**********************************************************************/
8033 const struct universal *target)
8034{
8035 switch (target->kind) {
8036 case VUT_IMPROVEMENT:
8037 case VUT_SITE:
8038 return impr_build_shield_cost(pcity, target->value.building);
8039 case VUT_UTYPE:
8040 return utype_build_shield_cost(pcity, NULL, target->value.utype);
8041 default:
8042 break;
8043 }
8044 return FC_INFINITY;
8045}
8046
8047/**********************************************************************/
8053 const struct universal *to_replace,
8054 const struct universal *replacement)
8055{
8056 bool changed = FALSE;
8057
8060 preq->source = *replacement;
8061 changed = TRUE;
8062 }
8064
8065 return changed;
8066}
8067
8068/**********************************************************************/
8073 const struct requirement_vector *reqs,
8074 const struct universal *psource)
8075{
8078 return TRUE;
8079 }
8081
8082 return FALSE;
8083}
8084
8085/**********************************************************************/
8095 struct universal *unis,
8096 size_t n_unis)
8097{
8098 int i;
8099
8100 for (i = 0; i < n_unis; i++) {
8102 /* This universal makes it impossible to fulfill the specified
8103 * requirement vector */
8104 return TRUE;
8105 }
8106 }
8107
8108 /* No specified universal is known to guarantee that the requirement
8109 * vector never will be fulfilled. */
8110 return FALSE;
8111}
8112
8113/**********************************************************************/
8128 struct universal *unis,
8129 size_t n_unis)
8130{
8132 int i;
8134
8135 for (i = 0; i < n_unis; i++) {
8136 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
8137 case ITF_NO:
8138 case ITF_YES:
8139 /* this req matched this source */
8141 break;
8142 case ITF_NOT_APPLICABLE:
8143 /* Not a mention. */
8144 break;
8145 }
8146 }
8147
8149 /* A requirement not relevant to any of the specified universals was
8150 * found in the requirement vector. */
8151 return FALSE;
8152 }
8154
8155 /* No requirement not relevant to any of the specified universals was
8156 * found in the requirement vector. */
8157 return TRUE;
8158}
8159
8160/**********************************************************************/
8163enum req_item_found
8165 const struct universal *source)
8166{
8169 "No req item found function for %s",
8171
8172 return (*universal_found_function[source->kind])(preq, source);
8173}
8174
8175/**********************************************************************/
8186 const struct requirement_vector *reqs,
8187 const struct universal *source)
8188{
8189 bool necessary = FALSE;
8190
8193 "No req item found function for %s",
8195
8197 switch ((*universal_found_function[source->kind])(preq, source)) {
8198 case ITF_NOT_APPLICABLE:
8199 continue;
8200 case ITF_NO:
8201 if (preq->present) {
8202 return FALSE;
8203 }
8204 break;
8205 case ITF_YES:
8206 if (preq->present) {
8207 necessary = TRUE;
8208 } else {
8209 return FALSE;
8210 }
8211 break;
8212 }
8214
8215 return (!check_necessary || necessary);
8216}
8217
8218/**********************************************************************/
8223 const struct universal *source)
8224{
8225 switch (universal_fulfills_requirement(req, source)) {
8226 case ITF_NOT_APPLICABLE:
8227 return FALSE;
8228 case ITF_NO:
8229 case ITF_YES:
8230 return TRUE;
8231 }
8232
8233 log_error("Unhandled item_found value");
8234 return FALSE;
8235}
8236
8237/**********************************************************************/
8241 const struct universal *source)
8242{
8243 fc_assert(source->value.nation);
8244
8245 switch (preq->source.kind) {
8246 case VUT_NATION:
8247 return preq->source.value.nation == source->value.nation ? ITF_YES
8248 : ITF_NO;
8249 case VUT_NATIONGROUP:
8250 return nation_is_in_group(source->value.nation,
8251 preq->source.value.nationgroup) ? ITF_YES
8252 : ITF_NO;
8253 default:
8254 break;
8255 }
8256
8257 return ITF_NOT_APPLICABLE;
8258}
8259
8260/**********************************************************************/
8264 const struct universal *source)
8265{
8266 fc_assert(source->value.govern);
8267
8268 if (preq->source.kind == VUT_GOVERNMENT) {
8269 return preq->source.value.govern == source->value.govern ? ITF_YES
8270 : ITF_NO;
8271 }
8272
8273 return ITF_NOT_APPLICABLE;
8274}
8275
8276/**********************************************************************/
8280 const struct universal *source)
8281{
8282 fc_assert(source->value.min_cities);
8283
8284 if (preq->source.kind == VUT_MINCITIES) {
8285 return preq->source.value.min_cities <= source->value.min_cities ? ITF_YES
8286 : ITF_NO;
8287 }
8288
8289 return ITF_NOT_APPLICABLE;
8290}
8291
8292/**********************************************************************/
8296 const struct universal *source)
8297{
8298 fc_assert(source->value.building);
8299
8300 /* We only ever return ITF_YES, because requiring a different
8301 * improvement does not mean that the improvement under consideration
8302 * cannot fulfill the requirements. This is necessary to allow
8303 * requirement vectors to specify multiple required improvements. */
8304
8305 switch (preq->source.kind) {
8306 case VUT_IMPROVEMENT:
8307 case VUT_SITE:
8308 if (source->value.building == preq->source.value.building) {
8309 return ITF_YES;
8310 }
8311 break;
8312 case VUT_IMPR_GENUS:
8313 if (source->value.building->genus == preq->source.value.impr_genus) {
8314 return ITF_YES;
8315 }
8316 break;
8317 case VUT_IMPR_FLAG:
8318 if (improvement_has_flag(source->value.building,
8319 preq->source.value.impr_flag)) {
8320 return ITF_YES;
8321 }
8322 break;
8323 default:
8324 break;
8325 }
8326
8327 return ITF_NOT_APPLICABLE;
8328}
8329
8330/**********************************************************************/
8334 const struct universal *source)
8335{
8336 fc_assert(source->value.uclass);
8337
8338 switch (preq->source.kind) {
8339 case VUT_UCLASS:
8340 return source->value.uclass == preq->source.value.uclass ? ITF_YES
8341 : ITF_NO;
8342 case VUT_UCFLAG:
8343 return uclass_has_flag(source->value.uclass,
8344 preq->source.value.unitclassflag) ? ITF_YES
8345 : ITF_NO;
8346
8347 default:
8348 /* Not found and not relevant. */
8349 return ITF_NOT_APPLICABLE;
8350 };
8351}
8352
8353/**********************************************************************/
8357 const struct universal *source)
8358{
8359 fc_assert(source->value.utype);
8360
8361 switch (preq->source.kind) {
8362 case VUT_UTYPE:
8363 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
8364 case VUT_UCLASS:
8365 return utype_class(source->value.utype) == preq->source.value.uclass
8366 ? ITF_YES : ITF_NO;
8367 case VUT_UTFLAG:
8368 return utype_has_flag(source->value.utype,
8369 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
8370 case VUT_UCFLAG:
8371 return uclass_has_flag(utype_class(source->value.utype),
8372 preq->source.value.unitclassflag) ? ITF_YES
8373 : ITF_NO;
8374 default:
8375 /* Not found and not relevant. */
8376 return ITF_NOT_APPLICABLE;
8377 };
8378}
8379
8380/**********************************************************************/
8383static enum req_item_found
8385 const struct universal *source)
8386{
8389
8390 switch (preq->source.kind) {
8391 case VUT_ACTIVITY:
8392 return source->value.activity == preq->source.value.activity ? ITF_YES
8393 : ITF_NO;
8394 default:
8395 /* Not found and not relevant. */
8396 return ITF_NOT_APPLICABLE;
8397 };
8398}
8399
8400/**********************************************************************/
8404 const struct universal *source)
8405{
8406 fc_assert(source->value.terrain);
8407
8408 switch (preq->source.kind) {
8409 case VUT_TERRAIN:
8410 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
8411 case VUT_TERRAINCLASS:
8412 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
8413 ? ITF_YES : ITF_NO;
8414 case VUT_TERRFLAG:
8415 return terrain_has_flag(source->value.terrain,
8416 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
8417 case VUT_TERRAINALTER:
8418 return (terrain_can_support_alteration(source->value.terrain,
8419 preq->source.value.terrainalter)
8420 ? ITF_YES : ITF_NO);
8421 default:
8422 /* Not found and not relevant. */
8423 return ITF_NOT_APPLICABLE;
8424 };
8425}
8426
8427/**********************************************************************/
8431 const struct universal *source)
8432{
8435
8436 switch (preq->source.kind) {
8437 case VUT_CITYTILE:
8438 return (source->value.citytile == preq->source.value.citytile
8439 ? ITF_YES
8440 /* The presence of one tile state doesn't block another */
8442 default:
8443 /* Not found and not relevant. */
8444 return ITF_NOT_APPLICABLE;
8445 };
8446}
8447
8448/**********************************************************************/
8452 const struct universal *source)
8453{
8454 fc_assert(source->value.extra);
8455
8456 switch (preq->source.kind) {
8457 case VUT_EXTRA:
8458 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
8459 case VUT_EXTRAFLAG:
8460 return extra_has_flag(source->value.extra,
8461 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
8462 case VUT_ROADFLAG:
8463 {
8464 struct road_type *r = extra_road_get(source->value.extra);
8465 return r && road_has_flag(r, preq->source.value.roadflag)
8466 ? ITF_YES : ITF_NO;
8467 }
8468 default:
8469 /* Not found and not relevant. */
8470 return ITF_NOT_APPLICABLE;
8471 }
8472}
8473
8474/**********************************************************************/
8478 const struct universal *source)
8479{
8480 fc_assert(source->value.action);
8481
8482 if (preq->source.kind == VUT_ACTION) {
8483 return preq->source.value.action == source->value.action ? ITF_YES
8484 : ITF_NO;
8485 }
8486
8487 return ITF_NOT_APPLICABLE;
8488}
8489
8490/**********************************************************************/
8494 const struct universal *source)
8495{
8497 || source->kind == VUT_DIPLREL_TILE
8498 || source->kind == VUT_DIPLREL_TILE_O
8499 || source->kind == VUT_DIPLREL_UNITANY
8500 || source->kind == VUT_DIPLREL_UNITANY_O),
8502
8503 if (preq->source.kind == source->kind) {
8504 if (preq->source.value.diplrel == source->value.diplrel) {
8505 /* The diplrel itself. */
8506 return ITF_YES;
8507 }
8508 if (preq->source.value.diplrel == DRO_FOREIGN
8509 && source->value.diplrel < DS_LAST) {
8510 /* All diplstate_type values are to foreigners. */
8511 return ITF_YES;
8512 }
8513 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
8514 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
8515 /* A real embassy is an embassy. */
8516 return ITF_YES;
8517 }
8518 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
8519 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
8520 /* A real embassy is an embassy. */
8521 return ITF_YES;
8522 }
8523 if (preq->source.value.diplrel < DS_LAST
8524 && source->value.diplrel < DS_LAST
8525 && preq->range == REQ_RANGE_LOCAL) {
8526 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
8527 ITF_YES);
8528 /* Can only have one diplstate_type to a specific player. */
8529 return ITF_NO;
8530 }
8531 /* Can't say this diplrel blocks the other diplrel. */
8532 return ITF_NOT_APPLICABLE;
8533 }
8534
8535 /* Not relevant. */
8536 return ITF_NOT_APPLICABLE;
8537}
8538
8539/**********************************************************************/
8543 const struct universal *source)
8544{
8545 switch (preq->source.kind) {
8546 case VUT_OTYPE:
8547 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
8548 : ITF_NO;
8549 default:
8550 /* Not found and not relevant. */
8551 return ITF_NOT_APPLICABLE;
8552 }
8553}
8554
8555/**********************************************************************/
8559 const struct universal *source)
8560{
8561 if (preq->range != REQ_RANGE_LOCAL) {
8562 return ITF_NOT_APPLICABLE;
8563 }
8564
8565 if (preq->source.kind == VUT_UNITSTATE) {
8566 switch (source->value.unit_state) {
8567 case USP_TRANSPORTED:
8568 case USP_TRANSPORTING:
8569 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
8570 case USP_LIVABLE_TILE:
8571 case USP_NATIVE_TILE:
8572 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
8573 * UTYF_COAST_STRICT. */
8574 case USP_HAS_HOME_CITY:
8575 case USP_NATIVE_EXTRA:
8577 if (source->value.unit_state == preq->source.value.unit_state) {
8578 /* The other unit states doesn't contradict */
8579 return ITF_YES;
8580 }
8581 break;
8582 case USP_COUNT:
8583 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
8585 }
8586 }
8587
8588 /* Not found and not relevant. */
8589 return ITF_NOT_APPLICABLE;
8590}
8591
8592/**********************************************************************/
8617
8618/**********************************************************************/
8626int requirement_kind_ereq(const int value,
8627 const enum req_range range,
8628 const bool present,
8629 const int max_value)
8630{
8631 /* The enumerators in each range starts with present for every possible
8632 * value followed by !present for every possible value. */
8633 const int pres_start = (present ? 0 : max_value);
8634
8635 /* The enumerators for every range follows all the positions of the
8636 * previous range(s). */
8637 const int range_start = ((max_value - 1) * 2) * range;
8638
8639 return range_start + pres_start + value;
8640}
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
struct achievement * achievement_by_number(int id)
int achievement_number(const struct achievement *pach)
const char * achievement_rule_name(struct achievement *pach)
struct achievement * achievement_by_rule_name(const char *name)
const char * achievement_name_translation(struct achievement *pach)
bool achievement_claimed(const struct achievement *pach)
const char * action_name_translation(const struct action *paction)
Definition actions.c:1230
bool action_is_in_use(struct action *paction)
Definition actions.c:5676
struct action * action_by_rule_name(const char *name)
Definition actions.c:1079
const char * action_rule_name(const struct action *action)
Definition actions.c:1216
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1239
int action_number(const struct action *action)
Definition actions.c:1208
static struct action * action_by_number(action_id act_id)
Definition actions.h:396
#define ACTION_NONE
Definition actions.h:55
void astr_free(struct astring *astr)
Definition astring.c:148
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:251
void astr_init(struct astring *astr)
Definition astring.c:139
#define n
Definition astring.c:77
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
const char * textcalfrag(int frag)
Definition calendar.c:101
const char * textyear(int year)
Definition calendar.c:121
citizens citizens_nation_foreign(const struct city *pcity)
Definition citizens.c:91
#define citizens_iterate_end
Definition citizens.h:54
#define citizens_iterate(_pcity, _pslot, _nationality)
Definition citizens.h:48
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:1240
Output_type_id output_type_by_identifier(const char *id)
Definition city.c:647
const char * get_output_identifier(Output_type_id output)
Definition city.c:619
const char * get_output_name(Output_type_id output)
Definition city.c:629
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
#define city_tile(_pcity_)
Definition city.h:561
static citizens city_size_get(const struct city *pcity)
Definition city.h:566
#define city_owner(_pcity_)
Definition city.h:560
static bool is_city_center(const struct city *pcity, const struct tile *ptile)
Definition city.h:865
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:227
#define city_tile_iterate_end
Definition city.h:235
#define city_built_iterate(_pcity, _p)
Definition city.h:831
#define city_built_iterate_end
Definition city.h:837
char * incite_cost
Definition comments.c:76
int counter_index(const struct counter *pcount)
Definition counters.c:174
const char * counter_name_translation(const struct counter *counter)
Definition counters.c:157
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:115
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:165
struct counter * counter_by_id(int id)
Definition counters.c:82
int counter_id(struct counter *pcount)
Definition counters.c:105
int city_culture(const struct city *pcity)
Definition culture.c:29
int player_culture(const struct player *plr)
Definition culture.c:49
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:56
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:57
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
struct @22::@23 reqs
int get_world_bonus(enum effect_type effect_type)
Definition effects.c:812
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
bool extra_flag_is_in_use(enum extra_flag_id id)
Definition extras.c:1001
bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:904
bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:884
bool is_extra_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:379
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:875
bool is_extra_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:363
struct extra_type * extra_by_number(int id)
Definition extras.c:183
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:194
#define extra_road_get(_e_)
Definition extras.h:191
static bool is_server(void)
int Tech_type_id
Definition fc_types.h:236
req_problem_type
Definition fc_types.h:531
@ RPT_POSSIBLE
Definition fc_types.h:532
#define MAX_LEN_NAME
Definition fc_types.h:66
@ VC_SPACERACE
Definition fc_types.h:979
@ O_LAST
Definition fc_types.h:101
signed short Continent_id
Definition fc_types.h:231
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
struct civ_game game
Definition game.c:61
struct world wld
Definition game.c:62
const char * government_name_translation(const struct government *pgovern)
Definition government.c:143
struct government * government_by_number(const Government_type_id gov)
Definition government.c:103
struct government * government_of_player(const struct player *pplayer)
Definition government.c:114
Government_type_id government_number(const struct government *pgovern)
Definition government.c:91
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
struct government * government_by_rule_name(const char *name)
Definition government.c:55
struct city * owner
Definition citydlg.c:226
static GtkWidget * source
Definition gotodlg.c:58
GType type
Definition repodlgs.c:1313
static const int bufsz
Definition helpdlg.c:70
struct impr_type * improvement_by_number(const Impr_type_id id)
bool great_wonder_is_built(const struct impr_type *pimprove)
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
bool wonder_is_built(const struct player *pplayer, const struct impr_type *pimprove)
Impr_type_id improvement_number(const struct impr_type *pimprove)
bool can_improvement_go_obsolete(const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
struct city * city_from_wonder(const struct player *pplayer, const struct impr_type *pimprove)
int impr_build_shield_cost(const struct city *pcity, const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
bool improvement_obsolete(const struct player *pplayer, const struct impr_type *pimprove, const struct city *pcity)
bool improvement_has_flag(const struct impr_type *pimprove, enum impr_flag_id flag)
struct impr_type * improvement_by_rule_name(const char *name)
const char * improvement_name_translation(const struct impr_type *pimprove)
bool great_wonder_is_available(const struct impr_type *pimprove)
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition log.h:209
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:686
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:1067
int map_signed_latitude(const struct tile *ptile)
Definition map.c:1692
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:1076
int get_island_surrounder(Continent_id id)
Definition map.c:842
int get_lake_surrounder(Continent_id id)
Definition map.c:875
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:699
#define current_topo_has_flag(flag)
Definition map.h:43
#define range_adjc_iterate(nmap, center_tile, range, itr_tile)
Definition map.h:498
#define MAP_MAX_LATITUDE
Definition map.h:602
#define adjc_iterate_end
Definition map.h:430
#define MAP_MAX_REAL_LATITUDE(_nmap)
Definition map.h:614
#define range_adjc_iterate_end
Definition map.h:501
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:388
#define cardinal_adjc_iterate_end
Definition map.h:456
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:425
#define is_whole_continent_known(cont)
Definition map.h:78
#define square_iterate_end
Definition map.h:391
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:452
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:398
#define current_wrap_has_flag(flag)
Definition map.h:46
#define is_whole_ocean_known(ocean)
Definition map.h:82
#define MAP_MIN_REAL_LATITUDE(_nmap)
Definition map.h:616
#define circle_iterate_end
Definition map.h:401
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
const char * move_points_text(int mp, bool reduce)
Definition movement.c:1016
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:318
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:330
struct nation_group * nation_group_by_rule_name(const char *name)
Definition nation.c:1021
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:486
const char * nation_adjective_translation(const struct nation_type *pnation)
Definition nation.c:149
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:475
const char * nation_group_rule_name(const struct nation_group *pgroup)
Definition nation.c:1079
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
bool nation_is_in_group(const struct nation_type *pnation, const struct nation_group *pgroup)
Definition nation.c:1099
const char * nation_group_name_translation(const struct nation_group *pgroup)
Definition nation.c:1090
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
struct nation_group * nation_group_by_number(int id)
Definition nation.c:1004
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:952
#define NO_NATION_SELECTED
Definition nation.h:30
bool player_knows_techs_with_flag(const struct player *pplayer, enum tech_flag_id flag)
Definition player.c:1328
bool player_has_state(const struct player *pplayer, enum plrstate_type state)
Definition player.c:2004
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Definition player.c:1829
int diplrel_by_rule_name(const char *value)
Definition player.c:1585
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1480
bool is_diplrel_to_other(const struct player *pplayer, int diplrel)
Definition player.c:1566
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1996
const char * diplrel_name_translation(int value)
Definition player.c:1631
bool is_diplrel_between(const struct player *player1, const struct player *player2, int diplrel)
Definition player.c:1516
int player_age(const struct player *pplayer)
Definition player.c:954
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1409
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:437
const char * diplrel_rule_name(int value)
Definition player.c:1619
#define players_iterate_end
Definition player.h:542
#define players_iterate(_pplayer)
Definition player.h:537
#define player_nation(_plr_)
Definition player.h:408
#define is_ai(plr)
Definition player.h:232
#define players_iterate_alive_end
Definition player.h:552
#define players_iterate_alive(_pplayer)
Definition player.h:547
static enum req_item_found terrain_type_found(const struct requirement *preq, const struct universal *source)
bool universal_never_there(const struct universal *source)
static enum fc_tristate is_unitclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unitflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_relevant_to_requirement(const struct requirement *req, const struct universal *source)
#define EXTRACT_INFO(req)
bool is_req_in_vec(const struct requirement *req, const struct requirement_vector *vec)
int universal_build_shield_cost(const struct city *pcity, const struct universal *target)
static enum fc_tristate is_terrainflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found city_tile_found(const struct requirement *preq, const struct universal *source)
struct req_vec_problem * req_vec_get_first_contradiction(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static universal_found universal_found_function[VUT_COUNT]
static enum req_unchanging_status unchanging_local(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
#define REQUC_CITYSTATUS
const struct req_context * req_context_empty(void)
static enum fc_tristate is_action_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found unit_type_found(const struct requirement *preq, const struct universal *source)
void universal_extraction(const struct universal *source, int *kind, int *value)
static int num_player_buildings(const struct player *pplayer, const struct impr_type *building)
static enum fc_tristate is_tech_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_none_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static int num_continent_buildings(const struct player *pplayer, int continent, const struct impr_type *building)
static enum fc_tristate is_minveteran_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * req_to_fstring(const struct requirement *req, struct astring *astr)
static enum fc_tristate is_counter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
req_vec_num_in_item req_vec_vector_number(const void *parent_item, const struct requirement_vector *vec)
static bool present_implies_not_present(const struct requirement *req1, const struct requirement *req2)
enum fc_tristate tri_req_active(const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct requirement_vector * req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
bool universal_fulfills_requirements(bool check_necessary, const struct requirement_vector *reqs, const struct universal *source)
static bool activity_is_valid_in_requirement(enum unit_activity act)
enum fc_tristate tri_reqs_cb_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, struct requirement_vector *maybe_reqs, req_tester_cb tester, void *data, int n_data)
static enum fc_tristate is_minsize_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_ai_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_noally(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_max_distance_sq_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_vec_change_apply(const struct req_vec_change *modification, requirement_vector_by_number getter, const void *parent_item)
void universal_copy(struct universal *dst, const struct universal *src)
static enum fc_tristate is_minculture_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_building(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_terrain_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_requirements_equal(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_minforeignpct_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_minyear_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found extra_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_buildingflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_in_range(const struct tile *target_tile, const struct player *other_player, enum req_range range, int diplrel)
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
struct requirement req_from_str(const char *type, const char *range, bool survives, bool present, bool quiet, const char *value)
struct req_vec_problem * req_vec_suggest_repair(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum fc_tristate is_wrap_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void universal_value_from_str(struct universal *source, const char *value)
static enum fc_tristate is_buildingflag_in_city(const struct city *pcity, enum impr_flag_id flag)
static enum fc_tristate is_latitude_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_get_values(const struct requirement *req, int *type, int *range, bool *survives, bool *present, bool *quiet, int *value)
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
static enum fc_tristate is_nationality_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * universal_rule_name(const struct universal *psource)
static enum req_unchanging_status unchanging_present(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
bool universal_replace_in_req_vec(struct requirement_vector *reqs, const struct universal *to_replace, const struct universal *replacement)
static enum req_item_found action_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_minmovefrags_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_requirements_contradictions(const struct requirement *req1, const struct requirement *req2)
#define REQUC_IMPR
static enum fc_tristate is_maxunitsontile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct req_vec_problem * req_vec_problem_new(int num_suggested_solutions, const char *descr,...)
static enum fc_tristate is_buildinggenus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_in_range(const struct player *target_player, const struct player *other_player, enum req_range range, int diplrel)
static enum fc_tristate is_mintechs_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool is_req_active(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, const enum req_problem_type prob_type)
static enum fc_tristate is_originalowner_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool are_bounds_contradictions(int bound1, bool is_upper1, int bound2, bool is_upper2)
static enum fc_tristate is_diplrel_tile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_legal_in_requirement(const struct universal *univ)
enum fc_tristate default_tester_cb(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, void *data, int n_data)
static enum fc_tristate tri_req_present(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
int requirement_kind_ereq(const int value, const enum req_range range, const bool present, const int max_value)
static enum fc_tristate is_achievement_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_vec_problem_free(struct req_vec_problem *issue)
static struct req_def req_definitions[VUT_COUNT]
static bool impr_contra_flag(const struct requirement *impr_req, const struct requirement *flag_req)
bool are_reqs_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
static enum req_item_found improvement_found(const struct requirement *preq, const struct universal *source)
struct req_vec_problem * req_vec_get_first_missing_univ(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum req_item_found mincities_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_extraflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum req_unchanging_status is_req_preventing(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, enum req_problem_type prob_type)
static enum fc_tristate is_plr_state_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool players_in_same_range(const struct player *pplayer1, const struct player *pplayer2, enum req_range range)
enum req_item_found(* universal_found)(const struct requirement *, const struct universal *)
static enum fc_tristate is_terrainclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct universal universal_by_number(const enum universals_n kind, const int value)
static enum fc_tristate is_roadflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum req_item_found universal_fulfills_requirement(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_building_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_reqs_active_ranges(const enum req_range min_range, const enum req_range max_range, const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
static enum fc_tristate is_gov_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_tile_o_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_good_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unitstate_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool city_center_contra(const struct requirement *cc_req, const struct requirement *ct_req)
static enum req_item_found ustate_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_terrainalter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_unittype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_vec_wants_type(const struct requirement_vector *reqs, enum universals_n kind)
static int num_world_buildings_total(const struct impr_type *building)
static enum req_unchanging_status unchanging_citytile(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum req_item_found output_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_citystatus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_tile_rel_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct req_vec_problem * req_vec_get_first_redundant_req(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum fc_tristate is_mincities_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool is_city_in_tile(const struct tile *ptile, const struct city *pcity)
bool does_req_contradicts_reqs(const struct requirement *req, const struct requirement_vector *vec)
static enum req_item_found government_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate does_region_surrounder_match(Continent_id cont, Continent_id surrounder)
static enum fc_tristate is_extra_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_unchanging_status unchanging_world(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_mincalfrag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_activity_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
static enum fc_tristate is_max_region_tiles_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
struct req_vec_problem * req_vec_problem_new_transl(int num_suggested_solutions, const char *description, const char *description_translated)
static enum fc_tristate is_nationgroup_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define REQUC_NALLY
static enum req_item_found unit_activity_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_minhitpoints_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
enum fc_tristate tri_req_active_turns(int pass, int period, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_outputtype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
#define REQUC_LOCAL
bool universals_say_everything(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
static enum fc_tristate is_unitclassflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found nation_found(const struct requirement *preq, const struct universal *source)
#define REQUC_WORLD
const char * universal_type_rule_name(const struct universal *psource)
#define REQUC_PRESENT
void universal_found_functions_init(void)
static enum fc_tristate is_style_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found unit_class_found(const struct requirement *preq, const struct universal *source)
#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind)
int universal_number(const struct universal *source)
static enum fc_tristate is_techflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool universal_is_mentioned_by_requirements(const struct requirement_vector *reqs, const struct universal *psource)
#define REQUC_CITYTILE
static enum fc_tristate is_citytile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum req_item_found diplrel_found(const struct requirement *preq, const struct universal *source)
bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
bool req_implies_req(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_specialist_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
void req_copy(struct requirement *dst, const struct requirement *src)
enum req_unchanging_status is_req_unchanging(const struct req_context *context, const struct requirement *req)
static bool player_has_ever_built(const struct player *pplayer, const struct impr_type *building)
enum fc_tristate(* is_req_active_cb)(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static bool nation_contra_group(const struct requirement *nation_req, const struct requirement *group_req)
static enum fc_tristate is_serversetting_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_plr_flag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_nation_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
bool req_is_impossible_to_fulfill(const struct requirement *req)
static bool are_tiles_in_range(const struct tile *tile1, const struct tile *tile2, enum req_range range)
static bool are_requirements_opposites(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_form_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static int num_world_buildings(const struct impr_type *building)
static enum req_unchanging_status unchanging_citystatus(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_topology_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_o_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
struct universal universal_by_rule_name(const char *kind, const char *value)
bool universals_mean_unfulfilled(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
struct req_vec_problem * req_vec_suggest_improvement(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static bool impr_contra_genus(const struct requirement *impr_req, const struct requirement *genus_req)
enum fc_tristate(* req_tester_cb)(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, void *data, int n_data)
#define requirement_diplrel_ereq(_id_, _range_, _present_)
signed char req_vec_num_in_item
req_vec_num_in_item a requirement vectors number in an item.
req_vec_num_in_item(* requirement_vector_number)(const void *parent_item, const struct requirement_vector *vec)
const char *(* requirement_vector_namer)(req_vec_num_in_item number)
#define universal_is_mentioned_by_requirement(preq, psource)
enum req_unchanging_status(* req_unchanging_cond_cb)(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
#define requirement_vector_iterate_end
struct universal universal_by_number(const enum universals_n kind, const int value)
struct requirement_vector *(* requirement_vector_by_number)(const void *parent_item, req_vec_num_in_item number)
#define requirement_vector_iterate(req_vec, preq)
req_item_found
@ ITF_NO
@ ITF_YES
@ ITF_NOT_APPLICABLE
req_unchanging_status
@ REQUCH_ACT
@ REQUCH_NO
@ REQUCH_SCRIPTS
@ REQUCH_YES
@ REQUCH_HACK
@ REQUCH_CTRL
struct research * research_get(const struct player *pplayer)
Definition research.c:128
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:619
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Definition road.c:416
bool is_road_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:446
bool is_road_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:425
bool ssetv_setting_has_value(ssetv val)
ssetv ssetv_by_rule_name(const char *name)
const char * ssetv_rule_name(ssetv val)
const char * ssetv_human_readable(ssetv val, bool present)
#define SSETV_NONE
enum fc_tristate fc_tristate_or(enum fc_tristate one, enum fc_tristate two)
Definition shared.c:143
fc_tristate
Definition shared.h:46
@ TRI_YES
Definition shared.h:46
@ TRI_NO
Definition shared.h:46
@ TRI_MAYBE
Definition shared.h:46
#define BOOL_TO_TRISTATE(tri)
Definition shared.h:47
#define FC_INFINITY
Definition shared.h:36
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c:112
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:100
Specialist_type_id specialist_number(const struct specialist *sp)
Definition specialist.c:91
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
const char * specialist_plural_translation(const struct specialist *sp)
Definition specialist.c:155
Definition city.h:317
struct packet_game_info info
Definition game.h:89
struct packet_calendar_info calendar
Definition game.h:90
int checkpoint
Definition counters.h:33
struct player * player
Definition nation.h:118
bool global_advances[A_LAST]
bool is_alive
Definition player.h:268
enum req_unchanging_status unchanging
req_unchanging_cond_cb unchanging_cond
const is_req_active_cb cb
req_vec_num_in_item vector_number
enum req_vec_change_operation operation
struct requirement req
char description[500]
char description_translated[500]
enum req_range range
struct universal source
Tech_type_id researching
Definition research.h:52
int techs_researched
Definition research.h:42
Definition tile.h:50
struct tile * tile
Definition unit.h:142
const struct unit_type * utype
Definition unit.h:141
enum universals_n kind
Definition fc_types.h:608
universals_u value
Definition fc_types.h:607
struct civ_map map
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
struct nation_style * style_by_number(int id)
Definition style.c:88
const char * style_name_translation(const struct nation_style *pstyle)
Definition style.c:99
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:108
int style_number(const struct nation_style *pstyle)
Definition style.c:68
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:822
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define bool
Definition support.h:71
#define fc__fallthrough
Definition support.h:119
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag)
Definition tech.c:216
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:300
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:309
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:186
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:612
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:591
const char * terrain_class_name_translation(enum terrain_class tclass)
Definition terrain.c:661
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:238
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:156
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Definition terrain.c:673
bool is_terrain_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:327
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:582
bool is_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:458
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:147
bool is_terrain_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:438
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:348
#define T_UNKNOWN
Definition terrain.h:62
#define terrain_has_flag(terr, flag)
Definition terrain.h:176
bool tile_has_extra_flag(const struct tile *ptile, enum extra_flag_id flag)
Definition tile.c:886
bool tile_has_native_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:324
bool tile_has_road_flag(const struct tile *ptile, enum road_flag_id flag)
Definition tile.c:868
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_terrain(_tile)
Definition tile.h:111
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
#define tile_owner(_tile)
Definition tile.h:97
bool goods_can_be_provided(const struct city *pcity, const struct goods_type *pgood, const struct unit *punit)
Goods_type_id goods_number(const struct goods_type *pgood)
bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
const char * goods_name_translation(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
#define trade_partners_iterate_end
#define trade_partners_iterate(c, p)
const struct unit_type * utype
Definition fc_types.h:553
int region_tiles
Definition fc_types.h:597
struct nation_style * style
Definition fc_types.h:557
enum ai_level ai_level
Definition fc_types.h:561
struct specialist * specialist
Definition fc_types.h:550
enum impr_genus_id impr_genus
Definition fc_types.h:584
enum citytile_type citytile
Definition fc_types.h:562
struct nation_group * nationgroup
Definition fc_types.h:556
struct extra_type * extra
Definition fc_types.h:554
enum wrap_flag wrap_property
Definition fc_types.h:600
enum plrstate_type plrstate
Definition fc_types.h:564
enum tilerel_type tilerel
Definition fc_types.h:565
struct nation_type * nation
Definition fc_types.h:547
int terrainclass
Definition fc_types.h:572
int unitclassflag
Definition fc_types.h:574
struct government * govern
Definition fc_types.h:545
struct nation_type * origowner
Definition fc_types.h:549
enum impr_flag_id impr_flag
Definition fc_types.h:585
int max_tile_units
Definition fc_types.h:588
int terrainalter
Definition fc_types.h:573
enum citystatus_type citystatus
Definition fc_types.h:563
int minforeignpct
Definition fc_types.h:568
const struct impr_type * building
Definition fc_types.h:546
struct achievement * achievement
Definition fc_types.h:555
ssetv ssetval
Definition fc_types.h:601
struct advance * advance
Definition fc_types.h:543
enum unit_activity activity
Definition fc_types.h:583
struct goods_type * good
Definition fc_types.h:559
struct terrain * terrain
Definition fc_types.h:551
int terrainflag
Definition fc_types.h:576
enum ustate_prop unit_state
Definition fc_types.h:582
Output_type_id outputtype
Definition fc_types.h:571
int distance_sq
Definition fc_types.h:596
enum topo_flag topo_property
Definition fc_types.h:599
struct counter * counter
Definition fc_types.h:544
int min_hit_points
Definition fc_types.h:590
struct unit_class * uclass
Definition fc_types.h:552
struct nation_type * nationality
Definition fc_types.h:548
struct action * action
Definition fc_types.h:558
enum plr_flag_id plr_flag
Definition fc_types.h:586
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1820
#define unit_tile(_pu)
Definition unit.h:404
#define unit_owner(_pu)
Definition unit.h:403
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const char * uclass_name_translation(const struct unit_class *pclass)
Definition unittype.c:1638
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
bool unit_has_class_flag(const struct unit *punit, enum unit_class_flag_id flag)
Definition unittype.c:1655
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1773
bool uclass_flag_is_in_use(enum unit_class_flag_id ucflag)
Definition unittype.c:2987
struct unit_class * uclass_by_number(const Unit_Class_id id)
Definition unittype.c:2483
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1584
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2505
struct unit_type * utype_by_number(const Unit_type_id id)
Definition unittype.c:112
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:196
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1647
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:1790
bool utype_flag_is_in_use(enum unit_type_flag_id uflag)
Definition unittype.c:3006
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1444
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2474
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1566
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:773
#define utype_class(_t_)
Definition unittype.h:756
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
bool victory_enabled(enum victory_condition_type victory)
Definition victory.c:26