Freeciv-3.2
Loading...
Searching...
No Matches
requirements.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2004 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17#include <stdarg.h>
18
19/* utility */
20#include "astring.h"
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "achievements.h"
27#include "calendar.h"
28#include "citizens.h"
29#include "counters.h"
30#include "culture.h"
31#include "game.h"
32#include "government.h"
33#include "improvement.h"
34#include "movement.h"
35#include "nation.h"
36#include "player.h"
37#include "map.h"
38#include "research.h"
39#include "road.h"
40#include "server_settings.h"
41#include "specialist.h"
42#include "style.h"
43#include "victory.h" /* victory_enabled() */
44
45#include "requirements.h"
46
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 player *other_player,
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 player *other_player,
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_ACTION:
477 source->value.action = action_by_rule_name(value);
478 if (source->value.action != NULL) {
479 return;
480 }
481 break;
482 case VUT_OTYPE:
483 source->value.outputtype = output_type_by_identifier(value);
484 if (source->value.outputtype != O_LAST) {
485 return;
486 }
487 break;
488 case VUT_SPECIALIST:
489 source->value.specialist = specialist_by_rule_name(value);
490 if (source->value.specialist) {
491 return;
492 }
493 break;
494 case VUT_MINSIZE:
495 source->value.minsize = atoi(value);
496 if (source->value.minsize > 0) {
497 return;
498 }
499 break;
500 case VUT_MINCULTURE:
501 source->value.minculture = atoi(value);
502 if (source->value.minculture > 0) {
503 return;
504 }
505 break;
507 source->value.minforeignpct = atoi(value);
508 if (source->value.minforeignpct > 0) {
509 return;
510 }
511 break;
512 case VUT_AI_LEVEL:
513 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
514 if (ai_level_is_valid(source->value.ai_level)) {
515 return;
516 }
517 break;
518 case VUT_MAXTILEUNITS:
519 source->value.max_tile_units = atoi(value);
520 if (0 <= source->value.max_tile_units) {
521 return;
522 }
523 break;
524 case VUT_TERRAINCLASS:
525 source->value.terrainclass
527 if (terrain_class_is_valid(source->value.terrainclass)) {
528 return;
529 }
530 break;
531 case VUT_ROADFLAG:
533 if (road_flag_id_is_valid(source->value.roadflag)) {
534 return;
535 }
536 break;
537 case VUT_EXTRAFLAG:
538 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
539 if (extra_flag_id_is_valid(source->value.extraflag)) {
540 return;
541 }
542 break;
543 case VUT_MINYEAR:
544 source->value.minyear = atoi(value);
545 return;
546 case VUT_MINCALFRAG:
547 /* Rule names are 0-based numbers, not pretty names from ruleset */
548 source->value.mincalfrag = atoi(value);
549 if (source->value.mincalfrag >= 0) {
550 /* More range checking done later, in sanity_check_req_individual() */
551 return;
552 }
553 break;
554 case VUT_TOPO:
555 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
556 if (topo_flag_is_valid(source->value.topo_property)) {
557 return;
558 }
559 break;
560 case VUT_WRAP:
561 source->value.wrap_property = wrap_flag_by_name(value, fc_strcasecmp);
562 if (wrap_flag_is_valid(source->value.wrap_property)) {
563 return;
564 }
565 break;
567 source->value.ssetval = ssetv_by_rule_name(value);
568 if (source->value.ssetval != SSETV_NONE) {
569 return;
570 }
571 break;
572 case VUT_TERRAINALTER:
573 source->value.terrainalter
575 if (terrain_alteration_is_valid(source->value.terrainalter)) {
576 return;
577 }
578 break;
579 case VUT_CITYTILE:
581 if (source->value.citytile != CITYT_LAST) {
582 return;
583 }
584 break;
585 case VUT_CITYSTATUS:
587 if (source->value.citystatus != CITYS_LAST) {
588 return;
589 }
590 break;
591 case VUT_PLAYER_STATE:
593 if (source->value.plrstate != PLRS_LAST) {
594 return;
595 }
596 break;
597 case VUT_MINLATITUDE:
598 case VUT_MAXLATITUDE:
599 source->value.latitude = atoi(value);
600 if (source->value.latitude >= -MAP_MAX_LATITUDE
601 && source->value.latitude <= MAP_MAX_LATITUDE) {
602 return;
603 }
604 break;
605 case VUT_COUNTER:
606 source->value.counter = counter_by_rule_name(value);
607 if (source->value.counter != NULL) {
608 return;
609 }
610 break;
611 case VUT_COUNT:
612 break;
613 }
614
615 /* If we reach here there's been an error. */
617}
618
619/**********************************************************************/
626{
627 struct universal source;
628
629 source.kind = kind;
630
631 switch (source.kind) {
632 case VUT_NONE:
633 /* Avoid compiler warning about unitialized source.value */
634 source.value.advance = NULL;
635
636 return source;
637 case VUT_ADVANCE:
638 source.value.advance = advance_by_number(value);
639 if (source.value.advance != NULL) {
640 return source;
641 }
642 break;
643 case VUT_TECHFLAG:
644 source.value.techflag = value;
645 return source;
646 case VUT_GOVERNMENT:
648 if (source.value.govern != NULL) {
649 return source;
650 }
651 break;
652 case VUT_ACHIEVEMENT:
653 source.value.achievement = achievement_by_number(value);
654 if (source.value.achievement != NULL) {
655 return source;
656 }
657 break;
658 case VUT_STYLE:
659 source.value.style = style_by_number(value);
660 if (source.value.style != NULL) {
661 return source;
662 }
663 break;
664 case VUT_IMPROVEMENT:
665 case VUT_SITE:
666 source.value.building = improvement_by_number(value);
667 if (source.value.building != NULL) {
668 return source;
669 }
670 break;
671 case VUT_IMPR_GENUS:
672 source.value.impr_genus = value;
673 return source;
674 case VUT_IMPR_FLAG:
675 source.value.impr_flag = value;
676 return source;
677 case VUT_PLAYER_FLAG:
678 source.value.plr_flag = value;
679 return source;
680 case VUT_EXTRA:
682 return source;
683 case VUT_GOOD:
684 source.value.good = goods_by_number(value);
685 return source;
686 case VUT_TERRAIN:
687 source.value.terrain = terrain_by_number(value);
688 if (source.value.terrain != NULL) {
689 return source;
690 }
691 break;
692 case VUT_TERRFLAG:
693 source.value.terrainflag = value;
694 return source;
695 case VUT_NATION:
697 if (source.value.nation != NULL) {
698 return source;
699 }
700 break;
701 case VUT_NATIONGROUP:
702 source.value.nationgroup = nation_group_by_number(value);
703 if (source.value.nationgroup != NULL) {
704 return source;
705 }
706 break;
707 case VUT_DIPLREL:
708 case VUT_DIPLREL_TILE:
712 source.value.diplrel = value;
713 if (source.value.diplrel != diplrel_other_invalid()) {
714 return source;
715 }
716 break;
717 case VUT_NATIONALITY:
719 if (source.value.nationality != NULL) {
720 return source;
721 }
722 break;
724 source.value.origowner = nation_by_number(value);
725 if (source.value.origowner != NULL) {
726 return source;
727 }
728 break;
729 case VUT_UTYPE:
730 source.value.utype = utype_by_number(value);
731 if (source.value.utype != NULL) {
732 return source;
733 }
734 break;
735 case VUT_UTFLAG:
736 source.value.unitflag = value;
737 return source;
738 case VUT_UCLASS:
740 if (source.value.uclass != NULL) {
741 return source;
742 }
743 break;
744 case VUT_UCFLAG:
745 source.value.unitclassflag = value;
746 return source;
747 case VUT_MINVETERAN:
748 source.value.minveteran = value;
749 return source;
750 case VUT_UNITSTATE:
751 source.value.unit_state = value;
752 return source;
753 case VUT_ACTIVITY:
754 source.value.activity = value;
755 return source;
756 case VUT_MINMOVES:
757 source.value.minmoves = value;
758 return source;
759 case VUT_MINHP:
761 return source;
762 case VUT_AGE:
763 source.value.age = value;
764 return source;
765 case VUT_FORM_AGE:
766 source.value.form_age = value;
767 return source;
768 case VUT_MINTECHS:
769 source.value.min_techs = value;
770 return source;
771 case VUT_ACTION:
773 if (source.value.action != NULL) {
774 return source;
775 }
776 break;
777 case VUT_OTYPE:
778 source.value.outputtype = value;
779 return source;
780 case VUT_SPECIALIST:
782 return source;
783 case VUT_MINSIZE:
784 source.value.minsize = value;
785 return source;
786 case VUT_MINCULTURE:
787 source.value.minculture = value;
788 return source;
790 source.value.minforeignpct = value;
791 return source;
792 case VUT_AI_LEVEL:
793 source.value.ai_level = value;
794 return source;
795 case VUT_MAXTILEUNITS:
797 return source;
798 case VUT_TERRAINCLASS:
799 source.value.terrainclass = value;
800 return source;
801 case VUT_ROADFLAG:
802 source.value.roadflag = value;
803 return source;
804 case VUT_EXTRAFLAG:
805 source.value.extraflag = value;
806 return source;
807 case VUT_MINYEAR:
808 source.value.minyear = value;
809 return source;
810 case VUT_MINCALFRAG:
811 source.value.mincalfrag = value;
812 return source;
813 case VUT_TOPO:
814 source.value.topo_property = value;
815 return source;
816 case VUT_WRAP:
817 source.value.wrap_property = value;
818 return source;
820 source.value.ssetval = value;
821 return source;
822 case VUT_TERRAINALTER:
823 source.value.terrainalter = value;
824 return source;
825 case VUT_CITYTILE:
826 source.value.citytile = value;
827 return source;
828 case VUT_CITYSTATUS:
829 source.value.citystatus = value;
830 return source;
831 case VUT_PLAYER_STATE:
832 source.value.plrstate = value;
833 return source;
834 case VUT_COUNTER:
836 return source;
837 case VUT_MINLATITUDE:
838 case VUT_MAXLATITUDE:
839 source.value.latitude = value;
840 return source;
841 case VUT_COUNT:
842 break;
843 }
844
845 /* If we reach here there's been an error. */
847 /* Avoid compiler warning about unitialized source.value */
848 source.value.advance = NULL;
849
850 return source;
851}
852
853/**********************************************************************/
856void universal_copy(struct universal *dst, const struct universal *src)
857{
858 dst->value = src->value;
859 dst->kind = src->kind;
860}
861
862/**********************************************************************/
867 int *kind, int *value)
868{
869 *kind = source->kind;
871}
872
873/**********************************************************************/
877{
878 switch (source->kind) {
879 case VUT_NONE:
880 return 0;
881 case VUT_ADVANCE:
882 return advance_number(source->value.advance);
883 case VUT_TECHFLAG:
884 return source->value.techflag;
885 case VUT_GOVERNMENT:
886 return government_number(source->value.govern);
887 case VUT_ACHIEVEMENT:
888 return achievement_number(source->value.achievement);
889 case VUT_STYLE:
890 return style_number(source->value.style);
891 case VUT_IMPROVEMENT:
892 case VUT_SITE:
893 return improvement_number(source->value.building);
894 case VUT_IMPR_GENUS:
895 return source->value.impr_genus;
896 case VUT_IMPR_FLAG:
897 return source->value.impr_flag;
898 case VUT_PLAYER_FLAG:
899 return source->value.plr_flag;
900 case VUT_EXTRA:
901 return extra_number(source->value.extra);
902 case VUT_GOOD:
903 return goods_number(source->value.good);
904 case VUT_TERRAIN:
905 return terrain_number(source->value.terrain);
906 case VUT_TERRFLAG:
907 return source->value.terrainflag;
908 case VUT_NATION:
909 return nation_number(source->value.nation);
910 case VUT_NATIONGROUP:
911 return nation_group_number(source->value.nationgroup);
912 case VUT_NATIONALITY:
913 return nation_number(source->value.nationality);
915 return nation_number(source->value.origowner);
916 case VUT_DIPLREL:
917 case VUT_DIPLREL_TILE:
921 return source->value.diplrel;
922 case VUT_UTYPE:
923 return utype_number(source->value.utype);
924 case VUT_UTFLAG:
925 return source->value.unitflag;
926 case VUT_UCLASS:
927 return uclass_number(source->value.uclass);
928 case VUT_UCFLAG:
929 return source->value.unitclassflag;
930 case VUT_MINVETERAN:
931 return source->value.minveteran;
932 case VUT_UNITSTATE:
933 return source->value.unit_state;
934 case VUT_ACTIVITY:
935 return source->value.activity;
936 case VUT_MINMOVES:
937 return source->value.minmoves;
938 case VUT_MINHP:
939 return source->value.min_hit_points;
940 case VUT_AGE:
941 return source->value.age;
942 case VUT_FORM_AGE:
943 return source->value.form_age;
944 case VUT_MINTECHS:
945 return source->value.min_techs;
946 case VUT_ACTION:
947 return action_number(source->value.action);
948 case VUT_OTYPE:
949 return source->value.outputtype;
950 case VUT_SPECIALIST:
951 return specialist_number(source->value.specialist);
952 case VUT_MINSIZE:
953 return source->value.minsize;
954 case VUT_MINCULTURE:
955 return source->value.minculture;
957 return source->value.minforeignpct;
958 case VUT_AI_LEVEL:
959 return source->value.ai_level;
960 case VUT_MAXTILEUNITS:
961 return source->value.max_tile_units;
962 case VUT_TERRAINCLASS:
963 return source->value.terrainclass;
964 case VUT_ROADFLAG:
965 return source->value.roadflag;
966 case VUT_EXTRAFLAG:
967 return source->value.extraflag;
968 case VUT_MINYEAR:
969 return source->value.minyear;
970 case VUT_MINCALFRAG:
971 return source->value.mincalfrag;
972 case VUT_TOPO:
973 return source->value.topo_property;
974 case VUT_WRAP:
975 return source->value.wrap_property;
977 return source->value.ssetval;
978 case VUT_TERRAINALTER:
979 return source->value.terrainalter;
980 case VUT_CITYTILE:
981 return source->value.citytile;
982 case VUT_CITYSTATUS:
983 return source->value.citystatus;
984 case VUT_PLAYER_STATE:
985 return source->value.plrstate;
986 case VUT_COUNTER:
987 return counter_id(source->value.counter);
988 case VUT_MINLATITUDE:
989 case VUT_MAXLATITUDE:
990 return source->value.latitude;
991 case VUT_COUNT:
992 break;
993 }
994
995 /* If we reach here there's been an error. */
996 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
997 source->kind);
998 return 0;
999}
1000
1001
1002/**********************************************************************/
1006{
1007 static const struct req_context empty = {};
1008 return &empty;
1009}
1010
1011
1012/**********************************************************************/
1020const char *req_to_fstring(const struct requirement *req,
1021 struct astring *astr)
1022{
1023 astr_init(astr);
1024
1025 astr_set(astr, "%s%s %s %s%s",
1026 req->survives ? "surviving " : "",
1027 req_range_name(req->range),
1029 req->present ? "" : "!",
1031
1032 return astr_str(astr);
1033}
1034
1035/**********************************************************************/
1043 bool survives, bool present, bool quiet,
1044 const char *value)
1045{
1046 struct requirement req;
1047 bool invalid;
1048 const char *error = NULL;
1049
1050 req.source = universal_by_rule_name(type, value);
1051
1053 if (invalid) {
1054 error = "bad type or name";
1055 } else {
1056 /* Scan the range string to find the range. If no range is given a
1057 * default fallback is used rather than giving an error. */
1058 if (range != NULL) {
1060 if (!req_range_is_valid(req.range)) {
1061 invalid = TRUE;
1062 }
1063 } else {
1064 switch (req.source.kind) {
1065 case VUT_NONE:
1066 case VUT_COUNT:
1067 break;
1068 case VUT_IMPROVEMENT:
1069 case VUT_SITE:
1070 case VUT_IMPR_GENUS:
1071 case VUT_IMPR_FLAG:
1072 case VUT_UTYPE:
1073 case VUT_UTFLAG:
1074 case VUT_UCLASS:
1075 case VUT_UCFLAG:
1076 case VUT_MINVETERAN:
1077 case VUT_UNITSTATE:
1078 case VUT_ACTIVITY:
1079 case VUT_MINMOVES:
1080 case VUT_MINHP:
1081 case VUT_AGE:
1082 case VUT_FORM_AGE:
1083 case VUT_ACTION:
1084 case VUT_OTYPE:
1085 case VUT_SPECIALIST:
1086 case VUT_DIPLREL_TILE_O:
1088 req.range = REQ_RANGE_LOCAL;
1089 break;
1090 case VUT_EXTRA:
1091 case VUT_ROADFLAG:
1092 case VUT_EXTRAFLAG:
1093 /* keep old behavior */
1094 req.range = REQ_RANGE_TILE;
1095 break;
1096 case VUT_TERRAIN:
1097 case VUT_TERRFLAG:
1098 case VUT_TERRAINCLASS:
1099 case VUT_TERRAINALTER:
1100 case VUT_CITYTILE:
1101 case VUT_MAXTILEUNITS:
1102 case VUT_MINLATITUDE:
1103 case VUT_MAXLATITUDE:
1104 req.range = REQ_RANGE_TILE;
1105 break;
1106 case VUT_COUNTER:
1107 case VUT_MINSIZE:
1108 case VUT_MINCULTURE:
1109 case VUT_MINFOREIGNPCT:
1110 case VUT_NATIONALITY:
1111 case VUT_ORIGINAL_OWNER:
1112 case VUT_CITYSTATUS:
1113 case VUT_GOOD:
1114 req.range = REQ_RANGE_CITY;
1115 break;
1116 case VUT_GOVERNMENT:
1117 case VUT_ACHIEVEMENT:
1118 case VUT_STYLE:
1119 case VUT_ADVANCE:
1120 case VUT_TECHFLAG:
1121 case VUT_NATION:
1122 case VUT_NATIONGROUP:
1123 case VUT_DIPLREL:
1124 case VUT_DIPLREL_TILE:
1126 case VUT_AI_LEVEL:
1127 case VUT_PLAYER_FLAG:
1128 case VUT_PLAYER_STATE:
1129 req.range = REQ_RANGE_PLAYER;
1130 break;
1131 case VUT_MINYEAR:
1132 case VUT_MINCALFRAG:
1133 case VUT_TOPO:
1134 case VUT_WRAP:
1135 case VUT_MINTECHS:
1136 case VUT_SERVERSETTING:
1137 req.range = REQ_RANGE_WORLD;
1138 break;
1139 }
1140 }
1141
1142 req.survives = survives;
1143 req.present = present;
1144 req.quiet = quiet;
1145
1146 /* These checks match what combinations are supported inside
1147 * is_req_active(). However, it's only possible to do basic checks,
1148 * not anything that might depend on the rest of the ruleset which
1149 * might not have been loaded yet. */
1150 switch (req.source.kind) {
1151 case VUT_TERRAIN:
1152 case VUT_TERRAINCLASS:
1153 case VUT_TERRFLAG:
1154 invalid = (req.range != REQ_RANGE_TILE
1155 && req.range != REQ_RANGE_CADJACENT
1156 && req.range != REQ_RANGE_ADJACENT
1157 && req.range != REQ_RANGE_CITY
1158 && req.range != REQ_RANGE_TRADE_ROUTE);
1159 break;
1160 case VUT_EXTRA:
1161 case VUT_ROADFLAG:
1162 case VUT_EXTRAFLAG:
1164 break;
1165 case VUT_ADVANCE:
1166 case VUT_TECHFLAG:
1167 case VUT_ACHIEVEMENT:
1168 case VUT_MINTECHS:
1169 invalid = (req.range < REQ_RANGE_PLAYER);
1170 break;
1171 case VUT_GOVERNMENT:
1172 case VUT_AI_LEVEL:
1173 case VUT_STYLE:
1174 invalid = (req.range != REQ_RANGE_PLAYER);
1175 break;
1176 case VUT_MINSIZE:
1177 case VUT_MINFOREIGNPCT:
1178 case VUT_NATIONALITY:
1179 case VUT_CITYSTATUS:
1180 invalid = (req.range != REQ_RANGE_CITY
1181 && req.range != REQ_RANGE_TRADE_ROUTE);
1182 break;
1183 case VUT_GOOD:
1184 case VUT_ORIGINAL_OWNER:
1185 invalid = (req.range != REQ_RANGE_CITY);
1186 break;
1187 case VUT_MINCULTURE:
1188 invalid = (req.range != REQ_RANGE_CITY
1190 && req.range != REQ_RANGE_PLAYER
1191 && req.range != REQ_RANGE_TEAM
1192 && req.range != REQ_RANGE_ALLIANCE
1193 && req.range != REQ_RANGE_WORLD);
1194 break;
1195 case VUT_DIPLREL:
1196 invalid = (req.range != REQ_RANGE_LOCAL
1197 && req.range != REQ_RANGE_PLAYER
1198 && req.range != REQ_RANGE_TEAM
1199 && req.range != REQ_RANGE_ALLIANCE
1200 && req.range != REQ_RANGE_WORLD)
1201 /* Non local foreign makes no sense. */
1202 || (req.source.value.diplrel == DRO_FOREIGN
1203 && req.range != REQ_RANGE_LOCAL);
1204 break;
1205 case VUT_DIPLREL_TILE:
1206 invalid = (req.range != REQ_RANGE_LOCAL
1207 && req.range != REQ_RANGE_PLAYER
1208 && req.range != REQ_RANGE_TEAM
1209 && req.range != REQ_RANGE_ALLIANCE)
1210 /* Non local foreign makes no sense. */
1211 || (req.source.value.diplrel == DRO_FOREIGN
1212 && req.range != REQ_RANGE_LOCAL);
1213 break;
1214 case VUT_DIPLREL_TILE_O:
1215 invalid = (req.range != REQ_RANGE_LOCAL);
1216 break;
1218 invalid = (req.range != REQ_RANGE_LOCAL
1219 && req.range != REQ_RANGE_PLAYER
1220 && req.range != REQ_RANGE_TEAM
1221 && req.range != REQ_RANGE_ALLIANCE)
1222 /* Non local foreign makes no sense. */
1223 || (req.source.value.diplrel == DRO_FOREIGN
1224 && req.range != REQ_RANGE_LOCAL);
1225 break;
1227 invalid = (req.range != REQ_RANGE_LOCAL);
1228 break;
1229 case VUT_NATION:
1230 case VUT_NATIONGROUP:
1232 && req.range != REQ_RANGE_TEAM
1233 && req.range != REQ_RANGE_ALLIANCE
1234 && req.range != REQ_RANGE_WORLD);
1235 break;
1236 case VUT_UTYPE:
1237 case VUT_UTFLAG:
1238 case VUT_UCLASS:
1239 case VUT_UCFLAG:
1240 case VUT_MINVETERAN:
1241 case VUT_UNITSTATE:
1242 case VUT_ACTIVITY:
1243 case VUT_MINMOVES:
1244 case VUT_MINHP:
1245 case VUT_ACTION:
1246 case VUT_OTYPE:
1247 case VUT_SPECIALIST:
1248 invalid = (req.range != REQ_RANGE_LOCAL);
1249 break;
1250 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1251 invalid = (req.range != REQ_RANGE_TILE);
1252 break;
1253 case VUT_CITYTILE:
1254 case VUT_MAXTILEUNITS:
1255 invalid = (req.range != REQ_RANGE_TILE
1256 && req.range != REQ_RANGE_CADJACENT
1257 && req.range != REQ_RANGE_ADJACENT);
1258 break;
1259 case VUT_MINLATITUDE:
1260 case VUT_MAXLATITUDE:
1261 invalid = (req.range != REQ_RANGE_TILE
1262 && req.range != REQ_RANGE_CADJACENT
1263 && req.range != REQ_RANGE_ADJACENT
1264 && req.range != REQ_RANGE_WORLD)
1265 /* Avoid redundancy at tile range: no negated requirements
1266 * that could be emulated by a present requirement of the
1267 * other type */
1268 || (req.range == REQ_RANGE_TILE && !req.present);
1269 break;
1270 case VUT_MINYEAR:
1271 case VUT_MINCALFRAG:
1272 case VUT_TOPO:
1273 case VUT_WRAP:
1274 case VUT_SERVERSETTING:
1275 invalid = (req.range != REQ_RANGE_WORLD);
1276 break;
1277 case VUT_AGE:
1278 /* FIXME: could support TRADE_ROUTE, TEAM, etc */
1279 invalid = (req.range != REQ_RANGE_LOCAL
1280 && req.range != REQ_RANGE_CITY
1281 && req.range != REQ_RANGE_PLAYER);
1282 break;
1283 case VUT_FORM_AGE:
1284 invalid = (req.range != REQ_RANGE_LOCAL);
1285 break;
1286 case VUT_IMPR_GENUS:
1287 /* TODO: Support other ranges too. */
1288 invalid = (req.range != REQ_RANGE_LOCAL);
1289 break;
1290 case VUT_IMPR_FLAG:
1291 invalid = (req.range != REQ_RANGE_LOCAL
1292 && req.range != REQ_RANGE_TILE
1293 && req.range != REQ_RANGE_CITY);
1294 break;
1295 case VUT_COUNTER:
1296 invalid = req.range != REQ_RANGE_CITY;
1297 break;
1298 case VUT_PLAYER_FLAG:
1299 case VUT_PLAYER_STATE:
1300 invalid = (req.range != REQ_RANGE_PLAYER);
1301 break;
1302 case VUT_IMPROVEMENT:
1303 case VUT_SITE:
1304 /* Valid ranges depend on the building genus (wonder/improvement),
1305 * which might not have been loaded from the ruleset yet.
1306 * So we allow anything here, and do a proper check once ruleset
1307 * loading is complete, in sanity_check_req_individual(). */
1308 case VUT_NONE:
1309 invalid = FALSE;
1310 break;
1311 case VUT_COUNT:
1312 break;
1313 }
1314 if (invalid) {
1315 error = "bad range";
1316 }
1317 }
1318
1319 if (!invalid) {
1320 /* Check 'survives'. */
1321 switch (req.source.kind) {
1322 case VUT_IMPROVEMENT:
1323 case VUT_SITE:
1324 /* See buildings_in_range(). */
1326 break;
1327 case VUT_NATION:
1328 case VUT_ADVANCE:
1330 break;
1331 case VUT_COUNTER:
1332 case VUT_IMPR_GENUS:
1333 case VUT_IMPR_FLAG:
1334 case VUT_PLAYER_FLAG:
1335 case VUT_PLAYER_STATE:
1336 case VUT_GOVERNMENT:
1337 case VUT_TERRAIN:
1338 case VUT_UTYPE:
1339 case VUT_UTFLAG:
1340 case VUT_UCLASS:
1341 case VUT_UCFLAG:
1342 case VUT_MINVETERAN:
1343 case VUT_UNITSTATE:
1344 case VUT_ACTIVITY:
1345 case VUT_MINMOVES:
1346 case VUT_MINHP:
1347 case VUT_AGE:
1348 case VUT_FORM_AGE:
1349 case VUT_ACTION:
1350 case VUT_OTYPE:
1351 case VUT_SPECIALIST:
1352 case VUT_MINSIZE:
1353 case VUT_MINCULTURE:
1354 case VUT_MINFOREIGNPCT:
1355 case VUT_AI_LEVEL:
1356 case VUT_TERRAINCLASS:
1357 case VUT_MINYEAR:
1358 case VUT_MINCALFRAG:
1359 case VUT_TOPO:
1360 case VUT_WRAP:
1361 case VUT_SERVERSETTING:
1362 case VUT_TERRAINALTER:
1363 case VUT_CITYTILE:
1364 case VUT_CITYSTATUS:
1365 case VUT_TERRFLAG:
1366 case VUT_NATIONALITY:
1367 case VUT_ORIGINAL_OWNER:
1368 case VUT_ROADFLAG:
1369 case VUT_EXTRAFLAG:
1370 case VUT_EXTRA:
1371 case VUT_GOOD:
1372 case VUT_TECHFLAG:
1373 case VUT_ACHIEVEMENT:
1374 case VUT_NATIONGROUP:
1375 case VUT_STYLE:
1376 case VUT_DIPLREL:
1377 case VUT_DIPLREL_TILE:
1378 case VUT_DIPLREL_TILE_O:
1381 case VUT_MAXTILEUNITS:
1382 case VUT_MINTECHS:
1383 case VUT_MINLATITUDE:
1384 case VUT_MAXLATITUDE:
1385 /* Most requirements don't support 'survives'. */
1386 invalid = survives;
1387 break;
1388 case VUT_NONE:
1389 case VUT_COUNT:
1390 break;
1391 }
1392 if (invalid) {
1393 error = "bad 'survives'";
1394 }
1395 }
1396
1397 if (invalid) {
1398 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1399 type, range, survives ? "survives" : "",
1400 present ? "present" : "", value, error);
1402 }
1403
1404 return req;
1405}
1406
1407/**********************************************************************/
1413 int value)
1414{
1415 struct requirement req;
1416
1417 req.source = universal_by_number(type, value);
1418 req.range = range;
1419 req.survives = survives;
1420 req.present = present;
1421 req.quiet = quiet;
1422
1423 return req;
1424}
1425
1426/**********************************************************************/
1430void req_get_values(const struct requirement *req,
1431 int *type, int *range,
1432 bool *survives, bool *present, bool *quiet,
1433 int *value)
1434{
1435 universal_extraction(&req->source, type, value);
1436 *range = req->range;
1437 *survives = req->survives;
1438 *present = req->present;
1439 *quiet = req->quiet;
1440}
1441
1442/**********************************************************************/
1445void req_copy(struct requirement *dst, const struct requirement *src)
1446{
1447 universal_copy(&(dst->source), &(src->source));
1448 dst->range = src->range;
1449 dst->survives = src->survives;
1450 dst->present = src->present;
1451 dst->quiet = src->quiet;
1452}
1453
1454/**********************************************************************/
1458bool are_requirements_equal(const struct requirement *req1,
1459 const struct requirement *req2)
1460{
1461 return (are_universals_equal(&req1->source, &req2->source)
1462 && req1->range == req2->range
1463 && req1->survives == req2->survives
1464 && req1->present == req2->present);
1465}
1466
1467/**********************************************************************/
1470static bool are_requirements_opposites(const struct requirement *req1,
1471 const struct requirement *req2)
1472{
1473 return (are_universals_equal(&req1->source, &req2->source)
1474 && req1->range == req2->range
1475 && req1->survives == req2->survives
1476 && req1->present != req2->present);
1477}
1478
1479/**********************************************************************/
1483static bool impr_contra_genus(const struct requirement *impr_req,
1484 const struct requirement *genus_req)
1485{
1486 /* The input is sane. */
1488 || impr_req->source.kind == VUT_SITE, FALSE);
1490
1491 if (impr_req->range == REQ_RANGE_LOCAL
1492 && genus_req->range == REQ_RANGE_LOCAL) {
1493 /* Applies to the same target building. */
1494
1495 if (impr_req->present && !genus_req->present) {
1496 /* The target building can't not have the genus it has. */
1497 return (impr_req->source.value.building->genus
1498 == genus_req->source.value.impr_genus);
1499 }
1500
1501 if (impr_req->present && genus_req->present) {
1502 /* The target building can't have another genus than it has. */
1503 return (impr_req->source.value.building->genus
1504 != genus_req->source.value.impr_genus);
1505 }
1506 }
1507
1508 /* No special knowledge. */
1509 return FALSE;
1510}
1511
1512/**********************************************************************/
1516static bool impr_contra_flag(const struct requirement *impr_req,
1517 const struct requirement *flag_req)
1518{
1519 /* The input is sane. */
1521 || impr_req->source.kind == VUT_SITE, FALSE);
1523
1524 if (impr_req->range == REQ_RANGE_LOCAL
1525 && flag_req->range == REQ_RANGE_LOCAL) {
1526 /* Applies to the same target building. */
1527
1528 if (impr_req->present && !flag_req->present) {
1529 /* The target building can't not have the flag it has. */
1530 return improvement_has_flag(impr_req->source.value.building,
1531 flag_req->source.value.impr_flag);
1532 }
1533
1534 if (impr_req->present && flag_req->present) {
1535 /* The target building can't have another flag than it has. */
1536 return !improvement_has_flag(impr_req->source.value.building,
1537 flag_req->source.value.impr_flag);
1538 }
1539 }
1540
1541 /* No special knowledge. */
1542 return FALSE;
1543}
1544
1545/**********************************************************************/
1550 const struct requirement *group_req)
1551{
1552 /* The input is sane. */
1553 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1555
1556 if (nation_req->range == REQ_RANGE_PLAYER
1557 && group_req->range == REQ_RANGE_PLAYER) {
1558 /* Applies to the same target building. */
1559
1560 if (nation_req->present && !group_req->present) {
1561 /* The target nation can't be in the group. */
1562 return nation_is_in_group(nation_req->source.value.nation,
1563 group_req->source.value.nationgroup);
1564 }
1565 }
1566
1567 /* No special knowledge. */
1568 return FALSE;
1569}
1570
1571/**********************************************************************/
1575static bool city_center_contra(const struct requirement *cc_req,
1576 const struct requirement *ct_req)
1577{
1578 /* The input is sane. */
1579 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1580 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1581
1582 if (cc_req->source.value.citytile == CITYT_CENTER
1583 && cc_req->present && cc_req->range <= ct_req->range) {
1584 switch (ct_req->source.value.citytile) {
1585 case CITYT_CENTER:
1586 case CITYT_CLAIMED:
1587 case CITYT_EXTRAS_OWNED:
1588 case CITYT_WORKED:
1590 /* Should be always on city center */
1591 return !ct_req->present;
1593 /* Handled later */
1594 break;
1595 case CITYT_LAST:
1596 /* Error */
1597 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1598 }
1599 }
1600 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1601 || cc_req->source.value.citytile == CITYT_CENTER)
1602 && ct_req->source.value.citytile
1604 && REQ_RANGE_TILE == cc_req->range
1605 && REQ_RANGE_TILE == ct_req->range) {
1606 /* Can't coexist */
1607 return cc_req->present ? ct_req->present : !ct_req->present;
1608 }
1609
1610 return FALSE;
1611}
1612
1613/**********************************************************************/
1618static bool present_implies_not_present(const struct requirement *req1,
1619 const struct requirement *req2)
1620{
1621 const struct requirement *absent, *present;
1622
1623 if (req1->present == req2->present) {
1624 /* Can't use the knowledge in universal_found_function when both are
1625 * required to be absent or when both are required to be present.
1626 * It is no contradiction to require !Spy unit and !Missile unit class.
1627 * It is no contradiction to require River and Irrigation at the same
1628 * tile. */
1629 return FALSE;
1630 }
1631
1632 if (req1->present) {
1633 absent = req2;
1634 present = req1;
1635 } else {
1636 absent = req1;
1637 present = req2;
1638 }
1639
1640 if (!universal_found_function[present->source.kind]) {
1641 /* No knowledge to exploit. */
1642 return FALSE;
1643 }
1644
1645 if (present->range != absent->range) {
1646 /* Larger ranges are not always strict supersets of smaller ranges.
1647 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1648 * but not in Trade Route. */
1649 return FALSE;
1650 }
1651
1653 &present->source);
1654}
1655
1656/**********************************************************************/
1659bool req_implies_req(const struct requirement *req1,
1660 const struct requirement *req2)
1661{
1662 struct requirement nreq2;
1663
1664 req_copy(&nreq2, req2);
1665 nreq2.present = !nreq2.present;
1667}
1668
1669/**********************************************************************/
1677 const struct requirement *req2)
1678{
1679 if (are_requirements_opposites(req1, req2)) {
1680 /* The exact opposite. */
1681 return TRUE;
1682 }
1683
1684 if (present_implies_not_present(req1, req2)) {
1685 return TRUE;
1686 }
1687
1688 switch (req1->source.kind) {
1689 case VUT_IMPROVEMENT:
1690 case VUT_SITE:
1691 if (req2->source.kind == VUT_IMPR_GENUS) {
1692 return impr_contra_genus(req1, req2);
1693 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1694 return impr_contra_flag(req1, req2);
1695 } else if (req2->source.kind == VUT_CITYTILE
1696 && req2->source.value.citytile == CITYT_CENTER
1697 && REQ_RANGE_TILE == req2->range
1698 && REQ_RANGE_TILE == req1->range
1699 && req1->present) {
1700 /* A building must be in a city */
1701 return !req2->present;
1702 }
1703
1704 /* No special knowledge. */
1705 return FALSE;
1706 case VUT_IMPR_GENUS:
1707 if (req2->source.kind == VUT_IMPROVEMENT
1708 || req2->source.kind == VUT_SITE) {
1709 return impr_contra_genus(req2, req1);
1710 }
1711
1712 /* No special knowledge. */
1713 return FALSE;
1714 case VUT_IMPR_FLAG:
1715 if (req2->source.kind == VUT_IMPROVEMENT
1716 || req2->source.kind == VUT_SITE) {
1717 return impr_contra_flag(req2, req1);
1718 }
1719
1720 /* No special knowledge. */
1721 return FALSE;
1722 case VUT_DIPLREL:
1723 case VUT_DIPLREL_TILE:
1724 case VUT_DIPLREL_TILE_O:
1727 if (req2->source.kind != req1->source.kind) {
1728 /* Finding contradictions across requirement kinds aren't supported
1729 * for DiplRel requirements. */
1730 return FALSE;
1731 } else {
1732 /* Use the special knowledge about DiplRel requirements to find
1733 * contradictions. */
1734
1736 int req2_pos;
1737
1740 req2->range,
1741 req2->present);
1742
1743 return BV_ISSET(req1_contra, req2_pos);
1744 }
1745 break;
1746 case VUT_MINMOVES:
1747 if (req2->source.kind != VUT_MINMOVES) {
1748 /* Finding contradictions across requirement kinds aren't supported
1749 * for MinMoveFrags requirements. */
1750 return FALSE;
1751 } else if (req1->present == req2->present) {
1752 /* No contradiction possible. */
1753 return FALSE;
1754 } else {
1755 /* Number of move fragments left can't be larger than the number
1756 * required to be present and smaller than the number required to not
1757 * be present when the number required to be present is smaller than
1758 * the number required to not be present. */
1759 if (req1->present) {
1760 return req1->source.value.minmoves >= req2->source.value.minmoves;
1761 } else {
1762 return req1->source.value.minmoves <= req2->source.value.minmoves;
1763 }
1764 }
1765 break;
1766 case VUT_MINLATITUDE:
1767 case VUT_MAXLATITUDE:
1768 if (req2->source.kind != VUT_MINLATITUDE
1769 && req2->source.kind != VUT_MAXLATITUDE) {
1770 /* Finding contradictions across requirement kinds other than each
1771 * other is not supported for MinLatitude and MaxLatitude. */
1772 return FALSE;
1773 } else {
1774 /* For a contradiction, we need
1775 * - a minimum (present MinLatitude or negated MaxLatitude)
1776 * - a maximum (negated MinLatitude or present MaxLatitude)
1777 * - the maximum to be less than the minimum
1778 * - a requirement at the larger range that applies to the entire
1779 * range (i.e. a negated requirement, unless the range is Tile)
1780 * Otherwise, the two requirements could still be fulfilled
1781 * simultaneously by different tiles in the range */
1782
1783 /* Initial values beyond the boundaries to avoid edge cases */
1784 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
1786
1787#define EXTRACT_INFO(req) \
1788 if (req->present) { \
1789 if (req->source.kind == VUT_MINLATITUDE) { \
1790 /* present MinLatitude */ \
1791 minimum = MAX(minimum, req->source.value.latitude); \
1792 } else { \
1793 /* present MaxLatitude */ \
1794 maximum = MIN(maximum, req->source.value.latitude); \
1795 } \
1796 } else { \
1797 covered_range = MAX(covered_range, req->range); \
1798 if (req->source.kind == VUT_MINLATITUDE) { \
1799 /* negated MinLatitude */ \
1800 maximum = MIN(maximum, req->source.value.latitude - 1); \
1801 } else { \
1802 /* negated MaxLatitude */ \
1803 minimum = MAX(minimum, req->source.value.latitude + 1); \
1804 } \
1805 }
1806
1807 EXTRACT_INFO(req1);
1808 EXTRACT_INFO(req2);
1809
1810#undef EXTRACT_INFO
1811
1812 return (maximum < minimum
1813 && covered_range >= req1->range
1814 && covered_range >= req2->range);
1815 }
1816 break;
1817 case VUT_NATION:
1818 if (req2->source.kind == VUT_NATIONGROUP) {
1819 return nation_contra_group(req1, req2);
1820 }
1821
1822 /* No special knowledge. */
1823 return FALSE;
1824 break;
1825 case VUT_NATIONGROUP:
1826 if (req2->source.kind == VUT_NATION) {
1827 return nation_contra_group(req2, req1);
1828 }
1829
1830 /* No special knowledge. */
1831 return FALSE;
1832 break;
1833 case VUT_CITYTILE:
1834 if (req2->source.kind == VUT_CITYTILE) {
1835 return city_center_contra(req1, req2)
1836 || city_center_contra(req2, req1);
1837 } else if (req1->source.value.citytile == CITYT_CENTER
1838 && (req2->source.kind == VUT_IMPROVEMENT
1839 || req2->source.kind == VUT_SITE)
1840 && REQ_RANGE_TILE == req2->range
1841 && REQ_RANGE_TILE == req1->range
1842 && req2->present) {
1843 /* A building must be in a city */
1844 return !req1->present;
1845 }
1846
1847 return FALSE;
1848 default:
1849 /* No special knowledge exists. The requirements aren't the exact
1850 * opposite of each other per the initial check. */
1851 return FALSE;
1852 }
1853}
1854
1855/**********************************************************************/
1860 const struct requirement_vector *vec)
1861{
1862 /* If the requirement is contradicted by any requirement in the vector it
1863 * contradicts the entire requirement vector. */
1866 return TRUE;
1867 }
1869
1870 /* Not a singe requirement in the requirement vector is contradicted be
1871 * the specified requirement. */
1872 return FALSE;
1873}
1874
1875/**********************************************************************/
1878static inline bool are_tiles_in_range(const struct tile *tile1,
1879 const struct tile *tile2,
1880 enum req_range range)
1881{
1882 switch (range) {
1883 case REQ_RANGE_ADJACENT:
1885 return TRUE;
1886 }
1888 case REQ_RANGE_TILE:
1889 return same_pos(tile1, tile2);
1891 return map_distance(tile1, tile2) <= 1;
1892 case REQ_RANGE_CITY:
1894 case REQ_RANGE_LOCAL:
1896 case REQ_RANGE_PLAYER:
1897 case REQ_RANGE_TEAM:
1898 case REQ_RANGE_ALLIANCE:
1899 case REQ_RANGE_WORLD:
1900 case REQ_RANGE_COUNT:
1901 /* Invalid */
1903 }
1904 return FALSE;
1905}
1906
1907/**********************************************************************/
1910static inline bool players_in_same_range(const struct player *pplayer1,
1911 const struct player *pplayer2,
1912 enum req_range range)
1913{
1914 switch (range) {
1915 case REQ_RANGE_WORLD:
1916 return TRUE;
1917 case REQ_RANGE_ALLIANCE:
1919 case REQ_RANGE_TEAM:
1921 case REQ_RANGE_PLAYER:
1922 return pplayer1 == pplayer2;
1925 case REQ_RANGE_CITY:
1926 case REQ_RANGE_ADJACENT:
1928 case REQ_RANGE_TILE:
1929 case REQ_RANGE_LOCAL:
1930 case REQ_RANGE_COUNT:
1931 break;
1932 }
1933
1934 fc_assert_msg(FALSE, "Invalid range %d.", range);
1935 return FALSE;
1936}
1937
1938#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
1939{ \
1940 fc_assert_ret_val(req != NULL, TRI_MAYBE); \
1941 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
1942 fc_assert(context != NULL); \
1943}
1944
1945/**********************************************************************/
1952static enum fc_tristate
1954 const struct req_context *context,
1955 const struct player *other_player,
1956 const struct requirement *req)
1957{
1959
1960 return TRI_YES;
1961}
1962
1963/**********************************************************************/
1967static int num_world_buildings_total(const struct impr_type *building)
1968{
1969 if (is_great_wonder(building)) {
1970 return (great_wonder_is_built(building)
1971 || great_wonder_is_destroyed(building) ? 1 : 0);
1972 } else {
1973 log_error("World-ranged requirements are only supported for wonders.");
1974 return 0;
1975 }
1976}
1977
1978/**********************************************************************/
1981static int num_world_buildings(const struct impr_type *building)
1982{
1983 if (is_great_wonder(building)) {
1984 return (great_wonder_is_built(building) ? 1 : 0);
1985 } else {
1986 log_error("World-ranged requirements are only supported for wonders.");
1987 return 0;
1988 }
1989}
1990
1991/**********************************************************************/
2002static bool player_has_ever_built(const struct player *pplayer,
2003 const struct impr_type *building)
2004{
2005 if (is_wonder(building)) {
2006 return (wonder_is_built(pplayer, building)
2007 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2008 } else {
2009 log_error("Player-ranged requirements are only supported for wonders.");
2010 return FALSE;
2011 }
2012}
2013
2014/**********************************************************************/
2017static int num_player_buildings(const struct player *pplayer,
2018 const struct impr_type *building)
2019{
2020 if (is_wonder(building)) {
2021 return (wonder_is_built(pplayer, building) ? 1 : 0);
2022 } else {
2023 log_error("Player-ranged requirements are only supported for wonders.");
2024 return 0;
2025 }
2026}
2027
2028/**********************************************************************/
2031static int num_continent_buildings(const struct player *pplayer,
2032 int continent,
2033 const struct impr_type *building)
2034{
2035 if (is_wonder(building)) {
2036 const struct city *pcity;
2037
2038 pcity = city_from_wonder(pplayer, building);
2039 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2040 return 1;
2041 }
2042 } else {
2043 log_error("Island-ranged requirements are only supported for wonders.");
2044 }
2045 return 0;
2046}
2047
2048/**********************************************************************/
2051static int num_city_buildings(const struct city *pcity,
2052 const struct impr_type *building)
2053{
2054 return (city_has_building(pcity, building) ? 1 : 0);
2055}
2056
2057/**********************************************************************/
2064static enum fc_tristate
2066 const struct req_context *context,
2067 const struct player *other_player,
2068 const struct requirement *req)
2069{
2070 const struct impr_type *building;
2071
2072 /* Can't use this assertion, as both VUT_IMPROVEMENT and VUT_SITE
2073 * are handled here. */
2074 /* IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT); */
2075
2076 building = req->source.value.building;
2077
2078 /* Check if it's certain that the building is obsolete given the
2079 * specification we have */
2080 if (req->source.kind == VUT_IMPROVEMENT
2081 && improvement_obsolete(context->player, building, context->city)) {
2082 return TRI_NO;
2083 }
2084
2085 if (req->survives) {
2086
2087 /* Check whether condition has ever held, using cached information. */
2088 switch (req->range) {
2089 case REQ_RANGE_WORLD:
2090 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2091 case REQ_RANGE_ALLIANCE:
2092 case REQ_RANGE_TEAM:
2093 if (context->player == NULL) {
2094 return TRI_MAYBE;
2095 }
2096 players_iterate_alive(plr2) {
2097 if (players_in_same_range(context->player, plr2, req->range)
2098 && player_has_ever_built(plr2, building)) {
2099 return TRI_YES;
2100 }
2102 return TRI_NO;
2103 case REQ_RANGE_PLAYER:
2104 if (context->player == NULL) {
2105 return TRI_MAYBE;
2106 }
2108 building));
2111 case REQ_RANGE_CITY:
2112 case REQ_RANGE_LOCAL:
2113 case REQ_RANGE_TILE:
2115 case REQ_RANGE_ADJACENT:
2116 /* There is no sources cache for this. */
2117 log_error("Surviving requirements are only supported at "
2118 "World/Alliance/Team/Player ranges.");
2119 return TRI_NO;
2120 case REQ_RANGE_COUNT:
2121 break;
2122 }
2123
2124 } else {
2125
2126 /* Non-surviving requirement. */
2127 switch (req->range) {
2128 case REQ_RANGE_WORLD:
2129 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2130 case REQ_RANGE_ALLIANCE:
2131 case REQ_RANGE_TEAM:
2132 if (context->player == NULL) {
2133 return TRI_MAYBE;
2134 }
2135 players_iterate_alive(plr2) {
2136 if (players_in_same_range(context->player, plr2, req->range)
2137 && num_player_buildings(plr2, building) > 0) {
2138 return TRI_YES;
2139 }
2141 return TRI_NO;
2142 case REQ_RANGE_PLAYER:
2143 if (context->player == NULL) {
2144 return TRI_MAYBE;
2145 }
2147 building)
2148 > 0);
2150 /* At present, "Continent" effects can affect only
2151 * cities and units in cities. */
2152 if (context->player && context->city) {
2153 int continent = tile_continent(context->city->tile);
2155 continent, building)
2156 > 0);
2157 } else {
2158 return TRI_MAYBE;
2159 }
2161 if (context->city) {
2162 if (num_city_buildings(context->city, building) > 0) {
2163 return TRI_YES;
2164 } else {
2165 enum fc_tristate ret = TRI_NO;
2166
2168 if (trade_partner == NULL) {
2169 ret = TRI_MAYBE;
2170 } else if (num_city_buildings(trade_partner, building) > 0) {
2171 return TRI_YES;
2172 }
2174
2175 return ret;
2176 }
2177 } else {
2178 return TRI_MAYBE;
2179 }
2180 case REQ_RANGE_CITY:
2181 if (context->city) {
2182 return BOOL_TO_TRISTATE(num_city_buildings(context->city, building)
2183 > 0);
2184 } else {
2185 return TRI_MAYBE;
2186 }
2187 case REQ_RANGE_LOCAL:
2188 if (context->building) {
2189 if (context->building == building) {
2190 return TRI_YES;
2191 } else {
2192 return TRI_NO;
2193 }
2194 } else {
2195 /* TODO: other local targets */
2196 return TRI_MAYBE;
2197 }
2198 case REQ_RANGE_TILE:
2199 if (context->tile) {
2200 const struct city *pcity = tile_city(context->tile);
2201
2202 if (pcity) {
2203 return BOOL_TO_TRISTATE(num_city_buildings(pcity, building) > 0);
2204 } else {
2205 return TRI_NO;
2206 }
2207 } else {
2208 return TRI_MAYBE;
2209 }
2211 case REQ_RANGE_ADJACENT:
2212 case REQ_RANGE_COUNT:
2213 break;
2214 }
2215
2216 }
2217
2218 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2219 return TRI_NO;
2220}
2221
2222/**********************************************************************/
2230static enum fc_tristate
2232 const struct req_context *context,
2233 const struct player *other_player,
2234 const struct requirement *req)
2235{
2237
2238 return (context->building ? BOOL_TO_TRISTATE(
2239 context->building->genus
2240 == req->source.value.impr_genus)
2241 : TRI_MAYBE);
2242}
2243
2244/**********************************************************************/
2247static enum fc_tristate is_buildingflag_in_city(const struct city *pcity,
2248 enum impr_flag_id flag)
2249{
2250 struct player *owner;
2251
2252 if (pcity == NULL) {
2253 return TRI_MAYBE;
2254 }
2255
2256 owner = city_owner(pcity);
2257 city_built_iterate(pcity, impr) {
2258 if (improvement_has_flag(impr, flag)
2259 && !improvement_obsolete(owner, impr, pcity)) {
2260 return TRI_YES;
2261 }
2263
2264 return TRI_NO;
2265}
2266
2267/**********************************************************************/
2275static enum fc_tristate
2277 const struct req_context *context,
2278 const struct player *other_player,
2279 const struct requirement *req)
2280{
2282
2283 switch (req->range) {
2284 case REQ_RANGE_LOCAL:
2285 return (context->building
2287 req->source.value.impr_flag))
2288 : TRI_MAYBE);
2289 case REQ_RANGE_CITY:
2291 case REQ_RANGE_TILE:
2292 if (context->tile == NULL) {
2293 return TRI_MAYBE;
2294 }
2296 req->source.value.impr_flag);
2298 case REQ_RANGE_ADJACENT:
2301 case REQ_RANGE_PLAYER:
2302 case REQ_RANGE_ALLIANCE:
2303 case REQ_RANGE_TEAM:
2304 case REQ_RANGE_WORLD:
2305 case REQ_RANGE_COUNT:
2306 break;
2307 }
2308
2309 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2310
2311 return TRI_MAYBE;
2312}
2313
2314/**********************************************************************/
2322static enum fc_tristate
2324 const struct req_context *context,
2325 const struct player *other_player,
2326 const struct requirement *req)
2327{
2329
2330 switch (req->range) {
2331 case REQ_RANGE_PLAYER:
2332 return (context->player != NULL
2334 req->source.value.plr_flag))
2335 : TRI_MAYBE);
2336 case REQ_RANGE_LOCAL:
2337 case REQ_RANGE_CITY:
2338 case REQ_RANGE_TILE:
2340 case REQ_RANGE_ADJACENT:
2343 case REQ_RANGE_ALLIANCE:
2344 case REQ_RANGE_TEAM:
2345 case REQ_RANGE_WORLD:
2346 case REQ_RANGE_COUNT:
2347 break;
2348 }
2349
2350 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2351
2352 return TRI_MAYBE;
2353}
2354
2355/**********************************************************************/
2363static enum fc_tristate
2365 const struct req_context *context,
2366 const struct player *other_player,
2367 const struct requirement *req)
2368{
2370
2371 switch (req->range) {
2372 case REQ_RANGE_PLAYER:
2373 return (context->player != NULL
2375 req->source.value.plrstate))
2376 : TRI_MAYBE);
2377 case REQ_RANGE_LOCAL:
2378 case REQ_RANGE_CITY:
2379 case REQ_RANGE_TILE:
2381 case REQ_RANGE_ADJACENT:
2384 case REQ_RANGE_ALLIANCE:
2385 case REQ_RANGE_TEAM:
2386 case REQ_RANGE_WORLD:
2387 case REQ_RANGE_COUNT:
2388 break;
2389 }
2390
2391 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2392
2393 return TRI_MAYBE;
2394}
2395
2396/**********************************************************************/
2403static enum fc_tristate
2405 const struct req_context *context,
2406 const struct player *other_player,
2407 const struct requirement *req)
2408{
2409 Tech_type_id tech;
2410
2412
2413 tech = advance_number(req->source.value.advance);
2414
2415 if (req->survives) {
2418 }
2419
2420 /* Not a 'surviving' requirement. */
2421 switch (req->range) {
2422 case REQ_RANGE_PLAYER:
2423 if (NULL != context->player) {
2425 (research_get(context->player), tech));
2426 } else {
2427 return TRI_MAYBE;
2428 }
2429 case REQ_RANGE_TEAM:
2430 case REQ_RANGE_ALLIANCE:
2431 case REQ_RANGE_WORLD:
2432 if (NULL == context->player) {
2433 return TRI_MAYBE;
2434 }
2435 players_iterate_alive(plr2) {
2436 if (players_in_same_range(context->player, plr2, req->range)) {
2437 if (research_invention_state(research_get(plr2), tech)
2438 == TECH_KNOWN) {
2439 return TRI_YES;
2440 }
2441 }
2443
2444 return TRI_NO;
2445 case REQ_RANGE_LOCAL:
2446 case REQ_RANGE_TILE:
2448 case REQ_RANGE_ADJACENT:
2449 case REQ_RANGE_CITY:
2452 case REQ_RANGE_COUNT:
2453 break;
2454 }
2455
2456 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2457
2458 return TRI_MAYBE;
2459}
2460
2461/**********************************************************************/
2468static enum fc_tristate
2470 const struct req_context *context,
2471 const struct player *other_player,
2472 const struct requirement *req)
2473{
2474 enum tech_flag_id techflag;
2475
2477
2478 techflag = req->source.value.techflag;
2479
2480 switch (req->range) {
2481 case REQ_RANGE_PLAYER:
2482 if (NULL != context->player) {
2484 techflag));
2485 } else {
2486 return TRI_MAYBE;
2487 }
2488 break;
2489 case REQ_RANGE_TEAM:
2490 case REQ_RANGE_ALLIANCE:
2491 if (NULL == context->player) {
2492 return TRI_MAYBE;
2493 }
2494 players_iterate_alive(plr2) {
2495 if (players_in_same_range(context->player, plr2, req->range)
2496 && player_knows_techs_with_flag(plr2, techflag)) {
2497 return TRI_YES;
2498 }
2500 return TRI_NO;
2501 case REQ_RANGE_WORLD:
2502 players_iterate(pplayer) {
2503 if (player_knows_techs_with_flag(pplayer, techflag)) {
2504 return TRI_YES;
2505 }
2507
2508 return TRI_NO;
2509 case REQ_RANGE_LOCAL:
2510 case REQ_RANGE_TILE:
2512 case REQ_RANGE_ADJACENT:
2513 case REQ_RANGE_CITY:
2516 case REQ_RANGE_COUNT:
2517 break;
2518 }
2519
2520 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2521
2522 return TRI_MAYBE;
2523}
2524
2525/**********************************************************************/
2532static enum fc_tristate
2534 const struct req_context *context,
2535 const struct player *other_player,
2536 const struct requirement *req)
2537{
2538 int minculture;
2539
2541
2542 minculture = req->source.value.minculture;
2543
2544 switch (req->range) {
2545 case REQ_RANGE_CITY:
2546 if (!context->city) {
2547 return TRI_MAYBE;
2548 }
2549 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2551 if (!context->city) {
2552 return TRI_MAYBE;
2553 }
2554 if (city_culture(context->city) >= minculture) {
2555 return TRI_YES;
2556 } else {
2557 enum fc_tristate ret = TRI_NO;
2558
2560 if (trade_partner == NULL) {
2561 ret = TRI_MAYBE;
2562 } else if (city_culture(trade_partner) >= minculture) {
2563 return TRI_YES;
2564 }
2566
2567 return ret;
2568 }
2569 case REQ_RANGE_PLAYER:
2570 case REQ_RANGE_TEAM:
2571 case REQ_RANGE_ALLIANCE:
2572 case REQ_RANGE_WORLD:
2573 if (NULL == context->player) {
2574 return TRI_MAYBE;
2575 }
2576 players_iterate_alive(plr2) {
2577 if (players_in_same_range(context->player, plr2, req->range)) {
2578 if (player_culture(plr2) >= minculture) {
2579 return TRI_YES;
2580 }
2581 }
2583 return TRI_NO;
2584 case REQ_RANGE_LOCAL:
2585 case REQ_RANGE_TILE:
2587 case REQ_RANGE_ADJACENT:
2589 case REQ_RANGE_COUNT:
2590 break;
2591 }
2592
2593 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2594
2595 return TRI_MAYBE;
2596}
2597
2598/**********************************************************************/
2606static enum fc_tristate
2608 const struct req_context *context,
2609 const struct player *other_player,
2610 const struct requirement *req)
2611{
2613
2615
2617
2618 switch (req->range) {
2619 case REQ_RANGE_CITY:
2620 if (!context->city) {
2621 return TRI_MAYBE;
2622 }
2624 / city_size_get(context->city);
2627 if (!context->city) {
2628 return TRI_MAYBE;
2629 }
2631 / city_size_get(context->city);
2633 return TRI_YES;
2634 } else {
2635 enum fc_tristate ret = TRI_NO;
2636
2638 if (trade_partner == NULL) {
2639 ret = TRI_MAYBE;
2640 } else {
2644 return TRI_YES;
2645 }
2646 }
2648
2649 return ret;
2650 }
2651 case REQ_RANGE_PLAYER:
2652 case REQ_RANGE_TEAM:
2653 case REQ_RANGE_ALLIANCE:
2654 case REQ_RANGE_WORLD:
2655 case REQ_RANGE_LOCAL:
2656 case REQ_RANGE_TILE:
2658 case REQ_RANGE_ADJACENT:
2660 case REQ_RANGE_COUNT:
2661 break;
2662 }
2663
2664 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2665
2666 return TRI_MAYBE;
2667}
2668
2669/**********************************************************************/
2677static enum fc_tristate
2679 const struct req_context *context,
2680 const struct player *other_player,
2681 const struct requirement *req)
2682{
2683 int max_units;
2684
2686
2688
2689 /* TODO: if can't see V_INVIS -> TRI_MAYBE */
2690 switch (req->range) {
2691 case REQ_RANGE_TILE:
2692 if (!context->tile) {
2693 return TRI_MAYBE;
2694 }
2695 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
2697 if (!context->tile) {
2698 return TRI_MAYBE;
2699 }
2700 if (unit_list_size(context->tile->units) <= max_units) {
2701 return TRI_YES;
2702 }
2704 if (unit_list_size(adjc_tile->units) <= max_units) {
2705 return TRI_YES;
2706 }
2708 return TRI_NO;
2709 case REQ_RANGE_ADJACENT:
2710 if (!context->tile) {
2711 return TRI_MAYBE;
2712 }
2713 if (unit_list_size(context->tile->units) <= max_units) {
2714 return TRI_YES;
2715 }
2717 if (unit_list_size(adjc_tile->units) <= max_units) {
2718 return TRI_YES;
2719 }
2721 return TRI_NO;
2722 case REQ_RANGE_CITY:
2725 case REQ_RANGE_PLAYER:
2726 case REQ_RANGE_TEAM:
2727 case REQ_RANGE_ALLIANCE:
2728 case REQ_RANGE_WORLD:
2729 case REQ_RANGE_LOCAL:
2730 case REQ_RANGE_COUNT:
2731 break;
2732 }
2733
2734 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2735
2736 return TRI_MAYBE;
2737}
2738
2739/**********************************************************************/
2746static enum fc_tristate
2748 const struct req_context *context,
2749 const struct player *other_player,
2750 const struct requirement *req)
2751{
2752 const struct extra_type *pextra;
2753 enum fc_tristate ret;
2754
2756
2757 pextra = req->source.value.extra;
2758
2759 switch (req->range) {
2760 case REQ_RANGE_LOCAL:
2761 if (!context->extra) {
2762 return TRI_MAYBE;
2763 }
2764 return BOOL_TO_TRISTATE(context->extra == pextra);
2765 case REQ_RANGE_TILE:
2766 /* The requirement is filled if the tile has extra of requested type. */
2767 if (!context->tile) {
2768 return TRI_MAYBE;
2769 }
2770 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
2772 if (!context->tile) {
2773 return TRI_MAYBE;
2774 }
2775 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2776 || is_extra_card_near(nmap, context->tile, pextra));
2777 case REQ_RANGE_ADJACENT:
2778 if (!context->tile) {
2779 return TRI_MAYBE;
2780 }
2781 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2782 || is_extra_near_tile(nmap, context->tile, pextra));
2783 case REQ_RANGE_CITY:
2784 if (!context->city) {
2785 return TRI_MAYBE;
2786 }
2788 city_tile(context->city), ptile) {
2789 if (tile_has_extra(ptile, pextra)) {
2790 return TRI_YES;
2791 }
2793
2794 return TRI_NO;
2795
2797 if (!context->city) {
2798 return TRI_MAYBE;
2799 }
2801 city_tile(context->city), ptile) {
2802 if (tile_has_extra(ptile, pextra)) {
2803 return TRI_YES;
2804 }
2806
2807 ret = TRI_NO;
2809 if (trade_partner == NULL) {
2810 ret = TRI_MAYBE;
2811 } else {
2813 city_tile(trade_partner), ptile) {
2814 if (tile_has_extra(ptile, pextra)) {
2815 return TRI_YES;
2816 }
2818 }
2820
2821 return ret;
2822
2824 case REQ_RANGE_PLAYER:
2825 case REQ_RANGE_TEAM:
2826 case REQ_RANGE_ALLIANCE:
2827 case REQ_RANGE_WORLD:
2828 case REQ_RANGE_COUNT:
2829 break;
2830 }
2831
2832 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2833
2834 return TRI_MAYBE;
2835}
2836
2837/**********************************************************************/
2844static enum fc_tristate
2846 const struct req_context *context,
2847 const struct player *other_player,
2848 const struct requirement *req)
2849{
2850 const struct goods_type *pgood;
2851
2853
2854 pgood = req->source.value.good;
2855
2856 switch (req->range) {
2857 case REQ_RANGE_LOCAL:
2858 case REQ_RANGE_CITY:
2859 /* The requirement is filled if the city imports good of requested type. */
2860 if (!context->city) {
2861 return TRI_MAYBE;
2862 }
2866 case REQ_RANGE_TILE:
2868 case REQ_RANGE_ADJACENT:
2871 case REQ_RANGE_PLAYER:
2872 case REQ_RANGE_TEAM:
2873 case REQ_RANGE_ALLIANCE:
2874 case REQ_RANGE_WORLD:
2875 case REQ_RANGE_COUNT:
2876 break;
2877 }
2878
2879 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2880
2881 return TRI_MAYBE;
2882}
2883
2884/**********************************************************************/
2891static enum fc_tristate
2893 const struct req_context *context,
2894 const struct player *other_player,
2895 const struct requirement *req)
2896{
2898
2899 return BOOL_TO_TRISTATE(context->action
2900 && action_number(context->action)
2901 == action_number(req->source.value.action));
2902}
2903
2904/**********************************************************************/
2912static enum fc_tristate
2914 const struct req_context *context,
2915 const struct player *other_player,
2916 const struct requirement *req)
2917{
2919
2920 return BOOL_TO_TRISTATE(context->output
2921 && context->output->index
2922 == req->source.value.outputtype);
2923}
2924
2925/**********************************************************************/
2932static enum fc_tristate
2934 const struct req_context *context,
2935 const struct player *other_player,
2936 const struct requirement *req)
2937{
2939
2940 return BOOL_TO_TRISTATE(context->specialist
2941 && context->specialist
2942 == req->source.value.specialist);
2943}
2944
2945/**********************************************************************/
2952static enum fc_tristate
2954 const struct req_context *context,
2955 const struct player *other_player,
2956 const struct requirement *req)
2957{
2958 const struct terrain *pterrain;
2959
2961
2962 pterrain = req->source.value.terrain;
2963
2964 switch (req->range) {
2965 case REQ_RANGE_TILE:
2966 /* The requirement is filled if the tile has the terrain. */
2967 if (!context->tile) {
2968 return TRI_MAYBE;
2969 }
2970 return pterrain && tile_terrain(context->tile) == pterrain;
2972 if (!context->tile) {
2973 return TRI_MAYBE;
2974 }
2975 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
2976 case REQ_RANGE_ADJACENT:
2977 if (!context->tile) {
2978 return TRI_MAYBE;
2979 }
2980 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
2981 case REQ_RANGE_CITY:
2982 if (!context->city) {
2983 return TRI_MAYBE;
2984 }
2985 if (pterrain != NULL) {
2987 city_tile(context->city), ptile) {
2988 if (tile_terrain(ptile) == pterrain) {
2989 return TRI_YES;
2990 }
2992 }
2993 return TRI_NO;
2995 if (!context->city) {
2996 return TRI_MAYBE;
2997 }
2998 if (pterrain != NULL) {
2999 enum fc_tristate ret;
3000
3002 city_tile(context->city), ptile) {
3003 if (tile_terrain(ptile) == pterrain) {
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_terrain(ptile) == pterrain) {
3016 return TRI_YES;
3017 }
3019 }
3021
3022 return ret;
3023 }
3024
3025 return TRI_MAYBE;
3027 case REQ_RANGE_PLAYER:
3028 case REQ_RANGE_TEAM:
3029 case REQ_RANGE_ALLIANCE:
3030 case REQ_RANGE_WORLD:
3031 case REQ_RANGE_LOCAL:
3032 case REQ_RANGE_COUNT:
3033 break;
3034 }
3035
3036 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3037
3038 return TRI_MAYBE;
3039}
3040
3041/**********************************************************************/
3049static enum fc_tristate
3051 const struct req_context *context,
3052 const struct player *other_player,
3053 const struct requirement *req)
3054{
3055 enum terrain_class pclass;
3056 enum fc_tristate ret;
3057
3059
3061
3062 switch (req->range) {
3063 case REQ_RANGE_TILE:
3064 /* The requirement is filled if the tile has the terrain of correct class. */
3065 if (!context->tile) {
3066 return TRI_MAYBE;
3067 }
3070 if (!context->tile) {
3071 return TRI_MAYBE;
3072 }
3075 case REQ_RANGE_ADJACENT:
3076 if (!context->tile) {
3077 return TRI_MAYBE;
3078 }
3081 case REQ_RANGE_CITY:
3082 if (!context->city) {
3083 return TRI_MAYBE;
3084 }
3086 city_tile(context->city), ptile) {
3087 const struct terrain *pterrain = tile_terrain(ptile);
3088
3089 if (pterrain != T_UNKNOWN
3090 && terrain_type_terrain_class(pterrain) == pclass) {
3091 return TRI_YES;
3092 }
3094
3095 return TRI_NO;
3097 if (!context->city) {
3098 return TRI_MAYBE;
3099 }
3101 city_tile(context->city), ptile) {
3102 const struct terrain *pterrain = tile_terrain(ptile);
3103
3104 if (pterrain != T_UNKNOWN
3105 && terrain_type_terrain_class(pterrain) == pclass) {
3106 return TRI_YES;
3107 }
3109
3110 ret = TRI_NO;
3112 if (trade_partner == NULL) {
3113 ret = TRI_MAYBE;
3114 } else {
3116 city_tile(trade_partner), ptile) {
3117 const struct terrain *pterrain = tile_terrain(ptile);
3118
3119 if (pterrain != T_UNKNOWN
3120 && terrain_type_terrain_class(pterrain) == pclass) {
3121 return TRI_YES;
3122 }
3124 }
3126
3127 return ret;
3129 case REQ_RANGE_PLAYER:
3130 case REQ_RANGE_TEAM:
3131 case REQ_RANGE_ALLIANCE:
3132 case REQ_RANGE_WORLD:
3133 case REQ_RANGE_LOCAL:
3134 case REQ_RANGE_COUNT:
3135 break;
3136 }
3137
3138 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3139
3140 return TRI_MAYBE;
3141}
3142
3143/**********************************************************************/
3151static enum fc_tristate
3153 const struct req_context *context,
3154 const struct player *other_player,
3155 const struct requirement *req)
3156{
3158 enum fc_tristate ret;
3159
3161
3163
3164 switch (req->range) {
3165 case REQ_RANGE_TILE:
3166 /* The requirement is fulfilled if the tile has a terrain with
3167 * correct flag. */
3168 if (!context->tile) {
3169 return TRI_MAYBE;
3170 }
3172 terrflag));
3174 if (!context->tile) {
3175 return TRI_MAYBE;
3176 }
3178 terrflag)
3180 terrflag));
3181 case REQ_RANGE_ADJACENT:
3182 if (!context->tile) {
3183 return TRI_MAYBE;
3184 }
3186 terrflag)
3188 terrflag));
3189 case REQ_RANGE_CITY:
3190 if (!context->city) {
3191 return TRI_MAYBE;
3192 }
3194 city_tile(context->city), ptile) {
3195 const struct terrain *pterrain = tile_terrain(ptile);
3196
3197 if (pterrain != T_UNKNOWN
3198 && terrain_has_flag(pterrain, terrflag)) {
3199 return TRI_YES;
3200 }
3202
3203 return TRI_NO;
3205 if (!context->city) {
3206 return TRI_MAYBE;
3207 }
3209 city_tile(context->city), ptile) {
3210 const struct terrain *pterrain = tile_terrain(ptile);
3211
3212 if (pterrain != T_UNKNOWN
3213 && terrain_has_flag(pterrain, terrflag)) {
3214 return TRI_YES;
3215 }
3217
3218 ret = TRI_NO;
3220 if (trade_partner == NULL) {
3221 ret = TRI_MAYBE;
3222 } else {
3224 city_tile(trade_partner), ptile) {
3225 const struct terrain *pterrain = tile_terrain(ptile);
3226
3227 if (pterrain != T_UNKNOWN
3228 && terrain_has_flag(pterrain, terrflag)) {
3229 return TRI_YES;
3230 }
3232 }
3234
3235 return ret;
3237 case REQ_RANGE_PLAYER:
3238 case REQ_RANGE_TEAM:
3239 case REQ_RANGE_ALLIANCE:
3240 case REQ_RANGE_WORLD:
3241 case REQ_RANGE_LOCAL:
3242 case REQ_RANGE_COUNT:
3243 break;
3244 }
3245
3246 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3247
3248 return TRI_MAYBE;
3249}
3250
3251/**********************************************************************/
3258static enum fc_tristate
3260 const struct req_context *context,
3261 const struct player *other_player,
3262 const struct requirement *req)
3263{
3264 enum road_flag_id roadflag;
3265 enum fc_tristate ret;
3266
3268
3269 roadflag = req->source.value.roadflag;
3270
3271 switch (req->range) {
3272 case REQ_RANGE_LOCAL:
3273 {
3274 if (!context->extra) {
3275 return TRI_MAYBE;
3276 }
3277 struct road_type *r = extra_road_get(context->extra);
3278
3279 return BOOL_TO_TRISTATE(
3280 r && road_has_flag(r, roadflag)
3281 );
3282 }
3283 case REQ_RANGE_TILE:
3284 /* The requirement is filled if the tile has a road with correct flag. */
3285 if (!context->tile) {
3286 return TRI_MAYBE;
3287 }
3288 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3290 if (!context->tile) {
3291 return TRI_MAYBE;
3292 }
3293 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3295 roadflag));
3296 case REQ_RANGE_ADJACENT:
3297 if (!context->tile) {
3298 return TRI_MAYBE;
3299 }
3300 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3302 roadflag));
3303 case REQ_RANGE_CITY:
3304 if (!context->city) {
3305 return TRI_MAYBE;
3306 }
3308 city_tile(context->city), ptile) {
3309 if (tile_has_road_flag(ptile, roadflag)) {
3310 return TRI_YES;
3311 }
3313
3314 return TRI_NO;
3316 if (!context->city) {
3317 return TRI_MAYBE;
3318 }
3320 city_tile(context->city), ptile) {
3321 if (tile_has_road_flag(ptile, roadflag)) {
3322 return TRI_YES;
3323 }
3325
3326 ret = TRI_NO;
3328 if (trade_partner == NULL) {
3329 ret = TRI_MAYBE;
3330 } else {
3332 city_tile(trade_partner), ptile) {
3333 if (tile_has_road_flag(ptile, roadflag)) {
3334 return TRI_YES;
3335 }
3337 }
3339
3340 return ret;
3342 case REQ_RANGE_PLAYER:
3343 case REQ_RANGE_TEAM:
3344 case REQ_RANGE_ALLIANCE:
3345 case REQ_RANGE_WORLD:
3346 case REQ_RANGE_COUNT:
3347 break;
3348 }
3349
3350 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3351
3352 return TRI_MAYBE;
3353}
3354
3355/**********************************************************************/
3362static enum fc_tristate
3364 const struct req_context *context,
3365 const struct player *other_player,
3366 const struct requirement *req)
3367{
3368 enum extra_flag_id extraflag;
3369 enum fc_tristate ret;
3370
3372
3373 extraflag = req->source.value.extraflag;
3374
3375 switch (req->range) {
3376 case REQ_RANGE_LOCAL:
3377 if (!context->extra) {
3378 return TRI_MAYBE;
3379 }
3380 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3381 case REQ_RANGE_TILE:
3382 /* The requirement is filled if the tile has an extra with correct flag. */
3383 if (!context->tile) {
3384 return TRI_MAYBE;
3385 }
3386 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3388 if (!context->tile) {
3389 return TRI_MAYBE;
3390 }
3391 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3392 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3393 case REQ_RANGE_ADJACENT:
3394 if (!context->tile) {
3395 return TRI_MAYBE;
3396 }
3397 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3398 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3399 case REQ_RANGE_CITY:
3400 if (!context->city) {
3401 return TRI_MAYBE;
3402 }
3404 city_tile(context->city), ptile) {
3405 if (tile_has_extra_flag(ptile, extraflag)) {
3406 return TRI_YES;
3407 }
3409
3410 return TRI_NO;
3412 if (!context->city) {
3413 return TRI_MAYBE;
3414 }
3416 city_tile(context->city), ptile) {
3417 if (tile_has_extra_flag(ptile, extraflag)) {
3418 return TRI_YES;
3419 }
3421
3422 ret = TRI_NO;
3424 if (trade_partner == NULL) {
3425 ret = TRI_MAYBE;
3426 } else {
3428 city_tile(trade_partner), ptile) {
3429 if (tile_has_extra_flag(ptile, extraflag)) {
3430 return TRI_YES;
3431 }
3433 }
3435
3436 return ret;
3438 case REQ_RANGE_PLAYER:
3439 case REQ_RANGE_TEAM:
3440 case REQ_RANGE_ALLIANCE:
3441 case REQ_RANGE_WORLD:
3442 case REQ_RANGE_COUNT:
3443 break;
3444 }
3445
3446 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3447
3448 return TRI_MAYBE;
3449}
3450
3451/**********************************************************************/
3459static enum fc_tristate
3461 const struct req_context *context,
3462 const struct player *other_player,
3463 const struct requirement *req)
3464{
3466
3468
3470
3471 if (!context->tile) {
3472 return TRI_MAYBE;
3473 }
3474
3475 switch (req->range) {
3476 case REQ_RANGE_TILE:
3480 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
3481 case REQ_RANGE_CITY:
3484 case REQ_RANGE_PLAYER:
3485 case REQ_RANGE_TEAM:
3486 case REQ_RANGE_ALLIANCE:
3487 case REQ_RANGE_WORLD:
3488 case REQ_RANGE_LOCAL:
3489 case REQ_RANGE_COUNT:
3490 break;
3491 }
3492
3493 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3494
3495 return TRI_MAYBE;
3496}
3497
3498/**********************************************************************/
3505static enum fc_tristate
3507 const struct req_context *context,
3508 const struct player *other_player,
3509 const struct requirement *req)
3510{
3512
3513 if (context->player == NULL) {
3514 return TRI_MAYBE;
3515 } else {
3517 == req->source.value.govern);
3518 }
3519}
3520
3521/**********************************************************************/
3528static enum fc_tristate
3530 const struct req_context *context,
3531 const struct player *other_player,
3532 const struct requirement *req)
3533{
3535
3536 if (context->player == NULL) {
3537 return TRI_MAYBE;
3538 } else {
3539 return BOOL_TO_TRISTATE(context->player->style
3540 == req->source.value.style);
3541 }
3542}
3543
3544/**********************************************************************/
3551static enum fc_tristate
3553 const struct req_context *context,
3554 const struct player *other_player,
3555 const struct requirement *req)
3556{
3558
3559 switch (req->range) {
3560 case REQ_RANGE_WORLD:
3561 /* "None" does not count */
3562 return ((game.info.global_advance_count - 1)
3563 >= req->source.value.min_techs);
3564 case REQ_RANGE_PLAYER:
3565 if (context->player == NULL) {
3566 return TRI_MAYBE;
3567 } else {
3568 /* "None" does not count */
3569 return BOOL_TO_TRISTATE(
3570 (research_get(context->player)->techs_researched - 1)
3571 >= req->source.value.min_techs
3572 );
3573 }
3574 default:
3575 return TRI_MAYBE;
3576 }
3577}
3578
3579/**********************************************************************/
3586static enum fc_tristate
3588 const struct req_context *context,
3589 const struct player *other_player,
3590 const struct requirement *req)
3591{
3593
3594 if (context->player == NULL) {
3595 return TRI_MAYBE;
3596 } else {
3597 return BOOL_TO_TRISTATE(is_ai(context->player)
3598 && context->player->ai_common.skill_level
3599 == req->source.value.ai_level);
3600 }
3601}
3602
3603/**********************************************************************/
3610static enum fc_tristate
3612 const struct req_context *context,
3613 const struct player *other_player,
3614 const struct requirement *req)
3615{
3616 const struct nation_type *nation;
3617
3619
3620 nation = req->source.value.nation;
3621
3622 switch (req->range) {
3623 case REQ_RANGE_PLAYER:
3624 if (context->player == NULL) {
3625 return TRI_MAYBE;
3626 }
3627 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
3628 case REQ_RANGE_TEAM:
3629 case REQ_RANGE_ALLIANCE:
3630 if (context->player == NULL) {
3631 return TRI_MAYBE;
3632 }
3633 players_iterate_alive(plr2) {
3634 if (players_in_same_range(context->player, plr2, req->range)) {
3635 if (nation_of_player(plr2) == nation) {
3636 return TRI_YES;
3637 }
3638 }
3640 return TRI_NO;
3641 case REQ_RANGE_WORLD:
3642 /* NB: if a player is ever removed outright from the game
3643 * (e.g. via /remove), rather than just dying, this 'survives'
3644 * requirement will stop being true for their nation.
3645 * create_command_newcomer() can also cause this to happen. */
3646 return BOOL_TO_TRISTATE(NULL != nation->player
3647 && (req->survives || nation->player->is_alive));
3648 case REQ_RANGE_LOCAL:
3649 case REQ_RANGE_TILE:
3651 case REQ_RANGE_ADJACENT:
3652 case REQ_RANGE_CITY:
3655 case REQ_RANGE_COUNT:
3656 break;
3657 }
3658
3659 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3660
3661 return TRI_MAYBE;
3662}
3663
3664/**********************************************************************/
3672static enum fc_tristate
3674 const struct req_context *context,
3675 const struct player *other_player,
3676 const struct requirement *req)
3677{
3678 const struct nation_group *ngroup;
3679
3681
3683
3684 switch (req->range) {
3685 case REQ_RANGE_PLAYER:
3686 if (context->player == NULL) {
3687 return TRI_MAYBE;
3688 }
3690 nation_of_player(context->player), ngroup));
3691 case REQ_RANGE_TEAM:
3692 case REQ_RANGE_ALLIANCE:
3693 case REQ_RANGE_WORLD:
3694 if (context->player == NULL) {
3695 return TRI_MAYBE;
3696 }
3697 players_iterate_alive(plr2) {
3698 if (players_in_same_range(context->player, plr2, req->range)) {
3700 return TRI_YES;
3701 }
3702 }
3704 return TRI_NO;
3705 case REQ_RANGE_LOCAL:
3706 case REQ_RANGE_TILE:
3708 case REQ_RANGE_ADJACENT:
3709 case REQ_RANGE_CITY:
3712 case REQ_RANGE_COUNT:
3713 break;
3714 }
3715
3716 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3717
3718 return TRI_MAYBE;
3719}
3720
3721/**********************************************************************/
3729static enum fc_tristate
3731 const struct req_context *context,
3732 const struct player *other_player,
3733 const struct requirement *req)
3734{
3735 const struct nation_type *nationality;
3736 enum fc_tristate ret;
3737
3739
3740 nationality = req->source.value.nationality;
3741
3742 switch (req->range) {
3743 case REQ_RANGE_CITY:
3744 if (context->city == NULL) {
3745 return TRI_MAYBE;
3746 }
3747 citizens_iterate(context->city, slot, count) {
3748 if (player_slot_get_player(slot)->nation == nationality) {
3749 return TRI_YES;
3750 }
3752
3753 return TRI_NO;
3755 if (context->city == NULL) {
3756 return TRI_MAYBE;
3757 }
3758 citizens_iterate(context->city, slot, count) {
3759 if (player_slot_get_player(slot)->nation == nationality) {
3760 return TRI_YES;
3761 }
3763
3764 ret = TRI_NO;
3766 if (trade_partner == NULL) {
3767 ret = TRI_MAYBE;
3768 } else {
3769 citizens_iterate(trade_partner, slot, count) {
3770 if (player_slot_get_player(slot)->nation == nationality) {
3771 return TRI_YES;
3772 }
3774 }
3776
3777 return ret;
3778 case REQ_RANGE_PLAYER:
3779 case REQ_RANGE_TEAM:
3780 case REQ_RANGE_ALLIANCE:
3781 case REQ_RANGE_WORLD:
3782 case REQ_RANGE_LOCAL:
3783 case REQ_RANGE_TILE:
3785 case REQ_RANGE_ADJACENT:
3787 case REQ_RANGE_COUNT:
3788 break;
3789 }
3790
3791 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3792
3793 return TRI_MAYBE;
3794}
3795
3796/**********************************************************************/
3804static enum fc_tristate
3806 const struct req_context *context,
3807 const struct player *other_player,
3808 const struct requirement *req)
3809{
3810 const struct nation_type *nation;
3811
3813
3814 nation = req->source.value.origowner;
3815
3816 switch (req->range) {
3817 case REQ_RANGE_CITY:
3818 if (context->city == NULL || context->city->original == NULL) {
3819 return TRI_MAYBE;
3820 }
3821 if (player_nation(context->city->original) == nation) {
3822 return TRI_YES;
3823 }
3824
3825 return TRI_NO;
3827 case REQ_RANGE_PLAYER:
3828 case REQ_RANGE_TEAM:
3829 case REQ_RANGE_ALLIANCE:
3830 case REQ_RANGE_WORLD:
3831 case REQ_RANGE_LOCAL:
3832 case REQ_RANGE_TILE:
3834 case REQ_RANGE_ADJACENT:
3836 case REQ_RANGE_COUNT:
3837 break;
3838 }
3839
3840 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3841
3842 return TRI_MAYBE;
3843}
3844
3845/**********************************************************************/
3849 const struct player *other_player,
3850 enum req_range range,
3851 int diplrel)
3852{
3853 switch (range) {
3854 case REQ_RANGE_PLAYER:
3855 if (target_player == NULL) {
3856 return TRI_MAYBE;
3857 }
3859 case REQ_RANGE_TEAM:
3860 case REQ_RANGE_ALLIANCE:
3861 case REQ_RANGE_WORLD:
3862 if (target_player == NULL) {
3863 return TRI_MAYBE;
3864 }
3865 players_iterate_alive(plr2) {
3867 if (is_diplrel_to_other(plr2, diplrel)) {
3868 return TRI_YES;
3869 }
3870 }
3872 return TRI_NO;
3873 case REQ_RANGE_LOCAL:
3874 if (target_player == NULL || other_player == NULL) {
3875 return TRI_MAYBE;
3876 }
3877 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
3878 case REQ_RANGE_TILE:
3880 case REQ_RANGE_ADJACENT:
3881 case REQ_RANGE_CITY:
3884 case REQ_RANGE_COUNT:
3885 break;
3886 }
3887
3888 fc_assert_msg(FALSE, "Invalid range %d.", range);
3889
3890 return TRI_MAYBE;
3891}
3892
3893/**********************************************************************/
3900static enum fc_tristate
3902 const struct req_context *context,
3903 const struct player *other_player,
3904 const struct requirement *req)
3905{
3907
3908 return is_diplrel_in_range(context->player, other_player, req->range,
3909 req->source.value.diplrel);
3910}
3911
3912/**********************************************************************/
3920static enum fc_tristate
3922 const struct req_context *context,
3923 const struct player *other_player,
3924 const struct requirement *req)
3925{
3927
3928 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
3929 : NULL,
3930 context->player,
3931 req->range,
3932 req->source.value.diplrel);
3933}
3934
3935/**********************************************************************/
3944static enum fc_tristate
3946 const struct req_context *context,
3947 const struct player *other_player,
3948 const struct requirement *req)
3949{
3951
3952 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
3953 : NULL,
3954 other_player,
3955 req->range,
3956 req->source.value.diplrel);
3957}
3958
3959/**********************************************************************/
3962static enum fc_tristate
3964 const struct player *other_player,
3965 enum req_range range,
3966 int diplrel)
3967{
3968 enum fc_tristate out = TRI_NO;
3969
3970 if (target_tile == NULL) {
3971 return TRI_MAYBE;
3972 }
3973
3976 unit_owner(target_unit), other_player, range, diplrel);
3977
3980
3981 return out;
3982}
3983
3984/**********************************************************************/
3993static enum fc_tristate
3995 const struct req_context *context,
3996 const struct player *other_player,
3997 const struct requirement *req)
3998{
4000
4001 return is_diplrel_unitany_in_range(context->tile, context->player,
4002 req->range,
4003 req->source.value.diplrel);
4004}
4005
4006/**********************************************************************/
4015static enum fc_tristate
4017 const struct req_context *context,
4018 const struct player *other_player,
4019 const struct requirement *req)
4020{
4022
4023 return is_diplrel_unitany_in_range(context->tile, other_player,
4024 req->range,
4025 req->source.value.diplrel);
4026}
4027
4028/**********************************************************************/
4035static enum fc_tristate
4037 const struct req_context *context,
4038 const struct player *other_player,
4039 const struct requirement *req)
4040{
4041 const struct unit_type *punittype;
4042
4044
4045 punittype = req->source.value.utype;
4046
4047 if (req->range != REQ_RANGE_LOCAL) {
4048 return TRI_NO;
4049 }
4050 if (!context->unittype) {
4051 return TRI_MAYBE;
4052 }
4053
4054 return BOOL_TO_TRISTATE(context->unittype == punittype);
4055}
4056
4057/**********************************************************************/
4064static enum fc_tristate
4066 const struct req_context *context,
4067 const struct player *other_player,
4068 const struct requirement *req)
4069{
4070 enum unit_type_flag_id unitflag;
4071
4073
4074 unitflag = req->source.value.unitflag;
4075
4076 if (req->range != REQ_RANGE_LOCAL) {
4077 return TRI_NO;
4078 }
4079 if (!context->unittype) {
4080 return TRI_MAYBE;
4081 }
4082
4083 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4084}
4085
4086/**********************************************************************/
4093static enum fc_tristate
4095 const struct req_context *context,
4096 const struct player *other_player,
4097 const struct requirement *req)
4098{
4099 const struct unit_class *pclass;
4100
4102
4103 pclass = req->source.value.uclass;
4104
4105 if (req->range != REQ_RANGE_LOCAL) {
4106 return TRI_NO;
4107 }
4108 if (!context->unittype) {
4109 return TRI_MAYBE;
4110 }
4111
4112 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4113}
4114
4115/**********************************************************************/
4123static enum fc_tristate
4125 const struct req_context *context,
4126 const struct player *other_player,
4127 const struct requirement *req)
4128{
4130
4132
4134
4135 if (req->range != REQ_RANGE_LOCAL) {
4136 return TRI_NO;
4137 }
4138 if (!context->unittype) {
4139 return TRI_MAYBE;
4140 }
4141
4143}
4144
4145/**********************************************************************/
4152static enum fc_tristate
4154 const struct req_context *context,
4155 const struct player *other_player,
4156 const struct requirement *req)
4157{
4158 enum ustate_prop uprop;
4159
4161
4163
4165 "Unsupported range \"%s\"",
4166 req_range_name(req->range));
4167
4168 /* Could be asked with incomplete data.
4169 * is_req_active() will handle it based on prob_type. */
4170 if (context->unit == NULL) {
4171 return TRI_MAYBE;
4172 }
4173
4174 switch (uprop) {
4175 case USP_TRANSPORTED:
4176 return BOOL_TO_TRISTATE(context->unit->transporter != NULL);
4177 case USP_LIVABLE_TILE:
4178 return BOOL_TO_TRISTATE(
4180 unit_tile(context->unit)));
4181 break;
4182 case USP_TRANSPORTING:
4184 case USP_HAS_HOME_CITY:
4185 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
4186 case USP_NATIVE_TILE:
4187 return BOOL_TO_TRISTATE(
4189 unit_tile(context->unit)));
4190 break;
4191 case USP_NATIVE_EXTRA:
4192 return BOOL_TO_TRISTATE(
4194 unit_type_get(context->unit)));
4195 break;
4197 return BOOL_TO_TRISTATE(context->unit->moved);
4198 case USP_COUNT:
4199 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
4200 /* Invalid property is unknowable. */
4201 return TRI_NO;
4202 }
4203
4204 /* Should never be reached */
4205 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
4206
4207 return TRI_NO;
4208}
4209
4210/**********************************************************************/
4217static enum fc_tristate
4219 const struct req_context *context,
4220 const struct player *other_player,
4221 const struct requirement *req)
4222{
4223 enum unit_activity activity;
4224
4226
4227 activity = req->source.value.activity;
4228
4230 "Unsupported range \"%s\"",
4231 req_range_name(req->range));
4232
4233 if (context->unit == NULL) {
4234 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
4235 * it's the zero value that context has by default - so many callers
4236 * who meant not to set specific activity actually have ACTIVITY_IDLE
4237 * instead of ACTIVITY_LAST */
4238 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
4239 return BOOL_TO_TRISTATE(activity == context->activity);
4240 }
4241
4242 /* Could be asked with incomplete data.
4243 * is_req_active() will handle it based on prob_type. */
4244 return TRI_MAYBE;
4245 }
4246
4247 switch (context->unit->activity) {
4248 case ACTIVITY_IDLE:
4249 case ACTIVITY_SENTRY:
4250 case ACTIVITY_GOTO:
4251 case ACTIVITY_EXPLORE:
4252 /* Seen as idle. */
4253 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
4254 default:
4255 /* Handled below. */
4256 break;
4257 }
4258
4259 return BOOL_TO_TRISTATE(context->unit->activity == activity);
4260}
4261
4262/**********************************************************************/
4269static enum fc_tristate
4271 const struct req_context *context,
4272 const struct player *other_player,
4273 const struct requirement *req)
4274{
4276
4277 if (context->unit == NULL) {
4278 return TRI_MAYBE;
4279 } else {
4280 return BOOL_TO_TRISTATE(context->unit->veteran
4281 >= req->source.value.minveteran);
4282 }
4283}
4284
4285/**********************************************************************/
4293static enum fc_tristate
4295 const struct req_context *context,
4296 const struct player *other_player,
4297 const struct requirement *req)
4298{
4300
4301 if (context->unit == NULL) {
4302 return TRI_MAYBE;
4303 } else {
4305 <= context->unit->moves_left);
4306 }
4307}
4308
4309/**********************************************************************/
4317static enum fc_tristate
4319 const struct req_context *context,
4320 const struct player *other_player,
4321 const struct requirement *req)
4322{
4324
4325 if (context->unit == NULL) {
4326 return TRI_MAYBE;
4327 } else {
4329 <= context->unit->hp);
4330 }
4331}
4332
4333/**********************************************************************/
4340static enum fc_tristate
4342 const struct req_context *context,
4343 const struct player *other_player,
4344 const struct requirement *req)
4345{
4347
4348 switch (req->range) {
4349 case REQ_RANGE_LOCAL:
4350 if (context->unit == NULL || !is_server()) {
4351 return TRI_MAYBE;
4352 } else {
4353 return BOOL_TO_TRISTATE(
4354 req->source.value.age <=
4355 game.info.turn - context->unit->birth_turn);
4356 }
4357 break;
4358 case REQ_RANGE_CITY:
4359 if (context->city == NULL) {
4360 return TRI_MAYBE;
4361 } else {
4362 return BOOL_TO_TRISTATE(
4363 req->source.value.age <=
4364 game.info.turn - context->city->turn_founded);
4365 }
4366 break;
4367 case REQ_RANGE_PLAYER:
4368 if (context->player == NULL) {
4369 return TRI_MAYBE;
4370 } else {
4371 return BOOL_TO_TRISTATE(req->source.value.age
4372 <= player_age(context->player));
4373 }
4374 break;
4375 default:
4376 return TRI_MAYBE;
4377 break;
4378 }
4379}
4380
4381/**********************************************************************/
4388static enum fc_tristate
4390 const struct req_context *context,
4391 const struct player *other_player,
4392 const struct requirement *req)
4393{
4395
4396 switch (req->range) {
4397 case REQ_RANGE_LOCAL:
4398 if (context->unit == NULL || !is_server()) {
4399 return TRI_MAYBE;
4400 } else {
4401 return BOOL_TO_TRISTATE(
4402 req->source.value.form_age <=
4403 game.info.turn - context->unit->current_form_turn);
4404 }
4405 break;
4406 default:
4407 return TRI_MAYBE;
4408 break;
4409 }
4410}
4411
4412/**********************************************************************/
4415static bool is_city_in_tile(const struct tile *ptile,
4416 const struct city *pcity)
4417{
4418 if (pcity == NULL) {
4419 return tile_city(ptile) != NULL;
4420 } else {
4421 return is_city_center(pcity, ptile);
4422 }
4423}
4424
4425/**********************************************************************/
4432static enum fc_tristate
4434 const struct req_context *context,
4435 const struct player *other_player,
4436 const struct requirement *req)
4437{
4438 enum citytile_type citytile;
4439
4441
4442 citytile = req->source.value.citytile;
4443
4445 if (context->tile == NULL) {
4446 return TRI_MAYBE;
4447 }
4448
4449 switch (citytile) {
4450 case CITYT_CENTER:
4451 switch (req->range) {
4452 case REQ_RANGE_TILE:
4454 context->city));
4456 if (is_city_in_tile(context->tile, context->city)) {
4457 return TRI_YES;
4458 }
4460 if (is_city_in_tile(adjc_tile, context->city)) {
4461 return TRI_YES;
4462 }
4464
4465 return TRI_NO;
4466 case REQ_RANGE_ADJACENT:
4467 if (is_city_in_tile(context->tile, context->city)) {
4468 return TRI_YES;
4469 }
4471 if (is_city_in_tile(adjc_tile, context->city)) {
4472 return TRI_YES;
4473 }
4475
4476 return TRI_NO;
4477 case REQ_RANGE_CITY:
4480 case REQ_RANGE_PLAYER:
4481 case REQ_RANGE_TEAM:
4482 case REQ_RANGE_ALLIANCE:
4483 case REQ_RANGE_WORLD:
4484 case REQ_RANGE_LOCAL:
4485 case REQ_RANGE_COUNT:
4486 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4487 break;
4488 }
4489
4490 return TRI_MAYBE;
4491 case CITYT_CLAIMED:
4492 switch (req->range) {
4493 case REQ_RANGE_TILE:
4494 return BOOL_TO_TRISTATE(context->tile->owner != NULL);
4496 if (context->tile->owner != NULL) {
4497 return TRI_YES;
4498 }
4500 if (adjc_tile->owner != NULL) {
4501 return TRI_YES;
4502 }
4504
4505 return TRI_NO;
4506 case REQ_RANGE_ADJACENT:
4507 if (context->tile->owner != NULL) {
4508 return TRI_YES;
4509 }
4511 if (adjc_tile->owner != NULL) {
4512 return TRI_YES;
4513 }
4515
4516 return TRI_NO;
4517 case REQ_RANGE_CITY:
4520 case REQ_RANGE_PLAYER:
4521 case REQ_RANGE_TEAM:
4522 case REQ_RANGE_ALLIANCE:
4523 case REQ_RANGE_WORLD:
4524 case REQ_RANGE_LOCAL:
4525 case REQ_RANGE_COUNT:
4526 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4527 break;
4528 }
4529
4530 return TRI_MAYBE;
4531 case CITYT_EXTRAS_OWNED:
4532 switch (req->range) {
4533 case REQ_RANGE_TILE:
4534 return BOOL_TO_TRISTATE(context->tile->extras_owner != NULL);
4536 if (context->tile->extras_owner != NULL) {
4537 return TRI_YES;
4538 }
4540 if (adjc_tile->extras_owner != NULL) {
4541 return TRI_YES;
4542 }
4544
4545 return TRI_NO;
4546 case REQ_RANGE_ADJACENT:
4547 if (context->tile->extras_owner != NULL) {
4548 return TRI_YES;
4549 }
4551 if (adjc_tile->extras_owner != NULL) {
4552 return TRI_YES;
4553 }
4555
4556 return TRI_NO;
4557 case REQ_RANGE_CITY:
4560 case REQ_RANGE_PLAYER:
4561 case REQ_RANGE_TEAM:
4562 case REQ_RANGE_ALLIANCE:
4563 case REQ_RANGE_WORLD:
4564 case REQ_RANGE_LOCAL:
4565 case REQ_RANGE_COUNT:
4566 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4567 break;
4568 }
4569
4570 return TRI_MAYBE;
4571 case CITYT_WORKED:
4572 switch (req->range) {
4573 case REQ_RANGE_TILE:
4574 return BOOL_TO_TRISTATE(context->tile->worked != NULL);
4576 if (context->tile->worked != NULL) {
4577 return TRI_YES;
4578 }
4580 if (adjc_tile->worked != NULL) {
4581 return TRI_YES;
4582 }
4584
4585 return TRI_NO;
4586 case REQ_RANGE_ADJACENT:
4587 if (context->tile->worked != NULL) {
4588 return TRI_YES;
4589 }
4591 if (adjc_tile->worked != NULL) {
4592 return TRI_YES;
4593 }
4595
4596 return TRI_NO;
4597 case REQ_RANGE_CITY:
4600 case REQ_RANGE_PLAYER:
4601 case REQ_RANGE_TEAM:
4602 case REQ_RANGE_ALLIANCE:
4603 case REQ_RANGE_WORLD:
4604 case REQ_RANGE_LOCAL:
4605 case REQ_RANGE_COUNT:
4606 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4607 break;
4608 }
4609
4610 return TRI_MAYBE;
4612 {
4614 const struct tile *target_tile = context->tile, *cc_tile;
4615
4616 if (!context->city) {
4617 return TRI_MAYBE;
4618 }
4619 cc_tile = city_tile(context->city);
4620 if (!cc_tile) {
4621 /* Unplaced virtual city */
4622 return TRI_MAYBE;
4623 }
4625 /* Note: No special treatment of 0 == cc here*/
4626 switch (req->range) {
4627 case REQ_RANGE_TILE:
4630 if (tile_continent(target_tile) == cc) {
4631 return TRI_YES;
4632 }
4634 if (tile_continent(adjc_tile) == cc) {
4635 return TRI_YES;
4636 }
4638
4639 return TRI_NO;
4640 case REQ_RANGE_ADJACENT:
4641 if (tile_continent(target_tile) == cc) {
4642 return TRI_YES;
4643 }
4645 if (tile_continent(adjc_tile) == cc) {
4646 return TRI_YES;
4647 }
4649
4650 return TRI_NO;
4651 case REQ_RANGE_CITY:
4654 case REQ_RANGE_PLAYER:
4655 case REQ_RANGE_TEAM:
4656 case REQ_RANGE_ALLIANCE:
4657 case REQ_RANGE_WORLD:
4658 case REQ_RANGE_LOCAL:
4659 case REQ_RANGE_COUNT:
4660 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4661 break;
4662 }
4663 }
4664
4665 return TRI_MAYBE;
4667 {
4668 int n = 0;
4670 bool ukt = FALSE;
4671 const struct tile *target_tile = context->tile, *cc_tile;
4672
4673 if (!context->city) {
4674 return TRI_MAYBE;
4675 }
4676 cc_tile = city_tile(context->city);
4677 if (!cc_tile) {
4678 /* Unplaced virtual city */
4679 return TRI_MAYBE;
4680 }
4682 if (!cc) {
4683 /* Don't know the city center terrain class.
4684 * Maybe, the city floats? Even if the rules prohibit it... */
4685 return TRI_MAYBE;
4686 }
4689
4690 if (0 != tc) {
4691 bool seen = FALSE;
4692 int i = n;
4693
4694 if (tc == cc) {
4695 continue;
4696 }
4697 while (--i >= 0) {
4698 if (adjc_cont[i] == tc) {
4699 seen = TRUE;
4700 break;
4701 }
4702 }
4703 if (seen) {
4704 continue;
4705 }
4707 } else {
4708 /* Likely, it's a black tile in client and we don't know
4709 * We possibly can calculate, but keep it simple. */
4710 ukt = TRUE;
4711 }
4713 if (0 == n) {
4714 return ukt ? TRI_MAYBE : TRI_NO;
4715 }
4716
4717 switch (req->range) {
4718 case REQ_RANGE_TILE:
4719 {
4721
4722 if (cc == tc) {
4723 return TRI_NO;
4724 }
4725 if (0 == tc || ukt) {
4726 return TRI_MAYBE;
4727 }
4728 for (int i = 0; i < n; i++) {
4729 if (tc == adjc_cont[i]) {
4730 return TRI_YES;
4731 }
4732 }
4733 }
4734
4735 return TRI_NO;
4736 case REQ_RANGE_ADJACENT:
4737 if (ukt) {
4738 /* If ALL the tiles in range are on cc, we can say it's false */
4740 if (tile_continent(adjc_tile) != cc) {
4741 return TRI_MAYBE;
4742 }
4744
4745 return TRI_NO;
4746 } else {
4749
4750 if (0 == tc) {
4751 return TRI_MAYBE;
4752 }
4753 for (int i = 0; i < n; i++) {
4754 if (tc == adjc_cont[i]) {
4755 return TRI_YES;
4756 }
4757 }
4759 }
4760
4761 return TRI_NO;
4763 if (ukt) {
4764 /* If ALL the tiles in range are on cc, we can say it's false */
4766 if (tile_continent(cadjc_tile) != cc) {
4767 return TRI_MAYBE;
4768 }
4770 } else {
4773
4774 if (0 == tc) {
4775 return TRI_MAYBE;
4776 }
4777 for (int i = 0; i < n; i++) {
4778 if (tc == adjc_cont[i]) {
4779 return TRI_YES;
4780 }
4781 }
4783 }
4784
4785 return TRI_NO;
4786 case REQ_RANGE_CITY:
4789 case REQ_RANGE_PLAYER:
4790 case REQ_RANGE_TEAM:
4791 case REQ_RANGE_ALLIANCE:
4792 case REQ_RANGE_WORLD:
4793 case REQ_RANGE_LOCAL:
4794 case REQ_RANGE_COUNT:
4795 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4796 break;
4797 }
4798 }
4799
4800 return TRI_MAYBE;
4801 case CITYT_LAST:
4802 /* Handled below */
4803 break;
4804 }
4805
4806 /* Not implemented */
4807 log_error("is_req_active(): citytile %d not supported.",
4808 citytile);
4809 return TRI_MAYBE;
4810}
4811
4812/**********************************************************************/
4820static enum fc_tristate
4822 const struct req_context *context,
4823 const struct player *other_player,
4824 const struct requirement *req)
4825{
4826 enum citystatus_type citystatus;
4827
4829
4830 citystatus = req->source.value.citystatus;
4831
4832 if (context->city == NULL) {
4833 return TRI_MAYBE;
4834 }
4835
4836 switch (citystatus) {
4838 switch (req->range) {
4839 case REQ_RANGE_CITY:
4840 if (context->city->original == NULL) {
4841 return TRI_MAYBE;
4842 }
4843 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
4845 {
4846 enum fc_tristate ret;
4847
4848 if (city_owner(context->city) == context->city->original) {
4849 return TRI_YES;
4850 }
4851
4852 ret = TRI_NO;
4854 if (trade_partner == NULL || trade_partner->original == NULL) {
4855 ret = TRI_MAYBE;
4856 } else if (city_owner(trade_partner) == trade_partner->original) {
4857 return TRI_YES;
4858 }
4860
4861 return ret;
4862 }
4863 case REQ_RANGE_LOCAL:
4864 case REQ_RANGE_TILE:
4866 case REQ_RANGE_ADJACENT:
4868 case REQ_RANGE_PLAYER:
4869 case REQ_RANGE_TEAM:
4870 case REQ_RANGE_ALLIANCE:
4871 case REQ_RANGE_WORLD:
4872 case REQ_RANGE_COUNT:
4873 break;
4874 }
4875
4876 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
4877 req->range);
4878
4879 return TRI_MAYBE;
4880
4881 case CITYS_STARVED:
4882 switch (req->range) {
4883 case REQ_RANGE_CITY:
4884 return BOOL_TO_TRISTATE(context->city->had_famine);
4886 {
4887 enum fc_tristate ret;
4888
4889 if (context->city->had_famine) {
4890 return TRI_YES;
4891 }
4892
4893 ret = TRI_NO;
4895 if (trade_partner == NULL) {
4896 ret = TRI_MAYBE;
4897 } else if (trade_partner->had_famine) {
4898 return TRI_YES;
4899 }
4901
4902 return ret;
4903 }
4904 case REQ_RANGE_LOCAL:
4905 case REQ_RANGE_TILE:
4907 case REQ_RANGE_ADJACENT:
4909 case REQ_RANGE_PLAYER:
4910 case REQ_RANGE_TEAM:
4911 case REQ_RANGE_ALLIANCE:
4912 case REQ_RANGE_WORLD:
4913 case REQ_RANGE_COUNT:
4914 break;
4915 }
4916
4917 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
4918 req->range);
4919
4920 return TRI_MAYBE;
4921
4922 case CITYS_DISORDER:
4923 switch (req->range) {
4924 case REQ_RANGE_CITY:
4925 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
4927 {
4928 enum fc_tristate ret;
4929
4930 if (context->city->anarchy > 0) {
4931 return TRI_YES;
4932 }
4933
4934 ret = TRI_NO;
4936 if (trade_partner == NULL) {
4937 ret = TRI_MAYBE;
4938 } else if (trade_partner->anarchy > 0) {
4939 return TRI_YES;
4940 }
4942
4943 return ret;
4944 }
4945 case REQ_RANGE_LOCAL:
4946 case REQ_RANGE_TILE:
4948 case REQ_RANGE_ADJACENT:
4950 case REQ_RANGE_PLAYER:
4951 case REQ_RANGE_TEAM:
4952 case REQ_RANGE_ALLIANCE:
4953 case REQ_RANGE_WORLD:
4954 case REQ_RANGE_COUNT:
4955 break;
4956 }
4957
4958 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
4959 req->range);
4960
4961 return TRI_MAYBE;
4962
4963 case CITYS_CELEBRATION:
4964 switch (req->range) {
4965 case REQ_RANGE_CITY:
4966 return BOOL_TO_TRISTATE(context->city->rapture > 0);
4968 {
4969 enum fc_tristate ret;
4970
4971 if (context->city->rapture > 0) {
4972 return TRI_YES;
4973 }
4974
4975 ret = TRI_NO;
4977 if (trade_partner == NULL) {
4978 ret = TRI_MAYBE;
4979 } else if (trade_partner->rapture > 0) {
4980 return TRI_YES;
4981 }
4983
4984 return ret;
4985 }
4986 case REQ_RANGE_LOCAL:
4987 case REQ_RANGE_TILE:
4989 case REQ_RANGE_ADJACENT:
4991 case REQ_RANGE_PLAYER:
4992 case REQ_RANGE_TEAM:
4993 case REQ_RANGE_ALLIANCE:
4994 case REQ_RANGE_WORLD:
4995 case REQ_RANGE_COUNT:
4996 break;
4997 }
4998
4999 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
5000 req->range);
5001
5002 return TRI_MAYBE;
5003
5004 case CITYS_TRANSFERRED:
5005 switch (req->range) {
5006 case REQ_RANGE_CITY:
5007 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
5009 {
5010 enum fc_tristate ret;
5011
5012 if (context->city->acquire_t != CACQ_FOUNDED) {
5013 return TRI_YES;
5014 }
5015
5016 ret = TRI_NO;
5018 if (trade_partner == NULL) {
5019 ret = TRI_MAYBE;
5020 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
5021 return TRI_YES;
5022 }
5024
5025 return ret;
5026 }
5027 case REQ_RANGE_LOCAL:
5028 case REQ_RANGE_TILE:
5030 case REQ_RANGE_ADJACENT:
5032 case REQ_RANGE_PLAYER:
5033 case REQ_RANGE_TEAM:
5034 case REQ_RANGE_ALLIANCE:
5035 case REQ_RANGE_WORLD:
5036 case REQ_RANGE_COUNT:
5037 break;
5038 }
5039
5040 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
5041 req->range);
5042
5043 return TRI_MAYBE;
5044
5045 case CITYS_LAST:
5046 break;
5047 }
5048
5049 /* Not implemented */
5050 log_error("is_req_active(): citystatus %d not supported.",
5051 citystatus);
5052
5053 return TRI_MAYBE;
5054}
5055
5056/**********************************************************************/
5063static enum fc_tristate
5065 const struct req_context *context,
5066 const struct player *other_player,
5067 const struct requirement *req)
5068{
5070
5071 if (context->city == NULL) {
5072 return TRI_MAYBE;
5073 } else {
5074 if (req->range == REQ_RANGE_TRADE_ROUTE) {
5075 enum fc_tristate ret;
5076
5077 if (city_size_get(context->city) >= req->source.value.minsize) {
5078 return TRI_YES;
5079 }
5080
5081 ret = TRI_NO;
5083 if (trade_partner == NULL) {
5084 ret = TRI_MAYBE;
5085 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
5086 return TRI_YES;
5087 }
5089
5090 return ret;
5091 } else {
5093 >= req->source.value.minsize);
5094 }
5095 }
5096}
5097
5098/**********************************************************************/
5105static enum fc_tristate
5107 const struct req_context *context,
5108 const struct player *other_player,
5109 const struct requirement *req)
5110{
5111 const struct counter *count;
5112
5114
5115 count = req->source.value.counter;
5116
5117 if (NULL == context->city) {
5118 return TRI_MAYBE;
5119 }
5120 return BOOL_TO_TRISTATE(count->checkpoint <=
5121 context->city->counter_values[
5122 counter_index(count)]);
5123}
5124
5125/**********************************************************************/
5133static enum fc_tristate
5135 const struct req_context *context,
5136 const struct player *other_player,
5137 const struct requirement *req)
5138{
5139 const struct achievement *achievement;
5140
5142
5144
5145 if (req->range == REQ_RANGE_WORLD) {
5147 } else if (context->player == NULL) {
5148 return TRI_MAYBE;
5149 } else if (req->range == REQ_RANGE_ALLIANCE
5150 || req->range == REQ_RANGE_TEAM) {
5151 players_iterate_alive(plr2) {
5152 if (players_in_same_range(context->player, plr2, req->range)
5154 return TRI_YES;
5155 }
5157 return TRI_NO;
5158 } else if (req->range == REQ_RANGE_PLAYER) {
5160 return TRI_YES;
5161 } else {
5162 return TRI_NO;
5163 }
5164 }
5165
5166 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
5167
5168 return TRI_MAYBE;
5169}
5170
5171/**********************************************************************/
5179static enum fc_tristate
5181 const struct req_context *context,
5182 const struct player *other_player,
5183 const struct requirement *req)
5184{
5185 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
5186
5189
5190 switch (req->source.kind) {
5191 case VUT_MINLATITUDE:
5192 min = req->source.value.latitude;
5193 break;
5194 case VUT_MAXLATITUDE:
5195 max = req->source.value.latitude;
5196 break;
5197 default:
5199 || req->source.kind == VUT_MAXLATITUDE);
5200 break;
5201 }
5202
5203 switch (req->range) {
5204 case REQ_RANGE_WORLD:
5206 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
5207
5208 case REQ_RANGE_TILE:
5209 if (context->tile == NULL) {
5210 return TRI_MAYBE;
5211 } else {
5213
5215 }
5216
5218 if (context->tile == NULL) {
5219 return TRI_MAYBE;
5220 }
5221
5224
5226 return TRI_YES;
5227 }
5229 return TRI_NO;
5230
5231 case REQ_RANGE_ADJACENT:
5232 if (!context->tile) {
5233 return TRI_MAYBE;
5234 }
5235
5238
5240 return TRI_YES;
5241 }
5243 return TRI_NO;
5244
5245 case REQ_RANGE_CITY:
5248 case REQ_RANGE_PLAYER:
5249 case REQ_RANGE_TEAM:
5250 case REQ_RANGE_ALLIANCE:
5251 case REQ_RANGE_LOCAL:
5252 case REQ_RANGE_COUNT:
5253 break;
5254 }
5255
5257 "Illegal range %d for latitude requirement.", req->range);
5258
5259 return TRI_MAYBE;
5260}
5261
5262/**********************************************************************/
5269static enum fc_tristate
5271 const struct req_context *context,
5272 const struct player *other_player,
5273 const struct requirement *req)
5274{
5276
5278}
5279
5280/**********************************************************************/
5287static enum fc_tristate
5289 const struct req_context *context,
5290 const struct player *other_player,
5291 const struct requirement *req)
5292{
5294
5296 >= req->source.value.mincalfrag);
5297}
5298
5299/**********************************************************************/
5306static enum fc_tristate
5308 const struct req_context *context,
5309 const struct player *other_player,
5310 const struct requirement *req)
5311{
5313
5314 return BOOL_TO_TRISTATE(
5316}
5317
5318/**********************************************************************/
5325static enum fc_tristate
5327 const struct req_context *context,
5328 const struct player *other_player,
5329 const struct requirement *req)
5330{
5332
5333 return BOOL_TO_TRISTATE(
5335}
5336
5337/**********************************************************************/
5345static enum fc_tristate
5347 const struct req_context *context,
5348 const struct player *other_player,
5349 const struct requirement *req)
5350{
5352
5354 req->source.value.ssetval));
5355}
5356
5357/* Not const for potential ruleset-related adjustment */
5360
5361 /* Alphabetical order of enum constant */
5420};
5421
5422/**********************************************************************/
5435 const struct player *other_player,
5436 const struct requirement *req,
5437 const enum req_problem_type prob_type)
5438{
5439 const struct civ_map *nmap = &(wld.map);
5440 enum fc_tristate eval = tri_req_present(nmap, context, other_player, req);
5441
5442 if (eval == TRI_MAYBE) {
5443 if (prob_type == RPT_POSSIBLE) {
5444 return TRUE;
5445 } else {
5446 return FALSE;
5447 }
5448 }
5449 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
5450}
5451
5452/**********************************************************************/
5460static
5462 const struct req_context *context,
5463 const struct player *other_player,
5464 const struct requirement *req)
5465{
5466 if (context == NULL) {
5468 }
5469
5470 if (req->source.kind >= VUT_COUNT) {
5471 log_error("tri_req_present(): invalid source kind %d.",
5472 req->source.kind);
5473 return TRI_NO;
5474 }
5475
5477
5478 return req_definitions[req->source.kind].cb(nmap, context,
5479 other_player, req);
5480}
5481
5482/**********************************************************************/
5491 const struct player *other_player,
5492 const struct requirement *req)
5493{
5494 const struct civ_map *nmap = &(wld.map);
5495 enum fc_tristate eval = tri_req_present(nmap, context, other_player, req);
5496
5497 if (!req->present) {
5498 if (TRI_NO == eval) {
5499 return TRI_YES;
5500 }
5501 if (TRI_YES == eval) {
5502 return TRI_NO;
5503 }
5504 }
5505
5506 return eval;
5507}
5508
5509/**********************************************************************/
5524 const struct player *other_player,
5525 const struct requirement_vector *reqs,
5526 const enum req_problem_type prob_type)
5527{
5529 if (!is_req_active(context, other_player, preq, prob_type)) {
5530 return FALSE;
5531 }
5533
5534 return TRUE;
5535}
5536
5537/**********************************************************************/
5542 const enum req_range max_range,
5543 const struct req_context *context,
5544 const struct player *other_player,
5545 const struct requirement_vector *reqs,
5546 const enum req_problem_type prob_type)
5547{
5549 if (preq->range >= min_range && preq->range <= max_range) {
5550 if (!is_req_active(context, other_player, preq, prob_type)) {
5551 return FALSE;
5552 }
5553 }
5555
5556 return TRUE;
5557}
5558
5559/**********************************************************************/
5565enum fc_tristate
5567 const struct req_context *context,
5568 const struct player *other_player,
5569 const struct requirement *req)
5570{
5571 /* FIXME: doubles code from calendar.c */
5575 int fragment1 = fragment; /* if fragments don't advance */
5576 int year_inc, year_inc1;
5579 bool present, present1;
5580
5581 fc_assert(pass >= 0 && period >= 0);
5582 if (slowdown >= 3) {
5583 if (ypt > 1) {
5584 ypt = 1;
5585 }
5586 } else if (slowdown >= 2) {
5587 if (ypt > 2) {
5588 ypt = 2;
5589 }
5590 } else if (slowdown >= 1) {
5591 if (ypt > 5) {
5592 ypt = 5;
5593 }
5594 }
5595 year_inc = ypt * pass;
5598 int fragment_years;
5599
5600 fragment += fpt * pass;
5608 }
5610 if (year_inc + game.info.year >= 0) {
5611 year_inc++;
5612 year_inc1++;
5613 } else if (year_inc1 + game.info.year >= 0) {
5614 year_inc1++;
5615 }
5616 }
5617
5618 switch (req->source.kind) {
5619 case VUT_AGE:
5620 switch (req->range) {
5621 case REQ_RANGE_LOCAL:
5622 if (context->unit == NULL || !is_server()) {
5623 return TRI_MAYBE;
5624 } else {
5625 int ua = game.info.turn + pass - context->unit->birth_turn;
5626
5627 present = req->source.value.age <= ua;
5628 present1 = req->source.value.age <= ua + period;
5629 }
5630 break;
5631 case REQ_RANGE_CITY:
5632 if (context->city == NULL) {
5633 return TRI_MAYBE;
5634 } else {
5635 int ca = game.info.turn + pass - context->city->turn_founded;
5636
5637 present = req->source.value.age <= ca;
5638 present1 = req->source.value.age <= ca + period;
5639 }
5640 break;
5641 case REQ_RANGE_PLAYER:
5642 if (context->player == NULL) {
5643 return TRI_MAYBE;
5644 } else {
5645 present = req->source.value.age
5646 <= player_age(context->player) + pass;
5647 present1 = req->source.value.age
5648 <= player_age(context->player) + pass + period;
5649 }
5650 break;
5651 default:
5652 return TRI_MAYBE;
5653 }
5654 break;
5655 case VUT_FORM_AGE:
5656 if (context->unit == NULL || !is_server()) {
5657 return TRI_MAYBE;
5658 } else {
5659 int ua = game.info.turn + pass - context->unit->current_form_turn;
5660
5661 present = req->source.value.form_age <= ua;
5662 present1 = req->source.value.form_age <= ua + period;
5663 }
5664 break;
5665 case VUT_MINYEAR:
5666 present = game.info.year + year_inc >= req->source.value.minyear;
5668 break;
5669 case VUT_MINCALFRAG:
5671 /* Hope that the requirement is valid and fragments advance fine */
5672 return TRI_YES;
5673 }
5674 present = fragment >= req->source.value.mincalfrag;
5676 break;
5677 default:
5678 /* No special handling invented */
5679 return tri_req_active(context, other_player, req);
5680 }
5681 return BOOL_TO_TRISTATE(req->present
5682 ? present || present1 : !(present && present1));
5683}
5684
5685/**********************************************************************/
5691 (const struct req_context *context,
5692 const struct player *other_player,
5693 const struct requirement *req,
5694 void *data, int n_data)
5695{
5696 int i;
5697
5698 fc_assert_ret_val(data || n_data == 0, TRI_NO);
5699
5700 for (i = 0; i < n_data; i++) {
5701 if (are_requirements_contradictions(&((struct requirement *) data)[i],
5702 req)) {
5703 return TRI_NO;
5704 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
5705 return TRI_YES;
5706 }
5707 }
5708
5709 return tri_req_active(context, other_player, req);
5710}
5711
5712/**********************************************************************/
5718enum fc_tristate
5720 const struct player *other_player,
5721 const struct requirement_vector *reqs,
5724 void *data, int n_data)
5725{
5726 bool active = TRUE;
5727 bool certain = TRUE;
5728
5731 switch(tester(context, other_player, preq,
5732 data, n_data)) {
5733 case TRI_NO:
5734 active = FALSE;
5735 certain = TRUE;
5736 break;
5737 case TRI_YES:
5738 break;
5739 case TRI_MAYBE:
5740 certain = FALSE;
5741 if (maybe_reqs) {
5743 }
5744 break;
5745 default:
5747 active = FALSE;
5748 }
5749 if (!active) {
5750 break;
5751 }
5753
5754 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
5755}
5756
5757/**********************************************************************/
5767 const struct requirement *req)
5768{
5769 enum req_unchanging_status s;
5770 const struct civ_map *nmap = &(wld.map);
5771
5774 "Invalid source kind %d.", req->source.kind);
5776
5777 if (req->survives) {
5778 /* Special case for surviving requirements */
5779 /* Buildings may obsolete even here */
5780 if (VUT_IMPROVEMENT == req->source.kind) {
5781 const struct impr_type *b = req->source.value.building;
5782
5784 if (improvement_obsolete(context->player, b, context->city)) {
5785 /* FIXME: sometimes can unobsolete, but considering it
5786 * may sometimes put the function on endless recursion */
5787 return REQUCH_ACT; /* Mostly about techs */
5788 } else {
5789 /* NOTE: may obsoletion reqs be unchanging? Hardly but why not. */
5790 return REQUCH_NO;
5791 }
5792 }
5793 }
5794 s = unchanging_present(nmap, s, context, req);
5795 if (s != REQUCH_NO) {
5796 return unchanging_noally(nmap, s, context, req);
5797 }
5798 } else {
5801
5802 if (cond) {
5803 return cond(nmap, s, context, req);
5804 }
5805 }
5806
5807 return s;
5808}
5809
5810/**********************************************************************/
5815 const struct player *other_player,
5816 const struct requirement *req,
5818{
5820
5821 if (REQUCH_NO != u) {
5822 /* Presence is precalculated */
5823 bool auto_present = (req->survives
5824 && !(VUT_IMPROVEMENT == req->source.kind
5828
5829 if (auto_present ? req->present
5830 : is_req_active(context, other_player, req, RPT_POSSIBLE)) {
5831 /* Unchanging but does not block */
5832 return REQUCH_NO;
5833 }
5834 }
5835
5836 return u;
5837}
5838
5839/**********************************************************************/
5843bool is_req_in_vec(const struct requirement *req,
5844 const struct requirement_vector *vec)
5845{
5847 if (are_requirements_equal(req, preq)) {
5848 return TRUE;
5849 }
5851
5852 return FALSE;
5853}
5854
5855/**********************************************************************/
5862 enum universals_n kind)
5863{
5865 if (preq->present && preq->source.kind == kind) {
5866 return TRUE;
5867 }
5869 return FALSE;
5870}
5871
5872/**********************************************************************/
5881{
5882 switch (source->kind) {
5883 case VUT_ACTION:
5884 return !action_is_in_use(source->value.action);
5885 case VUT_UTFLAG:
5886 return !utype_flag_is_in_use(source->value.unitflag);
5887 case VUT_UCFLAG:
5888 return !uclass_flag_is_in_use(source->value.unitclassflag);
5889 case VUT_EXTRAFLAG:
5890 return !extra_flag_is_in_use(source->value.extraflag);
5891 case VUT_MINLATITUDE:
5892 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
5893 case VUT_MAXLATITUDE:
5894 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
5895 case VUT_COUNTER:
5896 case VUT_OTYPE:
5897 case VUT_SPECIALIST:
5898 case VUT_AI_LEVEL:
5899 case VUT_CITYTILE:
5900 case VUT_CITYSTATUS:
5901 case VUT_STYLE:
5902 case VUT_TOPO:
5903 case VUT_WRAP:
5904 case VUT_SERVERSETTING:
5905 case VUT_NATION:
5906 case VUT_NATIONGROUP:
5907 case VUT_ADVANCE:
5908 case VUT_TECHFLAG:
5909 case VUT_GOVERNMENT:
5910 case VUT_ACHIEVEMENT:
5911 case VUT_IMPROVEMENT:
5912 case VUT_SITE:
5913 case VUT_IMPR_GENUS:
5914 case VUT_IMPR_FLAG:
5915 case VUT_PLAYER_FLAG:
5916 case VUT_PLAYER_STATE:
5917 case VUT_MINSIZE:
5918 case VUT_MINCULTURE:
5919 case VUT_MINFOREIGNPCT:
5920 case VUT_MINTECHS:
5921 case VUT_NATIONALITY:
5922 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
5923 case VUT_DIPLREL:
5924 case VUT_DIPLREL_TILE:
5925 case VUT_DIPLREL_TILE_O:
5928 case VUT_MAXTILEUNITS:
5929 case VUT_UTYPE:
5930 case VUT_UCLASS:
5931 case VUT_MINVETERAN:
5932 case VUT_UNITSTATE:
5933 case VUT_ACTIVITY:
5934 case VUT_MINMOVES:
5935 case VUT_MINHP:
5936 case VUT_AGE:
5937 case VUT_FORM_AGE:
5938 case VUT_ROADFLAG:
5939 case VUT_MINCALFRAG:
5940 case VUT_TERRAIN:
5941 case VUT_EXTRA:
5942 case VUT_GOOD:
5943 case VUT_TERRAINCLASS:
5944 case VUT_TERRFLAG:
5945 case VUT_TERRAINALTER:
5946 case VUT_MINYEAR:
5947 case VUT_NONE:
5948 case VUT_COUNT:
5949 /* Not implemented. */
5950 break;
5951 }
5952
5953 return FALSE;
5954}
5955
5956/**********************************************************************/
5964{
5965 /* Not known to be impossible to fulfill */
5966 return req->present && universal_never_there(&req->source);
5967}
5968
5969/**********************************************************************/
5977{
5980 return TRUE;
5981 }
5983
5984 /* Not known to be impossible to fulfill */
5985 return FALSE;
5986}
5987
5988/**********************************************************************/
5997 const struct requirement_vector *vec)
5998{
5999 if (vec) {
6000 return 0;
6001 } else {
6002 return -1;
6003 }
6004}
6005
6006/********************************************************************/
6014struct requirement_vector *
6016{
6017 fc_assert_ret_val(number == 0, NULL);
6018 return (struct requirement_vector *)parent_item;
6019}
6020
6021/**********************************************************************/
6031const char *req_vec_change_translation(const struct req_vec_change *change,
6033{
6034 const char *req_vec_description;
6035 static char buf[MAX_LEN_NAME * 3];
6036 struct astring astr;
6037
6038 fc_assert_ret_val(change, NULL);
6040 NULL);
6041
6042 /* Get rid of the previous. */
6043 buf[0] = '\0';
6044
6045 if (namer == NULL) {
6046 /* TRANS: default description of a requirement vector
6047 * (used in ruledit) */
6048 req_vec_description = _("the requirement vector");
6049 } else {
6051 }
6052
6053 switch (change->operation) {
6054 case RVCO_REMOVE:
6055 fc_snprintf(buf, sizeof(buf),
6056 /* TRANS: remove a requirement from a requirement vector
6057 * (in ruledit).
6058 * The first %s is the operation.
6059 * The second %s is the requirement.
6060 * The third %s is a description of the requirement vector,
6061 * like "actor_reqs" */
6062 _("%s %s from %s"),
6064 req_to_fstring(&change->req, &astr),
6066 astr_free(&astr);
6067 break;
6068 case RVCO_APPEND:
6069 fc_snprintf(buf, sizeof(buf),
6070 /* TRANS: append a requirement to a requirement vector
6071 * (in ruledit).
6072 * The first %s is the operation.
6073 * The second %s is the requirement.
6074 * The third %s is a description of the requirement vector,
6075 * like "actor_reqs" */
6076 _("%s %s to %s"),
6078 req_to_fstring(&change->req, &astr),
6080 astr_free(&astr);
6081 break;
6082 case RVCO_NOOP:
6083 fc_snprintf(buf, sizeof(buf),
6084 /* TRANS: do nothing to a requirement vector (in ruledit).
6085 * The first %s is a description of the requirement vector,
6086 * like "actor_reqs" */
6087 _("Do nothing to %s"), req_vec_description);
6088 break;
6089 }
6090
6091 return buf;
6092}
6093
6094/**********************************************************************/
6106 const void *parent_item)
6107{
6108 struct requirement_vector *target
6109 = getter(parent_item, modification->vector_number);
6110 int i = 0;
6111
6112 switch (modification->operation) {
6113 case RVCO_APPEND:
6115 return TRUE;
6116 case RVCO_REMOVE:
6120 return TRUE;
6121 }
6122 i++;
6124 return FALSE;
6125 case RVCO_NOOP:
6126 return FALSE;
6127 }
6128
6129 return FALSE;
6130}
6131
6132/**********************************************************************/
6141struct req_vec_problem *
6143 const char *description,
6144 const char *description_translated)
6145{
6146 struct req_vec_problem *out;
6147 int i;
6148
6149 out = fc_malloc(sizeof(*out));
6150
6151 fc_strlcpy(out->description, description, sizeof(out->description));
6152 fc_strlcpy(out->description_translated, _(description_translated),
6153 sizeof(out->description_translated));
6154
6155 out->num_suggested_solutions = num_suggested_solutions;
6156 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
6157 * sizeof(struct req_vec_change));
6158 for (i = 0; i < out->num_suggested_solutions; i++) {
6159 /* No suggestions are ready yet. */
6160 out->suggested_solutions[i].operation = RVCO_NOOP;
6161 out->suggested_solutions[i].vector_number = -1;
6162 out->suggested_solutions[i].req.source.kind = VUT_NONE;
6163 }
6164
6165 return out;
6166}
6167
6168/**********************************************************************/
6177 const char *descr, ...)
6178{
6179 char description[500];
6180 char description_translated[500];
6181 va_list ap;
6182
6183 va_start(ap, descr);
6184 fc_vsnprintf(description, sizeof(description), descr, ap);
6185 va_end(ap);
6186
6187 va_start(ap, descr);
6189 _(descr), ap);
6190 va_end(ap);
6191
6194}
6195
6196/**********************************************************************/
6202{
6203 FC_FREE(issue->suggested_solutions);
6204 issue->num_suggested_solutions = 0;
6205
6206 FC_FREE(issue);
6207}
6208
6209/**********************************************************************/
6220struct req_vec_problem *
6223 const void *parent_item)
6224{
6225 int i, j;
6227
6228 if (vec == NULL || requirement_vector_size(vec) == 0) {
6229 /* No vector. */
6230 return NULL;
6231 }
6232
6233 if (get_num == NULL || parent_item == NULL) {
6234 vec_num = 0;
6235 } else {
6236 vec_num = get_num(parent_item, vec);
6237 }
6238
6239 /* Look for contradictions */
6240 for (i = 0; i < requirement_vector_size(vec); i++) {
6241 struct requirement *preq = requirement_vector_get(vec, i);
6242 for (j = 0; j < requirement_vector_size(vec); j++) {
6243 struct requirement *nreq = requirement_vector_get(vec, j);
6244
6246 struct req_vec_problem *problem;
6247 struct astring astr;
6248 struct astring nastr;
6249
6251 N_("Requirements {%s} and {%s} contradict each other."),
6253
6254 astr_free(&astr);
6255 astr_free(&nastr);
6256
6257 /* The solution is to remove one of the contradictions. */
6258 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6259 problem->suggested_solutions[0].vector_number = vec_num;
6260 problem->suggested_solutions[0].req = *preq;
6261
6262 problem->suggested_solutions[1].operation = RVCO_REMOVE;
6263 problem->suggested_solutions[1].vector_number = vec_num;
6264 problem->suggested_solutions[1].req = *nreq;
6265
6266 /* Only the first contradiction is reported. */
6267 return problem;
6268 }
6269 }
6270 }
6271
6272 return NULL;
6273}
6274
6275/**********************************************************************/
6285struct req_vec_problem *
6288 const void *parent_item)
6289{
6290 /* Check for self contradictins. */
6292}
6293
6294/**********************************************************************/
6306struct req_vec_problem *
6309 const void *parent_item)
6310{
6311 int i;
6313 struct req_vec_problem *problem = NULL;
6314
6315 if (vec == NULL || requirement_vector_size(vec) == 0) {
6316 /* No vector. */
6317 return NULL;
6318 }
6319
6320 if (get_num == NULL || parent_item == NULL) {
6321 vec_num = 0;
6322 } else {
6323 vec_num = get_num(parent_item, vec);
6324 }
6325
6326 /* Look for contradictions */
6327 for (i = 0; i < requirement_vector_size(vec); i++) {
6328 struct requirement *preq = requirement_vector_get(vec, i);
6329
6330 if (universal_never_there(&preq->source)) {
6331 struct astring astr;
6332
6333 if (preq->present) {
6334 /* The requirement vector can never be fulfilled. Removing the
6335 * requirement makes it possible to fulfill it. This is a rule
6336 * change and shouldn't be "fixed" without thinking. Don't offer any
6337 * automatic solution to prevent mindless "fixes". */
6338 /* TRANS: ruledit warns a user about an unused requirement vector
6339 * that never can be fulfilled because it asks for something that
6340 * never will be there. */
6341 if (problem == NULL) {
6343 N_("Requirement {%s} requires %s but it will never be"
6344 " there."),
6346 astr_free(&astr);
6347 }
6348
6349 /* Continue to check if other problems have a solution proposal,
6350 * and prefer to return those. */
6351 continue;
6352 }
6353
6354 if (problem != NULL) {
6355 /* Free previous one (one with no solution proposals) */
6357 }
6358
6360 N_("Requirement {%s} mentions %s but it will never be there."),
6362
6363 astr_free(&astr);
6364
6365 /* The solution is to remove the reference to the missing
6366 * universal. */
6367 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6368 problem->suggested_solutions[0].vector_number = vec_num;
6369 problem->suggested_solutions[0].req = *preq;
6370
6371 /* Only the first missing universal is reported. */
6372 return problem;
6373 }
6374 }
6375
6376 return problem;
6377}
6378
6379/**********************************************************************/
6391struct req_vec_problem *
6394 const void *parent_item)
6395{
6396 int i, j;
6398
6399 if (vec == NULL || requirement_vector_size(vec) == 0) {
6400 /* No vector. */
6401 return NULL;
6402 }
6403
6404 if (get_num == NULL || parent_item == NULL) {
6405 vec_num = 0;
6406 } else {
6407 vec_num = get_num(parent_item, vec);
6408 }
6409
6410 /* Look for repeated requirements */
6411 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
6412 struct requirement *preq = requirement_vector_get(vec, i);
6413 for (j = i + 1; j < requirement_vector_size(vec); j++) {
6414 struct requirement *nreq = requirement_vector_get(vec, j);
6415
6417 struct req_vec_problem *problem;
6418 struct astring astr;
6419 struct astring nastr;
6420
6422 N_("Requirements {%s} and {%s} are the same."),
6424
6425 astr_free(&astr);
6426 astr_free(&nastr);
6427
6428 /* The solution is to remove one of the redundant requirements. */
6429 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6430 problem->suggested_solutions[0].vector_number = vec_num;
6431 problem->suggested_solutions[0].req = *preq;
6432
6433 problem->suggested_solutions[1].operation = RVCO_REMOVE;
6434 problem->suggested_solutions[1].vector_number = vec_num;
6435 problem->suggested_solutions[1].req = *nreq;
6436
6437 /* Only the first redundancy is reported. */
6438 return problem;
6439 }
6440 }
6441 }
6442
6443 return NULL;
6444}
6445
6446/**********************************************************************/
6457struct req_vec_problem *
6460 const void *parent_item)
6461{
6462 struct req_vec_problem *out;
6463
6465 if (out != NULL) {
6466 /* A bug, not just a potential improvement */
6467 return out;
6468 }
6469
6470 /* Check if a universal that never will appear in the game is checked. */
6472 if (out != NULL) {
6473 return out;
6474 }
6475
6476 /* Check if a requirement is redundant. */
6478 return out;
6479}
6480
6481/**********************************************************************/
6486 const struct universal *psource2)
6487{
6488 if (psource1->kind != psource2->kind) {
6489 return FALSE;
6490 }
6491 switch (psource1->kind) {
6492 case VUT_NONE:
6493 return TRUE;
6494 case VUT_COUNTER:
6495 return psource1->value.counter == psource2->value.counter;
6496 case VUT_ADVANCE:
6497 return psource1->value.advance == psource2->value.advance;
6498 case VUT_TECHFLAG:
6499 return psource1->value.techflag == psource2->value.techflag;
6500 case VUT_GOVERNMENT:
6501 return psource1->value.govern == psource2->value.govern;
6502 case VUT_ACHIEVEMENT:
6503 return psource1->value.achievement == psource2->value.achievement;
6504 case VUT_STYLE:
6505 return psource1->value.style == psource2->value.style;
6506 case VUT_IMPROVEMENT:
6507 case VUT_SITE:
6508 return psource1->value.building == psource2->value.building;
6509 case VUT_IMPR_GENUS:
6510 return psource1->value.impr_genus == psource2->value.impr_genus;
6511 case VUT_IMPR_FLAG:
6512 return psource1->value.impr_flag == psource2->value.impr_flag;
6513 case VUT_PLAYER_FLAG:
6514 return psource1->value.plr_flag == psource2->value.plr_flag;
6515 case VUT_PLAYER_STATE:
6516 return psource1->value.plrstate == psource2->value.plrstate;
6517 case VUT_EXTRA:
6518 return psource1->value.extra == psource2->value.extra;
6519 case VUT_GOOD:
6520 return psource1->value.good == psource2->value.good;
6521 case VUT_TERRAIN:
6522 return psource1->value.terrain == psource2->value.terrain;
6523 case VUT_TERRFLAG:
6524 return psource1->value.terrainflag == psource2->value.terrainflag;
6525 case VUT_NATION:
6526 return psource1->value.nation == psource2->value.nation;
6527 case VUT_NATIONGROUP:
6528 return psource1->value.nationgroup == psource2->value.nationgroup;
6529 case VUT_NATIONALITY:
6530 return psource1->value.nationality == psource2->value.nationality;
6531 case VUT_ORIGINAL_OWNER:
6532 return psource1->value.origowner == psource2->value.origowner;
6533 case VUT_DIPLREL:
6534 case VUT_DIPLREL_TILE:
6535 case VUT_DIPLREL_TILE_O:
6538 return psource1->value.diplrel == psource2->value.diplrel;
6539 case VUT_UTYPE:
6540 return psource1->value.utype == psource2->value.utype;
6541 case VUT_UTFLAG:
6542 return psource1->value.unitflag == psource2->value.unitflag;
6543 case VUT_UCLASS:
6544 return psource1->value.uclass == psource2->value.uclass;
6545 case VUT_UCFLAG:
6546 return psource1->value.unitclassflag == psource2->value.unitclassflag;
6547 case VUT_MINVETERAN:
6548 return psource1->value.minveteran == psource2->value.minveteran;
6549 case VUT_UNITSTATE:
6550 return psource1->value.unit_state == psource2->value.unit_state;
6551 case VUT_ACTIVITY:
6552 return psource1->value.activity == psource2->value.activity;
6553 case VUT_MINMOVES:
6554 return psource1->value.minmoves == psource2->value.minmoves;
6555 case VUT_MINHP:
6556 return psource1->value.min_hit_points == psource2->value.min_hit_points;
6557 case VUT_AGE:
6558 return psource1->value.age == psource2->value.age;
6559 case VUT_FORM_AGE:
6560 return psource1->value.form_age == psource2->value.form_age;
6561 case VUT_MINTECHS:
6562 return psource1->value.min_techs == psource2->value.min_techs;
6563 case VUT_ACTION:
6564 return (action_number(psource1->value.action)
6565 == action_number(psource2->value.action));
6566 case VUT_OTYPE:
6567 return psource1->value.outputtype == psource2->value.outputtype;
6568 case VUT_SPECIALIST:
6569 return psource1->value.specialist == psource2->value.specialist;
6570 case VUT_MINSIZE:
6571 return psource1->value.minsize == psource2->value.minsize;
6572 case VUT_MINCULTURE:
6573 return psource1->value.minculture == psource2->value.minculture;
6574 case VUT_MINFOREIGNPCT:
6575 return psource1->value.minforeignpct == psource2->value.minforeignpct;
6576 case VUT_AI_LEVEL:
6577 return psource1->value.ai_level == psource2->value.ai_level;
6578 case VUT_MAXTILEUNITS:
6579 return psource1->value.max_tile_units == psource2->value.max_tile_units;
6580 case VUT_TERRAINCLASS:
6581 return psource1->value.terrainclass == psource2->value.terrainclass;
6582 case VUT_ROADFLAG:
6583 return psource1->value.roadflag == psource2->value.roadflag;
6584 case VUT_EXTRAFLAG:
6585 return psource1->value.extraflag == psource2->value.extraflag;
6586 case VUT_MINYEAR:
6587 return psource1->value.minyear == psource2->value.minyear;
6588 case VUT_MINCALFRAG:
6589 return psource1->value.mincalfrag == psource2->value.mincalfrag;
6590 case VUT_TOPO:
6591 return psource1->value.topo_property == psource2->value.topo_property;
6592 case VUT_WRAP:
6593 return psource1->value.wrap_property == psource2->value.wrap_property;
6594 case VUT_SERVERSETTING:
6595 return psource1->value.ssetval == psource2->value.ssetval;
6596 case VUT_TERRAINALTER:
6597 return psource1->value.terrainalter == psource2->value.terrainalter;
6598 case VUT_CITYTILE:
6599 return psource1->value.citytile == psource2->value.citytile;
6600 case VUT_CITYSTATUS:
6601 return psource1->value.citystatus == psource2->value.citystatus;
6602 case VUT_MINLATITUDE:
6603 case VUT_MAXLATITUDE:
6604 return psource1->value.latitude == psource2->value.latitude;
6605 case VUT_COUNT:
6606 break;
6607 }
6608
6609 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
6610 return FALSE;
6611}
6612
6613/**********************************************************************/
6617const char *universal_rule_name(const struct universal *psource)
6618{
6619 static char buffer[10];
6620
6621 switch (psource->kind) {
6622 case VUT_NONE:
6623 return "(none)";
6624 case VUT_COUNTER:
6625 return counter_rule_name(psource->value.counter);
6626 case VUT_CITYTILE:
6627 return citytile_type_name(psource->value.citytile);
6628 case VUT_CITYSTATUS:
6629 return citystatus_type_name(psource->value.citystatus);
6630 case VUT_MINYEAR:
6631 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
6632
6633 return buffer;
6634 case VUT_MINCALFRAG:
6635 /* Rule name is 0-based number, not pretty name from ruleset */
6636 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
6637
6638 return buffer;
6639 case VUT_TOPO:
6640 return topo_flag_name(psource->value.topo_property);
6641 case VUT_WRAP:
6642 return wrap_flag_name(psource->value.wrap_property);
6643 case VUT_SERVERSETTING:
6644 return ssetv_rule_name(psource->value.ssetval);
6645 case VUT_ADVANCE:
6646 return advance_rule_name(psource->value.advance);
6647 case VUT_TECHFLAG:
6648 return tech_flag_id_name(psource->value.techflag);
6649 case VUT_GOVERNMENT:
6650 return government_rule_name(psource->value.govern);
6651 case VUT_ACHIEVEMENT:
6652 return achievement_rule_name(psource->value.achievement);
6653 case VUT_STYLE:
6654 return style_rule_name(psource->value.style);
6655 case VUT_IMPROVEMENT:
6656 case VUT_SITE:
6657 return improvement_rule_name(psource->value.building);
6658 case VUT_IMPR_GENUS:
6659 return impr_genus_id_name(psource->value.impr_genus);
6660 case VUT_IMPR_FLAG:
6661 return impr_flag_id_name(psource->value.impr_flag);
6662 case VUT_PLAYER_FLAG:
6663 return plr_flag_id_name(psource->value.plr_flag);
6664 case VUT_PLAYER_STATE:
6665 return plrstate_type_name(psource->value.plrstate);
6666 case VUT_EXTRA:
6667 return extra_rule_name(psource->value.extra);
6668 case VUT_GOOD:
6669 return goods_rule_name(psource->value.good);
6670 case VUT_TERRAIN:
6671 return terrain_rule_name(psource->value.terrain);
6672 case VUT_TERRFLAG:
6673 return terrain_flag_id_name(psource->value.terrainflag);
6674 case VUT_NATION:
6675 return nation_rule_name(psource->value.nation);
6676 case VUT_NATIONGROUP:
6677 return nation_group_rule_name(psource->value.nationgroup);
6678 case VUT_DIPLREL:
6679 case VUT_DIPLREL_TILE:
6680 case VUT_DIPLREL_TILE_O:
6683 return diplrel_rule_name(psource->value.diplrel);
6684 case VUT_NATIONALITY:
6685 return nation_rule_name(psource->value.nationality);
6686 case VUT_ORIGINAL_OWNER:
6687 return nation_rule_name(psource->value.origowner);
6688 case VUT_UTYPE:
6689 return utype_rule_name(psource->value.utype);
6690 case VUT_UTFLAG:
6691 return unit_type_flag_id_name(psource->value.unitflag);
6692 case VUT_UCLASS:
6693 return uclass_rule_name(psource->value.uclass);
6694 case VUT_UCFLAG:
6695 return unit_class_flag_id_name(psource->value.unitclassflag);
6696 case VUT_MINVETERAN:
6697 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
6698
6699 return buffer;
6700 case VUT_UNITSTATE:
6701 return ustate_prop_name(psource->value.unit_state);
6702 case VUT_ACTIVITY:
6703 return unit_activity_name(psource->value.activity);
6704 case VUT_MINMOVES:
6705 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
6706
6707 return buffer;
6708 case VUT_MINHP:
6709 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
6710
6711 return buffer;
6712 case VUT_AGE:
6713 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
6714
6715 return buffer;
6716 case VUT_FORM_AGE:
6717 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
6718
6719 return buffer;
6720 case VUT_MINTECHS:
6721 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
6722
6723 return buffer;
6724 case VUT_ACTION:
6725 return action_rule_name(psource->value.action);
6726 case VUT_OTYPE:
6727 return get_output_identifier(psource->value.outputtype);
6728 case VUT_SPECIALIST:
6729 return specialist_rule_name(psource->value.specialist);
6730 case VUT_MINSIZE:
6731 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
6732
6733 return buffer;
6734 case VUT_MINCULTURE:
6735 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
6736
6737 return buffer;
6738 case VUT_MINFOREIGNPCT:
6739 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
6740
6741 return buffer;
6742 case VUT_AI_LEVEL:
6743 return ai_level_name(psource->value.ai_level);
6744 case VUT_MAXTILEUNITS:
6745 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_units);
6746 return buffer;
6747 case VUT_TERRAINCLASS:
6748 return terrain_class_name(psource->value.terrainclass);
6749 case VUT_ROADFLAG:
6750 return road_flag_id_name(psource->value.roadflag);
6751 case VUT_EXTRAFLAG:
6752 return extra_flag_id_name(psource->value.extraflag);
6753 case VUT_TERRAINALTER:
6754 return terrain_alteration_name(psource->value.terrainalter);
6755 case VUT_MINLATITUDE:
6756 case VUT_MAXLATITUDE:
6757 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
6758
6759 return buffer;
6760 case VUT_COUNT:
6761 break;
6762 }
6763
6764 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
6765 return NULL;
6766}
6767
6768/**********************************************************************/
6777 char *buf, size_t bufsz)
6778{
6779 buf[0] = '\0'; /* to be safe. */
6780 switch (psource->kind) {
6781 case VUT_NONE:
6782 /* TRANS: missing value */
6783 fc_strlcat(buf, _("(none)"), bufsz);
6784 return buf;
6785 case VUT_ADVANCE:
6787 return buf;
6788 case VUT_COUNTER:
6790 return buf;
6791 case VUT_TECHFLAG:
6792 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
6793 tech_flag_id_translated_name(psource->value.techflag));
6794 return buf;
6795 case VUT_GOVERNMENT:
6797 bufsz);
6798 return buf;
6799 case VUT_ACHIEVEMENT:
6801 bufsz);
6802 return buf;
6803 case VUT_STYLE:
6805 bufsz);
6806 return buf;
6807 case VUT_IMPROVEMENT:
6809 bufsz);
6810 return buf;
6811 case VUT_SITE:
6812 {
6813 char local_buf[1024];
6814
6815 fc_snprintf(local_buf, sizeof(local_buf), _("%s site"),
6816 improvement_name_translation(psource->value.building));
6818 }
6819
6820 return buf;
6821 case VUT_IMPR_GENUS:
6823 impr_genus_id_translated_name(psource->value.impr_genus),
6824 bufsz);
6825 return buf;
6826 case VUT_IMPR_FLAG:
6828 impr_flag_id_translated_name(psource->value.impr_flag),
6829 bufsz);
6830 return buf;
6831 case VUT_PLAYER_FLAG:
6833 plr_flag_id_translated_name(psource->value.plr_flag),
6834 bufsz);
6835 return buf;
6836 case VUT_PLAYER_STATE:
6838 plrstate_type_translated_name(psource->value.plrstate),
6839 bufsz);
6840 return buf;
6841 case VUT_EXTRA:
6843 return buf;
6844 case VUT_GOOD:
6846 return buf;
6847 case VUT_TERRAIN:
6849 return buf;
6850 case VUT_NATION:
6852 bufsz);
6853 return buf;
6854 case VUT_NATIONGROUP:
6856 bufsz);
6857 return buf;
6858 case VUT_NATIONALITY:
6859 cat_snprintf(buf, bufsz, _("%s citizens"),
6860 nation_adjective_translation(psource->value.nationality));
6861 return buf;
6862 case VUT_ORIGINAL_OWNER:
6863 /* TRANS: Keep short. City founding nation. */
6864 cat_snprintf(buf, bufsz, _("%s original owner"),
6865 nation_adjective_translation(psource->value.origowner));
6866 return buf;
6867 case VUT_DIPLREL:
6868 case VUT_DIPLREL_TILE:
6869 case VUT_DIPLREL_TILE_O:
6873 bufsz);
6874 return buf;
6875 case VUT_UTYPE:
6877 return buf;
6878 case VUT_UTFLAG:
6880 /* TRANS: Unit type flag */
6881 Q_("?utflag:\"%s\" units"),
6883 psource->value.unitflag));
6884 return buf;
6885 case VUT_UCLASS:
6887 /* TRANS: Unit class */
6888 _("%s units"),
6889 uclass_name_translation(psource->value.uclass));
6890 return buf;
6891 case VUT_UCFLAG:
6893 /* TRANS: Unit class flag */
6894 Q_("?ucflag:\"%s\" units"),
6896 psource->value.unitclassflag));
6897 return buf;
6898 case VUT_MINVETERAN:
6899 /* FIXME */
6900 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
6901 psource->value.minveteran);
6902 return buf;
6903 case VUT_UNITSTATE:
6904 switch (psource->value.unit_state) {
6905 case USP_TRANSPORTED:
6906 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
6907 cat_snprintf(buf, bufsz, _("Transported"));
6908 break;
6909 case USP_LIVABLE_TILE:
6911 /* TRANS: unit state. (appears in strings like
6912 * "Missile+On livable tile") */
6913 _("On livable tile"));
6914 break;
6915 case USP_TRANSPORTING:
6916 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
6917 cat_snprintf(buf, bufsz, _("Transporting"));
6918 break;
6919 case USP_HAS_HOME_CITY:
6920 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
6921 cat_snprintf(buf, bufsz, _("Has a home city"));
6922 break;
6923 case USP_NATIVE_TILE:
6925 /* TRANS: unit state. (appears in strings like
6926 * "Missile+On native tile") */
6927 _("On native tile"));
6928 break;
6929 case USP_NATIVE_EXTRA:
6931 /* TRANS: unit state. (appears in strings like
6932 * "Missile+In native extra") */
6933 _("In native extra"));
6934 break;
6936 /* TRANS: unit state. (appears in strings like
6937 * "Missile+Has moved this turn") */
6938 cat_snprintf(buf, bufsz, _("Has moved this turn"));
6939 break;
6940 case USP_COUNT:
6941 fc_assert_msg(psource->value.unit_state != USP_COUNT,
6942 "Invalid unit state property.");
6943 break;
6944 }
6945 return buf;
6946 case VUT_ACTIVITY:
6947 cat_snprintf(buf, bufsz, _("%s activity"),
6948 Q_(unit_activity_name(psource->value.activity)));
6949 return buf;
6950 case VUT_MINMOVES:
6951 /* TRANS: Minimum unit movement points left for requirement to be met
6952 * (%s is a string like "1" or "2 1/3") */
6953 cat_snprintf(buf, bufsz, _("%s MP"),
6954 move_points_text(psource->value.minmoves, TRUE));
6955 return buf;
6956 case VUT_MINHP:
6957 /* TRANS: HP = hit points */
6958 cat_snprintf(buf, bufsz, _("%d HP"),
6959 psource->value.min_hit_points);
6960 return buf;
6961 case VUT_AGE:
6962 cat_snprintf(buf, bufsz, _("Age %d"),
6963 psource->value.age);
6964 return buf;
6965 case VUT_FORM_AGE:
6966 cat_snprintf(buf, bufsz, _("Form age %d"),
6967 psource->value.form_age);
6968 return buf;
6969 case VUT_MINTECHS:
6970 cat_snprintf(buf, bufsz, _("%d Techs"),
6971 psource->value.min_techs);
6972 return buf;
6973 case VUT_ACTION:
6975 bufsz);
6976 return buf;
6977 case VUT_OTYPE:
6978 /* FIXME */
6979 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
6980 return buf;
6981 case VUT_SPECIALIST:
6983 bufsz);
6984 return buf;
6985 case VUT_MINSIZE:
6986 cat_snprintf(buf, bufsz, _("Size %d"),
6987 psource->value.minsize);
6988 return buf;
6989 case VUT_MINCULTURE:
6990 cat_snprintf(buf, bufsz, _("Culture %d"),
6991 psource->value.minculture);
6992 return buf;
6993 case VUT_MINFOREIGNPCT:
6994 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
6995 psource->value.minforeignpct);
6996 return buf;
6997 case VUT_AI_LEVEL:
6998 /* TRANS: "Hard AI" */
6999 cat_snprintf(buf, bufsz, _("%s AI"),
7000 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
7001 return buf;
7002 case VUT_MAXTILEUNITS:
7003 /* TRANS: here <= means 'less than or equal' */
7004 cat_snprintf(buf, bufsz, PL_("<=%d unit",
7005 "<=%d units", psource->value.max_tile_units),
7006 psource->value.max_tile_units);
7007 return buf;
7008 case VUT_TERRAINCLASS:
7009 /* TRANS: Terrain class: "Land terrain" */
7010 cat_snprintf(buf, bufsz, _("%s terrain"),
7011 terrain_class_name_translation(psource->value.terrainclass));
7012 return buf;
7013 case VUT_TERRFLAG:
7015 /* TRANS: Terrain flag */
7016 Q_("?terrflag:\"%s\" terrain"),
7018 psource->value.terrainflag));
7019 return buf;
7020 case VUT_ROADFLAG:
7022 /* TRANS: Road flag */
7023 Q_("?roadflag:\"%s\" road"),
7024 road_flag_id_translated_name(psource->value.roadflag));
7025 return buf;
7026 case VUT_EXTRAFLAG:
7028 /* TRANS: Extra flag */
7029 Q_("?extraflag:\"%s\" extra"),
7030 extra_flag_id_translated_name(psource->value.extraflag));
7031 return buf;
7032 case VUT_MINYEAR:
7033 cat_snprintf(buf, bufsz, _("After %s"),
7034 textyear(psource->value.minyear));
7035 return buf;
7036 case VUT_MINCALFRAG:
7037 /* TRANS: here >= means 'greater than or equal'.
7038 * %s identifies a calendar fragment (may be bare number). */
7039 cat_snprintf(buf, bufsz, _(">=%s"),
7040 textcalfrag(psource->value.mincalfrag));
7041 return buf;
7042 case VUT_TOPO:
7043 /* TRANS: topology flag name ("Hex", "ISO") */
7044 cat_snprintf(buf, bufsz, _("%s map"),
7045 _(topo_flag_name(psource->value.topo_property)));
7046 return buf;
7047 case VUT_WRAP:
7048 /* TRANS: wrap flag name ("WrapX", "WrapY") */
7049 cat_snprintf(buf, bufsz, _("%s map"),
7050 _(wrap_flag_name(psource->value.wrap_property)));
7051 return buf;
7052 case VUT_SERVERSETTING:
7054 bufsz);
7055 return buf;
7056 case VUT_TERRAINALTER:
7057 /* TRANS: "Irrigation possible" */
7058 cat_snprintf(buf, bufsz, _("%s possible"),
7059 Q_(terrain_alteration_name(psource->value.terrainalter)));
7060 return buf;
7061 case VUT_CITYTILE:
7062 switch (psource->value.citytile) {
7063 case CITYT_CENTER:
7064 fc_strlcat(buf, _("City center"), bufsz);
7065 break;
7066 case CITYT_CLAIMED:
7067 fc_strlcat(buf, _("Tile claimed"), bufsz);
7068 break;
7069 case CITYT_EXTRAS_OWNED:
7070 fc_strlcat(buf, _("Extras owned"), bufsz);
7071 break;
7072 case CITYT_WORKED:
7073 fc_strlcat(buf, _("Worked tile"), bufsz);
7074 break;
7076 fc_strlcat(buf, _("Same continent tile"), bufsz);
7077 break;
7079 /* TRANS: Short for "a tile of other terrain class mass near city" */
7080 fc_strlcat(buf, _("Port reachable tile"), bufsz);
7081 break;
7082 case CITYT_LAST:
7083 fc_assert(psource->value.citytile != CITYT_LAST);
7084 fc_strlcat(buf, "error", bufsz);
7085 break;
7086 }
7087 return buf;
7088 case VUT_CITYSTATUS:
7089 switch (psource->value.citystatus) {
7091 fc_strlcat(buf, _("Owned by original"), bufsz);
7092 break;
7093 case CITYS_STARVED:
7094 fc_strlcat(buf, _("Starved"), bufsz);
7095 break;
7096 case CITYS_DISORDER:
7097 fc_strlcat(buf, _("Disorder"), bufsz);
7098 break;
7099 case CITYS_CELEBRATION:
7100 fc_strlcat(buf, _("Celebration"), bufsz);
7101 break;
7102 case CITYS_TRANSFERRED:
7103 /* TRANS: CityStatus value - city has changed hands */
7104 fc_strlcat(buf, _("Transferred"), bufsz);
7105 break;
7106 case CITYS_LAST:
7107 fc_assert(psource->value.citystatus != CITYS_LAST);
7108 fc_strlcat(buf, "error", bufsz);
7109 break;
7110 }
7111 return buf;
7112 case VUT_MINLATITUDE:
7113 /* TRANS: here >= means 'greater than or equal'. */
7114 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
7115 psource->value.latitude);
7116 return buf;
7117 case VUT_MAXLATITUDE:
7118 /* TRANS: here <= means 'less than or equal'. */
7119 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
7120 psource->value.latitude);
7121 return buf;
7122 case VUT_COUNT:
7123 break;
7124 }
7125
7126 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
7127 return buf;
7128}
7129
7130/**********************************************************************/
7134{
7135 return universals_n_name(psource->kind);
7136}
7137
7138/**********************************************************************/
7141int universal_build_shield_cost(const struct city *pcity,
7142 const struct universal *target)
7143{
7144 switch (target->kind) {
7145 case VUT_IMPROVEMENT:
7146 case VUT_SITE:
7147 return impr_build_shield_cost(pcity, target->value.building);
7148 case VUT_UTYPE:
7149 return utype_build_shield_cost(pcity, NULL, target->value.utype);
7150 default:
7151 break;
7152 }
7153 return FC_INFINITY;
7154}
7155
7156/**********************************************************************/
7162 const struct universal *to_replace,
7163 const struct universal *replacement)
7164{
7165 bool changed = FALSE;
7166
7169 preq->source = *replacement;
7170 changed = TRUE;
7171 }
7173
7174 return changed;
7175}
7176
7177/**********************************************************************/
7182 const struct requirement_vector *reqs,
7183 const struct universal *psource)
7184{
7187 return TRUE;
7188 }
7190
7191 return FALSE;
7192}
7193
7194/**********************************************************************/
7204 struct universal *unis,
7205 size_t n_unis)
7206{
7207 int i;
7208
7209 for (i = 0; i < n_unis; i++) {
7211 /* This universal makes it impossible to fulfill the specified
7212 * requirement vector */
7213 return TRUE;
7214 }
7215 }
7216
7217 /* No specified universal is known to guarantee that the requirement
7218 * vector never will be fulfilled. */
7219 return FALSE;
7220}
7221
7222/**********************************************************************/
7237 struct universal *unis,
7238 size_t n_unis)
7239{
7241 int i;
7243
7244 for (i = 0; i < n_unis; i++) {
7245 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
7246 case ITF_NO:
7247 case ITF_YES:
7248 /* this req matched this source */
7250 break;
7251 case ITF_NOT_APPLICABLE:
7252 /* Not a mention. */
7253 break;
7254 }
7255 }
7256
7258 /* A requirement not relevant to any of the specified universals was
7259 * found in the requirement vector. */
7260 return FALSE;
7261 }
7263
7264 /* No requirement not relevant to any of the specified universals was
7265 * found in the requirement vector. */
7266 return TRUE;
7267}
7268
7269/**********************************************************************/
7272enum req_item_found
7274 const struct universal *source)
7275{
7278 "No req item found function for %s",
7280
7281 return (*universal_found_function[source->kind])(preq, source);
7282}
7283
7284/**********************************************************************/
7295 const struct requirement_vector *reqs,
7296 const struct universal *source)
7297{
7298 bool necessary = FALSE;
7299
7302 "No req item found function for %s",
7304
7306 switch ((*universal_found_function[source->kind])(preq, source)) {
7307 case ITF_NOT_APPLICABLE:
7308 continue;
7309 case ITF_NO:
7310 if (preq->present) {
7311 return FALSE;
7312 }
7313 break;
7314 case ITF_YES:
7315 if (preq->present) {
7316 necessary = TRUE;
7317 } else {
7318 return FALSE;
7319 }
7320 break;
7321 }
7323
7324 return (!check_necessary || necessary);
7325}
7326
7327/**********************************************************************/
7332 const struct universal *source)
7333{
7334 switch (universal_fulfills_requirement(req, source)) {
7335 case ITF_NOT_APPLICABLE:
7336 return FALSE;
7337 case ITF_NO:
7338 case ITF_YES:
7339 return TRUE;
7340 }
7341
7342 log_error("Unhandled item_found value");
7343 return FALSE;
7344}
7345
7346/**********************************************************************/
7350 const struct universal *source)
7351{
7352 fc_assert(source->value.nation);
7353
7354 switch (preq->source.kind) {
7355 case VUT_NATION:
7356 return preq->source.value.nation == source->value.nation ? ITF_YES
7357 : ITF_NO;
7358 case VUT_NATIONGROUP:
7359 return nation_is_in_group(source->value.nation,
7360 preq->source.value.nationgroup) ? ITF_YES
7361 : ITF_NO;
7362 default:
7363 break;
7364 }
7365
7366 return ITF_NOT_APPLICABLE;
7367}
7368
7369/**********************************************************************/
7373 const struct universal *source)
7374{
7375 fc_assert(source->value.govern);
7376
7377 if (preq->source.kind == VUT_GOVERNMENT) {
7378 return preq->source.value.govern == source->value.govern ? ITF_YES
7379 : ITF_NO;
7380 }
7381
7382 return ITF_NOT_APPLICABLE;
7383}
7384
7385/**********************************************************************/
7389 const struct universal *source)
7390{
7391 fc_assert(source->value.building);
7392
7393 /* We only ever return ITF_YES, because requiring a different
7394 * improvement does not mean that the improvement under consideration
7395 * cannot fulfill the requirements. This is necessary to allow
7396 * requirement vectors to specify multiple required improvements. */
7397
7398 switch (preq->source.kind) {
7399 case VUT_IMPROVEMENT:
7400 case VUT_SITE:
7401 if (source->value.building == preq->source.value.building) {
7402 return ITF_YES;
7403 }
7404 break;
7405 case VUT_IMPR_GENUS:
7406 if (source->value.building->genus == preq->source.value.impr_genus) {
7407 return ITF_YES;
7408 }
7409 break;
7410 case VUT_IMPR_FLAG:
7411 if (improvement_has_flag(source->value.building,
7412 preq->source.value.impr_flag)) {
7413 return ITF_YES;
7414 }
7415 break;
7416 default:
7417 break;
7418 }
7419
7420 return ITF_NOT_APPLICABLE;
7421}
7422
7423/**********************************************************************/
7427 const struct universal *source)
7428{
7429 fc_assert(source->value.uclass);
7430
7431 switch (preq->source.kind) {
7432 case VUT_UCLASS:
7433 return source->value.uclass == preq->source.value.uclass ? ITF_YES
7434 : ITF_NO;
7435 case VUT_UCFLAG:
7436 return uclass_has_flag(source->value.uclass,
7437 preq->source.value.unitclassflag) ? ITF_YES
7438 : ITF_NO;
7439
7440 default:
7441 /* Not found and not relevant. */
7442 return ITF_NOT_APPLICABLE;
7443 };
7444}
7445
7446/**********************************************************************/
7450 const struct universal *source)
7451{
7452 fc_assert(source->value.utype);
7453
7454 switch (preq->source.kind) {
7455 case VUT_UTYPE:
7456 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
7457 case VUT_UCLASS:
7458 return utype_class(source->value.utype) == preq->source.value.uclass
7459 ? ITF_YES : ITF_NO;
7460 case VUT_UTFLAG:
7461 return utype_has_flag(source->value.utype,
7462 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
7463 case VUT_UCFLAG:
7464 return uclass_has_flag(utype_class(source->value.utype),
7465 preq->source.value.unitclassflag) ? ITF_YES
7466 : ITF_NO;
7467 default:
7468 /* Not found and not relevant. */
7469 return ITF_NOT_APPLICABLE;
7470 };
7471}
7472
7473/**********************************************************************/
7476static enum req_item_found
7478 const struct universal *source)
7479{
7482
7483 switch (preq->source.kind) {
7484 case VUT_ACTIVITY:
7485 return source->value.activity == preq->source.value.activity ? ITF_YES
7486 : ITF_NO;
7487 default:
7488 /* Not found and not relevant. */
7489 return ITF_NOT_APPLICABLE;
7490 };
7491}
7492
7493/**********************************************************************/
7497 const struct universal *source)
7498{
7499 fc_assert(source->value.terrain);
7500
7501 switch (preq->source.kind) {
7502 case VUT_TERRAIN:
7503 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
7504 case VUT_TERRAINCLASS:
7505 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
7506 ? ITF_YES : ITF_NO;
7507 case VUT_TERRFLAG:
7508 return terrain_has_flag(source->value.terrain,
7509 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
7510 case VUT_TERRAINALTER:
7511 return (terrain_can_support_alteration(source->value.terrain,
7512 preq->source.value.terrainalter)
7513 ? ITF_YES : ITF_NO);
7514 default:
7515 /* Not found and not relevant. */
7516 return ITF_NOT_APPLICABLE;
7517 };
7518}
7519
7520/**********************************************************************/
7524 const struct universal *source)
7525{
7528
7529 switch (preq->source.kind) {
7530 case VUT_CITYTILE:
7531 return (source->value.citytile == preq->source.value.citytile
7532 ? ITF_YES
7533 /* The presence of one tile state doesn't block another */
7535 default:
7536 /* Not found and not relevant. */
7537 return ITF_NOT_APPLICABLE;
7538 };
7539}
7540
7541/**********************************************************************/
7545 const struct universal *source)
7546{
7547 fc_assert(source->value.extra);
7548
7549 switch (preq->source.kind) {
7550 case VUT_EXTRA:
7551 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
7552 case VUT_EXTRAFLAG:
7553 return extra_has_flag(source->value.extra,
7554 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
7555 case VUT_ROADFLAG:
7556 {
7557 struct road_type *r = extra_road_get(source->value.extra);
7558 return r && road_has_flag(r, preq->source.value.roadflag)
7559 ? ITF_YES : ITF_NO;
7560 }
7561 default:
7562 /* Not found and not relevant. */
7563 return ITF_NOT_APPLICABLE;
7564 }
7565}
7566
7567/**********************************************************************/
7571 const struct universal *source)
7572{
7573 fc_assert(source->value.action);
7574
7575 if (preq->source.kind == VUT_ACTION) {
7576 return preq->source.value.action == source->value.action ? ITF_YES
7577 : ITF_NO;
7578 }
7579
7580 return ITF_NOT_APPLICABLE;
7581}
7582
7583/**********************************************************************/
7587 const struct universal *source)
7588{
7590 || source->kind == VUT_DIPLREL_TILE
7591 || source->kind == VUT_DIPLREL_TILE_O
7592 || source->kind == VUT_DIPLREL_UNITANY
7593 || source->kind == VUT_DIPLREL_UNITANY_O),
7595
7596 if (preq->source.kind == source->kind) {
7597 if (preq->source.value.diplrel == source->value.diplrel) {
7598 /* The diplrel itself. */
7599 return ITF_YES;
7600 }
7601 if (preq->source.value.diplrel == DRO_FOREIGN
7602 && source->value.diplrel < DS_LAST) {
7603 /* All diplstate_type values are to foreigners. */
7604 return ITF_YES;
7605 }
7606 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
7607 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
7608 /* A real embassy is an embassy. */
7609 return ITF_YES;
7610 }
7611 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
7612 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
7613 /* A real embassy is an embassy. */
7614 return ITF_YES;
7615 }
7616 if (preq->source.value.diplrel < DS_LAST
7617 && source->value.diplrel < DS_LAST
7618 && preq->range == REQ_RANGE_LOCAL) {
7619 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
7620 ITF_YES);
7621 /* Can only have one diplstate_type to a specific player. */
7622 return ITF_NO;
7623 }
7624 /* Can't say this diplrel blocks the other diplrel. */
7625 return ITF_NOT_APPLICABLE;
7626 }
7627
7628 /* Not relevant. */
7629 return ITF_NOT_APPLICABLE;
7630}
7631
7632/**********************************************************************/
7636 const struct universal *source)
7637{
7638 switch (preq->source.kind) {
7639 case VUT_OTYPE:
7640 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
7641 : ITF_NO;
7642 default:
7643 /* Not found and not relevant. */
7644 return ITF_NOT_APPLICABLE;
7645 }
7646}
7647
7648/**********************************************************************/
7652 const struct universal *source)
7653{
7654 if (preq->range != REQ_RANGE_LOCAL) {
7655 return ITF_NOT_APPLICABLE;
7656 }
7657
7658 if (preq->source.kind == VUT_UNITSTATE) {
7659 switch (source->value.unit_state) {
7660 case USP_TRANSPORTED:
7661 case USP_TRANSPORTING:
7662 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
7663 case USP_LIVABLE_TILE:
7664 case USP_NATIVE_TILE:
7665 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
7666 * UTYF_COAST_STRICT. */
7667 case USP_HAS_HOME_CITY:
7668 case USP_NATIVE_EXTRA:
7670 if (source->value.unit_state == preq->source.value.unit_state) {
7671 /* The other unit states doesn't contradict */
7672 return ITF_YES;
7673 }
7674 break;
7675 case USP_COUNT:
7676 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
7678 }
7679 }
7680
7681 /* Not found and not relevant. */
7682 return ITF_NOT_APPLICABLE;
7683}
7684
7685/**********************************************************************/
7709
7710/**********************************************************************/
7718int requirement_kind_ereq(const int value,
7719 const enum req_range range,
7720 const bool present,
7721 const int max_value)
7722{
7723 /* The enumerators in each range starts with present for every possible
7724 * value followed by !present for every possible value. */
7725 const int pres_start = (present ? 0 : max_value);
7726
7727 /* The enumerators for every range follows all the positions of the
7728 * previous range(s). */
7729 const int range_start = ((max_value - 1) * 2) * range;
7730
7731 return range_start + pres_start + value;
7732}
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
struct achievement * achievement_by_number(int id)
int achievement_number(const struct achievement *pach)
const char * achievement_rule_name(struct achievement *pach)
struct achievement * achievement_by_rule_name(const char *name)
const char * achievement_name_translation(struct achievement *pach)
bool achievement_claimed(const struct achievement *pach)
const char * action_name_translation(const struct action *action)
Definition actions.c:1991
bool action_is_in_use(struct action *paction)
Definition actions.c:6398
struct action * action_by_rule_name(const char *name)
Definition actions.c:1840
const char * action_rule_name(const struct action *action)
Definition actions.c:1977
int action_number(const struct action *action)
Definition actions.c:1969
static struct action * action_by_number(action_id act_id)
Definition actions.h:635
void astr_free(struct astring *astr)
Definition astring.c:153
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:267
void astr_init(struct astring *astr)
Definition astring.c:144
#define n
Definition astring.c:77
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
const char * textcalfrag(int frag)
Definition calendar.c:101
const char * textyear(int year)
Definition calendar.c:120
citizens citizens_nation_foreign(const struct city *pcity)
Definition citizens.c:91
#define citizens_iterate_end
Definition citizens.h:54
#define citizens_iterate(_pcity, _pslot, _nationality)
Definition citizens.h:48
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:1240
Output_type_id output_type_by_identifier(const char *id)
Definition city.c:647
const char * get_output_identifier(Output_type_id output)
Definition city.c:619
const char * get_output_name(Output_type_id output)
Definition city.c:629
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
#define city_tile(_pcity_)
Definition city.h:564
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
#define city_owner(_pcity_)
Definition city.h:563
static bool is_city_center(const struct city *pcity, const struct tile *ptile)
Definition city.h:868
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:230
#define city_tile_iterate_end
Definition city.h:238
#define city_built_iterate(_pcity, _p)
Definition city.h:834
#define city_built_iterate_end
Definition city.h:840
char * incite_cost
Definition comments.c:75
int counter_index(const struct counter *pcount)
Definition counters.c:174
const char * counter_name_translation(const struct counter *counter)
Definition counters.c:157
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:115
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:165
struct counter * counter_by_id(int id)
Definition counters.c:82
int counter_id(struct counter *pcount)
Definition counters.c:105
int city_culture(const struct city *pcity)
Definition culture.c:29
int player_culture(const struct player *plr)
Definition culture.c:46
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:56
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:57
struct @21::@22 reqs
int get_world_bonus(enum effect_type effect_type)
Definition effects.c:816
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
bool extra_flag_is_in_use(enum extra_flag_id id)
Definition extras.c:987
bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:890
bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:870
bool is_extra_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:379
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:861
bool is_extra_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:363
struct extra_type * extra_by_number(int id)
Definition extras.c:183
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:194
#define extra_road_get(_e_)
Definition extras.h:191
static bool is_server(void)
int Tech_type_id
Definition fc_types.h:377
req_problem_type
Definition fc_types.h:699
@ RPT_POSSIBLE
Definition fc_types.h:700
#define MAX_LEN_NAME
Definition fc_types.h:66
@ VC_SPACERACE
Definition fc_types.h:1271
@ O_LAST
Definition fc_types.h:101
signed short Continent_id
Definition fc_types.h:372
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
const char * government_name_translation(const struct government *pgovern)
Definition government.c:143
struct government * government_by_number(const Government_type_id gov)
Definition government.c:103
struct government * government_of_player(const struct player *pplayer)
Definition government.c:114
Government_type_id government_number(const struct government *pgovern)
Definition government.c:91
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
struct government * government_by_rule_name(const char *name)
Definition government.c:55
struct city * owner
Definition citydlg.c:226
static GtkWidget * source
Definition gotodlg.c:58
GType type
Definition repodlgs.c:1313
static const int bufsz
Definition helpdlg.c:70
struct impr_type * improvement_by_number(const Impr_type_id id)
bool great_wonder_is_built(const struct impr_type *pimprove)
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
bool wonder_is_built(const struct player *pplayer, const struct impr_type *pimprove)
Impr_type_id improvement_number(const struct impr_type *pimprove)
bool can_improvement_go_obsolete(const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
struct city * city_from_wonder(const struct player *pplayer, const struct impr_type *pimprove)
int impr_build_shield_cost(const struct city *pcity, const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
bool improvement_obsolete(const struct player *pplayer, const struct impr_type *pimprove, const struct city *pcity)
bool improvement_has_flag(const struct impr_type *pimprove, enum impr_flag_id flag)
struct impr_type * improvement_by_rule_name(const char *name)
const char * improvement_name_translation(const struct impr_type *pimprove)
bool great_wonder_is_available(const struct impr_type *pimprove)
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_error(message,...)
Definition log.h:103
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition log.h:208
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:931
int map_signed_latitude(const struct tile *ptile)
Definition map.c:1550
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:940
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:654
#define current_topo_has_flag(flag)
Definition map.h:48
#define MAP_MAX_LATITUDE
Definition map.h:574
#define adjc_iterate_end
Definition map.h:433
#define MAP_MAX_REAL_LATITUDE(_nmap)
Definition map.h:586
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:391
#define cardinal_adjc_iterate_end
Definition map.h:459
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:428
#define square_iterate_end
Definition map.h:394
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:455
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:401
#define current_wrap_has_flag(flag)
Definition map.h:51
#define MAP_MIN_REAL_LATITUDE(_nmap)
Definition map.h:588
#define circle_iterate_end
Definition map.h:404
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
const char * move_points_text(int mp, bool reduce)
Definition movement.c:1015
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:319
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:331
struct nation_group * nation_group_by_rule_name(const char *name)
Definition nation.c:1021
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:486
const char * nation_adjective_translation(const struct nation_type *pnation)
Definition nation.c:149
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:475
const char * nation_group_rule_name(const struct nation_group *pgroup)
Definition nation.c:1079
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
bool nation_is_in_group(const struct nation_type *pnation, const struct nation_group *pgroup)
Definition nation.c:1099
const char * nation_group_name_translation(const struct nation_group *pgroup)
Definition nation.c:1090
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
struct nation_group * nation_group_by_number(int id)
Definition nation.c:1004
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:952
#define NO_NATION_SELECTED
Definition nation.h:30
bool player_knows_techs_with_flag(const struct player *pplayer, enum tech_flag_id flag)
Definition player.c:1328
bool player_has_state(const struct player *pplayer, enum plrstate_type state)
Definition player.c:1998
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Definition player.c:1823
int diplrel_by_rule_name(const char *value)
Definition player.c:1581
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1476
bool is_diplrel_to_other(const struct player *pplayer, int diplrel)
Definition player.c:1562
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1990
const char * diplrel_name_translation(int value)
Definition player.c:1627
bool is_diplrel_between(const struct player *player1, const struct player *player2, int diplrel)
Definition player.c:1512
int player_age(const struct player *pplayer)
Definition player.c:954
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1405
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:437
const char * diplrel_rule_name(int value)
Definition player.c:1615
#define players_iterate_end
Definition player.h:537
#define players_iterate(_pplayer)
Definition player.h:532
#define player_nation(_plr_)
Definition player.h:406
#define is_ai(plr)
Definition player.h:230
#define players_iterate_alive_end
Definition player.h:547
#define players_iterate_alive(_pplayer)
Definition player.h:542
static enum fc_tristate is_latitude_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum req_item_found terrain_type_found(const struct requirement *preq, const struct universal *source)
bool universal_never_there(const struct universal *source)
static enum fc_tristate is_topology_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
bool universal_is_relevant_to_requirement(const struct requirement *req, const struct universal *source)
#define EXTRACT_INFO(req)
bool is_req_in_vec(const struct requirement *req, const struct requirement_vector *vec)
static int num_city_buildings(const struct city *pcity, const struct impr_type *building)
int universal_build_shield_cost(const struct city *pcity, const struct universal *target)
static enum req_item_found city_tile_found(const struct requirement *preq, const struct universal *source)
struct req_vec_problem * req_vec_get_first_contradiction(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static universal_found universal_found_function[VUT_COUNT]
static enum req_unchanging_status unchanging_local(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
#define REQUC_CITYSTATUS
const struct req_context * req_context_empty(void)
static enum req_item_found unit_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_mincalfrag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
void universal_extraction(const struct universal *source, int *kind, int *value)
static int num_player_buildings(const struct player *pplayer, const struct impr_type *building)
static enum fc_tristate is_extraflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_minforeignpct_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static int num_continent_buildings(const struct player *pplayer, int continent, const struct impr_type *building)
static enum fc_tristate tri_req_present(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
const char * req_to_fstring(const struct requirement *req, struct astring *astr)
static enum fc_tristate is_style_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
req_vec_num_in_item req_vec_vector_number(const void *parent_item, const struct requirement_vector *vec)
static bool present_implies_not_present(const struct requirement *req1, const struct requirement *req2)
static enum fc_tristate is_roadflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
struct requirement_vector * req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
bool universal_fulfills_requirements(bool check_necessary, const struct requirement_vector *reqs, const struct universal *source)
static bool activity_is_valid_in_requirement(enum unit_activity act)
static enum fc_tristate is_specialist_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum req_unchanging_status unchanging_noally(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_minveteran_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_unitstate_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
bool req_vec_change_apply(const struct req_vec_change *modification, requirement_vector_by_number getter, const void *parent_item)
void universal_copy(struct universal *dst, const struct universal *src)
static enum req_unchanging_status unchanging_building(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
bool are_requirements_equal(const struct requirement *req1, const struct requirement *req2)
static enum req_item_found extra_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_diplrel_unitany_in_range(const struct tile *target_tile, const struct player *other_player, enum req_range range, int diplrel)
bool are_reqs_active_ranges(const enum req_range min_range, const enum req_range max_range, const struct req_context *context, const struct player *other_player, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
static enum fc_tristate is_buildingflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_nation_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
bool is_req_active(const struct req_context *context, const struct player *other_player, const struct requirement *req, const enum req_problem_type prob_type)
static enum fc_tristate is_buildinggenus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
static enum fc_tristate is_diplrel_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
struct requirement req_from_str(const char *type, const char *range, bool survives, bool present, bool quiet, const char *value)
struct req_vec_problem * req_vec_suggest_repair(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
void universal_value_from_str(struct universal *source, const char *value)
static enum fc_tristate is_buildingflag_in_city(const struct city *pcity, enum impr_flag_id flag)
void req_get_values(const struct requirement *req, int *type, int *range, bool *survives, bool *present, bool *quiet, int *value)
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
bool are_reqs_active(const struct req_context *context, const struct player *other_player, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
const char * universal_rule_name(const struct universal *psource)
static enum fc_tristate is_ai_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum req_unchanging_status unchanging_present(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_plr_flag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_citytile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_nationality_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_activity_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
bool universal_replace_in_req_vec(struct requirement_vector *reqs, const struct universal *to_replace, const struct universal *replacement)
static enum fc_tristate is_wrap_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum req_item_found action_found(const struct requirement *preq, const struct universal *source)
enum fc_tristate default_tester_cb(const struct req_context *context, const struct player *other_player, const struct requirement *req, void *data, int n_data)
bool are_requirements_contradictions(const struct requirement *req1, const struct requirement *req2)
enum fc_tristate tri_req_active_turns(int pass, int period, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_diplrel_unitany_o_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
#define REQUC_IMPR
struct req_vec_problem * req_vec_problem_new(int num_suggested_solutions, const char *descr,...)
static enum fc_tristate is_form_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_diplrel_in_range(const struct player *target_player, const struct player *other_player, enum req_range range, int diplrel)
static enum fc_tristate is_counter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_none_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
bool universal_is_legal_in_requirement(const struct universal *univ)
static enum fc_tristate is_maxunitsontile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
int requirement_kind_ereq(const int value, const enum req_range range, const bool present, const int max_value)
static enum fc_tristate is_terrain_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
void req_vec_problem_free(struct req_vec_problem *issue)
static struct req_def req_definitions[VUT_COUNT]
static bool impr_contra_flag(const struct requirement *impr_req, const struct requirement *flag_req)
static enum req_item_found improvement_found(const struct requirement *preq, const struct universal *source)
struct req_vec_problem * req_vec_get_first_missing_univ(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum fc_tristate is_gov_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_terrainalter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_tech_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_good_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static bool players_in_same_range(const struct player *pplayer1, const struct player *pplayer2, enum req_range range)
enum req_item_found(* universal_found)(const struct requirement *, const struct universal *)
struct universal universal_by_number(const enum universals_n kind, const int value)
static enum fc_tristate is_achievement_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
enum req_item_found universal_fulfills_requirement(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_building_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static bool city_center_contra(const struct requirement *cc_req, const struct requirement *ct_req)
static enum fc_tristate is_unitclassflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum req_item_found ustate_found(const struct requirement *preq, const struct universal *source)
bool req_vec_wants_type(const struct requirement_vector *reqs, enum universals_n kind)
static int num_world_buildings_total(const struct impr_type *building)
static enum req_unchanging_status unchanging_citytile(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
enum fc_tristate tri_reqs_cb_active(const struct req_context *context, const struct player *other_player, const struct requirement_vector *reqs, struct requirement_vector *maybe_reqs, req_tester_cb tester, void *data, int n_data)
static enum req_item_found output_type_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_minhitpoints_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
struct req_vec_problem * req_vec_get_first_redundant_req(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static enum fc_tristate is_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_nationgroup_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static bool is_city_in_tile(const struct tile *ptile, const struct city *pcity)
enum fc_tristate(* is_req_active_cb)(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_originalowner_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_plr_state_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
bool does_req_contradicts_reqs(const struct requirement *req, const struct requirement_vector *vec)
static enum req_item_found government_found(const struct requirement *preq, const struct universal *source)
static enum req_unchanging_status unchanging_world(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_serversetting_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_action_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
struct req_vec_problem * req_vec_problem_new_transl(int num_suggested_solutions, const char *description, const char *description_translated)
#define REQUC_NALLY
static enum req_item_found unit_activity_found(const struct requirement *preq, const struct universal *source)
static enum fc_tristate is_mintechs_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_unitclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
enum fc_tristate tri_req_active(const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_terrainflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
#define REQUC_LOCAL
bool universals_say_everything(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
static enum fc_tristate is_extra_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum req_item_found nation_found(const struct requirement *preq, const struct universal *source)
#define REQUC_WORLD
const char * universal_type_rule_name(const struct universal *psource)
#define REQUC_PRESENT
void universal_found_functions_init(void)
static enum req_item_found unit_class_found(const struct requirement *preq, const struct universal *source)
#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind)
int universal_number(const struct universal *source)
static enum fc_tristate is_outputtype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
bool universal_is_mentioned_by_requirements(const struct requirement_vector *reqs, const struct universal *psource)
#define REQUC_CITYTILE
static enum fc_tristate is_minsize_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_diplrel_tile_o_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum req_item_found diplrel_found(const struct requirement *preq, const struct universal *source)
bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
static enum fc_tristate is_unitflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
bool req_implies_req(const struct requirement *req1, const struct requirement *req2)
void req_copy(struct requirement *dst, const struct requirement *src)
enum req_unchanging_status is_req_unchanging(const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_techflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static bool player_has_ever_built(const struct player *pplayer, const struct impr_type *building)
static enum fc_tristate is_terrainclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
enum req_unchanging_status is_req_preventing(const struct req_context *context, const struct player *other_player, const struct requirement *req, enum req_problem_type prob_type)
static bool nation_contra_group(const struct requirement *nation_req, const struct requirement *group_req)
bool req_is_impossible_to_fulfill(const struct requirement *req)
static bool are_tiles_in_range(const struct tile *tile1, const struct tile *tile2, enum req_range range)
static enum fc_tristate is_minyear_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static bool are_requirements_opposites(const struct requirement *req1, const struct requirement *req2)
static int num_world_buildings(const struct impr_type *building)
static enum fc_tristate is_minmovefrags_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum fc_tristate is_diplrel_tile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
static enum req_unchanging_status unchanging_citystatus(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
static enum fc_tristate is_minculture_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
struct universal universal_by_rule_name(const char *kind, const char *value)
static enum fc_tristate is_citystatus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
bool universals_mean_unfulfilled(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
struct req_vec_problem * req_vec_suggest_improvement(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
static bool impr_contra_genus(const struct requirement *impr_req, const struct requirement *genus_req)
static enum fc_tristate is_unittype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
#define requirement_diplrel_ereq(_id_, _range_, _present_)
signed char req_vec_num_in_item
req_vec_num_in_item a requirement vectors number in an item.
req_vec_num_in_item(* requirement_vector_number)(const void *parent_item, const struct requirement_vector *vec)
const char *(* requirement_vector_namer)(req_vec_num_in_item number)
#define universal_is_mentioned_by_requirement(preq, psource)
enum req_unchanging_status(* req_unchanging_cond_cb)(const struct civ_map *nmap, enum req_unchanging_status def, const struct req_context *context, const struct requirement *req)
enum fc_tristate(* req_tester_cb)(const struct req_context *context, const struct player *other_player, const struct requirement *req, void *data, int n_data)
#define requirement_vector_iterate_end
struct universal universal_by_number(const enum universals_n kind, const int value)
struct requirement_vector *(* requirement_vector_by_number)(const void *parent_item, req_vec_num_in_item number)
#define requirement_vector_iterate(req_vec, preq)
req_item_found
@ ITF_NO
@ ITF_YES
@ ITF_NOT_APPLICABLE
req_unchanging_status
@ REQUCH_ACT
@ REQUCH_NO
@ REQUCH_SCRIPTS
@ REQUCH_YES
@ REQUCH_HACK
@ REQUCH_CTRL
struct research * research_get(const struct player *pplayer)
Definition research.c:128
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:619
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Definition road.c:410
bool is_road_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:440
bool is_road_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:419
bool ssetv_setting_has_value(ssetv val)
ssetv ssetv_by_rule_name(const char *name)
const char * ssetv_rule_name(ssetv val)
const char * ssetv_human_readable(ssetv val, bool present)
#define SSETV_NONE
enum fc_tristate fc_tristate_or(enum fc_tristate one, enum fc_tristate two)
Definition shared.c:140
fc_tristate
Definition shared.h:46
@ TRI_YES
Definition shared.h:46
@ TRI_NO
Definition shared.h:46
@ TRI_MAYBE
Definition shared.h:46
#define BOOL_TO_TRISTATE(tri)
Definition shared.h:47
#define FC_INFINITY
Definition shared.h:36
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c:112
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:100
Specialist_type_id specialist_number(const struct specialist *sp)
Definition specialist.c:91
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
const char * specialist_plural_translation(const struct specialist *sp)
Definition specialist.c:155
Definition city.h:320
struct tile * tile
Definition city.h:322
struct packet_game_info info
Definition game.h:89
struct packet_calendar_info calendar
Definition game.h:90
int checkpoint
Definition counters.h:33
struct player * player
Definition nation.h:118
bool global_advances[A_LAST]
bool is_alive
Definition player.h:266
enum req_unchanging_status unchanging
req_unchanging_cond_cb unchanging_cond
const is_req_active_cb cb
req_vec_num_in_item vector_number
enum req_vec_change_operation operation
struct requirement req
char description[500]
char description_translated[500]
enum req_range range
struct universal source
int techs_researched
Definition research.h:42
Definition tile.h:50
struct tile * tile
Definition unit.h:140
enum universals_n kind
Definition fc_types.h:902
universals_u value
Definition fc_types.h:901
struct civ_map map
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
struct nation_style * style_by_number(int id)
Definition style.c:88
const char * style_name_translation(const struct nation_style *pstyle)
Definition style.c:99
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:108
int style_number(const struct nation_style *pstyle)
Definition style.c:68
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:791
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:836
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:900
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define bool
Definition support.h:71
#define fc__fallthrough
Definition support.h:119
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:290
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:299
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:186
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:612
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:591
const char * terrain_class_name_translation(enum terrain_class tclass)
Definition terrain.c:661
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:238
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:156
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Definition terrain.c:673
bool is_terrain_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:327
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:582
bool is_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:458
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:147
bool is_terrain_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:438
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:348
#define T_UNKNOWN
Definition terrain.h:57
#define terrain_has_flag(terr, flag)
Definition terrain.h:283
bool tile_has_extra_flag(const struct tile *ptile, enum extra_flag_id flag)
Definition tile.c:886
bool tile_has_native_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:324
bool tile_has_road_flag(const struct tile *ptile, enum road_flag_id flag)
Definition tile.c:868
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_terrain(_tile)
Definition tile.h:110
#define tile_continent(_tile)
Definition tile.h:92
#define tile_has_extra(ptile, pextra)
Definition tile.h:147
#define tile_owner(_tile)
Definition tile.h:96
Goods_type_id goods_number(const struct goods_type *pgood)
bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
const char * goods_name_translation(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
bool goods_can_be_provided(const struct city *pcity, const struct goods_type *pgood, struct unit *punit)
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
#define trade_partners_iterate_end
#define trade_partners_iterate(c, p)
const struct unit_type * utype
Definition fc_types.h:721
struct nation_style * style
Definition fc_types.h:725
enum ai_level ai_level
Definition fc_types.h:729
struct specialist * specialist
Definition fc_types.h:718
enum impr_genus_id impr_genus
Definition fc_types.h:751
enum citytile_type citytile
Definition fc_types.h:730
struct nation_group * nationgroup
Definition fc_types.h:724
struct extra_type * extra
Definition fc_types.h:722
enum wrap_flag wrap_property
Definition fc_types.h:764
enum plrstate_type plrstate
Definition fc_types.h:732
struct nation_type * nation
Definition fc_types.h:715
int terrainclass
Definition fc_types.h:739
int unitclassflag
Definition fc_types.h:741
struct government * govern
Definition fc_types.h:713
struct nation_type * origowner
Definition fc_types.h:717
enum impr_flag_id impr_flag
Definition fc_types.h:752
int max_tile_units
Definition fc_types.h:755
int terrainalter
Definition fc_types.h:740
enum citystatus_type citystatus
Definition fc_types.h:731
int minforeignpct
Definition fc_types.h:735
const struct impr_type * building
Definition fc_types.h:714
struct achievement * achievement
Definition fc_types.h:723
ssetv ssetval
Definition fc_types.h:765
struct advance * advance
Definition fc_types.h:711
enum unit_activity activity
Definition fc_types.h:750
struct goods_type * good
Definition fc_types.h:727
struct terrain * terrain
Definition fc_types.h:719
int terrainflag
Definition fc_types.h:743
enum ustate_prop unit_state
Definition fc_types.h:749
Output_type_id outputtype
Definition fc_types.h:738
enum topo_flag topo_property
Definition fc_types.h:763
struct counter * counter
Definition fc_types.h:712
int min_hit_points
Definition fc_types.h:757
struct unit_class * uclass
Definition fc_types.h:720
struct nation_type * nationality
Definition fc_types.h:716
struct action * action
Definition fc_types.h:726
enum plr_flag_id plr_flag
Definition fc_types.h:753
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1783
#define unit_tile(_pu)
Definition unit.h:397
#define unit_owner(_pu)
Definition unit.h:396
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const char * uclass_name_translation(const struct unit_class *pclass)
Definition unittype.c:1632
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1767
bool uclass_flag_is_in_use(enum unit_class_flag_id ucflag)
Definition unittype.c:2981
struct unit_class * uclass_by_number(const Unit_Class_id id)
Definition unittype.c:2477
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1578
struct unit_type * utype_by_number(const Unit_type_id id)
Definition unittype.c:112
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1641
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:100
struct unit_class * unit_class_by_rule_name(const char *s)
Definition unittype.c:1784
bool utype_flag_is_in_use(enum unit_type_flag_id uflag)
Definition unittype.c:3000
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1438
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2468
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:766
#define utype_class(_t_)
Definition unittype.h:749
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:617
bool victory_enabled(enum victory_condition_type victory)
Definition victory.c:26