Freeciv-3.1
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 "culture.h"
30#include "game.h"
31#include "government.h"
32#include "improvement.h"
33#include "movement.h"
34#include "player.h"
35#include "map.h"
36#include "research.h"
37#include "road.h"
38#include "server_settings.h"
39#include "specialist.h"
40#include "style.h"
41#include "victory.h" /* victory_enabled() */
42
43#include "requirements.h"
44
45/************************************************************************
46 Container for req_item_found functions
47************************************************************************/
48typedef enum req_item_found (*universal_found)(const struct requirement *,
49 const struct universal *);
50static universal_found universal_found_function[VUT_COUNT] = {NULL};
51
52static
53enum fc_tristate tri_req_present(const struct civ_map *nmap,
54 const struct req_context *context,
55 const struct player *other_player,
56 const struct requirement *req);
57
58/* Function pointer for requirement-type-specific is_req_active handlers */
59typedef enum fc_tristate
60(*is_req_active_cb)(const struct civ_map *nmap,
61 const struct req_context *context,
62 const struct player *other_player,
63 const struct requirement *req);
64
65static inline bool are_tiles_in_range(const struct tile *tile1,
66 const struct tile *tile2,
67 enum req_range range);
68
69/**********************************************************************/
74static enum req_unchanging_status
75 unchanging_local(const struct civ_map *nmap,
76 enum req_unchanging_status def,
77 const struct req_context *context,
78 const struct requirement *req)
79{
80 return req->range == REQ_RANGE_LOCAL ? REQUCH_YES : def;
81}
82#define REQUC_LOCAL unchanging_local
83
84/**********************************************************************/
87static enum req_unchanging_status
88 unchanging_present(const struct civ_map *nmap,
89 enum req_unchanging_status def,
90 const struct req_context *context,
91 const struct requirement *req)
92{
93 if (TRI_YES != tri_req_present(nmap, context, NULL, req)) {
94 return REQUCH_NO;
95 }
96 return def;
97}
98#define REQUC_PRESENT unchanging_present
99
100/**********************************************************************/
103static enum req_unchanging_status
104 unchanging_world(const struct civ_map *nmap,
105 enum req_unchanging_status def,
106 const struct req_context *context,
107 const struct requirement *req)
108{
109 return
110 unchanging_present(nmap, req->range == REQ_RANGE_WORLD ? REQUCH_YES : def,
111 context, req);
112}
113#define REQUC_WORLD unchanging_world
114
115/**********************************************************************/
119static enum req_unchanging_status
120 unchanging_noally(const struct civ_map *nmap,
121 enum req_unchanging_status def,
122 const struct req_context *context,
123 const struct requirement *req)
124{
125 if (REQ_RANGE_ALLIANCE == req->range
126 || REQ_RANGE_TEAM == req->range) {
127 struct requirement preq;
128
129 preq = *req;
130 preq.range = REQ_RANGE_PLAYER;
131 if (TRI_YES != tri_req_present(nmap, context, NULL, &preq)) {
132 return REQ_RANGE_TEAM == req->range ? REQUCH_ACT : REQUCH_NO;
133 }
134 }
135 return def;
136}
137#define REQUC_NALLY unchanging_noally
138
139/**********************************************************************/
143static enum req_unchanging_status
144 unchanging_citytile(const struct civ_map *nmap,
145 enum req_unchanging_status def,
146 const struct req_context *context,
147 const struct requirement *req)
148{
149 fc_assert_ret_val(VUT_CITYTILE == req->source.kind, REQUCH_NO);
150 if (CITYT_CENTER == req->source.value.citytile
151 || (NULL != context->city && NULL != context->tile
152 && NULL != city_tile(context->city)
153 && are_tiles_in_range(city_tile(context->city), context->tile,
154 req->range))){
155 /* Cities don't move */
156 return REQUCH_YES;
157 }
158 return def;
159}
160#define REQUC_CITYTILE unchanging_citytile
161
162/**********************************************************************/
165static enum req_unchanging_status
166 unchanging_citystatus(const struct civ_map *nmap,
167 enum req_unchanging_status def,
168 const struct req_context *context,
169 const struct requirement *req)
170{
171 fc_assert_ret_val(VUT_CITYSTATUS == req->source.kind, REQUCH_NO);
172 if (REQ_RANGE_CITY == req->range) {
173 return REQUCH_CTRL;
174 }
175 return def;
176}
177#define REQUC_CITYSTATUS unchanging_citystatus
178
179/**********************************************************************/
184static enum req_unchanging_status
185 unchanging_building(const struct civ_map *nmap,
186 enum req_unchanging_status def,
187 const struct req_context *context,
188 const struct requirement *req)
189{
190 const struct impr_type *b = req->source.value.building;
191
192 fc_assert_ret_val(VUT_IMPROVEMENT == req->source.kind, REQUCH_NO);
193
194 if (REQ_RANGE_LOCAL == req->range) {
195 /* Likely, won't be questioned for an obsolete building */
196 return REQUCH_YES;
197 }
198
199 if (improvement_obsolete(context->player, b, context->city)) {
200 /* FIXME: sometimes can unobsolete, but considering it
201 * may sometimes put the function on endless recursion */
202 return REQUCH_ACT; /* Mostly about techs */
203 }
204 if (is_great_wonder(b)) {
207 && (req->range <= REQ_RANGE_CITY && TRI_YES
208 == tri_req_present(nmap, context, NULL, req)))) {
209 /* If the wonder stays somewhere, it may either remain there
210 * or be destroyed. If it is destroyed, it is nowhere. */
211 return REQUCH_SCRIPTS;
212 }
213 }
214 return def;
215}
216#define REQUC_IMPR unchanging_building
217
223
224/**********************************************************************/
232 const char *value)
233{
234 struct universal source;
235
236 source.kind = universals_n_by_name(kind, fc_strcasecmp);
237 if (!universals_n_is_valid(source.kind)) {
238 return source;
239 }
240
242
243 return source;
244}
245
246/**********************************************************************/
250static bool activity_is_valid_in_requirement(enum unit_activity act)
251{
252 return unit_activity_is_valid(act)
253 && is_real_activity(act)
254 && act != ACTIVITY_SENTRY
255 && act != ACTIVITY_GOTO
256 && act != ACTIVITY_EXPLORE;
257}
258
259/**********************************************************************/
264{
265 if (univ->kind == VUT_ACTIVITY) {
267 }
268
269 return TRUE;
270}
271
272/**********************************************************************/
277{
278 /* Finally scan the value string based on the type of the source. */
279 switch (source->kind) {
280 case VUT_NONE:
281 return;
282 case VUT_ADVANCE:
283 source->value.advance = advance_by_rule_name(value);
284 if (source->value.advance != NULL) {
285 return;
286 }
287 break;
288 case VUT_TECHFLAG:
289 source->value.techflag
290 = tech_flag_id_by_name(value, fc_strcasecmp);
291 if (tech_flag_id_is_valid(source->value.techflag)) {
292 return;
293 }
294 break;
295 case VUT_GOVERNMENT:
296 source->value.govern = government_by_rule_name(value);
297 if (source->value.govern != NULL) {
298 return;
299 }
300 break;
301 case VUT_ACHIEVEMENT:
302 source->value.achievement = achievement_by_rule_name(value);
303 if (source->value.achievement != NULL) {
304 return;
305 }
306 break;
307 case VUT_STYLE:
308 source->value.style = style_by_rule_name(value);
309 if (source->value.style != NULL) {
310 return;
311 }
312 break;
313 case VUT_IMPROVEMENT:
314 source->value.building = improvement_by_rule_name(value);
315 if (source->value.building != NULL) {
316 return;
317 }
318 break;
319 case VUT_IMPR_GENUS:
320 source->value.impr_genus = impr_genus_id_by_name(value, fc_strcasecmp);
321 if (impr_genus_id_is_valid(source->value.impr_genus)) {
322 return;
323 }
324 break;
325 case VUT_EXTRA:
326 source->value.extra = extra_type_by_rule_name(value);
327 if (source->value.extra != NULL) {
328 return;
329 }
330 break;
331 case VUT_GOOD:
332 source->value.good = goods_by_rule_name(value);
333 if (source->value.good != NULL) {
334 return;
335 }
336 break;
337 case VUT_TERRAIN:
338 source->value.terrain = terrain_by_rule_name(value);
339 if (source->value.terrain != T_UNKNOWN) {
340 return;
341 }
342 break;
343 case VUT_TERRFLAG:
344 source->value.terrainflag
345 = terrain_flag_id_by_name(value, fc_strcasecmp);
346 if (terrain_flag_id_is_valid(source->value.terrainflag)) {
347 return;
348 }
349 break;
350 case VUT_NATION:
351 source->value.nation = nation_by_rule_name(value);
352 if (source->value.nation != NO_NATION_SELECTED) {
353 return;
354 }
355 break;
356 case VUT_NATIONGROUP:
357 source->value.nationgroup = nation_group_by_rule_name(value);
358 if (source->value.nationgroup != NULL) {
359 return;
360 }
361 break;
362 case VUT_NATIONALITY:
363 source->value.nationality = nation_by_rule_name(value);
364 if (source->value.nationality != NO_NATION_SELECTED) {
365 return;
366 }
367 break;
368 case VUT_DIPLREL:
369 case VUT_DIPLREL_TILE:
370 case VUT_DIPLREL_TILE_O:
371 case VUT_DIPLREL_UNITANY:
372 case VUT_DIPLREL_UNITANY_O:
373 source->value.diplrel = diplrel_by_rule_name(value);
374 if (source->value.diplrel != diplrel_other_invalid()) {
375 return;
376 }
377 break;
378 case VUT_UTYPE:
379 source->value.utype = unit_type_by_rule_name(value);
380 if (source->value.utype) {
381 return;
382 }
383 break;
384 case VUT_UTFLAG:
385 source->value.unitflag = unit_type_flag_id_by_name(value, fc_strcasecmp);
386 if (unit_type_flag_id_is_valid(source->value.unitflag)) {
387 return;
388 }
389 break;
390 case VUT_UCLASS:
391 source->value.uclass = unit_class_by_rule_name(value);
392 if (source->value.uclass) {
393 return;
394 }
395 break;
396 case VUT_UCFLAG:
397 source->value.unitclassflag
398 = unit_class_flag_id_by_name(value, fc_strcasecmp);
399 if (unit_class_flag_id_is_valid(source->value.unitclassflag)) {
400 return;
401 }
402 break;
403 case VUT_MINVETERAN:
404 source->value.minveteran = atoi(value);
405 if (source->value.minveteran > 0) {
406 return;
407 }
408 break;
409 case VUT_UNITSTATE:
410 source->value.unit_state = ustate_prop_by_name(value, fc_strcasecmp);
411 if (ustate_prop_is_valid(source->value.unit_state)) {
412 return;
413 }
414 break;
415 case VUT_ACTIVITY:
416 source->value.activity = unit_activity_by_name(value, fc_strcasecmp);
417 if (activity_is_valid_in_requirement(source->value.activity)) {
418 return;
419 }
420 break;
421 case VUT_MINMOVES:
422 source->value.minmoves = atoi(value);
423 if (source->value.minmoves > 0) {
424 return;
425 }
426 break;
427 case VUT_MINHP:
428 source->value.min_hit_points = atoi(value);
429 if (source->value.min_hit_points > 0) {
430 return;
431 }
432 break;
433 case VUT_AGE:
434 source->value.age = atoi(value);
435 if (source->value.age > 0) {
436 return;
437 }
438 break;
439 case VUT_MINTECHS:
440 source->value.min_techs = atoi(value);
441 if (source->value.min_techs > 0) {
442 return;
443 }
444 break;
445 case VUT_ACTION:
446 source->value.action = action_by_rule_name(value);
447 if (source->value.action != NULL) {
448 return;
449 }
450 break;
451 case VUT_OTYPE:
452 source->value.outputtype = output_type_by_identifier(value);
453 if (source->value.outputtype != O_LAST) {
454 return;
455 }
456 break;
457 case VUT_SPECIALIST:
458 source->value.specialist = specialist_by_rule_name(value);
459 if (source->value.specialist) {
460 return;
461 }
462 break;
463 case VUT_MINSIZE:
464 source->value.minsize = atoi(value);
465 if (source->value.minsize > 0) {
466 return;
467 }
468 break;
469 case VUT_MINCULTURE:
470 source->value.minculture = atoi(value);
471 if (source->value.minculture > 0) {
472 return;
473 }
474 break;
475 case VUT_MINFOREIGNPCT:
476 source->value.minforeignpct = atoi(value);
477 if (source->value.minforeignpct > 0) {
478 return;
479 }
480 break;
481 case VUT_AI_LEVEL:
482 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
483 if (ai_level_is_valid(source->value.ai_level)) {
484 return;
485 }
486 break;
487 case VUT_MAXTILEUNITS:
488 source->value.max_tile_units = atoi(value);
489 if (0 <= source->value.max_tile_units) {
490 return;
491 }
492 break;
493 case VUT_TERRAINCLASS:
494 source->value.terrainclass
495 = terrain_class_by_name(value, fc_strcasecmp);
496 if (terrain_class_is_valid(source->value.terrainclass)) {
497 return;
498 }
499 break;
500 case VUT_ROADFLAG:
501 source->value.roadflag = road_flag_id_by_name(value, fc_strcasecmp);
502 if (road_flag_id_is_valid(source->value.roadflag)) {
503 return;
504 }
505 break;
506 case VUT_EXTRAFLAG:
507 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
508 if (extra_flag_id_is_valid(source->value.extraflag)) {
509 return;
510 }
511 break;
512 case VUT_MINYEAR:
513 source->value.minyear = atoi(value);
514 return;
515 case VUT_MINCALFRAG:
516 /* Rule names are 0-based numbers, not pretty names from ruleset */
517 source->value.mincalfrag = atoi(value);
518 if (source->value.mincalfrag >= 0) {
519 /* More range checking done later, in sanity_check_req_individual() */
520 return;
521 }
522 break;
523 case VUT_TOPO:
524 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
525 if (topo_flag_is_valid(source->value.topo_property)) {
526 return;
527 }
528 break;
529 case VUT_SERVERSETTING:
530 source->value.ssetval = ssetv_by_rule_name(value);
531 if (source->value.ssetval != SSETV_NONE) {
532 return;
533 }
534 break;
535 case VUT_TERRAINALTER:
536 source->value.terrainalter
537 = terrain_alteration_by_name(value, fc_strcasecmp);
538 if (terrain_alteration_is_valid(source->value.terrainalter)) {
539 return;
540 }
541 break;
542 case VUT_CITYTILE:
543 source->value.citytile = citytile_type_by_name(value, fc_strcasecmp);
544 if (source->value.citytile != CITYT_LAST) {
545 return;
546 }
547 break;
548 case VUT_CITYSTATUS:
549 source->value.citystatus = citystatus_type_by_name(value, fc_strcasecmp);
550 if (source->value.citystatus != CITYS_LAST) {
551 return;
552 }
553 break;
554 case VUT_COUNT:
555 break;
556 }
557
558 /* If we reach here there's been an error. */
559 source->kind = universals_n_invalid();
560}
561
562/**********************************************************************/
567struct universal universal_by_number(const enum universals_n kind,
568 const int value)
569{
570 struct universal source;
571
572 source.kind = kind;
573
574 switch (source.kind) {
575 case VUT_NONE:
576 /* Avoid compiler warning about unitialized source.value */
577 source.value.advance = NULL;
578
579 return source;
580 case VUT_ADVANCE:
581 source.value.advance = advance_by_number(value);
582 if (source.value.advance != NULL) {
583 return source;
584 }
585 break;
586 case VUT_TECHFLAG:
587 source.value.techflag = value;
588 return source;
589 case VUT_GOVERNMENT:
591 if (source.value.govern != NULL) {
592 return source;
593 }
594 break;
595 case VUT_ACHIEVEMENT:
596 source.value.achievement = achievement_by_number(value);
597 if (source.value.achievement != NULL) {
598 return source;
599 }
600 break;
601 case VUT_STYLE:
602 source.value.style = style_by_number(value);
603 if (source.value.style != NULL) {
604 return source;
605 }
606 break;
607 case VUT_IMPROVEMENT:
608 source.value.building = improvement_by_number(value);
609 if (source.value.building != NULL) {
610 return source;
611 }
612 break;
613 case VUT_IMPR_GENUS:
614 source.value.impr_genus = value;
615 return source;
616 case VUT_EXTRA:
618 return source;
619 case VUT_GOOD:
620 source.value.good = goods_by_number(value);
621 return source;
622 case VUT_TERRAIN:
623 source.value.terrain = terrain_by_number(value);
624 if (source.value.terrain != NULL) {
625 return source;
626 }
627 break;
628 case VUT_TERRFLAG:
629 source.value.terrainflag = value;
630 return source;
631 case VUT_NATION:
633 if (source.value.nation != NULL) {
634 return source;
635 }
636 break;
637 case VUT_NATIONGROUP:
638 source.value.nationgroup = nation_group_by_number(value);
639 if (source.value.nationgroup != NULL) {
640 return source;
641 }
642 break;
643 case VUT_DIPLREL:
644 case VUT_DIPLREL_TILE:
645 case VUT_DIPLREL_TILE_O:
646 case VUT_DIPLREL_UNITANY:
647 case VUT_DIPLREL_UNITANY_O:
648 source.value.diplrel = value;
649 if (source.value.diplrel != diplrel_other_invalid()) {
650 return source;
651 }
652 break;
653 case VUT_NATIONALITY:
655 if (source.value.nationality != NULL) {
656 return source;
657 }
658 break;
659 case VUT_UTYPE:
660 source.value.utype = utype_by_number(value);
661 if (source.value.utype != NULL) {
662 return source;
663 }
664 break;
665 case VUT_UTFLAG:
666 source.value.unitflag = value;
667 return source;
668 case VUT_UCLASS:
670 if (source.value.uclass != NULL) {
671 return source;
672 }
673 break;
674 case VUT_UCFLAG:
675 source.value.unitclassflag = value;
676 return source;
677 case VUT_MINVETERAN:
678 source.value.minveteran = value;
679 return source;
680 case VUT_UNITSTATE:
681 source.value.unit_state = value;
682 return source;
683 case VUT_ACTIVITY:
684 source.value.activity = value;
685 return source;
686 case VUT_MINMOVES:
687 source.value.minmoves = value;
688 return source;
689 case VUT_MINHP:
691 return source;
692 case VUT_AGE:
693 source.value.age = value;
694 return source;
695 case VUT_MINTECHS:
696 source.value.min_techs = value;
697 return source;
698 case VUT_ACTION:
700 if (source.value.action != NULL) {
701 return source;
702 }
703 break;
704 case VUT_OTYPE:
705 source.value.outputtype = value;
706 return source;
707 case VUT_SPECIALIST:
709 return source;
710 case VUT_MINSIZE:
711 source.value.minsize = value;
712 return source;
713 case VUT_MINCULTURE:
714 source.value.minculture = value;
715 return source;
716 case VUT_MINFOREIGNPCT:
717 source.value.minforeignpct = value;
718 return source;
719 case VUT_AI_LEVEL:
720 source.value.ai_level = value;
721 return source;
722 case VUT_MAXTILEUNITS:
724 return source;
725 case VUT_TERRAINCLASS:
726 source.value.terrainclass = value;
727 return source;
728 case VUT_ROADFLAG:
729 source.value.roadflag = value;
730 return source;
731 case VUT_EXTRAFLAG:
732 source.value.extraflag = value;
733 return source;
734 case VUT_MINYEAR:
735 source.value.minyear = value;
736 return source;
737 case VUT_MINCALFRAG:
738 source.value.mincalfrag = value;
739 return source;
740 case VUT_TOPO:
741 source.value.topo_property = value;
742 return source;
743 case VUT_SERVERSETTING:
744 source.value.ssetval = value;
745 return source;
746 case VUT_TERRAINALTER:
747 source.value.terrainalter = value;
748 return source;
749 case VUT_CITYTILE:
750 source.value.citytile = value;
751 return source;
752 case VUT_CITYSTATUS:
753 source.value.citystatus = value;
754 return source;
755 case VUT_COUNT:
756 break;
757 }
758
759 /* If we reach here there's been an error. */
760 source.kind = universals_n_invalid();
761 /* Avoid compiler warning about unitialized source.value */
762 source.value.advance = NULL;
763
764 return source;
765}
766
767/**********************************************************************/
770void universal_copy(struct universal *dst, const struct universal *src)
771{
772 dst->value = src->value;
773 dst->kind = src->kind;
774}
775
776/**********************************************************************/
781 int *kind, int *value)
782{
783 *kind = source->kind;
785}
786
787/**********************************************************************/
791{
792 switch (source->kind) {
793 case VUT_NONE:
794 return 0;
795 case VUT_ADVANCE:
796 return advance_number(source->value.advance);
797 case VUT_TECHFLAG:
798 return source->value.techflag;
799 case VUT_GOVERNMENT:
800 return government_number(source->value.govern);
801 case VUT_ACHIEVEMENT:
802 return achievement_number(source->value.achievement);
803 case VUT_STYLE:
804 return style_number(source->value.style);
805 case VUT_IMPROVEMENT:
806 return improvement_number(source->value.building);
807 case VUT_IMPR_GENUS:
808 return source->value.impr_genus;
809 case VUT_EXTRA:
810 return extra_number(source->value.extra);
811 case VUT_GOOD:
812 return goods_number(source->value.good);
813 case VUT_TERRAIN:
814 return terrain_number(source->value.terrain);
815 case VUT_TERRFLAG:
816 return source->value.terrainflag;
817 case VUT_NATION:
818 return nation_number(source->value.nation);
819 case VUT_NATIONGROUP:
820 return nation_group_number(source->value.nationgroup);
821 case VUT_NATIONALITY:
822 return nation_number(source->value.nationality);
823 case VUT_DIPLREL:
824 case VUT_DIPLREL_TILE:
825 case VUT_DIPLREL_TILE_O:
826 case VUT_DIPLREL_UNITANY:
827 case VUT_DIPLREL_UNITANY_O:
828 return source->value.diplrel;
829 case VUT_UTYPE:
830 return utype_number(source->value.utype);
831 case VUT_UTFLAG:
832 return source->value.unitflag;
833 case VUT_UCLASS:
834 return uclass_number(source->value.uclass);
835 case VUT_UCFLAG:
836 return source->value.unitclassflag;
837 case VUT_MINVETERAN:
838 return source->value.minveteran;
839 case VUT_UNITSTATE:
840 return source->value.unit_state;
841 case VUT_ACTIVITY:
842 return source->value.activity;
843 case VUT_MINMOVES:
844 return source->value.minmoves;
845 case VUT_MINHP:
846 return source->value.min_hit_points;
847 case VUT_AGE:
848 return source->value.age;
849 case VUT_MINTECHS:
850 return source->value.min_techs;
851 case VUT_ACTION:
852 return action_number(source->value.action);
853 case VUT_OTYPE:
854 return source->value.outputtype;
855 case VUT_SPECIALIST:
856 return specialist_number(source->value.specialist);
857 case VUT_MINSIZE:
858 return source->value.minsize;
859 case VUT_MINCULTURE:
860 return source->value.minculture;
861 case VUT_MINFOREIGNPCT:
862 return source->value.minforeignpct;
863 case VUT_AI_LEVEL:
864 return source->value.ai_level;
865 case VUT_MAXTILEUNITS:
866 return source->value.max_tile_units;
867 case VUT_TERRAINCLASS:
868 return source->value.terrainclass;
869 case VUT_ROADFLAG:
870 return source->value.roadflag;
871 case VUT_EXTRAFLAG:
872 return source->value.extraflag;
873 case VUT_MINYEAR:
874 return source->value.minyear;
875 case VUT_MINCALFRAG:
876 return source->value.mincalfrag;
877 case VUT_TOPO:
878 return source->value.topo_property;
879 case VUT_SERVERSETTING:
880 return source->value.ssetval;
881 case VUT_TERRAINALTER:
882 return source->value.terrainalter;
883 case VUT_CITYTILE:
884 return source->value.citytile;
885 case VUT_CITYSTATUS:
886 return source->value.citystatus;
887 case VUT_COUNT:
888 break;
889 }
890
891 /* If we reach here there's been an error. */
892 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
893 source->kind);
894 return 0;
895}
896
897
898/**********************************************************************/
902{
903 static const struct req_context empty = {};
904 return &empty;
905}
906
907
908/**********************************************************************/
916const char *req_to_fstring(const struct requirement *req,
917 struct astring *astr)
918{
919 astr_init(astr);
920
921 astr_set(astr, "%s%s %s %s%s",
922 req->survives ? "surviving " : "",
923 req_range_name(req->range),
925 req->present ? "" : "!",
927
928 return astr_str(astr);
929}
930
931/**********************************************************************/
938struct requirement req_from_str(const char *type, const char *range,
939 bool survives, bool present, bool quiet,
940 const char *value)
941{
942 struct requirement req;
943 bool invalid;
944 const char *error = NULL;
945
946 req.source = universal_by_rule_name(type, value);
947
948 invalid = !universals_n_is_valid(req.source.kind);
949 if (invalid) {
950 error = "bad type or name";
951 } else {
952 /* Scan the range string to find the range. If no range is given a
953 * default fallback is used rather than giving an error. */
954 if (range != NULL) {
955 req.range = req_range_by_name(range, fc_strcasecmp);
956 if (!req_range_is_valid(req.range)) {
957 invalid = TRUE;
958 }
959 } else {
960 switch (req.source.kind) {
961 case VUT_NONE:
962 case VUT_COUNT:
963 break;
964 case VUT_IMPROVEMENT:
965 case VUT_IMPR_GENUS:
966 case VUT_EXTRA:
967 case VUT_TERRAIN:
968 case VUT_TERRFLAG:
969 case VUT_UTYPE:
970 case VUT_UTFLAG:
971 case VUT_UCLASS:
972 case VUT_UCFLAG:
973 case VUT_MINVETERAN:
974 case VUT_UNITSTATE:
975 case VUT_ACTIVITY:
976 case VUT_MINMOVES:
977 case VUT_MINHP:
978 case VUT_AGE:
979 case VUT_ACTION:
980 case VUT_OTYPE:
981 case VUT_SPECIALIST:
982 case VUT_TERRAINCLASS:
983 case VUT_ROADFLAG:
984 case VUT_EXTRAFLAG:
985 case VUT_TERRAINALTER:
986 case VUT_CITYTILE:
987 case VUT_MAXTILEUNITS:
988 case VUT_DIPLREL_TILE_O:
989 case VUT_DIPLREL_UNITANY_O:
990 req.range = REQ_RANGE_LOCAL;
991 break;
992 case VUT_MINSIZE:
993 case VUT_MINCULTURE:
994 case VUT_MINFOREIGNPCT:
995 case VUT_NATIONALITY:
996 case VUT_CITYSTATUS:
997 case VUT_GOOD:
998 req.range = REQ_RANGE_CITY;
999 break;
1000 case VUT_GOVERNMENT:
1001 case VUT_ACHIEVEMENT:
1002 case VUT_STYLE:
1003 case VUT_ADVANCE:
1004 case VUT_TECHFLAG:
1005 case VUT_NATION:
1006 case VUT_NATIONGROUP:
1007 case VUT_DIPLREL:
1008 case VUT_DIPLREL_TILE:
1009 case VUT_DIPLREL_UNITANY:
1010 case VUT_AI_LEVEL:
1011 req.range = REQ_RANGE_PLAYER;
1012 break;
1013 case VUT_MINYEAR:
1014 case VUT_MINCALFRAG:
1015 case VUT_TOPO:
1016 case VUT_MINTECHS:
1017 case VUT_SERVERSETTING:
1018 req.range = REQ_RANGE_WORLD;
1019 break;
1020 }
1021 }
1022
1023 req.survives = survives;
1024 req.present = present;
1025 req.quiet = quiet;
1026
1027 /* These checks match what combinations are supported inside
1028 * is_req_active(). However, it's only possible to do basic checks,
1029 * not anything that might depend on the rest of the ruleset which
1030 * might not have been loaded yet. */
1031 switch (req.source.kind) {
1032 case VUT_TERRAIN:
1033 case VUT_EXTRA:
1034 case VUT_TERRAINCLASS:
1035 case VUT_TERRFLAG:
1036 case VUT_ROADFLAG:
1037 case VUT_EXTRAFLAG:
1038 invalid = (req.range != REQ_RANGE_LOCAL
1039 && req.range != REQ_RANGE_CADJACENT
1040 && req.range != REQ_RANGE_ADJACENT
1041 && req.range != REQ_RANGE_CITY
1042 && req.range != REQ_RANGE_TRADE_ROUTE);
1043 break;
1044 case VUT_ADVANCE:
1045 case VUT_TECHFLAG:
1046 case VUT_ACHIEVEMENT:
1047 case VUT_MINTECHS:
1048 invalid = (req.range < REQ_RANGE_PLAYER);
1049 break;
1050 case VUT_GOVERNMENT:
1051 case VUT_AI_LEVEL:
1052 case VUT_STYLE:
1053 invalid = (req.range != REQ_RANGE_PLAYER);
1054 break;
1055 case VUT_MINSIZE:
1056 case VUT_MINFOREIGNPCT:
1057 case VUT_NATIONALITY:
1058 case VUT_CITYSTATUS:
1059 invalid = (req.range != REQ_RANGE_CITY
1060 && req.range != REQ_RANGE_TRADE_ROUTE);
1061 break;
1062 case VUT_GOOD:
1063 invalid = (req.range != REQ_RANGE_CITY);
1064 break;
1065 case VUT_MINCULTURE:
1066 invalid = (req.range != REQ_RANGE_CITY
1067 && req.range != REQ_RANGE_TRADE_ROUTE
1068 && req.range != REQ_RANGE_PLAYER
1069 && req.range != REQ_RANGE_TEAM
1070 && req.range != REQ_RANGE_ALLIANCE
1071 && req.range != REQ_RANGE_WORLD);
1072 break;
1073 case VUT_DIPLREL:
1074 invalid = (req.range != REQ_RANGE_LOCAL
1075 && req.range != REQ_RANGE_PLAYER
1076 && req.range != REQ_RANGE_TEAM
1077 && req.range != REQ_RANGE_ALLIANCE
1078 && req.range != REQ_RANGE_WORLD)
1079 /* Non local foreign makes no sense. */
1080 || (req.source.value.diplrel == DRO_FOREIGN
1081 && req.range != REQ_RANGE_LOCAL);
1082 break;
1083 case VUT_DIPLREL_TILE:
1084 invalid = (req.range != REQ_RANGE_LOCAL
1085 && req.range != REQ_RANGE_PLAYER
1086 && req.range != REQ_RANGE_TEAM
1087 && req.range != REQ_RANGE_ALLIANCE)
1088 /* Non local foreign makes no sense. */
1089 || (req.source.value.diplrel == DRO_FOREIGN
1090 && req.range != REQ_RANGE_LOCAL);
1091 break;
1092 case VUT_DIPLREL_TILE_O:
1093 invalid = (req.range != REQ_RANGE_LOCAL);
1094 break;
1095 case VUT_DIPLREL_UNITANY:
1096 invalid = (req.range != REQ_RANGE_LOCAL
1097 && req.range != REQ_RANGE_PLAYER
1098 && req.range != REQ_RANGE_TEAM
1099 && req.range != REQ_RANGE_ALLIANCE)
1100 /* Non local foreign makes no sense. */
1101 || (req.source.value.diplrel == DRO_FOREIGN
1102 && req.range != REQ_RANGE_LOCAL);
1103 break;
1104 case VUT_DIPLREL_UNITANY_O:
1105 invalid = (req.range != REQ_RANGE_LOCAL);
1106 break;
1107 case VUT_NATION:
1108 case VUT_NATIONGROUP:
1109 invalid = (req.range != REQ_RANGE_PLAYER
1110 && req.range != REQ_RANGE_TEAM
1111 && req.range != REQ_RANGE_ALLIANCE
1112 && req.range != REQ_RANGE_WORLD);
1113 break;
1114 case VUT_UTYPE:
1115 case VUT_UTFLAG:
1116 case VUT_UCLASS:
1117 case VUT_UCFLAG:
1118 case VUT_MINVETERAN:
1119 case VUT_UNITSTATE:
1120 case VUT_ACTIVITY:
1121 case VUT_MINMOVES:
1122 case VUT_MINHP:
1123 case VUT_ACTION:
1124 case VUT_OTYPE:
1125 case VUT_SPECIALIST:
1126 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1127 invalid = (req.range != REQ_RANGE_LOCAL);
1128 break;
1129 case VUT_CITYTILE:
1130 case VUT_MAXTILEUNITS:
1131 invalid = (req.range != REQ_RANGE_LOCAL
1132 && req.range != REQ_RANGE_CADJACENT
1133 && req.range != REQ_RANGE_ADJACENT);
1134 break;
1135 case VUT_MINYEAR:
1136 case VUT_MINCALFRAG:
1137 case VUT_TOPO:
1138 case VUT_SERVERSETTING:
1139 invalid = (req.range != REQ_RANGE_WORLD);
1140 break;
1141 case VUT_AGE:
1142 /* FIXME: could support TRADE_ROUTE, TEAM, etc */
1143 invalid = (req.range != REQ_RANGE_LOCAL
1144 && req.range != REQ_RANGE_CITY
1145 && req.range != REQ_RANGE_PLAYER);
1146 break;
1147 case VUT_IMPR_GENUS:
1148 /* TODO: Support other ranges too. */
1149 invalid = req.range != REQ_RANGE_LOCAL;
1150 break;
1151 case VUT_IMPROVEMENT:
1152 /* Valid ranges depend on the building genus (wonder/improvement),
1153 * which might not have been loaded from the ruleset yet.
1154 * So we allow anything here, and do a proper check once ruleset
1155 * loading is complete, in sanity_check_req_individual(). */
1156 case VUT_NONE:
1157 invalid = FALSE;
1158 break;
1159 case VUT_COUNT:
1160 break;
1161 }
1162 if (invalid) {
1163 error = "bad range";
1164 }
1165 }
1166
1167 if (!invalid) {
1168 /* Check 'survives'. */
1169 switch (req.source.kind) {
1170 case VUT_IMPROVEMENT:
1171 /* See buildings_in_range(). */
1172 invalid = survives && req.range <= REQ_RANGE_CONTINENT;
1173 break;
1174 case VUT_NATION:
1175 case VUT_ADVANCE:
1176 invalid = survives && req.range != REQ_RANGE_WORLD;
1177 break;
1178 case VUT_IMPR_GENUS:
1179 case VUT_GOVERNMENT:
1180 case VUT_TERRAIN:
1181 case VUT_UTYPE:
1182 case VUT_UTFLAG:
1183 case VUT_UCLASS:
1184 case VUT_UCFLAG:
1185 case VUT_MINVETERAN:
1186 case VUT_UNITSTATE:
1187 case VUT_ACTIVITY:
1188 case VUT_MINMOVES:
1189 case VUT_MINHP:
1190 case VUT_AGE:
1191 case VUT_ACTION:
1192 case VUT_OTYPE:
1193 case VUT_SPECIALIST:
1194 case VUT_MINSIZE:
1195 case VUT_MINCULTURE:
1196 case VUT_MINFOREIGNPCT:
1197 case VUT_AI_LEVEL:
1198 case VUT_TERRAINCLASS:
1199 case VUT_MINYEAR:
1200 case VUT_MINCALFRAG:
1201 case VUT_TOPO:
1202 case VUT_SERVERSETTING:
1203 case VUT_TERRAINALTER:
1204 case VUT_CITYTILE:
1205 case VUT_CITYSTATUS:
1206 case VUT_TERRFLAG:
1207 case VUT_NATIONALITY:
1208 case VUT_ROADFLAG:
1209 case VUT_EXTRAFLAG:
1210 case VUT_EXTRA:
1211 case VUT_GOOD:
1212 case VUT_TECHFLAG:
1213 case VUT_ACHIEVEMENT:
1214 case VUT_NATIONGROUP:
1215 case VUT_STYLE:
1216 case VUT_DIPLREL:
1217 case VUT_DIPLREL_TILE:
1218 case VUT_DIPLREL_TILE_O:
1219 case VUT_DIPLREL_UNITANY:
1220 case VUT_DIPLREL_UNITANY_O:
1221 case VUT_MAXTILEUNITS:
1222 case VUT_MINTECHS:
1223 /* Most requirements don't support 'survives'. */
1224 invalid = survives;
1225 break;
1226 case VUT_NONE:
1227 case VUT_COUNT:
1228 break;
1229 }
1230 if (invalid) {
1231 error = "bad 'survives'";
1232 }
1233 }
1234
1235 if (invalid) {
1236 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1237 type, range, survives ? "survives" : "",
1238 present ? "present" : "", value, error);
1239 req.source.kind = universals_n_invalid();
1240 }
1241
1242 return req;
1243}
1244
1245/**********************************************************************/
1251 int value)
1252{
1253 struct requirement req;
1254
1255 req.source = universal_by_number(type, value);
1256 req.range = range;
1257 req.survives = survives;
1258 req.present = present;
1259 req.quiet = quiet;
1260
1261 return req;
1262}
1263
1264/**********************************************************************/
1268void req_get_values(const struct requirement *req,
1269 int *type, int *range,
1270 bool *survives, bool *present, bool *quiet,
1271 int *value)
1272{
1273 universal_extraction(&req->source, type, value);
1274 *range = req->range;
1275 *survives = req->survives;
1276 *present = req->present;
1277 *quiet = req->quiet;
1278}
1279
1280/**********************************************************************/
1283void req_copy(struct requirement *dst, const struct requirement *src)
1284{
1285 universal_copy(&(dst->source), &(src->source));
1286 dst->range = src->range;
1287 dst->survives = src->survives;
1288 dst->present = src->present;
1289 dst->quiet = src->quiet;
1290}
1291
1292/**********************************************************************/
1296bool are_requirements_equal(const struct requirement *req1,
1297 const struct requirement *req2)
1298{
1299 return (are_universals_equal(&req1->source, &req2->source)
1300 && req1->range == req2->range
1301 && req1->survives == req2->survives
1302 && req1->present == req2->present);
1303}
1304
1305/**********************************************************************/
1308static bool are_requirements_opposites(const struct requirement *req1,
1309 const struct requirement *req2)
1310{
1311 return (are_universals_equal(&req1->source, &req2->source)
1312 && req1->range == req2->range
1313 && req1->survives == req2->survives
1314 && req1->present != req2->present);
1315}
1316
1317/**********************************************************************/
1321static bool impr_contra_genus(const struct requirement *impr_req,
1322 const struct requirement *genus_req)
1323{
1324 /* The input is sane. */
1325 fc_assert_ret_val(impr_req->source.kind == VUT_IMPROVEMENT, FALSE);
1326 fc_assert_ret_val(genus_req->source.kind == VUT_IMPR_GENUS, FALSE);
1327
1328 if (impr_req->range == REQ_RANGE_LOCAL
1329 && genus_req->range == REQ_RANGE_LOCAL) {
1330 /* Applies to the same target building. */
1331
1332 if (impr_req->present && !genus_req->present) {
1333 /* The target building can't not have the genus it has. */
1334 return (impr_req->source.value.building->genus
1335 == genus_req->source.value.impr_genus);
1336 }
1337
1338 if (impr_req->present && genus_req->present) {
1339 /* The target building can't have another genus than it has. */
1340 return (impr_req->source.value.building->genus
1341 != genus_req->source.value.impr_genus);
1342 }
1343 }
1344
1345 /* No special knowledge. */
1346 return FALSE;
1347}
1348
1349/**********************************************************************/
1353static bool nation_contra_group(const struct requirement *nation_req,
1354 const struct requirement *group_req)
1355{
1356 /* The input is sane. */
1357 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1358 fc_assert_ret_val(group_req->source.kind == VUT_NATIONGROUP, FALSE);
1359
1360 if (nation_req->range == REQ_RANGE_PLAYER
1361 && group_req->range == REQ_RANGE_PLAYER) {
1362 /* Applies to the same target building. */
1363
1364 if (nation_req->present && !group_req->present) {
1365 /* The target nation can't be in the group. */
1366 return nation_is_in_group(nation_req->source.value.nation,
1367 group_req->source.value.nationgroup);
1368 }
1369 }
1370
1371 /* No special knowledge. */
1372 return FALSE;
1373}
1374
1375/**********************************************************************/
1380static bool present_implies_not_present(const struct requirement *req1,
1381 const struct requirement *req2)
1382{
1383 const struct requirement *absent, *present;
1384
1385 if (req1->present == req2->present) {
1386 /* Can't use the knowledge in universal_found_function when both are
1387 * required to be absent or when both are required to be present.
1388 * It is no contradiction to require !Spy unit and !Missile unit class.
1389 * It is no contradiction to require River and Irrigation at the same
1390 * tile. */
1391 return FALSE;
1392 }
1393
1394 if (req1->present) {
1395 absent = req2;
1396 present = req1;
1397 } else {
1398 absent = req1;
1399 present = req2;
1400 }
1401
1402 if (!universal_found_function[present->source.kind]) {
1403 /* No knowledge to exploit. */
1404 return FALSE;
1405 }
1406
1407 if (present->range != absent->range) {
1408 /* Larger ranges are not always strict supersets of smaller ranges.
1409 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1410 * but not in Trade Route. */
1411 return FALSE;
1412 }
1413
1414 return ITF_YES == universal_fulfills_requirement(absent,
1415 &present->source);
1416}
1417
1418/**********************************************************************/
1421bool req_implies_req(const struct requirement *req1,
1422 const struct requirement *req2)
1423{
1424 struct requirement nreq2;
1425
1426 req_copy(&nreq2, req2);
1427 nreq2.present = !nreq2.present;
1428 return are_requirements_contradictions(req1, &nreq2);
1429}
1430
1431/**********************************************************************/
1439 const struct requirement *req2)
1440{
1441 if (are_requirements_opposites(req1, req2)) {
1442 /* The exact opposite. */
1443 return TRUE;
1444 }
1445
1446 if (present_implies_not_present(req1, req2)) {
1447 return TRUE;
1448 }
1449
1450 switch (req1->source.kind) {
1451 case VUT_IMPROVEMENT:
1452 if (req2->source.kind == VUT_IMPR_GENUS) {
1453 return impr_contra_genus(req1, req2);
1454 }
1455
1456 /* No special knowledge. */
1457 return FALSE;
1458 break;
1459 case VUT_IMPR_GENUS:
1460 if (req2->source.kind == VUT_IMPROVEMENT) {
1461 return impr_contra_genus(req2, req1);
1462 }
1463
1464 /* No special knowledge. */
1465 return FALSE;
1466 break;
1467 case VUT_DIPLREL:
1468 case VUT_DIPLREL_TILE:
1469 case VUT_DIPLREL_TILE_O:
1470 case VUT_DIPLREL_UNITANY:
1471 case VUT_DIPLREL_UNITANY_O:
1472 if (req2->source.kind != req1->source.kind) {
1473 /* Finding contradictions across requirement kinds aren't supported
1474 * for DiplRel requirements. */
1475 return FALSE;
1476 } else {
1477 /* Use the special knowledge about DiplRel requirements to find
1478 * contradictions. */
1479
1480 bv_diplrel_all_reqs req1_contra;
1481 int req2_pos;
1482
1483 req1_contra = diplrel_req_contradicts(req1);
1485 req2->range,
1486 req2->present);
1487
1488 return BV_ISSET(req1_contra, req2_pos);
1489 }
1490 break;
1491 case VUT_MINMOVES:
1492 if (req2->source.kind != VUT_MINMOVES) {
1493 /* Finding contradictions across requirement kinds aren't supported
1494 * for MinMoveFrags requirements. */
1495 return FALSE;
1496 } else if (req1->present == req2->present) {
1497 /* No contradiction possible. */
1498 return FALSE;
1499 } else {
1500 /* Number of move fragments left can't be larger than the number
1501 * required to be present and smaller than the number required to not
1502 * be present when the number required to be present is smaller than
1503 * the number required to not be present. */
1504 if (req1->present) {
1505 return req1->source.value.minmoves >= req2->source.value.minmoves;
1506 } else {
1507 return req1->source.value.minmoves <= req2->source.value.minmoves;
1508 }
1509 }
1510 break;
1511 case VUT_NATION:
1512 if (req2->source.kind == VUT_NATIONGROUP) {
1513 return nation_contra_group(req1, req2);
1514 }
1515
1516 /* No special knowledge. */
1517 return FALSE;
1518 break;
1519 case VUT_NATIONGROUP:
1520 if (req2->source.kind == VUT_NATION) {
1521 return nation_contra_group(req2, req1);
1522 }
1523
1524 /* No special knowledge. */
1525 return FALSE;
1526 break;
1527 default:
1528 /* No special knowledge exists. The requirements aren't the exact
1529 * opposite of each other per the initial check. */
1530 return FALSE;
1531 break;
1532 }
1533}
1534
1535/**********************************************************************/
1540 const struct requirement_vector *vec)
1541{
1542 /* If the requirement is contradicted by any requirement in the vector it
1543 * contradicts the entire requirement vector. */
1544 requirement_vector_iterate(vec, preq) {
1545 if (are_requirements_contradictions(req, preq)) {
1546 return TRUE;
1547 }
1549
1550 /* Not a singe requirement in the requirement vector is contradicted be
1551 * the specified requirement. */
1552 return FALSE;
1553}
1554
1555/**********************************************************************/
1558static inline bool are_tiles_in_range(const struct tile *tile1,
1559 const struct tile *tile2,
1560 enum req_range range)
1561{
1562 switch (range) {
1563 case REQ_RANGE_ADJACENT:
1564 if (is_tiles_adjacent(tile1, tile2)) {
1565 return TRUE;
1566 }
1567 if (same_pos(tile1, tile2)) {
1568 return TRUE;
1569 }
1570 break;
1571 case REQ_RANGE_CADJACENT:
1572 return map_distance(tile1, tile2) <= 1;
1573 case REQ_RANGE_CITY:
1574 case REQ_RANGE_TRADE_ROUTE:
1575 case REQ_RANGE_LOCAL:
1576 case REQ_RANGE_CONTINENT:
1577 case REQ_RANGE_PLAYER:
1578 case REQ_RANGE_TEAM:
1579 case REQ_RANGE_ALLIANCE:
1580 case REQ_RANGE_WORLD:
1581 case REQ_RANGE_COUNT:
1582 /* Invalid */
1584 }
1585 return FALSE;
1586}
1587
1588/**********************************************************************/
1591static inline bool players_in_same_range(const struct player *pplayer1,
1592 const struct player *pplayer2,
1593 enum req_range range)
1594{
1595 switch (range) {
1596 case REQ_RANGE_WORLD:
1597 return TRUE;
1598 case REQ_RANGE_ALLIANCE:
1599 return pplayers_allied(pplayer1, pplayer2);
1600 case REQ_RANGE_TEAM:
1601 return players_on_same_team(pplayer1, pplayer2);
1602 case REQ_RANGE_PLAYER:
1603 return pplayer1 == pplayer2;
1604 case REQ_RANGE_CONTINENT:
1605 case REQ_RANGE_TRADE_ROUTE:
1606 case REQ_RANGE_CITY:
1607 case REQ_RANGE_ADJACENT:
1608 case REQ_RANGE_CADJACENT:
1609 case REQ_RANGE_LOCAL:
1610 case REQ_RANGE_COUNT:
1611 break;
1612 }
1613
1614 fc_assert_msg(FALSE, "Invalid range %d.", range);
1615 return FALSE;
1616}
1617
1618#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
1619{ \
1620 fc_assert_ret_val(req != NULL, TRI_MAYBE); \
1621 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
1622 fc_assert(context != NULL); \
1623}
1624
1625/**********************************************************************/
1632static enum fc_tristate
1633is_none_req_active(const struct civ_map *nmap,
1634 const struct req_context *context,
1635 const struct player *other_player,
1636 const struct requirement *req)
1637{
1639
1640 return TRI_YES;
1641}
1642
1643/**********************************************************************/
1647static int num_world_buildings_total(const struct impr_type *building)
1648{
1649 if (is_great_wonder(building)) {
1650 return (great_wonder_is_built(building)
1651 || great_wonder_is_destroyed(building) ? 1 : 0);
1652 } else {
1653 log_error("World-ranged requirements are only supported for wonders.");
1654 return 0;
1655 }
1656}
1657
1658/**********************************************************************/
1661static int num_world_buildings(const struct impr_type *building)
1662{
1663 if (is_great_wonder(building)) {
1664 return (great_wonder_is_built(building) ? 1 : 0);
1665 } else {
1666 log_error("World-ranged requirements are only supported for wonders.");
1667 return 0;
1668 }
1669}
1670
1671/**********************************************************************/
1682static bool player_has_ever_built(const struct player *pplayer,
1683 const struct impr_type *building)
1684{
1685 if (is_wonder(building)) {
1686 return (wonder_is_built(pplayer, building)
1687 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
1688 } else {
1689 log_error("Player-ranged requirements are only supported for wonders.");
1690 return FALSE;
1691 }
1692}
1693
1694/**********************************************************************/
1697static int num_player_buildings(const struct player *pplayer,
1698 const struct impr_type *building)
1699{
1700 if (is_wonder(building)) {
1701 return (wonder_is_built(pplayer, building) ? 1 : 0);
1702 } else {
1703 log_error("Player-ranged requirements are only supported for wonders.");
1704 return 0;
1705 }
1706}
1707
1708/**********************************************************************/
1711static int num_continent_buildings(const struct player *pplayer,
1712 int continent,
1713 const struct impr_type *building)
1714{
1715 if (is_wonder(building)) {
1716 const struct city *pcity;
1717
1718 pcity = city_from_wonder(pplayer, building);
1719 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
1720 return 1;
1721 }
1722 } else {
1723 log_error("Island-ranged requirements are only supported for wonders.");
1724 }
1725 return 0;
1726}
1727
1728/**********************************************************************/
1731static int num_city_buildings(const struct city *pcity,
1732 const struct impr_type *building)
1733{
1734 return (city_has_building(pcity, building) ? 1 : 0);
1735}
1736
1737/**********************************************************************/
1744static enum fc_tristate
1746 const struct req_context *context,
1747 const struct player *other_player,
1748 const struct requirement *req)
1749{
1750 const struct impr_type *building;
1751
1752 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT);
1753
1754 building = req->source.value.building;
1755
1756 /* Check if it's certain that the building is obsolete given the
1757 * specification we have */
1758 if (improvement_obsolete(context->player, building, context->city)) {
1759 return TRI_NO;
1760 }
1761
1762 if (req->survives) {
1763
1764 /* Check whether condition has ever held, using cached information. */
1765 switch (req->range) {
1766 case REQ_RANGE_WORLD:
1767 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
1768 case REQ_RANGE_ALLIANCE:
1769 case REQ_RANGE_TEAM:
1770 if (context->player == NULL) {
1771 return TRI_MAYBE;
1772 }
1773 players_iterate_alive(plr2) {
1774 if (players_in_same_range(context->player, plr2, req->range)
1775 && player_has_ever_built(plr2, building)) {
1776 return TRI_YES;
1777 }
1779 return TRI_NO;
1780 case REQ_RANGE_PLAYER:
1781 if (context->player == NULL) {
1782 return TRI_MAYBE;
1783 }
1785 building));
1786 case REQ_RANGE_CONTINENT:
1787 case REQ_RANGE_TRADE_ROUTE:
1788 case REQ_RANGE_CITY:
1789 case REQ_RANGE_LOCAL:
1790 case REQ_RANGE_CADJACENT:
1791 case REQ_RANGE_ADJACENT:
1792 /* There is no sources cache for this. */
1793 log_error("Surviving requirements are only supported at "
1794 "World/Alliance/Team/Player ranges.");
1795 return TRI_NO;
1796 case REQ_RANGE_COUNT:
1797 break;
1798 }
1799
1800 } else {
1801
1802 /* Non-surviving requirement. */
1803 switch (req->range) {
1804 case REQ_RANGE_WORLD:
1805 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
1806 case REQ_RANGE_ALLIANCE:
1807 case REQ_RANGE_TEAM:
1808 if (context->player == NULL) {
1809 return TRI_MAYBE;
1810 }
1811 players_iterate_alive(plr2) {
1812 if (players_in_same_range(context->player, plr2, req->range)
1813 && num_player_buildings(plr2, building) > 0) {
1814 return TRI_YES;
1815 }
1817 return TRI_NO;
1818 case REQ_RANGE_PLAYER:
1819 if (context->player == NULL) {
1820 return TRI_MAYBE;
1821 }
1823 building)
1824 > 0);
1825 case REQ_RANGE_CONTINENT:
1826 /* At present, "Continent" effects can affect only
1827 * cities and units in cities. */
1828 if (context->player && context->city) {
1829 int continent = tile_continent(context->city->tile);
1831 continent, building)
1832 > 0);
1833 } else {
1834 return TRI_MAYBE;
1835 }
1836 case REQ_RANGE_TRADE_ROUTE:
1837 if (context->city) {
1838 if (num_city_buildings(context->city, building) > 0) {
1839 return TRI_YES;
1840 } else {
1841 enum fc_tristate ret = TRI_NO;
1842
1843 trade_partners_iterate(context->city, trade_partner) {
1844 if (trade_partner == NULL) {
1845 ret = TRI_MAYBE;
1846 } else if (num_city_buildings(trade_partner, building) > 0) {
1847 return TRI_YES;
1848 }
1850
1851 return ret;
1852 }
1853 } else {
1854 return TRI_MAYBE;
1855 }
1856 case REQ_RANGE_CITY:
1857 if (context->city) {
1858 return BOOL_TO_TRISTATE(num_city_buildings(context->city, building)
1859 > 0);
1860 } else {
1861 return TRI_MAYBE;
1862 }
1863 case REQ_RANGE_LOCAL:
1864 if (context->building) {
1865 if (context->building == building) {
1866 return TRI_YES;
1867 } else {
1868 return TRI_NO;
1869 }
1870 } else {
1871 /* TODO: other local targets */
1872 return TRI_MAYBE;
1873 }
1874 case REQ_RANGE_CADJACENT:
1875 case REQ_RANGE_ADJACENT:
1876 return TRI_NO;
1877 case REQ_RANGE_COUNT:
1878 break;
1879 }
1880
1881 }
1882
1883 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
1884 return TRI_NO;
1885}
1886
1887/**********************************************************************/
1895static enum fc_tristate
1897 const struct req_context *context,
1898 const struct player *other_player,
1899 const struct requirement *req)
1900{
1901 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPR_GENUS);
1902
1903 return (context->building ? BOOL_TO_TRISTATE(
1904 context->building->genus
1905 == req->source.value.impr_genus)
1906 : TRI_MAYBE);
1907}
1908
1909/**********************************************************************/
1916static enum fc_tristate
1917is_tech_req_active(const struct civ_map *nmap,
1918 const struct req_context *context,
1919 const struct player *other_player,
1920 const struct requirement *req)
1921{
1922 Tech_type_id tech;
1923
1924 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ADVANCE);
1925
1926 tech = advance_number(req->source.value.advance);
1927
1928 if (req->survives) {
1929 fc_assert(req->range == REQ_RANGE_WORLD);
1931 }
1932
1933 /* Not a 'surviving' requirement. */
1934 switch (req->range) {
1935 case REQ_RANGE_PLAYER:
1936 if (NULL != context->player) {
1937 return BOOL_TO_TRISTATE(TECH_KNOWN == research_invention_state
1938 (research_get(context->player), tech));
1939 } else {
1940 return TRI_MAYBE;
1941 }
1942 case REQ_RANGE_TEAM:
1943 case REQ_RANGE_ALLIANCE:
1944 case REQ_RANGE_WORLD:
1945 if (NULL == context->player) {
1946 return TRI_MAYBE;
1947 }
1948 players_iterate_alive(plr2) {
1949 if (players_in_same_range(context->player, plr2, req->range)) {
1950 if (research_invention_state(research_get(plr2), tech)
1951 == TECH_KNOWN) {
1952 return TRI_YES;
1953 }
1954 }
1956
1957 return TRI_NO;
1958 case REQ_RANGE_LOCAL:
1959 case REQ_RANGE_CADJACENT:
1960 case REQ_RANGE_ADJACENT:
1961 case REQ_RANGE_CITY:
1962 case REQ_RANGE_TRADE_ROUTE:
1963 case REQ_RANGE_CONTINENT:
1964 case REQ_RANGE_COUNT:
1965 break;
1966 }
1967
1968 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
1969
1970 return TRI_MAYBE;
1971}
1972
1973/**********************************************************************/
1980static enum fc_tristate
1982 const struct req_context *context,
1983 const struct player *other_player,
1984 const struct requirement *req)
1985{
1986 enum tech_flag_id techflag;
1987
1988 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TECHFLAG);
1989
1990 techflag = req->source.value.techflag;
1991
1992 switch (req->range) {
1993 case REQ_RANGE_PLAYER:
1994 if (NULL != context->player) {
1996 techflag));
1997 } else {
1998 return TRI_MAYBE;
1999 }
2000 break;
2001 case REQ_RANGE_TEAM:
2002 case REQ_RANGE_ALLIANCE:
2003 if (NULL == context->player) {
2004 return TRI_MAYBE;
2005 }
2006 players_iterate_alive(plr2) {
2007 if (players_in_same_range(context->player, plr2, req->range)
2008 && player_knows_techs_with_flag(plr2, techflag)) {
2009 return TRI_YES;
2010 }
2012 return TRI_NO;
2013 case REQ_RANGE_WORLD:
2014 players_iterate(pplayer) {
2015 if (player_knows_techs_with_flag(pplayer, techflag)) {
2016 return TRI_YES;
2017 }
2019
2020 return TRI_NO;
2021 case REQ_RANGE_LOCAL:
2022 case REQ_RANGE_CADJACENT:
2023 case REQ_RANGE_ADJACENT:
2024 case REQ_RANGE_CITY:
2025 case REQ_RANGE_TRADE_ROUTE:
2026 case REQ_RANGE_CONTINENT:
2027 case REQ_RANGE_COUNT:
2028 break;
2029 }
2030
2031 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2032
2033 return TRI_MAYBE;
2034}
2035
2036/**********************************************************************/
2043static enum fc_tristate
2045 const struct req_context *context,
2046 const struct player *other_player,
2047 const struct requirement *req)
2048{
2049 int minculture;
2050
2051 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINCULTURE);
2052
2053 minculture = req->source.value.minculture;
2054
2055 switch (req->range) {
2056 case REQ_RANGE_CITY:
2057 if (!context->city) {
2058 return TRI_MAYBE;
2059 }
2060 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2061 case REQ_RANGE_TRADE_ROUTE:
2062 if (!context->city) {
2063 return TRI_MAYBE;
2064 }
2065 if (city_culture(context->city) >= minculture) {
2066 return TRI_YES;
2067 } else {
2068 enum fc_tristate ret = TRI_NO;
2069
2070 trade_partners_iterate(context->city, trade_partner) {
2071 if (trade_partner == NULL) {
2072 ret = TRI_MAYBE;
2073 } else if (city_culture(trade_partner) >= minculture) {
2074 return TRI_YES;
2075 }
2077
2078 return ret;
2079 }
2080 case REQ_RANGE_PLAYER:
2081 case REQ_RANGE_TEAM:
2082 case REQ_RANGE_ALLIANCE:
2083 case REQ_RANGE_WORLD:
2084 if (NULL == context->player) {
2085 return TRI_MAYBE;
2086 }
2087 players_iterate_alive(plr2) {
2088 if (players_in_same_range(context->player, plr2, req->range)) {
2089 if (player_culture(plr2) >= minculture) {
2090 return TRI_YES;
2091 }
2092 }
2094 return TRI_NO;
2095 case REQ_RANGE_LOCAL:
2096 case REQ_RANGE_CADJACENT:
2097 case REQ_RANGE_ADJACENT:
2098 case REQ_RANGE_CONTINENT:
2099 case REQ_RANGE_COUNT:
2100 break;
2101 }
2102
2103 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2104
2105 return TRI_MAYBE;
2106}
2107
2108/**********************************************************************/
2116static enum fc_tristate
2118 const struct req_context *context,
2119 const struct player *other_player,
2120 const struct requirement *req)
2121{
2122 int min_foreign_pct, foreign_pct;
2123
2124 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINFOREIGNPCT);
2125
2126 min_foreign_pct = req->source.value.minforeignpct;
2127
2128 switch (req->range) {
2129 case REQ_RANGE_CITY:
2130 if (!context->city) {
2131 return TRI_MAYBE;
2132 }
2133 foreign_pct = citizens_nation_foreign(context->city) * 100
2134 / city_size_get(context->city);
2135 return BOOL_TO_TRISTATE(foreign_pct >= min_foreign_pct);
2136 case REQ_RANGE_TRADE_ROUTE:
2137 if (!context->city) {
2138 return TRI_MAYBE;
2139 }
2140 foreign_pct = citizens_nation_foreign(context->city) * 100
2141 / city_size_get(context->city);
2142 if (foreign_pct >= min_foreign_pct) {
2143 return TRI_YES;
2144 } else {
2145 enum fc_tristate ret = TRI_NO;
2146
2147 trade_partners_iterate(context->city, trade_partner) {
2148 if (trade_partner == NULL) {
2149 ret = TRI_MAYBE;
2150 } else {
2151 foreign_pct = citizens_nation_foreign(trade_partner) * 100
2152 / city_size_get(trade_partner);
2153 if (foreign_pct >= min_foreign_pct) {
2154 return TRI_YES;
2155 }
2156 }
2158
2159 return ret;
2160 }
2161 case REQ_RANGE_PLAYER:
2162 case REQ_RANGE_TEAM:
2163 case REQ_RANGE_ALLIANCE:
2164 case REQ_RANGE_WORLD:
2165 case REQ_RANGE_LOCAL:
2166 case REQ_RANGE_CADJACENT:
2167 case REQ_RANGE_ADJACENT:
2168 case REQ_RANGE_CONTINENT:
2169 case REQ_RANGE_COUNT:
2170 break;
2171 }
2172
2173 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2174
2175 return TRI_MAYBE;
2176}
2177
2178/**********************************************************************/
2186static enum fc_tristate
2188 const struct req_context *context,
2189 const struct player *other_player,
2190 const struct requirement *req)
2191{
2192 int max_units;
2193
2194 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MAXTILEUNITS);
2195
2196 max_units = req->source.value.max_tile_units;
2197
2198 /* TODO: if can't see V_INVIS -> TRI_MAYBE */
2199 switch (req->range) {
2200 case REQ_RANGE_LOCAL:
2201 if (!context->tile) {
2202 return TRI_MAYBE;
2203 }
2204 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
2205 case REQ_RANGE_CADJACENT:
2206 if (!context->tile) {
2207 return TRI_MAYBE;
2208 }
2209 if (unit_list_size(context->tile->units) <= max_units) {
2210 return TRI_YES;
2211 }
2212 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
2213 if (unit_list_size(adjc_tile->units) <= max_units) {
2214 return TRI_YES;
2215 }
2217 return TRI_NO;
2218 case REQ_RANGE_ADJACENT:
2219 if (!context->tile) {
2220 return TRI_MAYBE;
2221 }
2222 if (unit_list_size(context->tile->units) <= max_units) {
2223 return TRI_YES;
2224 }
2225 adjc_iterate(nmap, context->tile, adjc_tile) {
2226 if (unit_list_size(adjc_tile->units) <= max_units) {
2227 return TRI_YES;
2228 }
2230 return TRI_NO;
2231 case REQ_RANGE_CITY:
2232 case REQ_RANGE_TRADE_ROUTE:
2233 case REQ_RANGE_CONTINENT:
2234 case REQ_RANGE_PLAYER:
2235 case REQ_RANGE_TEAM:
2236 case REQ_RANGE_ALLIANCE:
2237 case REQ_RANGE_WORLD:
2238 case REQ_RANGE_COUNT:
2239 break;
2240 }
2241
2242 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2243
2244 return TRI_MAYBE;
2245}
2246
2247/**********************************************************************/
2254static enum fc_tristate
2255is_extra_req_active(const struct civ_map *nmap,
2256 const struct req_context *context,
2257 const struct player *other_player,
2258 const struct requirement *req)
2259{
2260 const struct extra_type *pextra;
2261 enum fc_tristate ret;
2262
2264
2265 pextra = req->source.value.extra;
2266
2267 switch (req->range) {
2268 case REQ_RANGE_LOCAL:
2269 /* The requirement is filled if the tile has extra of requested type. */
2270 if (!context->tile) {
2271 return TRI_MAYBE;
2272 }
2273 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
2274 case REQ_RANGE_CADJACENT:
2275 if (!context->tile) {
2276 return TRI_MAYBE;
2277 }
2278 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2279 || is_extra_card_near(nmap, context->tile, pextra));
2280 case REQ_RANGE_ADJACENT:
2281 if (!context->tile) {
2282 return TRI_MAYBE;
2283 }
2284 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2285 || is_extra_near_tile(nmap, context->tile, pextra));
2286 case REQ_RANGE_CITY:
2287 if (!context->city) {
2288 return TRI_MAYBE;
2289 }
2291 city_tile(context->city), ptile) {
2292 if (tile_has_extra(ptile, pextra)) {
2293 return TRI_YES;
2294 }
2296
2297 return TRI_NO;
2298
2299 case REQ_RANGE_TRADE_ROUTE:
2300 if (!context->city) {
2301 return TRI_MAYBE;
2302 }
2304 city_tile(context->city), ptile) {
2305 if (tile_has_extra(ptile, pextra)) {
2306 return TRI_YES;
2307 }
2309
2310 ret = TRI_NO;
2311 trade_partners_iterate(context->city, trade_partner) {
2312 if (trade_partner == NULL) {
2313 ret = TRI_MAYBE;
2314 } else {
2315 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
2316 city_tile(trade_partner), ptile) {
2317 if (tile_has_extra(ptile, pextra)) {
2318 return TRI_YES;
2319 }
2321 }
2323
2324 return ret;
2325
2326 case REQ_RANGE_CONTINENT:
2327 case REQ_RANGE_PLAYER:
2328 case REQ_RANGE_TEAM:
2329 case REQ_RANGE_ALLIANCE:
2330 case REQ_RANGE_WORLD:
2331 case REQ_RANGE_COUNT:
2332 break;
2333 }
2334
2335 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2336
2337 return TRI_MAYBE;
2338}
2339
2340/**********************************************************************/
2347static enum fc_tristate
2348is_good_req_active(const struct civ_map *nmap,
2349 const struct req_context *context,
2350 const struct player *other_player,
2351 const struct requirement *req)
2352{
2354
2355 switch (req->range) {
2356 case REQ_RANGE_LOCAL:
2357 case REQ_RANGE_CITY:
2358 /* The requirement is filled if the city imports good of requested type. */
2359 if (!context->city) {
2360 return TRI_MAYBE;
2361 }
2363 req->source.value.good));
2364 case REQ_RANGE_CADJACENT:
2365 case REQ_RANGE_ADJACENT:
2366 case REQ_RANGE_TRADE_ROUTE:
2367 case REQ_RANGE_CONTINENT:
2368 case REQ_RANGE_PLAYER:
2369 case REQ_RANGE_TEAM:
2370 case REQ_RANGE_ALLIANCE:
2371 case REQ_RANGE_WORLD:
2372 case REQ_RANGE_COUNT:
2373 break;
2374 }
2375
2376 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2377
2378 return TRI_MAYBE;
2379}
2380
2381/**********************************************************************/
2388static enum fc_tristate
2390 const struct req_context *context,
2391 const struct player *other_player,
2392 const struct requirement *req)
2393{
2394 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ACTION);
2395
2396 return BOOL_TO_TRISTATE(context->action
2397 && action_number(context->action)
2398 == action_number(req->source.value.action));
2399}
2400
2401/**********************************************************************/
2409static enum fc_tristate
2411 const struct req_context *context,
2412 const struct player *other_player,
2413 const struct requirement *req)
2414{
2416
2417 return BOOL_TO_TRISTATE(context->output
2418 && context->output->index
2419 == req->source.value.outputtype);
2420}
2421
2422/**********************************************************************/
2429static enum fc_tristate
2431 const struct req_context *context,
2432 const struct player *other_player,
2433 const struct requirement *req)
2434{
2435 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_SPECIALIST);
2436
2437 return BOOL_TO_TRISTATE(context->specialist
2438 && context->specialist
2439 == req->source.value.specialist);
2440}
2441
2442/**********************************************************************/
2449static enum fc_tristate
2451 const struct req_context *context,
2452 const struct player *other_player,
2453 const struct requirement *req)
2454{
2455 const struct terrain *pterrain;
2456
2457 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRAIN);
2458
2459 pterrain = req->source.value.terrain;
2460
2461 switch (req->range) {
2462 case REQ_RANGE_LOCAL:
2463 /* The requirement is filled if the tile has the terrain. */
2464 if (!context->tile) {
2465 return TRI_MAYBE;
2466 }
2467 return pterrain && tile_terrain(context->tile) == pterrain;
2468 case REQ_RANGE_CADJACENT:
2469 if (!context->tile) {
2470 return TRI_MAYBE;
2471 }
2472 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
2473 case REQ_RANGE_ADJACENT:
2474 if (!context->tile) {
2475 return TRI_MAYBE;
2476 }
2477 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
2478 case REQ_RANGE_CITY:
2479 if (!context->city) {
2480 return TRI_MAYBE;
2481 }
2482 if (pterrain != NULL) {
2484 city_tile(context->city), ptile) {
2485 if (tile_terrain(ptile) == pterrain) {
2486 return TRI_YES;
2487 }
2489 }
2490 return TRI_NO;
2491 case REQ_RANGE_TRADE_ROUTE:
2492 if (!context->city) {
2493 return TRI_MAYBE;
2494 }
2495 if (pterrain != NULL) {
2496 enum fc_tristate ret;
2497
2499 city_tile(context->city), ptile) {
2500 if (tile_terrain(ptile) == pterrain) {
2501 return TRI_YES;
2502 }
2504
2505 ret = TRI_NO;
2506 trade_partners_iterate(context->city, trade_partner) {
2507 if (trade_partner == NULL) {
2508 ret = TRI_MAYBE;
2509 } else {
2510 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
2511 city_tile(trade_partner), ptile) {
2512 if (tile_terrain(ptile) == pterrain) {
2513 return TRI_YES;
2514 }
2516 }
2518
2519 return ret;
2520 }
2521
2522 return TRI_MAYBE;
2523 case REQ_RANGE_CONTINENT:
2524 case REQ_RANGE_PLAYER:
2525 case REQ_RANGE_TEAM:
2526 case REQ_RANGE_ALLIANCE:
2527 case REQ_RANGE_WORLD:
2528 case REQ_RANGE_COUNT:
2529 break;
2530 }
2531
2532 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2533
2534 return TRI_MAYBE;
2535}
2536
2537/**********************************************************************/
2545static enum fc_tristate
2547 const struct req_context *context,
2548 const struct player *other_player,
2549 const struct requirement *req)
2550{
2551 enum terrain_class pclass;
2552 enum fc_tristate ret;
2553
2554 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRAINCLASS);
2555
2556 pclass = req->source.value.terrainclass;
2557
2558 switch (req->range) {
2559 case REQ_RANGE_LOCAL:
2560 /* The requirement is filled if the tile has the terrain of correct class. */
2561 if (!context->tile) {
2562 return TRI_MAYBE;
2563 }
2564 return BOOL_TO_TRISTATE(terrain_type_terrain_class(tile_terrain(context->tile)) == pclass);
2565 case REQ_RANGE_CADJACENT:
2566 if (!context->tile) {
2567 return TRI_MAYBE;
2568 }
2570 || is_terrain_class_card_near(nmap, context->tile, pclass));
2571 case REQ_RANGE_ADJACENT:
2572 if (!context->tile) {
2573 return TRI_MAYBE;
2574 }
2576 || is_terrain_class_near_tile(nmap, context->tile, pclass));
2577 case REQ_RANGE_CITY:
2578 if (!context->city) {
2579 return TRI_MAYBE;
2580 }
2582 city_tile(context->city), ptile) {
2583 const struct terrain *pterrain = tile_terrain(ptile);
2584
2585 if (pterrain != T_UNKNOWN
2586 && terrain_type_terrain_class(pterrain) == pclass) {
2587 return TRI_YES;
2588 }
2590
2591 return TRI_NO;
2592 case REQ_RANGE_TRADE_ROUTE:
2593 if (!context->city) {
2594 return TRI_MAYBE;
2595 }
2597 city_tile(context->city), ptile) {
2598 const struct terrain *pterrain = tile_terrain(ptile);
2599
2600 if (pterrain != T_UNKNOWN
2601 && terrain_type_terrain_class(pterrain) == pclass) {
2602 return TRI_YES;
2603 }
2605
2606 ret = TRI_NO;
2607 trade_partners_iterate(context->city, trade_partner) {
2608 if (trade_partner == NULL) {
2609 ret = TRI_MAYBE;
2610 } else {
2611 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
2612 city_tile(trade_partner), ptile) {
2613 const struct terrain *pterrain = tile_terrain(ptile);
2614
2615 if (pterrain != T_UNKNOWN
2616 && terrain_type_terrain_class(pterrain) == pclass) {
2617 return TRI_YES;
2618 }
2620 }
2622
2623 return ret;
2624 case REQ_RANGE_CONTINENT:
2625 case REQ_RANGE_PLAYER:
2626 case REQ_RANGE_TEAM:
2627 case REQ_RANGE_ALLIANCE:
2628 case REQ_RANGE_WORLD:
2629 case REQ_RANGE_COUNT:
2630 break;
2631 }
2632
2633 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2634
2635 return TRI_MAYBE;
2636}
2637
2638/**********************************************************************/
2646static enum fc_tristate
2648 const struct req_context *context,
2649 const struct player *other_player,
2650 const struct requirement *req)
2651{
2652 enum terrain_flag_id terrflag;
2653 enum fc_tristate ret;
2654
2655 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRFLAG);
2656
2657 terrflag = req->source.value.terrainflag;
2658
2659 switch (req->range) {
2660 case REQ_RANGE_LOCAL:
2661 /* The requirement is fulfilled if the tile has a terrain with
2662 * correct flag. */
2663 if (!context->tile) {
2664 return TRI_MAYBE;
2665 }
2667 terrflag));
2668 case REQ_RANGE_CADJACENT:
2669 if (!context->tile) {
2670 return TRI_MAYBE;
2671 }
2673 terrflag)
2674 || is_terrain_flag_card_near(nmap, context->tile,
2675 terrflag));
2676 case REQ_RANGE_ADJACENT:
2677 if (!context->tile) {
2678 return TRI_MAYBE;
2679 }
2681 terrflag)
2682 || is_terrain_flag_near_tile(nmap, context->tile,
2683 terrflag));
2684 case REQ_RANGE_CITY:
2685 if (!context->city) {
2686 return TRI_MAYBE;
2687 }
2689 city_tile(context->city), ptile) {
2690 const struct terrain *pterrain = tile_terrain(ptile);
2691
2692 if (pterrain != T_UNKNOWN
2693 && terrain_has_flag(pterrain, terrflag)) {
2694 return TRI_YES;
2695 }
2697
2698 return TRI_NO;
2699 case REQ_RANGE_TRADE_ROUTE:
2700 if (!context->city) {
2701 return TRI_MAYBE;
2702 }
2704 city_tile(context->city), ptile) {
2705 const struct terrain *pterrain = tile_terrain(ptile);
2706
2707 if (pterrain != T_UNKNOWN
2708 && terrain_has_flag(pterrain, terrflag)) {
2709 return TRI_YES;
2710 }
2712
2713 ret = TRI_NO;
2714 trade_partners_iterate(context->city, trade_partner) {
2715 if (trade_partner == NULL) {
2716 ret = TRI_MAYBE;
2717 } else {
2718 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
2719 city_tile(trade_partner), ptile) {
2720 const struct terrain *pterrain = tile_terrain(ptile);
2721
2722 if (pterrain != T_UNKNOWN
2723 && terrain_has_flag(pterrain, terrflag)) {
2724 return TRI_YES;
2725 }
2727 }
2729
2730 return ret;
2731 case REQ_RANGE_CONTINENT:
2732 case REQ_RANGE_PLAYER:
2733 case REQ_RANGE_TEAM:
2734 case REQ_RANGE_ALLIANCE:
2735 case REQ_RANGE_WORLD:
2736 case REQ_RANGE_COUNT:
2737 break;
2738 }
2739
2740 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2741
2742 return TRI_MAYBE;
2743}
2744
2745/**********************************************************************/
2752static enum fc_tristate
2754 const struct req_context *context,
2755 const struct player *other_player,
2756 const struct requirement *req)
2757{
2758 enum road_flag_id roadflag;
2759 enum fc_tristate ret;
2760
2761 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ROADFLAG);
2762
2763 roadflag = req->source.value.roadflag;
2764
2765 switch (req->range) {
2766 case REQ_RANGE_LOCAL:
2767 /* The requirement is filled if the tile has a road with correct flag. */
2768 if (!context->tile) {
2769 return TRI_MAYBE;
2770 }
2771 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
2772 case REQ_RANGE_CADJACENT:
2773 if (!context->tile) {
2774 return TRI_MAYBE;
2775 }
2776 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
2777 || is_road_flag_card_near(nmap, context->tile,
2778 roadflag));
2779 case REQ_RANGE_ADJACENT:
2780 if (!context->tile) {
2781 return TRI_MAYBE;
2782 }
2783 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
2784 || is_road_flag_near_tile(nmap, context->tile,
2785 roadflag));
2786 case REQ_RANGE_CITY:
2787 if (!context->city) {
2788 return TRI_MAYBE;
2789 }
2791 city_tile(context->city), ptile) {
2792 if (tile_has_road_flag(ptile, roadflag)) {
2793 return TRI_YES;
2794 }
2796
2797 return TRI_NO;
2798 case REQ_RANGE_TRADE_ROUTE:
2799 if (!context->city) {
2800 return TRI_MAYBE;
2801 }
2803 city_tile(context->city), ptile) {
2804 if (tile_has_road_flag(ptile, roadflag)) {
2805 return TRI_YES;
2806 }
2808
2809 ret = TRI_NO;
2810 trade_partners_iterate(context->city, trade_partner) {
2811 if (trade_partner == NULL) {
2812 ret = TRI_MAYBE;
2813 } else {
2814 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
2815 city_tile(trade_partner), ptile) {
2816 if (tile_has_road_flag(ptile, roadflag)) {
2817 return TRI_YES;
2818 }
2820 }
2822
2823 return ret;
2824 case REQ_RANGE_CONTINENT:
2825 case REQ_RANGE_PLAYER:
2826 case REQ_RANGE_TEAM:
2827 case REQ_RANGE_ALLIANCE:
2828 case REQ_RANGE_WORLD:
2829 case REQ_RANGE_COUNT:
2830 break;
2831 }
2832
2833 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2834
2835 return TRI_MAYBE;
2836}
2837
2838/**********************************************************************/
2845static enum fc_tristate
2847 const struct req_context *context,
2848 const struct player *other_player,
2849 const struct requirement *req)
2850{
2851 enum extra_flag_id extraflag;
2852 enum fc_tristate ret;
2853
2854 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_EXTRAFLAG);
2855
2856 extraflag = req->source.value.extraflag;
2857
2858 switch (req->range) {
2859 case REQ_RANGE_LOCAL:
2860 /* The requirement is filled if the tile has an extra with correct flag. */
2861 if (!context->tile) {
2862 return TRI_MAYBE;
2863 }
2864 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
2865 case REQ_RANGE_CADJACENT:
2866 if (!context->tile) {
2867 return TRI_MAYBE;
2868 }
2869 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
2870 || is_extra_flag_card_near(nmap, context->tile, extraflag));
2871 case REQ_RANGE_ADJACENT:
2872 if (!context->tile) {
2873 return TRI_MAYBE;
2874 }
2875 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
2876 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
2877 case REQ_RANGE_CITY:
2878 if (!context->city) {
2879 return TRI_MAYBE;
2880 }
2882 city_tile(context->city), ptile) {
2883 if (tile_has_extra_flag(ptile, extraflag)) {
2884 return TRI_YES;
2885 }
2887
2888 return TRI_NO;
2889 case REQ_RANGE_TRADE_ROUTE:
2890 if (!context->city) {
2891 return TRI_MAYBE;
2892 }
2894 city_tile(context->city), ptile) {
2895 if (tile_has_extra_flag(ptile, extraflag)) {
2896 return TRI_YES;
2897 }
2899
2900 ret = TRI_NO;
2901 trade_partners_iterate(context->city, trade_partner) {
2902 if (trade_partner == NULL) {
2903 ret = TRI_MAYBE;
2904 } else {
2905 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
2906 city_tile(trade_partner), ptile) {
2907 if (tile_has_extra_flag(ptile, extraflag)) {
2908 return TRI_YES;
2909 }
2911 }
2913
2914 return ret;
2915 case REQ_RANGE_CONTINENT:
2916 case REQ_RANGE_PLAYER:
2917 case REQ_RANGE_TEAM:
2918 case REQ_RANGE_ALLIANCE:
2919 case REQ_RANGE_WORLD:
2920 case REQ_RANGE_COUNT:
2921 break;
2922 }
2923
2924 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2925
2926 return TRI_MAYBE;
2927}
2928
2929/**********************************************************************/
2937static enum fc_tristate
2939 const struct req_context *context,
2940 const struct player *other_player,
2941 const struct requirement *req)
2942{
2943 enum terrain_alteration alteration;
2944
2945 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRAINALTER);
2946
2947 alteration = req->source.value.terrainalter;
2948
2949 if (!context->tile) {
2950 return TRI_MAYBE;
2951 }
2952
2953 switch (req->range) {
2954 case REQ_RANGE_LOCAL:
2956 tile_terrain(context->tile), alteration));
2957 case REQ_RANGE_CADJACENT:
2958 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
2959 case REQ_RANGE_CITY:
2960 case REQ_RANGE_TRADE_ROUTE:
2961 case REQ_RANGE_CONTINENT:
2962 case REQ_RANGE_PLAYER:
2963 case REQ_RANGE_TEAM:
2964 case REQ_RANGE_ALLIANCE:
2965 case REQ_RANGE_WORLD:
2966 case REQ_RANGE_COUNT:
2967 break;
2968 }
2969
2970 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2971
2972 return TRI_MAYBE;
2973}
2974
2975/**********************************************************************/
2982static enum fc_tristate
2983is_gov_req_active(const struct civ_map *nmap,
2984 const struct req_context *context,
2985 const struct player *other_player,
2986 const struct requirement *req)
2987{
2988 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_GOVERNMENT);
2989
2990 if (context->player == NULL) {
2991 return TRI_MAYBE;
2992 } else {
2994 == req->source.value.govern);
2995 }
2996}
2997
2998/**********************************************************************/
3005static enum fc_tristate
3006is_style_req_active(const struct civ_map *nmap,
3007 const struct req_context *context,
3008 const struct player *other_player,
3009 const struct requirement *req)
3010{
3012
3013 if (context->player == NULL) {
3014 return TRI_MAYBE;
3015 } else {
3016 return BOOL_TO_TRISTATE(context->player->style
3017 == req->source.value.style);
3018 }
3019}
3020
3021/**********************************************************************/
3028static enum fc_tristate
3030 const struct req_context *context,
3031 const struct player *other_player,
3032 const struct requirement *req)
3033{
3034 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINTECHS);
3035
3036 switch (req->range) {
3037 case REQ_RANGE_WORLD:
3038 /* "None" does not count */
3039 return ((game.info.global_advance_count - 1)
3040 >= req->source.value.min_techs);
3041 case REQ_RANGE_PLAYER:
3042 if (context->player == NULL) {
3043 return TRI_MAYBE;
3044 } else {
3045 /* "None" does not count */
3046 return BOOL_TO_TRISTATE(
3047 (research_get(context->player)->techs_researched - 1)
3048 >= req->source.value.min_techs
3049 );
3050 }
3051 default:
3052 return TRI_MAYBE;
3053 }
3054}
3055
3056/**********************************************************************/
3063static enum fc_tristate
3064is_ai_req_active(const struct civ_map *nmap,
3065 const struct req_context *context,
3066 const struct player *other_player,
3067 const struct requirement *req)
3068{
3069 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_AI_LEVEL);
3070
3071 if (context->player == NULL) {
3072 return TRI_MAYBE;
3073 } else {
3074 return BOOL_TO_TRISTATE(is_ai(context->player)
3075 && context->player->ai_common.skill_level
3076 == req->source.value.ai_level);
3077 }
3078}
3079
3080/**********************************************************************/
3087static enum fc_tristate
3089 const struct req_context *context,
3090 const struct player *other_player,
3091 const struct requirement *req)
3092{
3093 const struct nation_type *nation;
3094
3095 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NATION);
3096
3097 nation = req->source.value.nation;
3098
3099 switch (req->range) {
3100 case REQ_RANGE_PLAYER:
3101 if (context->player == NULL) {
3102 return TRI_MAYBE;
3103 }
3104 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
3105 case REQ_RANGE_TEAM:
3106 case REQ_RANGE_ALLIANCE:
3107 if (context->player == NULL) {
3108 return TRI_MAYBE;
3109 }
3110 players_iterate_alive(plr2) {
3111 if (players_in_same_range(context->player, plr2, req->range)) {
3112 if (nation_of_player(plr2) == nation) {
3113 return TRI_YES;
3114 }
3115 }
3117 return TRI_NO;
3118 case REQ_RANGE_WORLD:
3119 /* NB: if a player is ever removed outright from the game
3120 * (e.g. via /remove), rather than just dying, this 'survives'
3121 * requirement will stop being true for their nation.
3122 * create_command_newcomer() can also cause this to happen. */
3123 return BOOL_TO_TRISTATE(NULL != nation->player
3124 && (req->survives || nation->player->is_alive));
3125 case REQ_RANGE_LOCAL:
3126 case REQ_RANGE_CADJACENT:
3127 case REQ_RANGE_ADJACENT:
3128 case REQ_RANGE_CITY:
3129 case REQ_RANGE_TRADE_ROUTE:
3130 case REQ_RANGE_CONTINENT:
3131 case REQ_RANGE_COUNT:
3132 break;
3133 }
3134
3135 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3136
3137 return TRI_MAYBE;
3138}
3139
3140/**********************************************************************/
3148static enum fc_tristate
3150 const struct req_context *context,
3151 const struct player *other_player,
3152 const struct requirement *req)
3153{
3154 const struct nation_group *ngroup;
3155
3156 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NATIONGROUP);
3157
3158 ngroup = req->source.value.nationgroup;
3159
3160 switch (req->range) {
3161 case REQ_RANGE_PLAYER:
3162 if (context->player == NULL) {
3163 return TRI_MAYBE;
3164 }
3166 nation_of_player(context->player), ngroup));
3167 case REQ_RANGE_TEAM:
3168 case REQ_RANGE_ALLIANCE:
3169 case REQ_RANGE_WORLD:
3170 if (context->player == NULL) {
3171 return TRI_MAYBE;
3172 }
3173 players_iterate_alive(plr2) {
3174 if (players_in_same_range(context->player, plr2, req->range)) {
3175 if (nation_is_in_group(nation_of_player(plr2), ngroup)) {
3176 return TRI_YES;
3177 }
3178 }
3180 return TRI_NO;
3181 case REQ_RANGE_LOCAL:
3182 case REQ_RANGE_CADJACENT:
3183 case REQ_RANGE_ADJACENT:
3184 case REQ_RANGE_CITY:
3185 case REQ_RANGE_TRADE_ROUTE:
3186 case REQ_RANGE_CONTINENT:
3187 case REQ_RANGE_COUNT:
3188 break;
3189 }
3190
3191 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3192
3193 return TRI_MAYBE;
3194}
3195
3196/**********************************************************************/
3204static enum fc_tristate
3206 const struct req_context *context,
3207 const struct player *other_player,
3208 const struct requirement *req)
3209{
3210 const struct nation_type *nationality;
3211 enum fc_tristate ret;
3212
3213 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NATIONALITY);
3214
3215 nationality = req->source.value.nationality;
3216
3217 switch (req->range) {
3218 case REQ_RANGE_CITY:
3219 if (context->city == NULL) {
3220 return TRI_MAYBE;
3221 }
3222 citizens_iterate(context->city, slot, count) {
3223 if (player_slot_get_player(slot)->nation == nationality) {
3224 return TRI_YES;
3225 }
3227
3228 return TRI_NO;
3229 case REQ_RANGE_TRADE_ROUTE:
3230 if (context->city == NULL) {
3231 return TRI_MAYBE;
3232 }
3233 citizens_iterate(context->city, slot, count) {
3234 if (player_slot_get_player(slot)->nation == nationality) {
3235 return TRI_YES;
3236 }
3238
3239 ret = TRI_NO;
3240 trade_partners_iterate(context->city, trade_partner) {
3241 if (trade_partner == NULL) {
3242 ret = TRI_MAYBE;
3243 } else {
3244 citizens_iterate(trade_partner, slot, count) {
3245 if (player_slot_get_player(slot)->nation == nationality) {
3246 return TRI_YES;
3247 }
3249 }
3251
3252 return ret;
3253 case REQ_RANGE_PLAYER:
3254 case REQ_RANGE_TEAM:
3255 case REQ_RANGE_ALLIANCE:
3256 case REQ_RANGE_WORLD:
3257 case REQ_RANGE_LOCAL:
3258 case REQ_RANGE_CADJACENT:
3259 case REQ_RANGE_ADJACENT:
3260 case REQ_RANGE_CONTINENT:
3261 case REQ_RANGE_COUNT:
3262 break;
3263 }
3264
3265 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3266
3267 return TRI_MAYBE;
3268}
3269
3270/**********************************************************************/
3273static enum fc_tristate is_diplrel_in_range(const struct player *target_player,
3274 const struct player *other_player,
3275 enum req_range range,
3276 int diplrel)
3277{
3278 switch (range) {
3279 case REQ_RANGE_PLAYER:
3280 if (target_player == NULL) {
3281 return TRI_MAYBE;
3282 }
3283 return BOOL_TO_TRISTATE(is_diplrel_to_other(target_player, diplrel));
3284 case REQ_RANGE_TEAM:
3285 case REQ_RANGE_ALLIANCE:
3286 case REQ_RANGE_WORLD:
3287 if (target_player == NULL) {
3288 return TRI_MAYBE;
3289 }
3290 players_iterate_alive(plr2) {
3291 if (players_in_same_range(target_player, plr2, range)) {
3292 if (is_diplrel_to_other(plr2, diplrel)) {
3293 return TRI_YES;
3294 }
3295 }
3297 return TRI_NO;
3298 case REQ_RANGE_LOCAL:
3299 if (target_player == NULL || other_player == NULL) {
3300 return TRI_MAYBE;
3301 }
3302 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
3303 case REQ_RANGE_CADJACENT:
3304 case REQ_RANGE_ADJACENT:
3305 case REQ_RANGE_CITY:
3306 case REQ_RANGE_TRADE_ROUTE:
3307 case REQ_RANGE_CONTINENT:
3308 case REQ_RANGE_COUNT:
3309 break;
3310 }
3311
3312 fc_assert_msg(FALSE, "Invalid range %d.", range);
3313
3314 return TRI_MAYBE;
3315}
3316
3317/**********************************************************************/
3324static enum fc_tristate
3326 const struct req_context *context,
3327 const struct player *other_player,
3328 const struct requirement *req)
3329{
3330 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL);
3331
3332 return is_diplrel_in_range(context->player, other_player, req->range,
3333 req->source.value.diplrel);
3334}
3335
3336/**********************************************************************/
3344static enum fc_tristate
3346 const struct req_context *context,
3347 const struct player *other_player,
3348 const struct requirement *req)
3349{
3350 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_TILE);
3351
3352 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
3353 : NULL,
3354 context->player,
3355 req->range,
3356 req->source.value.diplrel);
3357}
3358
3359/**********************************************************************/
3368static enum fc_tristate
3370 const struct req_context *context,
3371 const struct player *other_player,
3372 const struct requirement *req)
3373{
3374 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_TILE_O);
3375
3376 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
3377 : NULL,
3378 other_player,
3379 req->range,
3380 req->source.value.diplrel);
3381}
3382
3383/**********************************************************************/
3386static enum fc_tristate
3388 const struct player *other_player,
3389 enum req_range range,
3390 int diplrel)
3391{
3392 enum fc_tristate out = TRI_NO;
3393
3394 if (target_tile == NULL) {
3395 return TRI_MAYBE;
3396 }
3397
3399 enum fc_tristate for_target_unit = is_diplrel_in_range(
3400 unit_owner(target_unit), other_player, range, diplrel);
3401
3402 out = fc_tristate_or(out, for_target_unit);
3404
3405 return out;
3406}
3407
3408/**********************************************************************/
3417static enum fc_tristate
3419 const struct req_context *context,
3420 const struct player *other_player,
3421 const struct requirement *req)
3422{
3423 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_UNITANY);
3424
3425 return is_diplrel_unitany_in_range(context->tile, context->player,
3426 req->range,
3427 req->source.value.diplrel);
3428}
3429
3430/**********************************************************************/
3439static enum fc_tristate
3441 const struct req_context *context,
3442 const struct player *other_player,
3443 const struct requirement *req)
3444{
3445 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_UNITANY_O);
3446
3447 return is_diplrel_unitany_in_range(context->tile, other_player,
3448 req->range,
3449 req->source.value.diplrel);
3450}
3451
3452/**********************************************************************/
3459static enum fc_tristate
3461 const struct req_context *context,
3462 const struct player *other_player,
3463 const struct requirement *req)
3464{
3465 const struct unit_type *punittype;
3466
3468
3469 punittype = req->source.value.utype;
3470
3471 if (req->range != REQ_RANGE_LOCAL) {
3472 return TRI_NO;
3473 }
3474 if (!context->unittype) {
3475 return TRI_MAYBE;
3476 }
3477
3478 return BOOL_TO_TRISTATE(context->unittype == punittype);
3479}
3480
3481/**********************************************************************/
3488static enum fc_tristate
3490 const struct req_context *context,
3491 const struct player *other_player,
3492 const struct requirement *req)
3493{
3494 enum unit_type_flag_id unitflag;
3495
3496 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UTFLAG);
3497
3498 unitflag = req->source.value.unitflag;
3499
3500 if (req->range != REQ_RANGE_LOCAL) {
3501 return TRI_NO;
3502 }
3503 if (!context->unittype) {
3504 return TRI_MAYBE;
3505 }
3506
3507 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
3508}
3509
3510/**********************************************************************/
3517static enum fc_tristate
3519 const struct req_context *context,
3520 const struct player *other_player,
3521 const struct requirement *req)
3522{
3523 const struct unit_class *pclass;
3524
3525 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UCLASS);
3526
3527 pclass = req->source.value.uclass;
3528
3529 if (req->range != REQ_RANGE_LOCAL) {
3530 return TRI_NO;
3531 }
3532 if (!context->unittype) {
3533 return TRI_MAYBE;
3534 }
3535
3536 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
3537}
3538
3539/**********************************************************************/
3547static enum fc_tristate
3549 const struct req_context *context,
3550 const struct player *other_player,
3551 const struct requirement *req)
3552{
3553 enum unit_class_flag_id ucflag;
3554
3555 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UCFLAG);
3556
3557 ucflag = req->source.value.unitclassflag;
3558
3559 if (req->range != REQ_RANGE_LOCAL) {
3560 return TRI_NO;
3561 }
3562 if (!context->unittype) {
3563 return TRI_MAYBE;
3564 }
3565
3566 return BOOL_TO_TRISTATE(uclass_has_flag(utype_class(context->unittype), ucflag));
3567}
3568
3569/**********************************************************************/
3576static enum fc_tristate
3578 const struct req_context *context,
3579 const struct player *other_player,
3580 const struct requirement *req)
3581{
3582 enum ustate_prop uprop;
3583
3584 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UNITSTATE);
3585
3586 uprop = req->source.value.unit_state;
3587
3588 fc_assert_ret_val_msg(req->range == REQ_RANGE_LOCAL, TRI_NO,
3589 "Unsupported range \"%s\"",
3590 req_range_name(req->range));
3591
3592 /* Could be asked with incomplete data.
3593 * is_req_active() will handle it based on prob_type. */
3594 if (context->unit == NULL) {
3595 return TRI_MAYBE;
3596 }
3597
3598 switch (uprop) {
3599 case USP_TRANSPORTED:
3600 return BOOL_TO_TRISTATE(context->unit->transporter != NULL);
3601 case USP_LIVABLE_TILE:
3602 return BOOL_TO_TRISTATE(
3603 can_unit_exist_at_tile(nmap, context->unit,
3604 unit_tile(context->unit)));
3605 break;
3606 case USP_TRANSPORTING:
3607 return BOOL_TO_TRISTATE(0 < get_transporter_occupancy(context->unit));
3608 case USP_HAS_HOME_CITY:
3609 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
3610 case USP_NATIVE_TILE:
3611 return BOOL_TO_TRISTATE(
3613 unit_tile(context->unit)));
3614 break;
3615 case USP_NATIVE_EXTRA:
3616 return BOOL_TO_TRISTATE(
3618 unit_type_get(context->unit)));
3619 break;
3620 case USP_MOVED_THIS_TURN:
3621 return BOOL_TO_TRISTATE(context->unit->moved);
3622 case USP_COUNT:
3623 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
3624 /* Invalid property is unknowable. */
3625 return TRI_NO;
3626 }
3627
3628 /* Should never be reached */
3629 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
3630
3631 return TRI_NO;
3632}
3633
3634/**********************************************************************/
3641static enum fc_tristate
3643 const struct req_context *context,
3644 const struct player *other_player,
3645 const struct requirement *req)
3646{
3647 enum unit_activity activity;
3648
3649 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ACTIVITY);
3650
3651 activity = req->source.value.activity;
3652
3653 fc_assert_ret_val_msg(req->range == REQ_RANGE_LOCAL, TRI_NO,
3654 "Unsupported range \"%s\"",
3655 req_range_name(req->range));
3656
3657 /* Could be asked with incomplete data.
3658 * is_req_active() will handle it based on prob_type. */
3659 if (context->unit == NULL) {
3660 return TRI_MAYBE;
3661 }
3662
3663 switch (context->unit->activity) {
3664 case ACTIVITY_IDLE:
3665 case ACTIVITY_SENTRY:
3666 case ACTIVITY_GOTO:
3667 case ACTIVITY_EXPLORE:
3668 /* Seen as idle. */
3669 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
3670 default:
3671 /* Handled below. */
3672 break;
3673 }
3674
3675 return BOOL_TO_TRISTATE(context->unit->activity == activity);
3676}
3677
3678/**********************************************************************/
3685static enum fc_tristate
3687 const struct req_context *context,
3688 const struct player *other_player,
3689 const struct requirement *req)
3690{
3691 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINVETERAN);
3692
3693 if (context->unit == NULL) {
3694 return TRI_MAYBE;
3695 } else {
3696 return BOOL_TO_TRISTATE(context->unit->veteran
3697 >= req->source.value.minveteran);
3698 }
3699}
3700
3701/**********************************************************************/
3709static enum fc_tristate
3711 const struct req_context *context,
3712 const struct player *other_player,
3713 const struct requirement *req)
3714{
3715 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINMOVES);
3716
3717 if (context->unit == NULL) {
3718 return TRI_MAYBE;
3719 } else {
3721 <= context->unit->moves_left);
3722 }
3723}
3724
3725/**********************************************************************/
3733static enum fc_tristate
3735 const struct req_context *context,
3736 const struct player *other_player,
3737 const struct requirement *req)
3738{
3740
3741 if (context->unit == NULL) {
3742 return TRI_MAYBE;
3743 } else {
3745 <= context->unit->hp);
3746 }
3747}
3748
3749/**********************************************************************/
3756static enum fc_tristate
3757is_age_req_active(const struct civ_map *nmap,
3758 const struct req_context *context,
3759 const struct player *other_player,
3760 const struct requirement *req)
3761{
3763
3764 switch (req->range) {
3765 case REQ_RANGE_LOCAL:
3766 if (context->unit == NULL || !is_server()) {
3767 return TRI_MAYBE;
3768 } else {
3769 return BOOL_TO_TRISTATE(
3770 req->source.value.age <=
3771 game.info.turn - context->unit->server.birth_turn);
3772 }
3773 break;
3774 case REQ_RANGE_CITY:
3775 if (context->city == NULL || context->city->original == NULL) {
3776 return TRI_MAYBE;
3777 } else {
3778 return BOOL_TO_TRISTATE(
3779 req->source.value.age <=
3780 game.info.turn - context->city->turn_founded);
3781 }
3782 break;
3783 case REQ_RANGE_PLAYER:
3784 if (context->player == NULL) {
3785 return TRI_MAYBE;
3786 } else {
3787 return BOOL_TO_TRISTATE(req->source.value.age
3788 <= player_age(context->player));
3789 }
3790 break;
3791 default:
3792 return TRI_MAYBE;
3793 break;
3794 }
3795}
3796
3797/**********************************************************************/
3800static bool is_city_in_tile(const struct tile *ptile,
3801 const struct city *pcity)
3802{
3803 if (pcity == NULL) {
3804 return tile_city(ptile) != NULL;
3805 } else {
3806 return is_city_center(pcity, ptile);
3807 }
3808}
3809
3810/**********************************************************************/
3817static enum fc_tristate
3819 const struct req_context *context,
3820 const struct player *other_player,
3821 const struct requirement *req)
3822{
3823 enum citytile_type citytile;
3824
3825 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_CITYTILE);
3826
3827 citytile = req->source.value.citytile;
3828
3829 fc_assert_ret_val(req_range_is_valid(req->range), TRI_MAYBE);
3830 if (context->tile == NULL) {
3831 return TRI_MAYBE;
3832 }
3833
3834 switch (citytile) {
3835 case CITYT_CENTER:
3836 switch (req->range) {
3837 case REQ_RANGE_LOCAL:
3838 return BOOL_TO_TRISTATE(is_city_in_tile(context->tile,
3839 context->city));
3840 case REQ_RANGE_CADJACENT:
3841 if (is_city_in_tile(context->tile, context->city)) {
3842 return TRI_YES;
3843 }
3844 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
3845 if (is_city_in_tile(adjc_tile, context->city)) {
3846 return TRI_YES;
3847 }
3849
3850 return TRI_NO;
3851 case REQ_RANGE_ADJACENT:
3852 if (is_city_in_tile(context->tile, context->city)) {
3853 return TRI_YES;
3854 }
3855 adjc_iterate(nmap, context->tile, adjc_tile) {
3856 if (is_city_in_tile(adjc_tile, context->city)) {
3857 return TRI_YES;
3858 }
3860
3861 return TRI_NO;
3862 case REQ_RANGE_CITY:
3863 case REQ_RANGE_TRADE_ROUTE:
3864 case REQ_RANGE_CONTINENT:
3865 case REQ_RANGE_PLAYER:
3866 case REQ_RANGE_TEAM:
3867 case REQ_RANGE_ALLIANCE:
3868 case REQ_RANGE_WORLD:
3869 case REQ_RANGE_COUNT:
3870 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
3871 break;
3872 }
3873
3874 return TRI_MAYBE;
3875 case CITYT_CLAIMED:
3876 switch (req->range) {
3877 case REQ_RANGE_LOCAL:
3878 return BOOL_TO_TRISTATE(context->tile->owner != NULL);
3879 case REQ_RANGE_CADJACENT:
3880 if (context->tile->owner != NULL) {
3881 return TRI_YES;
3882 }
3883 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
3884 if (adjc_tile->owner != NULL) {
3885 return TRI_YES;
3886 }
3888
3889 return TRI_NO;
3890 case REQ_RANGE_ADJACENT:
3891 if (context->tile->owner != NULL) {
3892 return TRI_YES;
3893 }
3894 adjc_iterate(nmap, context->tile, adjc_tile) {
3895 if (adjc_tile->owner != NULL) {
3896 return TRI_YES;
3897 }
3899
3900 return TRI_NO;
3901 case REQ_RANGE_CITY:
3902 case REQ_RANGE_TRADE_ROUTE:
3903 case REQ_RANGE_CONTINENT:
3904 case REQ_RANGE_PLAYER:
3905 case REQ_RANGE_TEAM:
3906 case REQ_RANGE_ALLIANCE:
3907 case REQ_RANGE_WORLD:
3908 case REQ_RANGE_COUNT:
3909 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
3910 break;
3911 }
3912
3913 return TRI_MAYBE;
3914 case CITYT_EXTRAS_OWNED:
3915 switch (req->range) {
3916 case REQ_RANGE_LOCAL:
3917 return BOOL_TO_TRISTATE(context->tile->extras_owner != NULL);
3918 case REQ_RANGE_CADJACENT:
3919 if (context->tile->extras_owner != NULL) {
3920 return TRI_YES;
3921 }
3922 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
3923 if (adjc_tile->extras_owner != NULL) {
3924 return TRI_YES;
3925 }
3927
3928 return TRI_NO;
3929 case REQ_RANGE_ADJACENT:
3930 if (context->tile->extras_owner != NULL) {
3931 return TRI_YES;
3932 }
3933 adjc_iterate(nmap, context->tile, adjc_tile) {
3934 if (adjc_tile->extras_owner != NULL) {
3935 return TRI_YES;
3936 }
3938
3939 return TRI_NO;
3940 case REQ_RANGE_CITY:
3941 case REQ_RANGE_TRADE_ROUTE:
3942 case REQ_RANGE_CONTINENT:
3943 case REQ_RANGE_PLAYER:
3944 case REQ_RANGE_TEAM:
3945 case REQ_RANGE_ALLIANCE:
3946 case REQ_RANGE_WORLD:
3947 case REQ_RANGE_COUNT:
3948 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
3949 break;
3950 }
3951
3952 return TRI_MAYBE;
3953 case CITYT_LAST:
3954 /* Handled below */
3955 break;
3956 }
3957
3958 /* Not implemented */
3959 log_error("is_req_active(): citytile %d not supported.",
3960 citytile);
3961 return TRI_MAYBE;
3962}
3963
3964/**********************************************************************/
3972static enum fc_tristate
3974 const struct req_context *context,
3975 const struct player *other_player,
3976 const struct requirement *req)
3977{
3978 enum citystatus_type citystatus;
3979
3980 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_CITYSTATUS);
3981
3982 citystatus = req->source.value.citystatus;
3983
3984 if (context->city == NULL) {
3985 return TRI_MAYBE;
3986 }
3987
3988 if (citystatus == CITYS_OWNED_BY_ORIGINAL) {
3989 switch (req->range) {
3990 case REQ_RANGE_CITY:
3991 if (context->city->original == NULL) {
3992 return TRI_MAYBE;
3993 }
3994 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
3995 case REQ_RANGE_TRADE_ROUTE:
3996 {
3997 enum fc_tristate ret;
3998
3999 if (city_owner(context->city) == context->city->original) {
4000 return TRI_YES;
4001 }
4002
4003 ret = TRI_NO;
4004 trade_partners_iterate(context->city, trade_partner) {
4005 if (trade_partner == NULL || trade_partner->original == NULL) {
4006 ret = TRI_MAYBE;
4007 } else if (city_owner(trade_partner) == trade_partner->original) {
4008 return TRI_YES;
4009 }
4011
4012 return ret;
4013 }
4014 case REQ_RANGE_LOCAL:
4015 case REQ_RANGE_CADJACENT:
4016 case REQ_RANGE_ADJACENT:
4017 case REQ_RANGE_CONTINENT:
4018 case REQ_RANGE_PLAYER:
4019 case REQ_RANGE_TEAM:
4020 case REQ_RANGE_ALLIANCE:
4021 case REQ_RANGE_WORLD:
4022 case REQ_RANGE_COUNT:
4023 break;
4024 }
4025
4026 fc_assert_msg(FALSE, "Invalid range %d for citystatus.", req->range);
4027
4028 return TRI_MAYBE;
4029 } else {
4030 /* Not implemented */
4031 log_error("is_req_active(): citystatus %d not supported.",
4032 citystatus);
4033 return TRI_MAYBE;
4034 }
4035}
4036
4037/**********************************************************************/
4044static enum fc_tristate
4046 const struct req_context *context,
4047 const struct player *other_player,
4048 const struct requirement *req)
4049{
4050 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINSIZE);
4051
4052 if (context->city == NULL) {
4053 return TRI_MAYBE;
4054 } else {
4055 if (req->range == REQ_RANGE_TRADE_ROUTE) {
4056 enum fc_tristate ret;
4057
4058 if (city_size_get(context->city) >= req->source.value.minsize) {
4059 return TRI_YES;
4060 }
4061
4062 ret = TRI_NO;
4063 trade_partners_iterate(context->city, trade_partner) {
4064 if (trade_partner == NULL) {
4065 ret = TRI_MAYBE;
4066 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
4067 return TRI_YES;
4068 }
4070
4071 return ret;
4072 } else {
4073 return BOOL_TO_TRISTATE(city_size_get(context->city)
4074 >= req->source.value.minsize);
4075 }
4076 }
4077}
4078
4079/**********************************************************************/
4087static enum fc_tristate
4089 const struct req_context *context,
4090 const struct player *other_player,
4091 const struct requirement *req)
4092{
4093 const struct achievement *achievement;
4094
4095 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ACHIEVEMENT);
4096
4098
4099 if (req->range == REQ_RANGE_WORLD) {
4101 } else if (context->player == NULL) {
4102 return TRI_MAYBE;
4103 } else if (req->range == REQ_RANGE_ALLIANCE
4104 || req->range == REQ_RANGE_TEAM) {
4105 players_iterate_alive(plr2) {
4106 if (players_in_same_range(context->player, plr2, req->range)
4108 return TRI_YES;
4109 }
4111 return TRI_NO;
4112 } else if (req->range == REQ_RANGE_PLAYER) {
4113 if (achievement_player_has(achievement, context->player)) {
4114 return TRI_YES;
4115 } else {
4116 return TRI_NO;
4117 }
4118 }
4119
4120 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
4121
4122 return TRI_MAYBE;
4123}
4124
4125/**********************************************************************/
4132static enum fc_tristate
4134 const struct req_context *context,
4135 const struct player *other_player,
4136 const struct requirement *req)
4137{
4138 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINYEAR);
4139
4141}
4142
4143/**********************************************************************/
4150static enum fc_tristate
4152 const struct req_context *context,
4153 const struct player *other_player,
4154 const struct requirement *req)
4155{
4156 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINCALFRAG);
4157
4159 >= req->source.value.mincalfrag);
4160}
4161
4162/**********************************************************************/
4169static enum fc_tristate
4171 const struct req_context *context,
4172 const struct player *other_player,
4173 const struct requirement *req)
4174{
4176
4177 return BOOL_TO_TRISTATE(
4179}
4180
4181/**********************************************************************/
4189static enum fc_tristate
4191 const struct req_context *context,
4192 const struct player *other_player,
4193 const struct requirement *req)
4194{
4195 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_SERVERSETTING);
4196
4198 req->source.value.ssetval));
4199}
4200
4201/* Not const for potential ruleset-related adjustment */
4202static struct req_def req_definitions[VUT_COUNT] = {
4203 [VUT_NONE] = {is_none_req_active, REQUCH_YES},
4204
4205 /* alphabetical order of enum constant */
4206 [VUT_ACHIEVEMENT] = {is_achievement_req_active, REQUCH_YES, REQUC_PRESENT},
4207 [VUT_ACTION] = {is_action_req_active, REQUCH_YES},
4208 [VUT_ACTIVITY] = {is_activity_req_active, REQUCH_NO},
4209 [VUT_ADVANCE] = {is_tech_req_active, REQUCH_NO},
4211 [VUT_AI_LEVEL] = {is_ai_req_active, REQUCH_HACK},
4213 [VUT_CITYTILE] = {is_citytile_req_active, REQUCH_NO, REQUC_CITYTILE},
4214 [VUT_DIPLREL] = {is_diplrel_req_active, REQUCH_NO},
4215 [VUT_DIPLREL_TILE] = {is_diplrel_tile_req_active, REQUCH_NO},
4216 [VUT_DIPLREL_TILE_O] = {is_diplrel_tile_o_req_active, REQUCH_NO},
4217 [VUT_DIPLREL_UNITANY] = {is_diplrel_unitany_req_active, REQUCH_NO},
4218 [VUT_DIPLREL_UNITANY_O] = {is_diplrel_unitany_o_req_active, REQUCH_NO},
4219 [VUT_EXTRA] = {is_extra_req_active, REQUCH_NO, REQUC_LOCAL},
4220 [VUT_EXTRAFLAG] = {is_extraflag_req_active, REQUCH_NO, REQUC_LOCAL},
4221 [VUT_GOOD] = {is_good_req_active, REQUCH_NO},
4222 [VUT_GOVERNMENT] = {is_gov_req_active, REQUCH_NO},
4223 [VUT_IMPROVEMENT] = {is_building_req_active, REQUCH_NO, REQUC_IMPR},
4224 [VUT_IMPR_GENUS] = {is_buildinggenus_req_active, REQUCH_YES},
4225 [VUT_MAXTILEUNITS] = {is_maxunitsontile_req_active, REQUCH_NO},
4226 [VUT_MINCALFRAG] = {is_mincalfrag_req_active, REQUCH_NO},
4227 [VUT_MINCULTURE] = {is_minculture_req_active, REQUCH_NO},
4228 [VUT_MINFOREIGNPCT] = {is_minforeignpct_req_active, REQUCH_NO},
4229 [VUT_MINHP] = {is_minhitpoints_req_active, REQUCH_NO},
4230 [VUT_MINMOVES] = {is_minmovefrags_req_active, REQUCH_NO},
4231 [VUT_MINSIZE] = {is_minsize_req_active, REQUCH_NO},
4232 [VUT_MINTECHS] = {is_mintechs_req_active, REQUCH_ACT, REQUC_WORLD},
4235 [VUT_NATION] = {is_nation_req_active, REQUCH_HACK, REQUC_NALLY},
4236 [VUT_NATIONALITY] = {is_nationality_req_active, REQUCH_NO},
4237 [VUT_NATIONGROUP] = {is_nationgroup_req_active, REQUCH_HACK, REQUC_NALLY},
4238 [VUT_OTYPE] = {is_outputtype_req_active, REQUCH_YES},
4239 [VUT_ROADFLAG] = {is_roadflag_req_active, REQUCH_NO, REQUC_LOCAL},
4240 [VUT_SERVERSETTING] = {is_serversetting_req_active, REQUCH_HACK},
4241 [VUT_SPECIALIST] = {is_specialist_req_active, REQUCH_YES},
4242 [VUT_STYLE] = {is_style_req_active, REQUCH_HACK},
4243 [VUT_TECHFLAG] = {is_techflag_req_active, REQUCH_NO},
4244 [VUT_TERRAIN] = {is_terrain_req_active, REQUCH_NO},
4245 [VUT_TERRAINALTER] = {is_terrainalter_req_active, REQUCH_NO},
4246 [VUT_TERRAINCLASS] = {is_terrainclass_req_active, REQUCH_NO},
4247 [VUT_TERRFLAG] = {is_terrainflag_req_active, REQUCH_NO},
4248 [VUT_TOPO] = {is_topology_req_active, REQUCH_YES},
4249 [VUT_UCFLAG] = {is_unitclassflag_req_active, REQUCH_YES},
4250 [VUT_UCLASS] = {is_unitclass_req_active, REQUCH_YES},
4251 [VUT_UNITSTATE] = {is_unitstate_req_active, REQUCH_NO},
4252 [VUT_UTFLAG] = {is_unitflag_req_active, REQUCH_YES},
4253 [VUT_UTYPE] = {is_unittype_req_active, REQUCH_YES}
4254};
4255
4256/**********************************************************************/
4268bool is_req_active(const struct req_context *context,
4269 const struct player *other_player,
4270 const struct requirement *req,
4271 const enum req_problem_type prob_type)
4272{
4273 const struct civ_map *nmap = &(wld.map);
4274 enum fc_tristate eval = tri_req_present(nmap, context, other_player, req);
4275
4276 if (eval == TRI_MAYBE) {
4277 if (prob_type == RPT_POSSIBLE) {
4278 return TRUE;
4279 } else {
4280 return FALSE;
4281 }
4282 }
4283 if (req->present) {
4284 return (eval == TRI_YES);
4285 } else {
4286 return (eval == TRI_NO);
4287 }
4288}
4289
4290/**********************************************************************/
4298static
4299enum fc_tristate tri_req_present(const struct civ_map *nmap,
4300 const struct req_context *context,
4301 const struct player *other_player,
4302 const struct requirement *req)
4303{
4304 if (context == NULL) {
4305 context = req_context_empty();
4306 }
4307
4308 if (req->source.kind >= VUT_COUNT) {
4309 log_error("tri_req_present(): invalid source kind %d.",
4310 req->source.kind);
4311 return TRI_NO;
4312 }
4313
4315
4316 return req_definitions[req->source.kind].cb(nmap, context,
4317 other_player, req);
4318}
4319
4320/**********************************************************************/
4328enum fc_tristate tri_req_active(const struct req_context *context,
4329 const struct player *other_player,
4330 const struct requirement *req)
4331{
4332 const struct civ_map *nmap = &(wld.map);
4333 enum fc_tristate eval = tri_req_present(nmap, context, other_player, req);
4334
4335 if (!req->present) {
4336 if (TRI_NO == eval) {
4337 return TRI_YES;
4338 }
4339 if (TRI_YES == eval) {
4340 return TRI_NO;
4341 }
4342 }
4343
4344 return eval;
4345}
4346
4347/**********************************************************************/
4361bool are_reqs_active(const struct req_context *context,
4362 const struct player *other_player,
4363 const struct requirement_vector *reqs,
4364 const enum req_problem_type prob_type)
4365{
4367 if (!is_req_active(context, other_player, preq, prob_type)) {
4368 return FALSE;
4369 }
4371 return TRUE;
4372}
4373
4374/**********************************************************************/
4380enum fc_tristate
4381tri_req_active_turns(int pass, int period,
4382 const struct req_context *context,
4383 const struct player *other_player,
4384 const struct requirement *req)
4385{
4386 /* FIXME: doubles code from calendar.c */
4387 int ypt = get_world_bonus(EFT_TURN_YEARS);
4388 int fpt = get_world_bonus(EFT_TURN_FRAGMENTS);
4389 int fragment = game.info.fragment_count;
4390 int fragment1 = fragment; /* if fragments don't advance */
4391 int year_inc, year_inc1;
4392 const int slowdown = (victory_enabled(VC_SPACERACE)
4393 ? get_world_bonus(EFT_SLOW_DOWN_TIMELINE) : 0);
4394 bool present, present1;
4395
4396 fc_assert(pass >= 0 && period >= 0);
4397 if (slowdown >= 3) {
4398 if (ypt > 1) {
4399 ypt = 1;
4400 }
4401 } else if (slowdown >= 2) {
4402 if (ypt > 2) {
4403 ypt = 2;
4404 }
4405 } else if (slowdown >= 1) {
4406 if (ypt > 5) {
4407 ypt = 5;
4408 }
4409 }
4410 year_inc = ypt * pass;
4411 year_inc1 = year_inc + ypt * period;
4413 int fragment_years;
4414
4415 fragment += fpt * pass;
4416 fragment_years = fragment / game.calendar.calendar_fragments;
4417 year_inc += fragment_years;
4418 fragment -= fragment_years * game.calendar.calendar_fragments;
4419 fragment1 = fragment + fpt * period;
4420 fragment_years += fragment1 / game.calendar.calendar_fragments;
4421 year_inc1 += fragment_years;
4422 fragment1 -= fragment_years * game.calendar.calendar_fragments;
4423 }
4425 if (year_inc + game.info.year >= 0) {
4426 year_inc++;
4427 year_inc1++;
4428 } else if (year_inc1 + game.info.year >= 0) {
4429 year_inc1++;
4430 }
4431 }
4432
4433 switch (req->source.kind) {
4434 case VUT_AGE:
4435 switch (req->range) {
4436 case REQ_RANGE_LOCAL:
4437 if (context->unit == NULL || !is_server()) {
4438 return TRI_MAYBE;
4439 } else {
4440 int ua = game.info.turn + pass - context->unit->server.birth_turn;
4441
4442 present = req->source.value.age <= ua;
4443 present1 = req->source.value.age <= ua + period;
4444 }
4445 break;
4446 case REQ_RANGE_CITY:
4447 if (context->city == NULL) {
4448 return TRI_MAYBE;
4449 } else {
4450 int ca = game.info.turn + pass - context->city->turn_founded;
4451
4452 present = req->source.value.age <= ca;
4453 present1 = req->source.value.age <= ca + period;
4454 }
4455 break;
4456 case REQ_RANGE_PLAYER:
4457 if (context->player == NULL) {
4458 return TRI_MAYBE;
4459 } else {
4460 present = req->source.value.age
4461 <= player_age(context->player) + pass;
4462 present1 = req->source.value.age
4463 <= player_age(context->player) + pass + period;
4464 }
4465 break;
4466 default:
4467 return TRI_MAYBE;
4468 }
4469 break;
4470 case VUT_MINYEAR:
4471 present = game.info.year + year_inc >= req->source.value.minyear;
4472 present1 = game.info.year + year_inc1 >= req->source.value.minyear;
4473 break;
4474 case VUT_MINCALFRAG:
4475 if (game.calendar.calendar_fragments <= period) {
4476 /* Hope that the requirement is valid and fragments advance fine */
4477 return TRI_YES;
4478 }
4479 present = fragment >= req->source.value.mincalfrag;
4480 present1 = fragment1 >= req->source.value.mincalfrag;
4481 break;
4482 default:
4483 /* No special handling invented */
4484 return tri_req_active(context, other_player, req);
4485 }
4486 return BOOL_TO_TRISTATE(req->present
4487 ? present || present1 : !(present && present1));
4488}
4489
4490/**********************************************************************/
4496 (const struct req_context *context,
4497 const struct player *other_player,
4498 const struct requirement *req,
4499 void *data, int n_data)
4500{
4501 int i;
4502
4503 fc_assert_ret_val(data || n_data == 0, TRI_NO);
4504
4505 for (i = 0; i < n_data; i++) {
4506 if (are_requirements_contradictions(&((struct requirement *) data)[i],
4507 req)) {
4508 return TRI_NO;
4509 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
4510 return TRI_YES;
4511 }
4512 }
4513
4514 return tri_req_active(context, other_player, req);
4515}
4516
4517/**********************************************************************/
4523enum fc_tristate
4524 tri_reqs_cb_active(const struct req_context *context,
4525 const struct player *other_player,
4526 const struct requirement_vector *reqs,
4527 struct requirement_vector *maybe_reqs,
4528 req_tester_cb tester,
4529 void *data, int n_data)
4530{
4531 bool active = TRUE;
4532 bool certain = TRUE;
4533
4534 fc_assert_ret_val(NULL != tester, TRI_NO);
4536 switch(tester(context, other_player, preq,
4537 data, n_data)) {
4538 case TRI_NO:
4539 active = FALSE;
4540 certain = TRUE;
4541 break;
4542 case TRI_YES:
4543 break;
4544 case TRI_MAYBE:
4545 certain = FALSE;
4546 if (maybe_reqs) {
4547 requirement_vector_append(maybe_reqs, *preq);
4548 }
4549 break;
4550 default:
4552 active = FALSE;
4553 }
4554 if (!active) {
4555 break;
4556 }
4558
4559 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
4560}
4561
4562/**********************************************************************/
4571 is_req_unchanging(const struct req_context *context,
4572 const struct requirement *req)
4573{
4574 enum req_unchanging_status s;
4575 const struct civ_map *nmap = &(wld.map);
4576
4578 fc_assert_ret_val_msg(universals_n_is_valid(req->source.kind), REQUCH_NO,
4579 "Invalid source kind %d.", req->source.kind);
4581
4582 if (req->survives) {
4583 /* Special case for surviving requirements */
4584 /* Buildings may obsolete even here */
4585 if (VUT_IMPROVEMENT == req->source.kind) {
4586 const struct impr_type *b = req->source.value.building;
4587
4589 if (improvement_obsolete(context->player, b, context->city)) {
4590 /* FIXME: sometimes can unobsolete, but considering it
4591 * may sometimes put the function on endless recursion */
4592 return REQUCH_ACT; /* Mostly about techs */
4593 } else {
4594 /* NOTE: may obsoletion reqs be unchanging? Hardly but why not. */
4595 return REQUCH_NO;
4596 }
4597 }
4598 }
4599 s = unchanging_present(nmap, s, context, req);
4600 if (s != REQUCH_NO) {
4601 return unchanging_noally(nmap, s, context, req);
4602 }
4603 } else {
4606
4607 if (cond) {
4608 return cond(nmap, s, context, req);
4609 }
4610 }
4611
4612 return s;
4613}
4614
4615/**********************************************************************/
4619 is_req_preventing(const struct req_context *context,
4620 const struct player *other_player,
4621 const struct requirement *req,
4622 enum req_problem_type prob_type)
4623{
4624 enum req_unchanging_status u = is_req_unchanging(context, req);
4625
4626 if (REQUCH_NO != u) {
4627 /* presence is precalculated */
4628 bool auto_present
4629 = (req->survives
4630 && !(VUT_IMPROVEMENT == req->source.kind
4634
4635 if (auto_present ? req->present
4636 : is_req_active(context, other_player, req, prob_type)) {
4637 /* Unchanging but does not block */
4638 return REQUCH_NO;
4639 }
4640 }
4641
4642 return u;
4643}
4644
4645/**********************************************************************/
4649bool is_req_in_vec(const struct requirement *req,
4650 const struct requirement_vector *vec)
4651{
4652 requirement_vector_iterate(vec, preq) {
4653 if (are_requirements_equal(req, preq)) {
4654 return TRUE;
4655 }
4657
4658 return FALSE;
4659}
4660
4661/**********************************************************************/
4667bool req_vec_wants_type(const struct requirement_vector *reqs,
4668 enum universals_n kind)
4669{
4671 if (preq->present && preq->source.kind == kind) {
4672 return TRUE;
4673 }
4675 return FALSE;
4676}
4677
4678/**********************************************************************/
4686{
4687 switch (source->kind) {
4688 case VUT_ACTION:
4689 return !action_is_in_use(source->value.action);
4690 case VUT_UTFLAG:
4691 return !utype_flag_is_in_use(source->value.unitflag);
4692 case VUT_UCFLAG:
4693 return !uclass_flag_is_in_use(source->value.unitclassflag);
4694 case VUT_EXTRAFLAG:
4695 return !extra_flag_is_in_use(source->value.extraflag);
4696 case VUT_OTYPE:
4697 case VUT_SPECIALIST:
4698 case VUT_AI_LEVEL:
4699 case VUT_CITYTILE:
4700 case VUT_CITYSTATUS:
4701 case VUT_STYLE:
4702 case VUT_TOPO:
4703 case VUT_SERVERSETTING:
4704 case VUT_NATION:
4705 case VUT_NATIONGROUP:
4706 case VUT_ADVANCE:
4707 case VUT_TECHFLAG:
4708 case VUT_GOVERNMENT:
4709 case VUT_ACHIEVEMENT:
4710 case VUT_IMPROVEMENT:
4711 case VUT_IMPR_GENUS:
4712 case VUT_MINSIZE:
4713 case VUT_MINCULTURE:
4714 case VUT_MINFOREIGNPCT:
4715 case VUT_MINTECHS:
4716 case VUT_NATIONALITY:
4717 case VUT_DIPLREL:
4718 case VUT_DIPLREL_TILE:
4719 case VUT_DIPLREL_TILE_O:
4720 case VUT_DIPLREL_UNITANY:
4721 case VUT_DIPLREL_UNITANY_O:
4722 case VUT_MAXTILEUNITS:
4723 case VUT_UTYPE:
4724 case VUT_UCLASS:
4725 case VUT_MINVETERAN:
4726 case VUT_UNITSTATE:
4727 case VUT_ACTIVITY:
4728 case VUT_MINMOVES:
4729 case VUT_MINHP:
4730 case VUT_AGE:
4731 case VUT_ROADFLAG:
4732 case VUT_MINCALFRAG:
4733 case VUT_TERRAIN:
4734 case VUT_EXTRA:
4735 case VUT_GOOD:
4736 case VUT_TERRAINCLASS:
4737 case VUT_TERRFLAG:
4738 case VUT_TERRAINALTER:
4739 case VUT_MINYEAR:
4740 case VUT_NONE:
4741 case VUT_COUNT:
4742 /* Not implemented. */
4743 break;
4744 }
4745
4746 return FALSE;
4747}
4748
4749/**********************************************************************/
4757{
4758 /* Not known to be impossible to fulfill */
4759 return req->present && universal_never_there(&req->source);
4760}
4761
4762/**********************************************************************/
4769bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
4770{
4772 if (req_is_impossible_to_fulfill(preq)) {
4773 return TRUE;
4774 }
4776
4777 /* Not known to be impossible to fulfill */
4778 return FALSE;
4779}
4780
4781/**********************************************************************/
4789req_vec_vector_number(const void *parent_item,
4790 const struct requirement_vector *vec)
4791{
4792 if (vec) {
4793 return 0;
4794 } else {
4795 return -1;
4796 }
4797}
4798
4799/********************************************************************/
4807struct requirement_vector *
4808req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
4809{
4810 fc_assert_ret_val(number == 0, NULL);
4811 return (struct requirement_vector *)parent_item;
4812}
4813
4814/**********************************************************************/
4824const char *req_vec_change_translation(const struct req_vec_change *change,
4825 const requirement_vector_namer namer)
4826{
4827 const char *req_vec_description;
4828 static char buf[MAX_LEN_NAME * 3];
4829 struct astring astr;
4830
4831 fc_assert_ret_val(change, NULL);
4832 fc_assert_ret_val(req_vec_change_operation_is_valid(change->operation),
4833 NULL);
4834
4835 /* Get rid of the previous. */
4836 buf[0] = '\0';
4837
4838 if (namer == NULL) {
4839 /* TRANS: default description of a requirement vector
4840 * (used in ruledit) */
4841 req_vec_description = _("the requirement vector");
4842 } else {
4843 req_vec_description = namer(change->vector_number);
4844 }
4845
4846 switch (change->operation) {
4847 case RVCO_REMOVE:
4848 fc_snprintf(buf, sizeof(buf),
4849 /* TRANS: remove a requirement from a requirement vector
4850 * (in ruledit).
4851 * The first %s is the operation.
4852 * The second %s is the requirement.
4853 * The third %s is a description of the requirement vector,
4854 * like "actor_reqs" */
4855 _("%s %s from %s"),
4856 req_vec_change_operation_name(change->operation),
4857 req_to_fstring(&change->req, &astr),
4858 req_vec_description);
4859 astr_free(&astr);
4860 break;
4861 case RVCO_APPEND:
4862 fc_snprintf(buf, sizeof(buf),
4863 /* TRANS: append a requirement to a requirement vector
4864 * (in ruledit).
4865 * The first %s is the operation.
4866 * The second %s is the requirement.
4867 * The third %s is a description of the requirement vector,
4868 * like "actor_reqs" */
4869 _("%s %s to %s"),
4870 req_vec_change_operation_name(change->operation),
4871 req_to_fstring(&change->req, &astr),
4872 req_vec_description);
4873 astr_free(&astr);
4874 break;
4875 case RVCO_NOOP:
4876 fc_snprintf(buf, sizeof(buf),
4877 /* TRANS: do nothing to a requirement vector (in ruledit).
4878 * The first %s is a description of the requirement vector,
4879 * like "actor_reqs" */
4880 _("Do nothing to %s"), req_vec_description);
4881 break;
4882 }
4883
4884 return buf;
4885}
4886
4887/**********************************************************************/
4897bool req_vec_change_apply(const struct req_vec_change *modification,
4899 const void *parent_item)
4900{
4901 struct requirement_vector *target
4902 = getter(parent_item, modification->vector_number);
4903 int i = 0;
4904
4905 switch (modification->operation) {
4906 case RVCO_APPEND:
4907 requirement_vector_append(target, modification->req);
4908 return TRUE;
4909 case RVCO_REMOVE:
4910 requirement_vector_iterate(target, preq) {
4911 if (are_requirements_equal(&modification->req, preq)) {
4912 requirement_vector_remove(target, i);
4913 return TRUE;
4914 }
4915 i++;
4917 return FALSE;
4918 case RVCO_NOOP:
4919 return FALSE;
4920 }
4921
4922 return FALSE;
4923}
4924
4925/**********************************************************************/
4934struct req_vec_problem *
4936 const char *description,
4937 const char *description_translated)
4938{
4939 struct req_vec_problem *out;
4940 int i;
4941
4942 out = fc_malloc(sizeof(*out));
4943
4944 fc_strlcpy(out->description, description, sizeof(out->description));
4946 sizeof(out->description_translated));
4947
4950 * sizeof(struct req_vec_change));
4951 for (i = 0; i < out->num_suggested_solutions; i++) {
4952 /* No suggestions are ready yet. */
4953 out->suggested_solutions[i].operation = RVCO_NOOP;
4955 out->suggested_solutions[i].req.source.kind = VUT_NONE;
4956 }
4957
4958 return out;
4959}
4960
4961/**********************************************************************/
4970 const char *descr, ...)
4971{
4972 char description[500];
4973 char description_translated[500];
4974 va_list ap;
4975
4976 va_start(ap, descr);
4977 fc_vsnprintf(description, sizeof(description), descr, ap);
4978 va_end(ap);
4979
4980 va_start(ap, descr);
4982 _(descr), ap);
4983 va_end(ap);
4984
4987}
4988
4989/**********************************************************************/
4995{
4997 issue->num_suggested_solutions = 0;
4998
4999 FC_FREE(issue);
5000}
5001
5002/**********************************************************************/
5013struct req_vec_problem *
5014req_vec_get_first_contradiction(const struct requirement_vector *vec,
5016 const void *parent_item)
5017{
5018 int i, j;
5019 req_vec_num_in_item vec_num;
5020
5021 if (vec == NULL || requirement_vector_size(vec) == 0) {
5022 /* No vector. */
5023 return NULL;
5024 }
5025
5026 if (get_num == NULL || parent_item == NULL) {
5027 vec_num = 0;
5028 } else {
5029 vec_num = get_num(parent_item, vec);
5030 }
5031
5032 /* Look for contradictions */
5033 for (i = 0; i < requirement_vector_size(vec); i++) {
5034 struct requirement *preq = requirement_vector_get(vec, i);
5035 for (j = 0; j < requirement_vector_size(vec); j++) {
5036 struct requirement *nreq = requirement_vector_get(vec, j);
5037
5038 if (are_requirements_contradictions(preq, nreq)) {
5039 struct req_vec_problem *problem;
5040 struct astring astr;
5041 struct astring nastr;
5042
5043 problem = req_vec_problem_new(2,
5044 N_("Requirements {%s} and {%s} contradict each other."),
5045 req_to_fstring(preq, &astr), req_to_fstring(nreq, &nastr));
5046
5047 astr_free(&astr);
5048 astr_free(&nastr);
5049
5050 /* The solution is to remove one of the contradictions. */
5051 problem->suggested_solutions[0].operation = RVCO_REMOVE;
5052 problem->suggested_solutions[0].vector_number = vec_num;
5053 problem->suggested_solutions[0].req = *preq;
5054
5055 problem->suggested_solutions[1].operation = RVCO_REMOVE;
5056 problem->suggested_solutions[1].vector_number = vec_num;
5057 problem->suggested_solutions[1].req = *nreq;
5058
5059 /* Only the first contradiction is reported. */
5060 return problem;
5061 }
5062 }
5063 }
5064
5065 return NULL;
5066}
5067
5068/**********************************************************************/
5078struct req_vec_problem *
5079req_vec_suggest_repair(const struct requirement_vector *vec,
5081 const void *parent_item)
5082{
5083 /* Check for self contradictins. */
5084 return req_vec_get_first_contradiction(vec, get_num, parent_item);
5085}
5086
5087/**********************************************************************/
5099struct req_vec_problem *
5100req_vec_get_first_missing_univ(const struct requirement_vector *vec,
5102 const void *parent_item)
5103{
5104 int i;
5105 req_vec_num_in_item vec_num;
5106 struct req_vec_problem *problem = NULL;
5107
5108 if (vec == NULL || requirement_vector_size(vec) == 0) {
5109 /* No vector. */
5110 return NULL;
5111 }
5112
5113 if (get_num == NULL || parent_item == NULL) {
5114 vec_num = 0;
5115 } else {
5116 vec_num = get_num(parent_item, vec);
5117 }
5118
5119 /* Look for contradictions */
5120 for (i = 0; i < requirement_vector_size(vec); i++) {
5121 struct requirement *preq = requirement_vector_get(vec, i);
5122
5123 if (universal_never_there(&preq->source)) {
5124 struct astring astr;
5125
5126 if (preq->present) {
5127 /* The requirement vector can never be fulfilled. Removing the
5128 * requirement makes it possible to fulfill it. This is a rule
5129 * change and shouldn't be "fixed" without thinking. Don't offer any
5130 * automatic solution to prevent mindless "fixes". */
5131 /* TRANS: ruledit warns a user about an unused requirement vector
5132 * that never can be fulfilled because it asks for something that
5133 * never will be there. */
5134 if (problem == NULL) {
5135 problem = req_vec_problem_new(0,
5136 N_("Requirement {%s} requires %s but it will never be"
5137 " there."),
5138 req_to_fstring(preq, &astr), universal_rule_name(&preq->source));
5139 astr_free(&astr);
5140 }
5141
5142 /* Continue to check if other problems have a solution proposal,
5143 * and prefer to return those. */
5144 continue;
5145 }
5146
5147 if (problem != NULL) {
5148 /* Free previous one (one with no solution proposals) */
5149 req_vec_problem_free(problem);
5150 }
5151
5152 problem = req_vec_problem_new(1,
5153 N_("Requirement {%s} mentions %s but it will never be there."),
5154 req_to_fstring(preq, &astr), universal_rule_name(&preq->source));
5155
5156 astr_free(&astr);
5157
5158 /* The solution is to remove the reference to the missing
5159 * universal. */
5160 problem->suggested_solutions[0].operation = RVCO_REMOVE;
5161 problem->suggested_solutions[0].vector_number = vec_num;
5162 problem->suggested_solutions[0].req = *preq;
5163
5164 /* Only the first missing universal is reported. */
5165 return problem;
5166 }
5167 }
5168
5169 return problem;
5170}
5171
5172/**********************************************************************/
5184struct req_vec_problem *
5185req_vec_get_first_redundant_req(const struct requirement_vector *vec,
5187 const void *parent_item)
5188{
5189 int i, j;
5190 req_vec_num_in_item vec_num;
5191
5192 if (vec == NULL || requirement_vector_size(vec) == 0) {
5193 /* No vector. */
5194 return NULL;
5195 }
5196
5197 if (get_num == NULL || parent_item == NULL) {
5198 vec_num = 0;
5199 } else {
5200 vec_num = get_num(parent_item, vec);
5201 }
5202
5203 /* Look for repeated requirements */
5204 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
5205 struct requirement *preq = requirement_vector_get(vec, i);
5206 for (j = i + 1; j < requirement_vector_size(vec); j++) {
5207 struct requirement *nreq = requirement_vector_get(vec, j);
5208
5209 if (are_requirements_equal(preq, nreq)) {
5210 struct req_vec_problem *problem;
5211 struct astring astr;
5212 struct astring nastr;
5213
5214 problem = req_vec_problem_new(2,
5215 N_("Requirements {%s} and {%s} are the same."),
5216 req_to_fstring(preq, &astr), req_to_fstring(nreq, &nastr));
5217
5218 astr_free(&astr);
5219 astr_free(&nastr);
5220
5221 /* The solution is to remove one of the redundant requirements. */
5222 problem->suggested_solutions[0].operation = RVCO_REMOVE;
5223 problem->suggested_solutions[0].vector_number = vec_num;
5224 problem->suggested_solutions[0].req = *preq;
5225
5226 problem->suggested_solutions[1].operation = RVCO_REMOVE;
5227 problem->suggested_solutions[1].vector_number = vec_num;
5228 problem->suggested_solutions[1].req = *nreq;
5229
5230 /* Only the first redundancy is reported. */
5231 return problem;
5232 }
5233 }
5234 }
5235
5236 return NULL;
5237}
5238
5239/**********************************************************************/
5250struct req_vec_problem *
5251req_vec_suggest_improvement(const struct requirement_vector *vec,
5253 const void *parent_item)
5254{
5255 struct req_vec_problem *out;
5256
5257 out = req_vec_suggest_repair(vec, get_num, parent_item);
5258 if (out != NULL) {
5259 /* A bug, not just a potential improvement */
5260 return out;
5261 }
5262
5263 /* Check if a universal that never will appear in the game is checked. */
5264 out = req_vec_get_first_missing_univ(vec, get_num, parent_item);
5265 if (out != NULL) {
5266 return out;
5267 }
5268
5269 /* Check if a requirement is redundant. */
5270 out = req_vec_get_first_redundant_req(vec, get_num, parent_item);
5271 return out;
5272}
5273
5274/**********************************************************************/
5278bool are_universals_equal(const struct universal *psource1,
5279 const struct universal *psource2)
5280{
5281 if (psource1->kind != psource2->kind) {
5282 return FALSE;
5283 }
5284 switch (psource1->kind) {
5285 case VUT_NONE:
5286 return TRUE;
5287 case VUT_ADVANCE:
5288 return psource1->value.advance == psource2->value.advance;
5289 case VUT_TECHFLAG:
5290 return psource1->value.techflag == psource2->value.techflag;
5291 case VUT_GOVERNMENT:
5292 return psource1->value.govern == psource2->value.govern;
5293 case VUT_ACHIEVEMENT:
5294 return psource1->value.achievement == psource2->value.achievement;
5295 case VUT_STYLE:
5296 return psource1->value.style == psource2->value.style;
5297 case VUT_IMPROVEMENT:
5298 return psource1->value.building == psource2->value.building;
5299 case VUT_IMPR_GENUS:
5300 return psource1->value.impr_genus == psource2->value.impr_genus;
5301 case VUT_EXTRA:
5302 return psource1->value.extra == psource2->value.extra;
5303 case VUT_GOOD:
5304 return psource1->value.good == psource2->value.good;
5305 case VUT_TERRAIN:
5306 return psource1->value.terrain == psource2->value.terrain;
5307 case VUT_TERRFLAG:
5308 return psource1->value.terrainflag == psource2->value.terrainflag;
5309 case VUT_NATION:
5310 return psource1->value.nation == psource2->value.nation;
5311 case VUT_NATIONGROUP:
5312 return psource1->value.nationgroup == psource2->value.nationgroup;
5313 case VUT_NATIONALITY:
5314 return psource1->value.nationality == psource2->value.nationality;
5315 case VUT_DIPLREL:
5316 case VUT_DIPLREL_TILE:
5317 case VUT_DIPLREL_TILE_O:
5318 case VUT_DIPLREL_UNITANY:
5319 case VUT_DIPLREL_UNITANY_O:
5320 return psource1->value.diplrel == psource2->value.diplrel;
5321 case VUT_UTYPE:
5322 return psource1->value.utype == psource2->value.utype;
5323 case VUT_UTFLAG:
5324 return psource1->value.unitflag == psource2->value.unitflag;
5325 case VUT_UCLASS:
5326 return psource1->value.uclass == psource2->value.uclass;
5327 case VUT_UCFLAG:
5328 return psource1->value.unitclassflag == psource2->value.unitclassflag;
5329 case VUT_MINVETERAN:
5330 return psource1->value.minveteran == psource2->value.minveteran;
5331 case VUT_UNITSTATE:
5332 return psource1->value.unit_state == psource2->value.unit_state;
5333 case VUT_ACTIVITY:
5334 return psource1->value.activity == psource2->value.activity;
5335 case VUT_MINMOVES:
5336 return psource1->value.minmoves == psource2->value.minmoves;
5337 case VUT_MINHP:
5338 return psource1->value.min_hit_points == psource2->value.min_hit_points;
5339 case VUT_AGE:
5340 return psource1->value.age == psource2->value.age;
5341 case VUT_MINTECHS:
5342 return psource1->value.min_techs == psource2->value.min_techs;
5343 case VUT_ACTION:
5344 return (action_number(psource1->value.action)
5345 == action_number(psource2->value.action));
5346 case VUT_OTYPE:
5347 return psource1->value.outputtype == psource2->value.outputtype;
5348 case VUT_SPECIALIST:
5349 return psource1->value.specialist == psource2->value.specialist;
5350 case VUT_MINSIZE:
5351 return psource1->value.minsize == psource2->value.minsize;
5352 case VUT_MINCULTURE:
5353 return psource1->value.minculture == psource2->value.minculture;
5354 case VUT_MINFOREIGNPCT:
5355 return psource1->value.minforeignpct == psource2->value.minforeignpct;
5356 case VUT_AI_LEVEL:
5357 return psource1->value.ai_level == psource2->value.ai_level;
5358 case VUT_MAXTILEUNITS:
5359 return psource1->value.max_tile_units == psource2->value.max_tile_units;
5360 case VUT_TERRAINCLASS:
5361 return psource1->value.terrainclass == psource2->value.terrainclass;
5362 case VUT_ROADFLAG:
5363 return psource1->value.roadflag == psource2->value.roadflag;
5364 case VUT_EXTRAFLAG:
5365 return psource1->value.extraflag == psource2->value.extraflag;
5366 case VUT_MINYEAR:
5367 return psource1->value.minyear == psource2->value.minyear;
5368 case VUT_MINCALFRAG:
5369 return psource1->value.mincalfrag == psource2->value.mincalfrag;
5370 case VUT_TOPO:
5371 return psource1->value.topo_property == psource2->value.topo_property;
5372 case VUT_SERVERSETTING:
5373 return psource1->value.ssetval == psource2->value.ssetval;
5374 case VUT_TERRAINALTER:
5375 return psource1->value.terrainalter == psource2->value.terrainalter;
5376 case VUT_CITYTILE:
5377 return psource1->value.citytile == psource2->value.citytile;
5378 case VUT_CITYSTATUS:
5379 return psource1->value.citystatus == psource2->value.citystatus;
5380 case VUT_COUNT:
5381 break;
5382 }
5383
5384 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
5385 return FALSE;
5386}
5387
5388/**********************************************************************/
5392const char *universal_rule_name(const struct universal *psource)
5393{
5394 static char buffer[10];
5395
5396 switch (psource->kind) {
5397 case VUT_NONE:
5398 return "(none)";
5399 case VUT_CITYTILE:
5400 return citytile_type_name(psource->value.citytile);
5401 case VUT_CITYSTATUS:
5402 return citystatus_type_name(psource->value.citystatus);
5403 case VUT_MINYEAR:
5404 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
5405
5406 return buffer;
5407 case VUT_MINCALFRAG:
5408 /* Rule name is 0-based number, not pretty name from ruleset */
5409 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
5410
5411 return buffer;
5412 case VUT_TOPO:
5413 return topo_flag_name(psource->value.topo_property);
5414 case VUT_SERVERSETTING:
5415 return ssetv_rule_name(psource->value.ssetval);
5416 case VUT_ADVANCE:
5417 return advance_rule_name(psource->value.advance);
5418 case VUT_TECHFLAG:
5419 return tech_flag_id_name(psource->value.techflag);
5420 case VUT_GOVERNMENT:
5421 return government_rule_name(psource->value.govern);
5422 case VUT_ACHIEVEMENT:
5423 return achievement_rule_name(psource->value.achievement);
5424 case VUT_STYLE:
5425 return style_rule_name(psource->value.style);
5426 case VUT_IMPROVEMENT:
5427 return improvement_rule_name(psource->value.building);
5428 case VUT_IMPR_GENUS:
5429 return impr_genus_id_name(psource->value.impr_genus);
5430 case VUT_EXTRA:
5431 return extra_rule_name(psource->value.extra);
5432 case VUT_GOOD:
5433 return goods_rule_name(psource->value.good);
5434 case VUT_TERRAIN:
5435 return terrain_rule_name(psource->value.terrain);
5436 case VUT_TERRFLAG:
5437 return terrain_flag_id_name(psource->value.terrainflag);
5438 case VUT_NATION:
5439 return nation_rule_name(psource->value.nation);
5440 case VUT_NATIONGROUP:
5441 return nation_group_rule_name(psource->value.nationgroup);
5442 case VUT_DIPLREL:
5443 case VUT_DIPLREL_TILE:
5444 case VUT_DIPLREL_TILE_O:
5445 case VUT_DIPLREL_UNITANY:
5446 case VUT_DIPLREL_UNITANY_O:
5447 return diplrel_rule_name(psource->value.diplrel);
5448 case VUT_NATIONALITY:
5449 return nation_rule_name(psource->value.nationality);
5450 case VUT_UTYPE:
5451 return utype_rule_name(psource->value.utype);
5452 case VUT_UTFLAG:
5453 return unit_type_flag_id_name(psource->value.unitflag);
5454 case VUT_UCLASS:
5455 return uclass_rule_name(psource->value.uclass);
5456 case VUT_UCFLAG:
5457 return unit_class_flag_id_name(psource->value.unitclassflag);
5458 case VUT_MINVETERAN:
5459 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
5460
5461 return buffer;
5462 case VUT_UNITSTATE:
5463 return ustate_prop_name(psource->value.unit_state);
5464 case VUT_ACTIVITY:
5465 return unit_activity_name(psource->value.activity);
5466 case VUT_MINMOVES:
5467 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
5468
5469 return buffer;
5470 case VUT_MINHP:
5471 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
5472
5473 return buffer;
5474 case VUT_AGE:
5475 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
5476
5477 return buffer;
5478 case VUT_MINTECHS:
5479 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
5480
5481 return buffer;
5482 case VUT_ACTION:
5483 return action_rule_name(psource->value.action);
5484 case VUT_OTYPE:
5485 return get_output_identifier(psource->value.outputtype);
5486 case VUT_SPECIALIST:
5487 return specialist_rule_name(psource->value.specialist);
5488 case VUT_MINSIZE:
5489 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
5490
5491 return buffer;
5492 case VUT_MINCULTURE:
5493 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
5494
5495 return buffer;
5496 case VUT_MINFOREIGNPCT:
5497 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
5498
5499 return buffer;
5500 case VUT_AI_LEVEL:
5501 return ai_level_name(psource->value.ai_level);
5502 case VUT_MAXTILEUNITS:
5503 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_units);
5504 return buffer;
5505 case VUT_TERRAINCLASS:
5506 return terrain_class_name(psource->value.terrainclass);
5507 case VUT_ROADFLAG:
5508 return road_flag_id_name(psource->value.roadflag);
5509 case VUT_EXTRAFLAG:
5510 return extra_flag_id_name(psource->value.extraflag);
5511 case VUT_TERRAINALTER:
5512 return terrain_alteration_name(psource->value.terrainalter);
5513 case VUT_COUNT:
5514 break;
5515 }
5516
5517 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
5518 return NULL;
5519}
5520
5521/**********************************************************************/
5529const char *universal_name_translation(const struct universal *psource,
5530 char *buf, size_t bufsz)
5531{
5532 buf[0] = '\0'; /* to be safe. */
5533 switch (psource->kind) {
5534 case VUT_NONE:
5535 /* TRANS: missing value */
5536 fc_strlcat(buf, _("(none)"), bufsz);
5537 return buf;
5538 case VUT_ADVANCE:
5540 return buf;
5541 case VUT_TECHFLAG:
5542 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
5543 tech_flag_id_translated_name(psource->value.techflag));
5544 return buf;
5545 case VUT_GOVERNMENT:
5547 bufsz);
5548 return buf;
5549 case VUT_ACHIEVEMENT:
5551 bufsz);
5552 return buf;
5553 case VUT_STYLE:
5555 bufsz);
5556 return buf;
5557 case VUT_IMPROVEMENT:
5559 bufsz);
5560 return buf;
5561 case VUT_IMPR_GENUS:
5562 fc_strlcat(buf,
5563 impr_genus_id_translated_name(psource->value.impr_genus),
5564 bufsz);
5565 return buf;
5566 case VUT_EXTRA:
5568 return buf;
5569 case VUT_GOOD:
5571 return buf;
5572 case VUT_TERRAIN:
5574 return buf;
5575 case VUT_NATION:
5577 bufsz);
5578 return buf;
5579 case VUT_NATIONGROUP:
5581 bufsz);
5582 return buf;
5583 case VUT_NATIONALITY:
5584 cat_snprintf(buf, bufsz, _("%s citizens"),
5586 return buf;
5587 case VUT_DIPLREL:
5588 case VUT_DIPLREL_TILE:
5589 case VUT_DIPLREL_TILE_O:
5590 case VUT_DIPLREL_UNITANY:
5591 case VUT_DIPLREL_UNITANY_O:
5593 bufsz);
5594 return buf;
5595 case VUT_UTYPE:
5597 return buf;
5598 case VUT_UTFLAG:
5599 cat_snprintf(buf, bufsz,
5600 /* TRANS: Unit type flag */
5601 Q_("?utflag:\"%s\" units"),
5602 unit_type_flag_id_translated_name(
5603 psource->value.unitflag));
5604 return buf;
5605 case VUT_UCLASS:
5606 cat_snprintf(buf, bufsz,
5607 /* TRANS: Unit class */
5608 _("%s units"),
5610 return buf;
5611 case VUT_UCFLAG:
5612 cat_snprintf(buf, bufsz,
5613 /* TRANS: Unit class flag */
5614 Q_("?ucflag:\"%s\" units"),
5615 unit_class_flag_id_translated_name(
5616 psource->value.unitclassflag));
5617 return buf;
5618 case VUT_MINVETERAN:
5619 /* FIXME */
5620 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
5621 psource->value.minveteran);
5622 return buf;
5623 case VUT_UNITSTATE:
5624 switch (psource->value.unit_state) {
5625 case USP_TRANSPORTED:
5626 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
5627 cat_snprintf(buf, bufsz, _("Transported"));
5628 break;
5629 case USP_LIVABLE_TILE:
5630 cat_snprintf(buf, bufsz,
5631 /* TRANS: unit state. (appears in strings like
5632 * "Missile+On livable tile") */
5633 _("On livable tile"));
5634 break;
5635 case USP_TRANSPORTING:
5636 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
5637 cat_snprintf(buf, bufsz, _("Transporting"));
5638 break;
5639 case USP_HAS_HOME_CITY:
5640 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
5641 cat_snprintf(buf, bufsz, _("Has a home city"));
5642 break;
5643 case USP_NATIVE_TILE:
5644 cat_snprintf(buf, bufsz,
5645 /* TRANS: unit state. (appears in strings like
5646 * "Missile+On native tile") */
5647 _("On native tile"));
5648 break;
5649 case USP_NATIVE_EXTRA:
5650 cat_snprintf(buf, bufsz,
5651 /* TRANS: unit state. (appears in strings like
5652 * "Missile+In native extra") */
5653 _("In native extra"));
5654 break;
5655 case USP_MOVED_THIS_TURN:
5656 /* TRANS: unit state. (appears in strings like
5657 * "Missile+Has moved this turn") */
5658 cat_snprintf(buf, bufsz, _("Has moved this turn"));
5659 break;
5660 case USP_COUNT:
5661 fc_assert_msg(psource->value.unit_state != USP_COUNT,
5662 "Invalid unit state property.");
5663 break;
5664 }
5665 return buf;
5666 case VUT_ACTIVITY:
5667 cat_snprintf(buf, bufsz, _("%s activity"),
5668 Q_(unit_activity_name(psource->value.activity)));
5669 return buf;
5670 case VUT_MINMOVES:
5671 /* TRANS: Minimum unit movement points left for requirement to be met
5672 * (%s is a string like "1" or "2 1/3") */
5673 cat_snprintf(buf, bufsz, _("%s MP"),
5674 move_points_text(psource->value.minmoves, TRUE));
5675 return buf;
5676 case VUT_MINHP:
5677 /* TRANS: HP = hit points */
5678 cat_snprintf(buf, bufsz, _("%d HP"),
5679 psource->value.min_hit_points);
5680 return buf;
5681 case VUT_AGE:
5682 cat_snprintf(buf, bufsz, _("Age %d"),
5683 psource->value.age);
5684 return buf;
5685 case VUT_MINTECHS:
5686 cat_snprintf(buf, bufsz, _("%d Techs"),
5687 psource->value.min_techs);
5688 return buf;
5689 case VUT_ACTION:
5691 bufsz);
5692 return buf;
5693 case VUT_OTYPE:
5694 /* FIXME */
5696 return buf;
5697 case VUT_SPECIALIST:
5699 bufsz);
5700 return buf;
5701 case VUT_MINSIZE:
5702 cat_snprintf(buf, bufsz, _("Size %d"),
5703 psource->value.minsize);
5704 return buf;
5705 case VUT_MINCULTURE:
5706 cat_snprintf(buf, bufsz, _("Culture %d"),
5707 psource->value.minculture);
5708 return buf;
5709 case VUT_MINFOREIGNPCT:
5710 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
5711 psource->value.minforeignpct);
5712 return buf;
5713 case VUT_AI_LEVEL:
5714 /* TRANS: "Hard AI" */
5715 cat_snprintf(buf, bufsz, _("%s AI"),
5716 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
5717 return buf;
5718 case VUT_MAXTILEUNITS:
5719 /* TRANS: here <= means 'less than or equal' */
5720 cat_snprintf(buf, bufsz, PL_("<=%d unit",
5721 "<=%d units", psource->value.max_tile_units),
5722 psource->value.max_tile_units);
5723 return buf;
5724 case VUT_TERRAINCLASS:
5725 /* TRANS: Terrain class: "Land terrain" */
5726 cat_snprintf(buf, bufsz, _("%s terrain"),
5728 return buf;
5729 case VUT_TERRFLAG:
5730 cat_snprintf(buf, bufsz,
5731 /* TRANS: Terrain flag */
5732 Q_("?terrflag:\"%s\" terrain"),
5733 terrain_flag_id_translated_name(
5734 psource->value.terrainflag));
5735 return buf;
5736 case VUT_ROADFLAG:
5737 cat_snprintf(buf, bufsz,
5738 /* TRANS: Road flag */
5739 Q_("?roadflag:\"%s\" road"),
5740 road_flag_id_translated_name(psource->value.roadflag));
5741 return buf;
5742 case VUT_EXTRAFLAG:
5743 cat_snprintf(buf, bufsz,
5744 /* TRANS: Extra flag */
5745 Q_("?extraflag:\"%s\" extra"),
5746 extra_flag_id_translated_name(psource->value.extraflag));
5747 return buf;
5748 case VUT_MINYEAR:
5749 cat_snprintf(buf, bufsz, _("After %s"),
5750 textyear(psource->value.minyear));
5751 return buf;
5752 case VUT_MINCALFRAG:
5753 /* TRANS: here >= means 'greater than or equal'.
5754 * %s identifies a calendar fragment (may be bare number). */
5755 cat_snprintf(buf, bufsz, _(">=%s"),
5756 textcalfrag(psource->value.mincalfrag));
5757 return buf;
5758 case VUT_TOPO:
5759 /* TRANS: topology flag name ("WrapX", "ISO", etc) */
5760 cat_snprintf(buf, bufsz, _("%s map"),
5761 _(topo_flag_name(psource->value.topo_property)));
5762 return buf;
5763 case VUT_SERVERSETTING:
5765 bufsz);
5766 return buf;
5767 case VUT_TERRAINALTER:
5768 /* TRANS: "Irrigation possible" */
5769 cat_snprintf(buf, bufsz, _("%s possible"),
5770 Q_(terrain_alteration_name(psource->value.terrainalter)));
5771 return buf;
5772 case VUT_CITYTILE:
5773 switch (psource->value.citytile) {
5774 case CITYT_CENTER:
5775 fc_strlcat(buf, _("City center"), bufsz);
5776 break;
5777 case CITYT_CLAIMED:
5778 fc_strlcat(buf, _("Tile claimed"), bufsz);
5779 break;
5780 case CITYT_EXTRAS_OWNED:
5781 fc_strlcat(buf, _("Extras owned"), bufsz);
5782 break;
5783 case CITYT_LAST:
5784 fc_assert(psource->value.citytile != CITYT_LAST);
5785 fc_strlcat(buf, "error", bufsz);
5786 break;
5787 }
5788 return buf;
5789 case VUT_CITYSTATUS:
5790 switch (psource->value.citystatus) {
5791 case CITYS_OWNED_BY_ORIGINAL:
5792 fc_strlcat(buf, _("Owned by original"), bufsz);
5793 break;
5794 case CITYS_LAST:
5795 fc_assert(psource->value.citystatus != CITYS_LAST);
5796 fc_strlcat(buf, "error", bufsz);
5797 break;
5798 }
5799 return buf;
5800 case VUT_COUNT:
5801 break;
5802 }
5803
5804 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
5805 return buf;
5806}
5807
5808/**********************************************************************/
5811const char *universal_type_rule_name(const struct universal *psource)
5812{
5813 return universals_n_name(psource->kind);
5814}
5815
5816/**********************************************************************/
5819int universal_build_shield_cost(const struct city *pcity,
5820 const struct universal *target)
5821{
5822 switch (target->kind) {
5823 case VUT_IMPROVEMENT:
5824 return impr_build_shield_cost(pcity, target->value.building);
5825 case VUT_UTYPE:
5826 return utype_build_shield_cost(pcity, NULL, target->value.utype);
5827 default:
5828 break;
5829 }
5830 return FC_INFINITY;
5831}
5832
5833/**********************************************************************/
5838bool universal_replace_in_req_vec(struct requirement_vector *reqs,
5839 const struct universal *to_replace,
5840 const struct universal *replacement)
5841{
5842 bool changed = FALSE;
5843
5845 if (universal_is_mentioned_by_requirement(preq, to_replace)) {
5846 preq->source = *replacement;
5847 changed = TRUE;
5848 }
5850
5851 return changed;
5852}
5853
5854/**********************************************************************/
5859 const struct requirement_vector *reqs,
5860 const struct universal *psource)
5861{
5863 if (universal_is_mentioned_by_requirement(preq, psource)) {
5864 return TRUE;
5865 }
5867
5868 return FALSE;
5869}
5870
5871/**********************************************************************/
5880bool universals_mean_unfulfilled(struct requirement_vector *reqs,
5881 struct universal *unis,
5882 size_t n_unis)
5883{
5884 int i;
5885
5886 for (i = 0; i < n_unis; i++) {
5887 if (!universal_fulfills_requirements(FALSE, reqs, &unis[i])) {
5888 /* This universal makes it impossible to fulfill the specified
5889 * requirement vector */
5890 return TRUE;
5891 }
5892 }
5893
5894 /* No specified universal is known to guarantee that the requirement
5895 * vector never will be fulfilled. */
5896 return FALSE;
5897}
5898
5899/**********************************************************************/
5913bool universals_say_everything(struct requirement_vector *reqs,
5914 struct universal *unis,
5915 size_t n_unis)
5916{
5918 int i;
5919 bool req_mentioned_a_source = FALSE;
5920
5921 for (i = 0; i < n_unis; i++) {
5922 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
5923 case ITF_NO:
5924 case ITF_YES:
5925 /* this req matched this source */
5926 req_mentioned_a_source = TRUE;
5927 break;
5928 case ITF_NOT_APPLICABLE:
5929 /* Not a mention. */
5930 break;
5931 }
5932 }
5933
5934 if (!req_mentioned_a_source) {
5935 /* A requirement not relevant to any of the specified universals was
5936 * found in the requirement vector. */
5937 return FALSE;
5938 }
5940
5941 /* No requirement not relevant to any of the specified universals was
5942 * found in the requirement vector. */
5943 return TRUE;
5944}
5945
5946/**********************************************************************/
5949enum req_item_found
5951 const struct universal *source)
5952{
5955 "No req item found function for %s",
5957
5958 return (*universal_found_function[source->kind])(preq, source);
5959}
5960
5961/**********************************************************************/
5971bool universal_fulfills_requirements(bool check_necessary,
5972 const struct requirement_vector *reqs,
5973 const struct universal *source)
5974{
5975 bool necessary = FALSE;
5976
5978 !check_necessary,
5979 "No req item found function for %s",
5981
5983 switch ((*universal_found_function[source->kind])(preq, source)) {
5984 case ITF_NOT_APPLICABLE:
5985 continue;
5986 case ITF_NO:
5987 if (preq->present) {
5988 return FALSE;
5989 }
5990 break;
5991 case ITF_YES:
5992 if (preq->present) {
5993 necessary = TRUE;
5994 } else {
5995 return FALSE;
5996 }
5997 break;
5998 }
6000
6001 return (!check_necessary || necessary);
6002}
6003
6004/**********************************************************************/
6009 const struct universal *source)
6010{
6011 switch (universal_fulfills_requirement(req, source)) {
6012 case ITF_NOT_APPLICABLE:
6013 return FALSE;
6014 case ITF_NO:
6015 case ITF_YES:
6016 return TRUE;
6017 }
6018
6019 log_error("Unhandled item_found value");
6020 return FALSE;
6021}
6022
6023/**********************************************************************/
6026static enum req_item_found nation_found(const struct requirement *preq,
6027 const struct universal *source)
6028{
6029 fc_assert(source->value.nation);
6030
6031 switch (preq->source.kind) {
6032 case VUT_NATION:
6033 return preq->source.value.nation == source->value.nation ? ITF_YES
6034 : ITF_NO;
6035 case VUT_NATIONGROUP:
6036 return nation_is_in_group(source->value.nation,
6038 : ITF_NO;
6039 default:
6040 break;
6041 }
6042
6043 return ITF_NOT_APPLICABLE;
6044}
6045
6046/**********************************************************************/
6049static enum req_item_found government_found(const struct requirement *preq,
6050 const struct universal *source)
6051{
6052 fc_assert(source->value.govern);
6053
6054 if (preq->source.kind == VUT_GOVERNMENT) {
6055 return preq->source.value.govern == source->value.govern ? ITF_YES
6056 : ITF_NO;
6057 }
6058
6059 return ITF_NOT_APPLICABLE;
6060}
6061
6062/**********************************************************************/
6065static enum req_item_found improvement_found(const struct requirement *preq,
6066 const struct universal *source)
6067{
6068 fc_assert(source->value.building);
6069
6070 /* We only ever return ITF_YES, because requiring a different
6071 * improvement does not mean that the improvement under consideration
6072 * cannot fulfill the requirements. This is necessary to allow
6073 * requirement vectors to specify multiple required improvements. */
6074
6075 switch (preq->source.kind) {
6076 case VUT_IMPROVEMENT:
6077 if (source->value.building == preq->source.value.building) {
6078 return ITF_YES;
6079 }
6080 break;
6081 case VUT_IMPR_GENUS:
6082 if (source->value.building->genus == preq->source.value.impr_genus) {
6083 return ITF_YES;
6084 }
6085 break;
6086 default:
6087 break;
6088 }
6089
6090 return ITF_NOT_APPLICABLE;
6091}
6092
6093/**********************************************************************/
6096static enum req_item_found unit_class_found(const struct requirement *preq,
6097 const struct universal *source)
6098{
6099 fc_assert(source->value.uclass);
6100
6101 switch (preq->source.kind) {
6102 case VUT_UCLASS:
6103 return source->value.uclass == preq->source.value.uclass ? ITF_YES
6104 : ITF_NO;
6105 case VUT_UCFLAG:
6106 return uclass_has_flag(source->value.uclass,
6108 : ITF_NO;
6109
6110 default:
6111 /* Not found and not relevant. */
6112 return ITF_NOT_APPLICABLE;
6113 };
6114}
6115
6116/**********************************************************************/
6119static enum req_item_found unit_type_found(const struct requirement *preq,
6120 const struct universal *source)
6121{
6122 fc_assert(source->value.utype);
6123
6124 switch (preq->source.kind) {
6125 case VUT_UTYPE:
6126 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
6127 case VUT_UCLASS:
6128 return utype_class(source->value.utype) == preq->source.value.uclass
6129 ? ITF_YES : ITF_NO;
6130 case VUT_UTFLAG:
6131 return utype_has_flag(source->value.utype,
6132 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
6133 case VUT_UCFLAG:
6134 return uclass_has_flag(utype_class(source->value.utype),
6136 : ITF_NO;
6137 default:
6138 /* Not found and not relevant. */
6139 return ITF_NOT_APPLICABLE;
6140 };
6141}
6142
6143/**********************************************************************/
6146static enum req_item_found
6148 const struct universal *source)
6149{
6150 fc_assert_ret_val(unit_activity_is_valid(source->value.activity),
6152
6153 switch (preq->source.kind) {
6154 case VUT_ACTIVITY:
6155 return source->value.activity == preq->source.value.activity ? ITF_YES
6156 : ITF_NO;
6157 default:
6158 /* Not found and not relevant. */
6159 return ITF_NOT_APPLICABLE;
6160 };
6161}
6162
6163/**********************************************************************/
6166static enum req_item_found terrain_type_found(const struct requirement *preq,
6167 const struct universal *source)
6168{
6169 fc_assert(source->value.terrain);
6170
6171 switch (preq->source.kind) {
6172 case VUT_TERRAIN:
6173 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
6174 case VUT_TERRAINCLASS:
6175 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
6176 ? ITF_YES : ITF_NO;
6177 case VUT_TERRFLAG:
6178 return terrain_has_flag(source->value.terrain,
6180 case VUT_TERRAINALTER:
6181 return (terrain_can_support_alteration(source->value.terrain,
6183 ? ITF_YES : ITF_NO);
6184 default:
6185 /* Not found and not relevant. */
6186 return ITF_NOT_APPLICABLE;
6187 };
6188}
6189
6190/**********************************************************************/
6193static enum req_item_found city_tile_found(const struct requirement *preq,
6194 const struct universal *source)
6195{
6196 fc_assert_ret_val(citytile_type_is_valid(source->value.citytile),
6198
6199 switch (preq->source.kind) {
6200 case VUT_CITYTILE:
6201 return (source->value.citytile == preq->source.value.citytile
6202 ? ITF_YES
6203 /* The presence of one tile state doesn't block another */
6205 default:
6206 /* Not found and not relevant. */
6207 return ITF_NOT_APPLICABLE;
6208 };
6209}
6210
6211/**********************************************************************/
6214static enum req_item_found extra_type_found(const struct requirement *preq,
6215 const struct universal *source)
6216{
6217 fc_assert(source->value.extra);
6218
6219 switch (preq->source.kind) {
6220 case VUT_EXTRA:
6221 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
6222 case VUT_EXTRAFLAG:
6223 return extra_has_flag(source->value.extra,
6224 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
6225 case VUT_ROADFLAG:
6226 {
6227 struct road_type *r = extra_road_get(source->value.extra);
6228
6229 return r && road_has_flag(r, preq->source.value.roadflag)
6230 ? ITF_YES : ITF_NO;
6231 }
6232 default:
6233 /* Not found and not relevant. */
6234 return ITF_NOT_APPLICABLE;
6235 }
6236}
6237
6238/**********************************************************************/
6241static enum req_item_found action_found(const struct requirement *preq,
6242 const struct universal *source)
6243{
6244 fc_assert(source->value.action);
6245
6246 if (preq->source.kind == VUT_ACTION) {
6247 return preq->source.value.action == source->value.action ? ITF_YES
6248 : ITF_NO;
6249 }
6250
6251 return ITF_NOT_APPLICABLE;
6252}
6253
6254/**********************************************************************/
6257static enum req_item_found diplrel_found(const struct requirement *preq,
6258 const struct universal *source)
6259{
6260 fc_assert_ret_val((source->kind == VUT_DIPLREL
6261 || source->kind == VUT_DIPLREL_TILE
6262 || source->kind == VUT_DIPLREL_TILE_O
6263 || source->kind == VUT_DIPLREL_UNITANY
6264 || source->kind == VUT_DIPLREL_UNITANY_O),
6266
6267 if (preq->source.kind == source->kind) {
6268 if (preq->source.value.diplrel == source->value.diplrel) {
6269 /* The diplrel itself. */
6270 return ITF_YES;
6271 }
6272 if (preq->source.value.diplrel == DRO_FOREIGN
6273 && source->value.diplrel < DS_LAST) {
6274 /* All diplstate_type values are to foreigners. */
6275 return ITF_YES;
6276 }
6277 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
6278 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
6279 /* A real embassy is an embassy. */
6280 return ITF_YES;
6281 }
6282 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
6283 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
6284 /* A real embassy is an embassy. */
6285 return ITF_YES;
6286 }
6287 if (preq->source.value.diplrel < DS_LAST
6288 && source->value.diplrel < DS_LAST
6289 && preq->range == REQ_RANGE_LOCAL) {
6290 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
6291 ITF_YES);
6292 /* Can only have one diplstate_type to a specific player. */
6293 return ITF_NO;
6294 }
6295 /* Can't say this diplrel blocks the other diplrel. */
6296 return ITF_NOT_APPLICABLE;
6297 }
6298
6299 /* Not relevant. */
6300 return ITF_NOT_APPLICABLE;
6301}
6302
6303/**********************************************************************/
6306static enum req_item_found output_type_found(const struct requirement *preq,
6307 const struct universal *source)
6308{
6309 switch (preq->source.kind) {
6310 case VUT_OTYPE:
6311 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
6312 : ITF_NO;
6313 default:
6314 /* Not found and not relevant. */
6315 return ITF_NOT_APPLICABLE;
6316 }
6317}
6318
6319/**********************************************************************/
6322static enum req_item_found ustate_found(const struct requirement *preq,
6323 const struct universal *source)
6324{
6325 if (preq->range != REQ_RANGE_LOCAL) {
6326 return ITF_NOT_APPLICABLE;
6327 }
6328
6329 if (preq->source.kind == VUT_UNITSTATE) {
6330 switch (source->value.unit_state) {
6331 case USP_TRANSPORTED:
6332 case USP_TRANSPORTING:
6333 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
6334 case USP_LIVABLE_TILE:
6335 case USP_NATIVE_TILE:
6336 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
6337 * UTYF_COAST_STRICT. */
6338 case USP_HAS_HOME_CITY:
6339 case USP_NATIVE_EXTRA:
6340 case USP_MOVED_THIS_TURN:
6341 if (source->value.unit_state == preq->source.value.unit_state) {
6342 /* The other unit states doesn't contradict */
6343 return ITF_YES;
6344 }
6345 break;
6346 case USP_COUNT:
6347 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
6349 }
6350 }
6351
6352 /* Not found and not relevant. */
6353 return ITF_NOT_APPLICABLE;
6354}
6355
6356/**********************************************************************/
6360{
6361 universal_found_function[VUT_GOVERNMENT] = &government_found;
6363 universal_found_function[VUT_IMPROVEMENT] = &improvement_found;
6373 universal_found_function[VUT_DIPLREL_TILE] = &diplrel_found;
6374 universal_found_function[VUT_DIPLREL_TILE_O] = &diplrel_found;
6375 universal_found_function[VUT_DIPLREL_UNITANY] = &diplrel_found;
6376 universal_found_function[VUT_DIPLREL_UNITANY_O] = &diplrel_found;
6377 universal_found_function[VUT_UNITSTATE] = &ustate_found;
6378}
6379
6380/**********************************************************************/
6388int requirement_kind_ereq(const int value,
6389 const enum req_range range,
6390 const bool present,
6391 const int max_value)
6392{
6393 /* The enumerators in each range starts with present for every possible
6394 * value followed by !present for every possible value. */
6395 const int pres_start = (present ? 0 : max_value);
6396
6397 /* The enumerators for every range follows all the positions of the
6398 * previous range(s). */
6399 const int range_start = ((max_value - 1) * 2) * range;
6400
6401 return range_start + pres_start + value;
6402}
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:1890
bool action_is_in_use(struct action *paction)
Definition actions.c:7326
struct action * action_by_rule_name(const char *name)
Definition actions.c:1708
const char * action_rule_name(const struct action *action)
Definition actions.c:1876
int action_number(const struct action *action)
Definition actions.c:1868
static struct action * action_by_number(action_id act_id)
Definition actions.h:638
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
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:1216
Output_type_id output_type_by_identifier(const char *id)
Definition city.c:642
const char * get_output_identifier(Output_type_id output)
Definition city.c:614
const char * get_output_name(Output_type_id output)
Definition city.c:624
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:132
#define city_tile(_pcity_)
Definition city.h:544
static citizens city_size_get(const struct city *pcity)
Definition city.h:549
#define city_owner(_pcity_)
Definition city.h:543
static bool is_city_center(const struct city *pcity, const struct tile *ptile)
Definition city.h:844
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:222
#define city_tile_iterate_end
Definition city.h:230
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:55
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:56
struct @21::@22 reqs
int get_world_bonus(enum effect_type effect_type)
Definition effects.c:759
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:204
bool extra_flag_is_in_use(enum extra_flag_id id)
Definition extras.c:936
bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:839
bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:819
bool is_extra_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:353
int extra_number(const struct extra_type *pextra)
Definition extras.c:153
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:810
bool is_extra_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:337
struct extra_type * extra_by_number(int id)
Definition extras.c:175
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:195
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:186
#define extra_road_get(_e_)
Definition extras.h:185
static bool is_server(void)
int Tech_type_id
Definition fc_types.h:347
req_problem_type
Definition fc_types.h:584
@ RPT_POSSIBLE
Definition fc_types.h:585
#define MAX_LEN_NAME
Definition fc_types.h:66
@ VC_SPACERACE
Definition fc_types.h:1123
@ O_LAST
Definition fc_types.h:91
#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:57
struct world wld
Definition game.c:58
const char * government_name_translation(const struct government *pgovern)
Definition government.c:142
struct government * government_by_number(const Government_type_id gov)
Definition government.c:102
struct government * government_of_player(const struct player *pplayer)
Definition government.c:113
Government_type_id government_number(const struct government *pgovern)
Definition government.c:90
const char * government_rule_name(const struct government *pgovern)
Definition government.c:132
struct government * government_by_rule_name(const char *name)
Definition government.c:54
static GtkWidget * source
Definition gotodlg.c:58
GType type
Definition repodlgs.c:1312
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)
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:929
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:938
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:652
#define current_topo_has_flag(flag)
Definition map.h:45
#define adjc_iterate_end
Definition map.h:427
#define cardinal_adjc_iterate_end
Definition map.h:453
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:422
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:449
#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:973
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:304
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:316
struct nation_group * nation_group_by_rule_name(const char *name)
Definition nation.c:1020
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:137
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:485
const char * nation_adjective_translation(const struct nation_type *pnation)
Definition nation.c:148
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:474
const char * nation_group_rule_name(const struct nation_group *pgroup)
Definition nation.c:1078
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:443
bool nation_is_in_group(const struct nation_type *pnation, const struct nation_group *pgroup)
Definition nation.c:1098
const char * nation_group_name_translation(const struct nation_group *pgroup)
Definition nation.c:1089
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:120
struct nation_group * nation_group_by_number(int id)
Definition nation.c:1003
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:951
#define NO_NATION_SELECTED
Definition nation.h:29
bool player_knows_techs_with_flag(const struct player *pplayer, enum tech_flag_id flag)
Definition player.c:1304
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Definition player.c:1787
int diplrel_by_rule_name(const char *value)
Definition player.c:1545
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1452
bool is_diplrel_to_other(const struct player *pplayer, int diplrel)
Definition player.c:1526
const char * diplrel_name_translation(int value)
Definition player.c:1591
bool is_diplrel_between(const struct player *player1, const struct player *player2, int diplrel)
Definition player.c:1480
int player_age(const struct player *pplayer)
Definition player.c:945
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1381
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:430
const char * diplrel_rule_name(int value)
Definition player.c:1579
#define players_iterate_end
Definition player.h:535
#define players_iterate(_pplayer)
Definition player.h:530
#define is_ai(plr)
Definition player.h:234
#define players_iterate_alive_end
Definition player.h:545
#define players_iterate_alive(_pplayer)
Definition player.h:540
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)
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)
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)
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_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 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_diplrel_in_range(const struct player *target_player, const struct player *other_player, enum req_range range, int diplrel)
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 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 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)
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:126
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:616
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:309
struct player * original
Definition city.h:313
int turn_founded
Definition city.h:372
struct tile * tile
Definition city.h:311
struct packet_game_info info
Definition game.h:89
struct packet_calendar_info calendar
Definition game.h:90
enum impr_genus_id genus
Definition improvement.h:80
struct player * player
Definition nation.h:117
int index
Definition city.h:252
bool global_advances[A_LAST]
enum ai_level skill_level
Definition player.h:122
struct player_ai ai_common
Definition player.h:288
bool is_alive
Definition player.h:268
struct nation_style * style
Definition player.h:279
const struct impr_type * building
const struct action * action
const struct tile * tile
const struct player * player
const struct output_type * output
const struct unit_type * unittype
const struct unit * unit
const struct city * city
const struct specialist * specialist
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]
struct req_vec_change * suggested_solutions
enum req_range range
struct universal source
int techs_researched
Definition research.h:42
Definition tile.h:49
struct unit_list * units
Definition tile.h:57
struct player * extras_owner
Definition tile.h:62
struct player * owner
Definition tile.h:59
enum unit_activity activity
Definition unit.h:157
int moves_left
Definition unit.h:150
bool moved
Definition unit.h:173
int hp
Definition unit.h:151
struct unit::@80::@83 server
int homecity
Definition unit.h:146
struct unit * transporter
Definition unit.h:183
int birth_turn
Definition unit.h:235
int veteran
Definition unit.h:152
enum universals_n kind
Definition fc_types.h:758
universals_u value
Definition fc_types.h:757
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:969
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:787
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:832
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:995
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:896
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define bool
Definition support.h:61
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:174
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:600
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:579
const char * terrain_class_name_translation(enum terrain_class tclass)
Definition terrain.c:649
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:226
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:144
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Definition terrain.c:661
bool is_terrain_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:315
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:235
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:570
bool is_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:446
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:135
bool is_terrain_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:426
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:336
#define T_UNKNOWN
Definition terrain.h:57
#define terrain_has_flag(terr, flag)
Definition terrain.h:269
bool tile_has_extra_flag(const struct tile *ptile, enum extra_flag_id flag)
Definition tile.c:871
bool tile_has_native_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:318
bool tile_has_road_flag(const struct tile *ptile, enum road_flag_id flag)
Definition tile.c:853
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_terrain(_tile)
Definition tile.h:109
#define tile_continent(_tile)
Definition tile.h:91
#define tile_has_extra(ptile, pextra)
Definition tile.h:146
#define tile_owner(_tile)
Definition tile.h:95
Goods_type_id goods_number(const struct goods_type *pgood)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
const char * goods_name_translation(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
#define trade_partners_iterate_end
#define trade_partners_iterate(c, p)
const struct unit_type * utype
Definition fc_types.h:604
struct nation_style * style
Definition fc_types.h:608
enum ai_level ai_level
Definition fc_types.h:612
struct specialist * specialist
Definition fc_types.h:601
enum impr_genus_id impr_genus
Definition fc_types.h:633
enum citytile_type citytile
Definition fc_types.h:613
struct nation_group * nationgroup
Definition fc_types.h:607
struct extra_type * extra
Definition fc_types.h:605
struct nation_type * nation
Definition fc_types.h:599
int terrainclass
Definition fc_types.h:621
int unitclassflag
Definition fc_types.h:623
struct government * govern
Definition fc_types.h:597
int max_tile_units
Definition fc_types.h:635
int terrainalter
Definition fc_types.h:622
enum citystatus_type citystatus
Definition fc_types.h:614
int minforeignpct
Definition fc_types.h:617
const struct impr_type * building
Definition fc_types.h:598
struct achievement * achievement
Definition fc_types.h:606
ssetv ssetval
Definition fc_types.h:642
struct advance * advance
Definition fc_types.h:596
enum unit_activity activity
Definition fc_types.h:632
struct goods_type * good
Definition fc_types.h:610
struct terrain * terrain
Definition fc_types.h:602
int terrainflag
Definition fc_types.h:625
enum ustate_prop unit_state
Definition fc_types.h:631
Output_type_id outputtype
Definition fc_types.h:620
enum topo_flag topo_property
Definition fc_types.h:641
int min_hit_points
Definition fc_types.h:637
struct unit_class * uclass
Definition fc_types.h:603
struct nation_type * nationality
Definition fc_types.h:600
struct action * action
Definition fc_types.h:609
bool is_real_activity(enum unit_activity activity)
Definition unit.c:609
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1767
#define unit_tile(_pu)
Definition unit.h:395
#define unit_owner(_pu)
Definition unit.h:394
#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:1684
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:1819
bool uclass_flag_is_in_use(enum unit_class_flag_id ucflag)
Definition unittype.c:2997
struct unit_class * uclass_by_number(const Unit_Class_id id)
Definition unittype.c:2525
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1630
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:1693
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:1836
bool utype_flag_is_in_use(enum unit_type_flag_id uflag)
Definition unittype.c:3016
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1490
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2516
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1612
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:753
#define utype_class(_t_)
Definition unittype.h:736
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:604
bool victory_enabled(enum victory_condition_type victory)
Definition victory.c:26