Freeciv-3.2: /fast/freeciv/nightly/S3_2/common/requirements.c Source File

Freeciv-3.2

Loading...
Searching...
No Matches
requirements.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2004 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17#include <stdarg.h>
18
19/* utility */
20#include "astring.h"
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "achievements.h"
27#include "calendar.h"
28#include "citizens.h"
29#include "counters.h"
30#include "culture.h"
31#include "game.h"
32#include "government.h"
33#include "improvement.h"
34#include "movement.h"
35#include "nation.h"
36#include "player.h"
37#include "map.h"
38#include "research.h"
39#include "road.h"
40#include "server_settings.h"
41#include "specialist.h"
42#include "style.h"
43#include "victory.h" /* victory_enabled() */
44
45#include "requirements.h"
46
47/************************************************************************
48 Container for req_item_found functions
49************************************************************************/
50typedef enum req_item_found (*universal_found)(const struct requirement *,
51 const struct universal *);
52 static universal_found universal_found_function[VUT_COUNT] = {NULL};
53
54static
55 enum fc_tristate tri_req_present(const struct civ_map *nmap,
56 const struct req_context *context,
57 const struct player *other_player,
58 const struct requirement *req);
59
60/* Function pointer for requirement-type-specific is_req_active handlers */
61typedef enum fc_tristate
62(*is_req_active_cb)(const struct civ_map *nmap,
63 const struct req_context *context,
64 const struct player *other_player,
65 const struct requirement *req);
66
67static inline bool are_tiles_in_range(const struct tile *tile1,
68 const struct tile *tile2,
69 enum req_range range);
70
71/**********************************************************************/
76static enum req_unchanging_status
77 unchanging_local(const struct civ_map *nmap,
78 enum req_unchanging_status def,
79 const struct req_context *context,
80 const struct requirement *req)
81{
82 return req->range == REQ_RANGE_LOCAL ? REQUCH_YES : def;
83}
84#define REQUC_LOCAL unchanging_local
85
86/**********************************************************************/
89static enum req_unchanging_status
90 unchanging_present(const struct civ_map *nmap,
91 enum req_unchanging_status def,
92 const struct req_context *context,
93 const struct requirement *req)
94{
95 if (TRI_YES != tri_req_present(nmap, context, NULL, req)) {
96 return REQUCH_NO;
97 }
98 return def;
99}
100#define REQUC_PRESENT unchanging_present
101
102/**********************************************************************/
105static enum req_unchanging_status
106 unchanging_world(const struct civ_map *nmap,
107 enum req_unchanging_status def,
108 const struct req_context *context,
109 const struct requirement *req)
110{
111 return
112 unchanging_present(nmap, req->range == REQ_RANGE_WORLD ? REQUCH_YES : def,
113 context, req);
114}
115#define REQUC_WORLD unchanging_world
116
117/**********************************************************************/
121static enum req_unchanging_status
122 unchanging_noally(const struct civ_map *nmap,
123 enum req_unchanging_status def,
124 const struct req_context *context,
125 const struct requirement *req)
126{
127 if (REQ_RANGE_ALLIANCE == req->range
128 || REQ_RANGE_TEAM == req->range) {
129 struct requirement preq;
130
131 req_copy(&preq, req);
132 preq.range = REQ_RANGE_PLAYER;
133 if (TRI_YES != tri_req_present(nmap, context, NULL, &preq)) {
134 return REQ_RANGE_TEAM == req->range ? REQUCH_ACT : REQUCH_NO;
135 }
136 }
137 return def;
138}
139#define REQUC_NALLY unchanging_noally
140
141/**********************************************************************/
144static enum req_unchanging_status
145 unchanging_citytile(const struct civ_map *nmap,
146 enum req_unchanging_status def,
147 const struct req_context *context,
148 const struct requirement *req)
149{
150 fc_assert_ret_val(VUT_CITYTILE == req->source.kind, REQUCH_NO);
151 if (CITYT_CENTER == req->source.value.citytile
152 || (CITYT_BORDERING_TCLASS_REGION != req->source.value.citytile
153 && NULL != context->city && NULL != context->tile
154 && NULL != city_tile(context->city)
155 && are_tiles_in_range(city_tile(context->city), context->tile,
156 req->range))){
157 /* Cities don't move, and most reqs are present on city center */
158 return REQUCH_YES;
159 }
160 return def;
161}
162#define REQUC_CITYTILE unchanging_citytile
163
164/**********************************************************************/
167static enum req_unchanging_status
168 unchanging_citystatus(const struct civ_map *nmap,
169 enum req_unchanging_status def,
170 const struct req_context *context,
171 const struct requirement *req)
172{
173 fc_assert_ret_val(VUT_CITYSTATUS == req->source.kind, REQUCH_NO);
174
175 if (REQ_RANGE_CITY == req->range
176 && (CITYS_OWNED_BY_ORIGINAL == req->source.value.citystatus
177 || CITYS_TRANSFERRED == req->source.value.citystatus)) {
178 return REQUCH_CTRL;
179 }
180
181 return def;
182}
183#define REQUC_CITYSTATUS unchanging_citystatus
184
185/**********************************************************************/
190static enum req_unchanging_status
191 unchanging_building(const struct civ_map *nmap,
192 enum req_unchanging_status def,
193 const struct req_context *context,
194 const struct requirement *req)
195{
196 const struct impr_type *b = req->source.value.building;
197
198 fc_assert_ret_val(VUT_IMPROVEMENT == req->source.kind, REQUCH_NO);
199 if (REQ_RANGE_LOCAL == req->range) {
200 /* Likely, won't be questioned for an obsolete building */
201 return REQUCH_YES;
202 }
203
204 if (improvement_obsolete(context->player, b, context->city)) {
205 /* FIXME: sometimes can unobsolete, but considering it
206 * may sometimes put the function on endless recursion */
207 return REQUCH_ACT; /* Mostly about techs */
208 }
209 if (is_great_wonder(b)) {
210 if (great_wonder_is_destroyed(b)
211 || (!great_wonder_is_available(b)
212 && (req->range <= REQ_RANGE_CITY && TRI_YES
213 == tri_req_present(nmap, context, NULL, req)))) {
214 /* If the wonder stays somewhere, it may either remain there
215 * or be destroyed. If it is destroyed, it is nowhere. */
216 return REQUCH_SCRIPTS;
217 }
218 }
219 return def;
220}
221#define REQUC_IMPR unchanging_building
222
223 struct req_def {
224 const is_req_active_cb cb;
225 enum req_unchanging_status unchanging;
226 req_unchanging_cond_cb unchanging_cond;
227};
228
229/**********************************************************************/
236 struct universal universal_by_rule_name(const char *kind,
237 const char *value)
238{
239 struct universal source;
240
241 source.kind = universals_n_by_name(kind, fc_strcasecmp);
242 if (!universals_n_is_valid(source.kind)) {
243 return source;
244 }
245
246 universal_value_from_str(&source, value);
247
248 return source;
249}
250
251/**********************************************************************/
255 static bool activity_is_valid_in_requirement(enum unit_activity act)
256{
257 return unit_activity_is_valid(act)
258 && act != ACTIVITY_SENTRY
259 && act != ACTIVITY_GOTO
260 && act != ACTIVITY_EXPLORE;
261}
262
263/**********************************************************************/
267 bool universal_is_legal_in_requirement(const struct universal *univ)
268{
269 if (univ->kind == VUT_ACTIVITY) {
270 return activity_is_valid_in_requirement(univ->value.activity);
271 }
272
273 return TRUE;
274}
275
276/**********************************************************************/
280 void universal_value_from_str(struct universal *source, const char *value)
281{
282 /* Finally scan the value string based on the type of the source. */
283 switch (source->kind) {
284 case VUT_NONE:
285 return;
286 case VUT_ADVANCE:
287 source->value.advance = advance_by_rule_name(value);
288 if (source->value.advance != NULL) {
289 return;
290 }
291 break;
292 case VUT_TECHFLAG:
293 source->value.techflag
294 = tech_flag_id_by_name(value, fc_strcasecmp);
295 if (tech_flag_id_is_valid(source->value.techflag)) {
296 return;
297 }
298 break;
299 case VUT_GOVERNMENT:
300 source->value.govern = government_by_rule_name(value);
301 if (source->value.govern != NULL) {
302 return;
303 }
304 break;
305 case VUT_ACHIEVEMENT:
306 source->value.achievement = achievement_by_rule_name(value);
307 if (source->value.achievement != NULL) {
308 return;
309 }
310 break;
311 case VUT_STYLE:
312 source->value.style = style_by_rule_name(value);
313 if (source->value.style != NULL) {
314 return;
315 }
316 break;
317 case VUT_IMPROVEMENT:
318 source->value.building = improvement_by_rule_name(value);
319 if (source->value.building != NULL) {
320 return;
321 }
322 break;
323 case VUT_IMPR_GENUS:
324 source->value.impr_genus = impr_genus_id_by_name(value, fc_strcasecmp);
325 if (impr_genus_id_is_valid(source->value.impr_genus)) {
326 return;
327 }
328 break;
329 case VUT_IMPR_FLAG:
330 source->value.impr_flag = impr_flag_id_by_name(value, fc_strcasecmp);
331 if (impr_flag_id_is_valid(source->value.impr_flag)) {
332 return;
333 }
334 break;
335 case VUT_PLAYER_FLAG:
336 source->value.plr_flag = plr_flag_id_by_name(value, fc_strcasecmp);
337 if (plr_flag_id_is_valid(source->value.plr_flag)) {
338 return;
339 }
340 break;
341 case VUT_EXTRA:
342 source->value.extra = extra_type_by_rule_name(value);
343 if (source->value.extra != NULL) {
344 return;
345 }
346 break;
347 case VUT_GOOD:
348 source->value.good = goods_by_rule_name(value);
349 if (source->value.good != NULL) {
350 return;
351 }
352 break;
353 case VUT_TERRAIN:
354 source->value.terrain = terrain_by_rule_name(value);
355 if (source->value.terrain != T_UNKNOWN) {
356 return;
357 }
358 break;
359 case VUT_TERRFLAG:
360 source->value.terrainflag
361 = terrain_flag_id_by_name(value, fc_strcasecmp);
362 if (terrain_flag_id_is_valid(source->value.terrainflag)) {
363 return;
364 }
365 break;
366 case VUT_NATION:
367 source->value.nation = nation_by_rule_name(value);
368 if (source->value.nation != NO_NATION_SELECTED) {
369 return;
370 }
371 break;
372 case VUT_NATIONGROUP:
373 source->value.nationgroup = nation_group_by_rule_name(value);
374 if (source->value.nationgroup != NULL) {
375 return;
376 }
377 break;
378 case VUT_NATIONALITY:
379 source->value.nationality = nation_by_rule_name(value);
380 if (source->value.nationality != NO_NATION_SELECTED) {
381 return;
382 }
383 break;
384 case VUT_ORIGINAL_OWNER:
385 source->value.origowner = nation_by_rule_name(value);
386 if (source->value.origowner != NO_NATION_SELECTED) {
387 return;
388 }
389 break;
390 case VUT_DIPLREL:
391 case VUT_DIPLREL_TILE:
392 case VUT_DIPLREL_TILE_O:
393 case VUT_DIPLREL_UNITANY:
394 case VUT_DIPLREL_UNITANY_O:
395 source->value.diplrel = diplrel_by_rule_name(value);
396 if (source->value.diplrel != diplrel_other_invalid()) {
397 return;
398 }
399 break;
400 case VUT_UTYPE:
401 source->value.utype = unit_type_by_rule_name(value);
402 if (source->value.utype) {
403 return;
404 }
405 break;
406 case VUT_UTFLAG:
407 source->value.unitflag = unit_type_flag_id_by_name(value, fc_strcasecmp);
408 if (unit_type_flag_id_is_valid(source->value.unitflag)) {
409 return;
410 }
411 break;
412 case VUT_UCLASS:
413 source->value.uclass = unit_class_by_rule_name(value);
414 if (source->value.uclass) {
415 return;
416 }
417 break;
418 case VUT_UCFLAG:
419 source->value.unitclassflag
420 = unit_class_flag_id_by_name(value, fc_strcasecmp);
421 if (unit_class_flag_id_is_valid(source->value.unitclassflag)) {
422 return;
423 }
424 break;
425 case VUT_MINVETERAN:
426 source->value.minveteran = atoi(value);
427 if (source->value.minveteran > 0) {
428 return;
429 }
430 break;
431 case VUT_UNITSTATE:
432 source->value.unit_state = ustate_prop_by_name(value, fc_strcasecmp);
433 if (ustate_prop_is_valid(source->value.unit_state)) {
434 return;
435 }
436 break;
437 case VUT_ACTIVITY:
438 source->value.activity = unit_activity_by_name(value, fc_strcasecmp);
439 if (activity_is_valid_in_requirement(source->value.activity)) {
440 return;
441 }
442 break;
443 case VUT_MINMOVES:
444 source->value.minmoves = atoi(value);
445 if (source->value.minmoves > 0) {
446 return;
447 }
448 break;
449 case VUT_MINHP:
450 source->value.min_hit_points = atoi(value);
451 if (source->value.min_hit_points > 0) {
452 return;
453 }
454 break;
455 case VUT_AGE:
456 source->value.age = atoi(value);
457 if (source->value.age > 0) {
458 return;
459 }
460 break;
461 case VUT_FORM_AGE:
462 source->value.form_age = atoi(value);
463 if (source->value.form_age > 0) {
464 return;
465 }
466 break;
467 case VUT_MINTECHS:
468 source->value.min_techs = atoi(value);
469 if (source->value.min_techs > 0) {
470 return;
471 }
472 break;
473 case VUT_ACTION:
474 source->value.action = action_by_rule_name(value);
475 if (source->value.action != NULL) {
476 return;
477 }
478 break;
479 case VUT_OTYPE:
480 source->value.outputtype = output_type_by_identifier(value);
481 if (source->value.outputtype != O_LAST) {
482 return;
483 }
484 break;
485 case VUT_SPECIALIST:
486 source->value.specialist = specialist_by_rule_name(value);
487 if (source->value.specialist) {
488 return;
489 }
490 break;
491 case VUT_MINSIZE:
492 source->value.minsize = atoi(value);
493 if (source->value.minsize > 0) {
494 return;
495 }
496 break;
497 case VUT_MINCULTURE:
498 source->value.minculture = atoi(value);
499 if (source->value.minculture > 0) {
500 return;
501 }
502 break;
503 case VUT_MINFOREIGNPCT:
504 source->value.minforeignpct = atoi(value);
505 if (source->value.minforeignpct > 0) {
506 return;
507 }
508 break;
509 case VUT_AI_LEVEL:
510 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
511 if (ai_level_is_valid(source->value.ai_level)) {
512 return;
513 }
514 break;
515 case VUT_MAXTILEUNITS:
516 source->value.max_tile_units = atoi(value);
517 if (0 <= source->value.max_tile_units) {
518 return;
519 }
520 break;
521 case VUT_TERRAINCLASS:
522 source->value.terrainclass
523 = terrain_class_by_name(value, fc_strcasecmp);
524 if (terrain_class_is_valid(source->value.terrainclass)) {
525 return;
526 }
527 break;
528 case VUT_ROADFLAG:
529 source->value.roadflag = road_flag_id_by_name(value, fc_strcasecmp);
530 if (road_flag_id_is_valid(source->value.roadflag)) {
531 return;
532 }
533 break;
534 case VUT_EXTRAFLAG:
535 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
536 if (extra_flag_id_is_valid(source->value.extraflag)) {
537 return;
538 }
539 break;
540 case VUT_MINYEAR:
541 source->value.minyear = atoi(value);
542 return;
543 case VUT_MINCALFRAG:
544 /* Rule names are 0-based numbers, not pretty names from ruleset */
545 source->value.mincalfrag = atoi(value);
546 if (source->value.mincalfrag >= 0) {
547 /* More range checking done later, in sanity_check_req_individual() */
548 return;
549 }
550 break;
551 case VUT_TOPO:
552 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
553 if (topo_flag_is_valid(source->value.topo_property)) {
554 return;
555 }
556 break;
557 case VUT_WRAP:
558 source->value.wrap_property = wrap_flag_by_name(value, fc_strcasecmp);
559 if (wrap_flag_is_valid(source->value.wrap_property)) {
560 return;
561 }
562 break;
563 case VUT_SERVERSETTING:
564 source->value.ssetval = ssetv_by_rule_name(value);
565 if (source->value.ssetval != SSETV_NONE) {
566 return;
567 }
568 break;
569 case VUT_TERRAINALTER:
570 source->value.terrainalter
571 = terrain_alteration_by_name(value, fc_strcasecmp);
572 if (terrain_alteration_is_valid(source->value.terrainalter)) {
573 return;
574 }
575 break;
576 case VUT_CITYTILE:
577 source->value.citytile = citytile_type_by_name(value, fc_strcasecmp);
578 if (source->value.citytile != CITYT_LAST) {
579 return;
580 }
581 break;
582 case VUT_CITYSTATUS:
583 source->value.citystatus = citystatus_type_by_name(value, fc_strcasecmp);
584 if (source->value.citystatus != CITYS_LAST) {
585 return;
586 }
587 break;
588 case VUT_PLAYER_STATE:
589 source->value.plrstate = plrstate_type_by_name(value, fc_strcasecmp);
590 if (source->value.plrstate != PLRS_LAST) {
591 return;
592 }
593 break;
594 case VUT_MINLATITUDE:
595 case VUT_MAXLATITUDE:
596 source->value.latitude = atoi(value);
597 if (source->value.latitude >= -MAP_MAX_LATITUDE
598 && source->value.latitude <= MAP_MAX_LATITUDE) {
599 return;
600 }
601 break;
602 case VUT_COUNTER:
603 source->value.counter = counter_by_rule_name(value);
604 if (source->value.counter != NULL) {
605 return;
606 }
607 break;
608 case VUT_COUNT:
609 break;
610 }
611
612 /* If we reach here there's been an error. */
613 source->kind = universals_n_invalid();
614}
615
616/**********************************************************************/
621 struct universal universal_by_number(const enum universals_n kind,
622 const int value)
623{
624 struct universal source;
625
626 source.kind = kind;
627
628 switch (source.kind) {
629 case VUT_NONE:
630 /* Avoid compiler warning about unitialized source.value */
631 source.value.advance = NULL;
632
633 return source;
634 case VUT_ADVANCE:
635 source.value.advance = advance_by_number(value);
636 if (source.value.advance != NULL) {
637 return source;
638 }
639 break;
640 case VUT_TECHFLAG:
641 source.value.techflag = value;
642 return source;
643 case VUT_GOVERNMENT:
644 source.value.govern = government_by_number(value);
645 if (source.value.govern != NULL) {
646 return source;
647 }
648 break;
649 case VUT_ACHIEVEMENT:
650 source.value.achievement = achievement_by_number(value);
651 if (source.value.achievement != NULL) {
652 return source;
653 }
654 break;
655 case VUT_STYLE:
656 source.value.style = style_by_number(value);
657 if (source.value.style != NULL) {
658 return source;
659 }
660 break;
661 case VUT_IMPROVEMENT:
662 source.value.building = improvement_by_number(value);
663 if (source.value.building != NULL) {
664 return source;
665 }
666 break;
667 case VUT_IMPR_GENUS:
668 source.value.impr_genus = value;
669 return source;
670 case VUT_IMPR_FLAG:
671 source.value.impr_flag = value;
672 return source;
673 case VUT_PLAYER_FLAG:
674 source.value.plr_flag = value;
675 return source;
676 case VUT_EXTRA:
677 source.value.extra = extra_by_number(value);
678 return source;
679 case VUT_GOOD:
680 source.value.good = goods_by_number(value);
681 return source;
682 case VUT_TERRAIN:
683 source.value.terrain = terrain_by_number(value);
684 if (source.value.terrain != NULL) {
685 return source;
686 }
687 break;
688 case VUT_TERRFLAG:
689 source.value.terrainflag = value;
690 return source;
691 case VUT_NATION:
692 source.value.nation = nation_by_number(value);
693 if (source.value.nation != NULL) {
694 return source;
695 }
696 break;
697 case VUT_NATIONGROUP:
698 source.value.nationgroup = nation_group_by_number(value);
699 if (source.value.nationgroup != NULL) {
700 return source;
701 }
702 break;
703 case VUT_DIPLREL:
704 case VUT_DIPLREL_TILE:
705 case VUT_DIPLREL_TILE_O:
706 case VUT_DIPLREL_UNITANY:
707 case VUT_DIPLREL_UNITANY_O:
708 source.value.diplrel = value;
709 if (source.value.diplrel != diplrel_other_invalid()) {
710 return source;
711 }
712 break;
713 case VUT_NATIONALITY:
714 source.value.nationality = nation_by_number(value);
715 if (source.value.nationality != NULL) {
716 return source;
717 }
718 break;
719 case VUT_ORIGINAL_OWNER:
720 source.value.origowner = nation_by_number(value);
721 if (source.value.origowner != NULL) {
722 return source;
723 }
724 break;
725 case VUT_UTYPE:
726 source.value.utype = utype_by_number(value);
727 if (source.value.utype != NULL) {
728 return source;
729 }
730 break;
731 case VUT_UTFLAG:
732 source.value.unitflag = value;
733 return source;
734 case VUT_UCLASS:
735 source.value.uclass = uclass_by_number(value);
736 if (source.value.uclass != NULL) {
737 return source;
738 }
739 break;
740 case VUT_UCFLAG:
741 source.value.unitclassflag = value;
742 return source;
743 case VUT_MINVETERAN:
744 source.value.minveteran = value;
745 return source;
746 case VUT_UNITSTATE:
747 source.value.unit_state = value;
748 return source;
749 case VUT_ACTIVITY:
750 source.value.activity = value;
751 return source;
752 case VUT_MINMOVES:
753 source.value.minmoves = value;
754 return source;
755 case VUT_MINHP:
756 source.value.min_hit_points = value;
757 return source;
758 case VUT_AGE:
759 source.value.age = value;
760 return source;
761 case VUT_FORM_AGE:
762 source.value.form_age = value;
763 return source;
764 case VUT_MINTECHS:
765 source.value.min_techs = value;
766 return source;
767 case VUT_ACTION:
768 source.value.action = action_by_number(value);
769 if (source.value.action != NULL) {
770 return source;
771 }
772 break;
773 case VUT_OTYPE:
774 source.value.outputtype = value;
775 return source;
776 case VUT_SPECIALIST:
777 source.value.specialist = specialist_by_number(value);
778 return source;
779 case VUT_MINSIZE:
780 source.value.minsize = value;
781 return source;
782 case VUT_MINCULTURE:
783 source.value.minculture = value;
784 return source;
785 case VUT_MINFOREIGNPCT:
786 source.value.minforeignpct = value;
787 return source;
788 case VUT_AI_LEVEL:
789 source.value.ai_level = value;
790 return source;
791 case VUT_MAXTILEUNITS:
792 source.value.max_tile_units = value;
793 return source;
794 case VUT_TERRAINCLASS:
795 source.value.terrainclass = value;
796 return source;
797 case VUT_ROADFLAG:
798 source.value.roadflag = value;
799 return source;
800 case VUT_EXTRAFLAG:
801 source.value.extraflag = value;
802 return source;
803 case VUT_MINYEAR:
804 source.value.minyear = value;
805 return source;
806 case VUT_MINCALFRAG:
807 source.value.mincalfrag = value;
808 return source;
809 case VUT_TOPO:
810 source.value.topo_property = value;
811 return source;
812 case VUT_WRAP:
813 source.value.wrap_property = value;
814 return source;
815 case VUT_SERVERSETTING:
816 source.value.ssetval = value;
817 return source;
818 case VUT_TERRAINALTER:
819 source.value.terrainalter = value;
820 return source;
821 case VUT_CITYTILE:
822 source.value.citytile = value;
823 return source;
824 case VUT_CITYSTATUS:
825 source.value.citystatus = value;
826 return source;
827 case VUT_PLAYER_STATE:
828 source.value.plrstate = value;
829 return source;
830 case VUT_COUNTER:
831 source.value.counter = counter_by_id(value);
832 return source;
833 case VUT_MINLATITUDE:
834 case VUT_MAXLATITUDE:
835 source.value.latitude = value;
836 return source;
837 case VUT_COUNT:
838 break;
839 }
840
841 /* If we reach here there's been an error. */
842 source.kind = universals_n_invalid();
843 /* Avoid compiler warning about unitialized source.value */
844 source.value.advance = NULL;
845
846 return source;
847}
848
849/**********************************************************************/
852 void universal_copy(struct universal *dst, const struct universal *src)
853{
854 dst->value = src->value;
855 dst->kind = src->kind;
856}
857
858/**********************************************************************/
862 void universal_extraction(const struct universal *source,
863 int *kind, int *value)
864{
865 *kind = source->kind;
866 *value = universal_number(source);
867}
868
869/**********************************************************************/
872 int universal_number(const struct universal *source)
873{
874 switch (source->kind) {
875 case VUT_NONE:
876 return 0;
877 case VUT_ADVANCE:
878 return advance_number(source->value.advance);
879 case VUT_TECHFLAG:
880 return source->value.techflag;
881 case VUT_GOVERNMENT:
882 return government_number(source->value.govern);
883 case VUT_ACHIEVEMENT:
884 return achievement_number(source->value.achievement);
885 case VUT_STYLE:
886 return style_number(source->value.style);
887 case VUT_IMPROVEMENT:
888 return improvement_number(source->value.building);
889 case VUT_IMPR_GENUS:
890 return source->value.impr_genus;
891 case VUT_IMPR_FLAG:
892 return source->value.impr_flag;
893 case VUT_PLAYER_FLAG:
894 return source->value.plr_flag;
895 case VUT_EXTRA:
896 return extra_number(source->value.extra);
897 case VUT_GOOD:
898 return goods_number(source->value.good);
899 case VUT_TERRAIN:
900 return terrain_number(source->value.terrain);
901 case VUT_TERRFLAG:
902 return source->value.terrainflag;
903 case VUT_NATION:
904 return nation_number(source->value.nation);
905 case VUT_NATIONGROUP:
906 return nation_group_number(source->value.nationgroup);
907 case VUT_NATIONALITY:
908 return nation_number(source->value.nationality);
909 case VUT_ORIGINAL_OWNER:
910 return nation_number(source->value.origowner);
911 case VUT_DIPLREL:
912 case VUT_DIPLREL_TILE:
913 case VUT_DIPLREL_TILE_O:
914 case VUT_DIPLREL_UNITANY:
915 case VUT_DIPLREL_UNITANY_O:
916 return source->value.diplrel;
917 case VUT_UTYPE:
918 return utype_number(source->value.utype);
919 case VUT_UTFLAG:
920 return source->value.unitflag;
921 case VUT_UCLASS:
922 return uclass_number(source->value.uclass);
923 case VUT_UCFLAG:
924 return source->value.unitclassflag;
925 case VUT_MINVETERAN:
926 return source->value.minveteran;
927 case VUT_UNITSTATE:
928 return source->value.unit_state;
929 case VUT_ACTIVITY:
930 return source->value.activity;
931 case VUT_MINMOVES:
932 return source->value.minmoves;
933 case VUT_MINHP:
934 return source->value.min_hit_points;
935 case VUT_AGE:
936 return source->value.age;
937 case VUT_FORM_AGE:
938 return source->value.form_age;
939 case VUT_MINTECHS:
940 return source->value.min_techs;
941 case VUT_ACTION:
942 return action_number(source->value.action);
943 case VUT_OTYPE:
944 return source->value.outputtype;
945 case VUT_SPECIALIST:
946 return specialist_number(source->value.specialist);
947 case VUT_MINSIZE:
948 return source->value.minsize;
949 case VUT_MINCULTURE:
950 return source->value.minculture;
951 case VUT_MINFOREIGNPCT:
952 return source->value.minforeignpct;
953 case VUT_AI_LEVEL:
954 return source->value.ai_level;
955 case VUT_MAXTILEUNITS:
956 return source->value.max_tile_units;
957 case VUT_TERRAINCLASS:
958 return source->value.terrainclass;
959 case VUT_ROADFLAG:
960 return source->value.roadflag;
961 case VUT_EXTRAFLAG:
962 return source->value.extraflag;
963 case VUT_MINYEAR:
964 return source->value.minyear;
965 case VUT_MINCALFRAG:
966 return source->value.mincalfrag;
967 case VUT_TOPO:
968 return source->value.topo_property;
969 case VUT_WRAP:
970 return source->value.wrap_property;
971 case VUT_SERVERSETTING:
972 return source->value.ssetval;
973 case VUT_TERRAINALTER:
974 return source->value.terrainalter;
975 case VUT_CITYTILE:
976 return source->value.citytile;
977 case VUT_CITYSTATUS:
978 return source->value.citystatus;
979 case VUT_PLAYER_STATE:
980 return source->value.plrstate;
981 case VUT_COUNTER:
982 return counter_id(source->value.counter);
983 case VUT_MINLATITUDE:
984 case VUT_MAXLATITUDE:
985 return source->value.latitude;
986 case VUT_COUNT:
987 break;
988 }
989
990 /* If we reach here there's been an error. */
991 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
992 source->kind);
993 return 0;
994}
995
996
997/**********************************************************************/
1000 const struct req_context *req_context_empty(void)
1001{
1002 static const struct req_context empty = {};
1003 return &empty;
1004}
1005
1006
1007/**********************************************************************/
1015 const char *req_to_fstring(const struct requirement *req,
1016 struct astring *astr)
1017{
1018 astr_init(astr);
1019
1020 astr_set(astr, "%s%s %s %s%s",
1021 req->survives ? "surviving " : "",
1022 req_range_name(req->range),
1023 universal_type_rule_name(&req->source),
1024 req->present ? "" : "!",
1025 universal_rule_name(&req->source));
1026
1027 return astr_str(astr);
1028}
1029
1030/**********************************************************************/
1037 struct requirement req_from_str(const char *type, const char *range,
1038 bool survives, bool present, bool quiet,
1039 const char *value)
1040{
1041 struct requirement req;
1042 bool invalid;
1043 const char *error = NULL;
1044
1045 req.source = universal_by_rule_name(type, value);
1046
1047 invalid = !universals_n_is_valid(req.source.kind);
1048 if (invalid) {
1049 error = "bad type or name";
1050 } else {
1051 /* Scan the range string to find the range. If no range is given a
1052 * default fallback is used rather than giving an error. */
1053 if (range != NULL) {
1054 req.range = req_range_by_name(range, fc_strcasecmp);
1055 if (!req_range_is_valid(req.range)) {
1056 invalid = TRUE;
1057 }
1058 } else {
1059 switch (req.source.kind) {
1060 case VUT_NONE:
1061 case VUT_COUNT:
1062 break;
1063 case VUT_IMPROVEMENT:
1064 case VUT_IMPR_GENUS:
1065 case VUT_IMPR_FLAG:
1066 case VUT_UTYPE:
1067 case VUT_UTFLAG:
1068 case VUT_UCLASS:
1069 case VUT_UCFLAG:
1070 case VUT_MINVETERAN:
1071 case VUT_UNITSTATE:
1072 case VUT_ACTIVITY:
1073 case VUT_MINMOVES:
1074 case VUT_MINHP:
1075 case VUT_AGE:
1076 case VUT_FORM_AGE:
1077 case VUT_ACTION:
1078 case VUT_OTYPE:
1079 case VUT_SPECIALIST:
1080 case VUT_DIPLREL_TILE_O:
1081 case VUT_DIPLREL_UNITANY_O:
1082 req.range = REQ_RANGE_LOCAL;
1083 break;
1084 case VUT_EXTRA:
1085 case VUT_ROADFLAG:
1086 case VUT_EXTRAFLAG:
1087 /* keep old behavior */
1088 req.range = REQ_RANGE_TILE;
1089 break;
1090 case VUT_TERRAIN:
1091 case VUT_TERRFLAG:
1092 case VUT_TERRAINCLASS:
1093 case VUT_TERRAINALTER:
1094 case VUT_CITYTILE:
1095 case VUT_MAXTILEUNITS:
1096 case VUT_MINLATITUDE:
1097 case VUT_MAXLATITUDE:
1098 req.range = REQ_RANGE_TILE;
1099 break;
1100 case VUT_COUNTER:
1101 case VUT_MINSIZE:
1102 case VUT_MINCULTURE:
1103 case VUT_MINFOREIGNPCT:
1104 case VUT_NATIONALITY:
1105 case VUT_ORIGINAL_OWNER:
1106 case VUT_CITYSTATUS:
1107 case VUT_GOOD:
1108 req.range = REQ_RANGE_CITY;
1109 break;
1110 case VUT_GOVERNMENT:
1111 case VUT_ACHIEVEMENT:
1112 case VUT_STYLE:
1113 case VUT_ADVANCE:
1114 case VUT_TECHFLAG:
1115 case VUT_NATION:
1116 case VUT_NATIONGROUP:
1117 case VUT_DIPLREL:
1118 case VUT_DIPLREL_TILE:
1119 case VUT_DIPLREL_UNITANY:
1120 case VUT_AI_LEVEL:
1121 case VUT_PLAYER_FLAG:
1122 case VUT_PLAYER_STATE:
1123 req.range = REQ_RANGE_PLAYER;
1124 break;
1125 case VUT_MINYEAR:
1126 case VUT_MINCALFRAG:
1127 case VUT_TOPO:
1128 case VUT_WRAP:
1129 case VUT_MINTECHS:
1130 case VUT_SERVERSETTING:
1131 req.range = REQ_RANGE_WORLD;
1132 break;
1133 }
1134 }
1135
1136 req.survives = survives;
1137 req.present = present;
1138 req.quiet = quiet;
1139
1140 /* These checks match what combinations are supported inside
1141 * is_req_active(). However, it's only possible to do basic checks,
1142 * not anything that might depend on the rest of the ruleset which
1143 * might not have been loaded yet. */
1144 switch (req.source.kind) {
1145 case VUT_TERRAIN:
1146 case VUT_TERRAINCLASS:
1147 case VUT_TERRFLAG:
1148 invalid = (req.range != REQ_RANGE_TILE
1149 && req.range != REQ_RANGE_CADJACENT
1150 && req.range != REQ_RANGE_ADJACENT
1151 && req.range != REQ_RANGE_CITY
1152 && req.range != REQ_RANGE_TRADE_ROUTE);
1153 break;
1154 case VUT_EXTRA:
1155 case VUT_ROADFLAG:
1156 case VUT_EXTRAFLAG:
1157 invalid = (req.range > REQ_RANGE_TRADE_ROUTE);
1158 break;
1159 case VUT_ADVANCE:
1160 case VUT_TECHFLAG:
1161 case VUT_ACHIEVEMENT:
1162 case VUT_MINTECHS:
1163 invalid = (req.range < REQ_RANGE_PLAYER);
1164 break;
1165 case VUT_GOVERNMENT:
1166 case VUT_AI_LEVEL:
1167 case VUT_STYLE:
1168 invalid = (req.range != REQ_RANGE_PLAYER);
1169 break;
1170 case VUT_MINSIZE:
1171 case VUT_MINFOREIGNPCT:
1172 case VUT_NATIONALITY:
1173 case VUT_CITYSTATUS:
1174 invalid = (req.range != REQ_RANGE_CITY
1175 && req.range != REQ_RANGE_TRADE_ROUTE);
1176 break;
1177 case VUT_GOOD:
1178 case VUT_ORIGINAL_OWNER:
1179 invalid = (req.range != REQ_RANGE_CITY);
1180 break;
1181 case VUT_MINCULTURE:
1182 invalid = (req.range != REQ_RANGE_CITY
1183 && req.range != REQ_RANGE_TRADE_ROUTE
1184 && req.range != REQ_RANGE_PLAYER
1185 && req.range != REQ_RANGE_TEAM
1186 && req.range != REQ_RANGE_ALLIANCE
1187 && req.range != REQ_RANGE_WORLD);
1188 break;
1189 case VUT_DIPLREL:
1190 invalid = (req.range != REQ_RANGE_LOCAL
1191 && req.range != REQ_RANGE_PLAYER
1192 && req.range != REQ_RANGE_TEAM
1193 && req.range != REQ_RANGE_ALLIANCE
1194 && req.range != REQ_RANGE_WORLD)
1195 /* Non local foreign makes no sense. */
1196 || (req.source.value.diplrel == DRO_FOREIGN
1197 && req.range != REQ_RANGE_LOCAL);
1198 break;
1199 case VUT_DIPLREL_TILE:
1200 invalid = (req.range != REQ_RANGE_LOCAL
1201 && req.range != REQ_RANGE_PLAYER
1202 && req.range != REQ_RANGE_TEAM
1203 && req.range != REQ_RANGE_ALLIANCE)
1204 /* Non local foreign makes no sense. */
1205 || (req.source.value.diplrel == DRO_FOREIGN
1206 && req.range != REQ_RANGE_LOCAL);
1207 break;
1208 case VUT_DIPLREL_TILE_O:
1209 invalid = (req.range != REQ_RANGE_LOCAL);
1210 break;
1211 case VUT_DIPLREL_UNITANY:
1212 invalid = (req.range != REQ_RANGE_LOCAL
1213 && req.range != REQ_RANGE_PLAYER
1214 && req.range != REQ_RANGE_TEAM
1215 && req.range != REQ_RANGE_ALLIANCE)
1216 /* Non local foreign makes no sense. */
1217 || (req.source.value.diplrel == DRO_FOREIGN
1218 && req.range != REQ_RANGE_LOCAL);
1219 break;
1220 case VUT_DIPLREL_UNITANY_O:
1221 invalid = (req.range != REQ_RANGE_LOCAL);
1222 break;
1223 case VUT_NATION:
1224 case VUT_NATIONGROUP:
1225 invalid = (req.range != REQ_RANGE_PLAYER
1226 && req.range != REQ_RANGE_TEAM
1227 && req.range != REQ_RANGE_ALLIANCE
1228 && req.range != REQ_RANGE_WORLD);
1229 break;
1230 case VUT_UTYPE:
1231 case VUT_UTFLAG:
1232 case VUT_UCLASS:
1233 case VUT_UCFLAG:
1234 case VUT_MINVETERAN:
1235 case VUT_UNITSTATE:
1236 case VUT_ACTIVITY:
1237 case VUT_MINMOVES:
1238 case VUT_MINHP:
1239 case VUT_ACTION:
1240 case VUT_OTYPE:
1241 case VUT_SPECIALIST:
1242 invalid = (req.range != REQ_RANGE_LOCAL);
1243 break;
1244 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1245 invalid = (req.range != REQ_RANGE_TILE);
1246 break;
1247 case VUT_CITYTILE:
1248 case VUT_MAXTILEUNITS:
1249 invalid = (req.range != REQ_RANGE_TILE
1250 && req.range != REQ_RANGE_CADJACENT
1251 && req.range != REQ_RANGE_ADJACENT);
1252 break;
1253 case VUT_MINLATITUDE:
1254 case VUT_MAXLATITUDE:
1255 invalid = (req.range != REQ_RANGE_TILE
1256 && req.range != REQ_RANGE_CADJACENT
1257 && req.range != REQ_RANGE_ADJACENT
1258 && req.range != REQ_RANGE_WORLD)
1259 /* Avoid redundancy at tile range: no negated requirements
1260 * that could be emulated by a present requirement of the
1261 * other type */
1262 || (req.range == REQ_RANGE_TILE && !req.present);
1263 break;
1264 case VUT_MINYEAR:
1265 case VUT_MINCALFRAG:
1266 case VUT_TOPO:
1267 case VUT_WRAP:
1268 case VUT_SERVERSETTING:
1269 invalid = (req.range != REQ_RANGE_WORLD);
1270 break;
1271 case VUT_AGE:
1272 /* FIXME: could support TRADE_ROUTE, TEAM, etc */
1273 invalid = (req.range != REQ_RANGE_LOCAL
1274 && req.range != REQ_RANGE_CITY
1275 && req.range != REQ_RANGE_PLAYER);
1276 break;
1277 case VUT_FORM_AGE:
1278 invalid = (req.range != REQ_RANGE_LOCAL);
1279 break;
1280 case VUT_IMPR_GENUS:
1281 /* TODO: Support other ranges too. */
1282 invalid = (req.range != REQ_RANGE_LOCAL);
1283 break;
1284 case VUT_IMPR_FLAG:
1285 invalid = (req.range != REQ_RANGE_LOCAL
1286 && req.range != REQ_RANGE_TILE
1287 && req.range != REQ_RANGE_CITY);
1288 break;
1289 case VUT_COUNTER:
1290 invalid = req.range != REQ_RANGE_CITY;
1291 break;
1292 case VUT_PLAYER_FLAG:
1293 case VUT_PLAYER_STATE:
1294 invalid = (req.range != REQ_RANGE_PLAYER);
1295 break;
1296 case VUT_IMPROVEMENT:
1297 /* Valid ranges depend on the building genus (wonder/improvement),
1298 * which might not have been loaded from the ruleset yet.
1299 * So we allow anything here, and do a proper check once ruleset
1300 * loading is complete, in sanity_check_req_individual(). */
1301 case VUT_NONE:
1302 invalid = FALSE;
1303 break;
1304 case VUT_COUNT:
1305 break;
1306 }
1307 if (invalid) {
1308 error = "bad range";
1309 }
1310 }
1311
1312 if (!invalid) {
1313 /* Check 'survives'. */
1314 switch (req.source.kind) {
1315 case VUT_IMPROVEMENT:
1316 /* See buildings_in_range(). */
1317 invalid = survives && req.range <= REQ_RANGE_CONTINENT;
1318 break;
1319 case VUT_NATION:
1320 case VUT_ADVANCE:
1321 invalid = survives && req.range != REQ_RANGE_WORLD;
1322 break;
1323 case VUT_COUNTER:
1324 case VUT_IMPR_GENUS:
1325 case VUT_IMPR_FLAG:
1326 case VUT_PLAYER_FLAG:
1327 case VUT_PLAYER_STATE:
1328 case VUT_GOVERNMENT:
1329 case VUT_TERRAIN:
1330 case VUT_UTYPE:
1331 case VUT_UTFLAG:
1332 case VUT_UCLASS:
1333 case VUT_UCFLAG:
1334 case VUT_MINVETERAN:
1335 case VUT_UNITSTATE:
1336 case VUT_ACTIVITY:
1337 case VUT_MINMOVES:
1338 case VUT_MINHP:
1339 case VUT_AGE:
1340 case VUT_FORM_AGE:
1341 case VUT_ACTION:
1342 case VUT_OTYPE:
1343 case VUT_SPECIALIST:
1344 case VUT_MINSIZE:
1345 case VUT_MINCULTURE:
1346 case VUT_MINFOREIGNPCT:
1347 case VUT_AI_LEVEL:
1348 case VUT_TERRAINCLASS:
1349 case VUT_MINYEAR:
1350 case VUT_MINCALFRAG:
1351 case VUT_TOPO:
1352 case VUT_WRAP:
1353 case VUT_SERVERSETTING:
1354 case VUT_TERRAINALTER:
1355 case VUT_CITYTILE:
1356 case VUT_CITYSTATUS:
1357 case VUT_TERRFLAG:
1358 case VUT_NATIONALITY:
1359 case VUT_ORIGINAL_OWNER:
1360 case VUT_ROADFLAG:
1361 case VUT_EXTRAFLAG:
1362 case VUT_EXTRA:
1363 case VUT_GOOD:
1364 case VUT_TECHFLAG:
1365 case VUT_ACHIEVEMENT:
1366 case VUT_NATIONGROUP:
1367 case VUT_STYLE:
1368 case VUT_DIPLREL:
1369 case VUT_DIPLREL_TILE:
1370 case VUT_DIPLREL_TILE_O:
1371 case VUT_DIPLREL_UNITANY:
1372 case VUT_DIPLREL_UNITANY_O:
1373 case VUT_MAXTILEUNITS:
1374 case VUT_MINTECHS:
1375 case VUT_MINLATITUDE:
1376 case VUT_MAXLATITUDE:
1377 /* Most requirements don't support 'survives'. */
1378 invalid = survives;
1379 break;
1380 case VUT_NONE:
1381 case VUT_COUNT:
1382 break;
1383 }
1384 if (invalid) {
1385 error = "bad 'survives'";
1386 }
1387 }
1388
1389 if (invalid) {
1390 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1391 type, range, survives ? "survives" : "",
1392 present ? "present" : "", value, error);
1393 req.source.kind = universals_n_invalid();
1394 }
1395
1396 return req;
1397}
1398
1399/**********************************************************************/
1403 struct requirement req_from_values(int type, int range,
1404 bool survives, bool present, bool quiet,
1405 int value)
1406{
1407 struct requirement req;
1408
1409 req.source = universal_by_number(type, value);
1410 req.range = range;
1411 req.survives = survives;
1412 req.present = present;
1413 req.quiet = quiet;
1414
1415 return req;
1416}
1417
1418/**********************************************************************/
1422 void req_get_values(const struct requirement *req,
1423 int *type, int *range,
1424 bool *survives, bool *present, bool *quiet,
1425 int *value)
1426{
1427 universal_extraction(&req->source, type, value);
1428 *range = req->range;
1429 *survives = req->survives;
1430 *present = req->present;
1431 *quiet = req->quiet;
1432}
1433
1434/**********************************************************************/
1437 void req_copy(struct requirement *dst, const struct requirement *src)
1438{
1439 universal_copy(&(dst->source), &(src->source));
1440 dst->range = src->range;
1441 dst->survives = src->survives;
1442 dst->present = src->present;
1443 dst->quiet = src->quiet;
1444}
1445
1446/**********************************************************************/
1450 bool are_requirements_equal(const struct requirement *req1,
1451 const struct requirement *req2)
1452{
1453 return (are_universals_equal(&req1->source, &req2->source)
1454 && req1->range == req2->range
1455 && req1->survives == req2->survives
1456 && req1->present == req2->present);
1457}
1458
1459/**********************************************************************/
1462 static bool are_requirements_opposites(const struct requirement *req1,
1463 const struct requirement *req2)
1464{
1465 return (are_universals_equal(&req1->source, &req2->source)
1466 && req1->range == req2->range
1467 && req1->survives == req2->survives
1468 && req1->present != req2->present);
1469}
1470
1471/**********************************************************************/
1475 static bool impr_contra_genus(const struct requirement *impr_req,
1476 const struct requirement *genus_req)
1477{
1478 /* The input is sane. */
1479 fc_assert_ret_val(impr_req->source.kind == VUT_IMPROVEMENT, FALSE);
1480 fc_assert_ret_val(genus_req->source.kind == VUT_IMPR_GENUS, FALSE);
1481
1482 if (impr_req->range == REQ_RANGE_LOCAL
1483 && genus_req->range == REQ_RANGE_LOCAL) {
1484 /* Applies to the same target building. */
1485
1486 if (impr_req->present && !genus_req->present) {
1487 /* The target building can't not have the genus it has. */
1488 return (impr_req->source.value.building->genus
1489 == genus_req->source.value.impr_genus);
1490 }
1491
1492 if (impr_req->present && genus_req->present) {
1493 /* The target building can't have another genus than it has. */
1494 return (impr_req->source.value.building->genus
1495 != genus_req->source.value.impr_genus);
1496 }
1497 }
1498
1499 /* No special knowledge. */
1500 return FALSE;
1501}
1502
1503/**********************************************************************/
1507 static bool impr_contra_flag(const struct requirement *impr_req,
1508 const struct requirement *flag_req)
1509{
1510 /* The input is sane. */
1511 fc_assert_ret_val(impr_req->source.kind == VUT_IMPROVEMENT, FALSE);
1512 fc_assert_ret_val(flag_req->source.kind == VUT_IMPR_FLAG, FALSE);
1513
1514 if (impr_req->range == REQ_RANGE_LOCAL
1515 && flag_req->range == REQ_RANGE_LOCAL) {
1516 /* Applies to the same target building. */
1517
1518 if (impr_req->present && !flag_req->present) {
1519 /* The target building can't not have the flag it has. */
1520 return improvement_has_flag(impr_req->source.value.building,
1521 flag_req->source.value.impr_flag);
1522 }
1523
1524 if (impr_req->present && flag_req->present) {
1525 /* The target building can't have another flag than it has. */
1526 return !improvement_has_flag(impr_req->source.value.building,
1527 flag_req->source.value.impr_flag);
1528 }
1529 }
1530
1531 /* No special knowledge. */
1532 return FALSE;
1533}
1534
1535/**********************************************************************/
1539 static bool nation_contra_group(const struct requirement *nation_req,
1540 const struct requirement *group_req)
1541{
1542 /* The input is sane. */
1543 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1544 fc_assert_ret_val(group_req->source.kind == VUT_NATIONGROUP, FALSE);
1545
1546 if (nation_req->range == REQ_RANGE_PLAYER
1547 && group_req->range == REQ_RANGE_PLAYER) {
1548 /* Applies to the same target building. */
1549
1550 if (nation_req->present && !group_req->present) {
1551 /* The target nation can't be in the group. */
1552 return nation_is_in_group(nation_req->source.value.nation,
1553 group_req->source.value.nationgroup);
1554 }
1555 }
1556
1557 /* No special knowledge. */
1558 return FALSE;
1559}
1560
1561/**********************************************************************/
1565 static bool city_center_contra(const struct requirement *cc_req,
1566 const struct requirement *ct_req)
1567{
1568 /* The input is sane. */
1569 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1570 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1571
1572 if (cc_req->source.value.citytile == CITYT_CENTER
1573 && cc_req->present && cc_req->range <= ct_req->range) {
1574 switch (ct_req->source.value.citytile) {
1575 case CITYT_CENTER:
1576 case CITYT_CLAIMED:
1577 case CITYT_EXTRAS_OWNED:
1578 case CITYT_WORKED:
1579 case CITYT_SAME_CONTINENT:
1580 /* Should be always on city center */
1581 return !ct_req->present;
1582 case CITYT_BORDERING_TCLASS_REGION:
1583 /* Handled later */
1584 break;
1585 case CITYT_LAST:
1586 /* Error */
1587 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1588 }
1589 }
1590 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1591 || cc_req->source.value.citytile == CITYT_CENTER)
1592 && ct_req->source.value.citytile
1593 == CITYT_BORDERING_TCLASS_REGION
1594 && REQ_RANGE_TILE == cc_req->range
1595 && REQ_RANGE_TILE == ct_req->range) {
1596 /* Can't coexist */
1597 return cc_req->present ? ct_req->present : !ct_req->present;
1598 }
1599
1600 return FALSE;
1601}
1602
1603/**********************************************************************/
1608 static bool present_implies_not_present(const struct requirement *req1,
1609 const struct requirement *req2)
1610{
1611 const struct requirement *absent, *present;
1612
1613 if (req1->present == req2->present) {
1614 /* Can't use the knowledge in universal_found_function when both are
1615 * required to be absent or when both are required to be present.
1616 * It is no contradiction to require !Spy unit and !Missile unit class.
1617 * It is no contradiction to require River and Irrigation at the same
1618 * tile. */
1619 return FALSE;
1620 }
1621
1622 if (req1->present) {
1623 absent = req2;
1624 present = req1;
1625 } else {
1626 absent = req1;
1627 present = req2;
1628 }
1629
1630 if (!universal_found_function[present->source.kind]) {
1631 /* No knowledge to exploit. */
1632 return FALSE;
1633 }
1634
1635 if (present->range != absent->range) {
1636 /* Larger ranges are not always strict supersets of smaller ranges.
1637 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1638 * but not in Trade Route. */
1639 return FALSE;
1640 }
1641
1642 return ITF_YES == universal_fulfills_requirement(absent,
1643 &present->source);
1644}
1645
1646/**********************************************************************/
1649 bool req_implies_req(const struct requirement *req1,
1650 const struct requirement *req2)
1651{
1652 struct requirement nreq2;
1653
1654 req_copy(&nreq2, req2);
1655 nreq2.present = !nreq2.present;
1656 return are_requirements_contradictions(req1, &nreq2);
1657}
1658
1659/**********************************************************************/
1666 bool are_requirements_contradictions(const struct requirement *req1,
1667 const struct requirement *req2)
1668{
1669 if (are_requirements_opposites(req1, req2)) {
1670 /* The exact opposite. */
1671 return TRUE;
1672 }
1673
1674 if (present_implies_not_present(req1, req2)) {
1675 return TRUE;
1676 }
1677
1678 switch (req1->source.kind) {
1679 case VUT_IMPROVEMENT:
1680 if (req2->source.kind == VUT_IMPR_GENUS) {
1681 return impr_contra_genus(req1, req2);
1682 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1683 return impr_contra_flag(req1, req2);
1684 } else if (req2->source.kind == VUT_CITYTILE
1685 && req2->source.value.citytile == CITYT_CENTER
1686 && REQ_RANGE_TILE == req2->range
1687 && REQ_RANGE_TILE == req1->range
1688 && req1->present) {
1689 /* A building must be in a city */
1690 return !req2->present;
1691 }
1692
1693 /* No special knowledge. */
1694 return FALSE;
1695 case VUT_IMPR_GENUS:
1696 if (req2->source.kind == VUT_IMPROVEMENT) {
1697 return impr_contra_genus(req2, req1);
1698 }
1699
1700 /* No special knowledge. */
1701 return FALSE;
1702 case VUT_IMPR_FLAG:
1703 if (req2->source.kind == VUT_IMPROVEMENT) {
1704 return impr_contra_flag(req2, req1);
1705 }
1706
1707 /* No special knowledge. */
1708 return FALSE;
1709 case VUT_DIPLREL:
1710 case VUT_DIPLREL_TILE:
1711 case VUT_DIPLREL_TILE_O:
1712 case VUT_DIPLREL_UNITANY:
1713 case VUT_DIPLREL_UNITANY_O:
1714 if (req2->source.kind != req1->source.kind) {
1715 /* Finding contradictions across requirement kinds aren't supported
1716 * for DiplRel requirements. */
1717 return FALSE;
1718 } else {
1719 /* Use the special knowledge about DiplRel requirements to find
1720 * contradictions. */
1721
1722 bv_diplrel_all_reqs req1_contra;
1723 int req2_pos;
1724
1725 req1_contra = diplrel_req_contradicts(req1);
1726 req2_pos = requirement_diplrel_ereq(req2->source.value.diplrel,
1727 req2->range,
1728 req2->present);
1729
1730 return BV_ISSET(req1_contra, req2_pos);
1731 }
1732 break;
1733 case VUT_MINMOVES:
1734 if (req2->source.kind != VUT_MINMOVES) {
1735 /* Finding contradictions across requirement kinds aren't supported
1736 * for MinMoveFrags requirements. */
1737 return FALSE;
1738 } else if (req1->present == req2->present) {
1739 /* No contradiction possible. */
1740 return FALSE;
1741 } else {
1742 /* Number of move fragments left can't be larger than the number
1743 * required to be present and smaller than the number required to not
1744 * be present when the number required to be present is smaller than
1745 * the number required to not be present. */
1746 if (req1->present) {
1747 return req1->source.value.minmoves >= req2->source.value.minmoves;
1748 } else {
1749 return req1->source.value.minmoves <= req2->source.value.minmoves;
1750 }
1751 }
1752 break;
1753 case VUT_MINLATITUDE:
1754 case VUT_MAXLATITUDE:
1755 if (req2->source.kind != VUT_MINLATITUDE
1756 && req2->source.kind != VUT_MAXLATITUDE) {
1757 /* Finding contradictions across requirement kinds other than each
1758 * other is not supported for MinLatitude and MaxLatitude. */
1759 return FALSE;
1760 } else {
1761 /* For a contradiction, we need
1762 * - a minimum (present MinLatitude or negated MaxLatitude)
1763 * - a maximum (negated MinLatitude or present MaxLatitude)
1764 * - the maximum to be less than the minimum
1765 * - a requirement at the larger range that applies to the entire
1766 * range (i.e. a negated requirement, unless the range is Tile)
1767 * Otherwise, the two requirements could still be fulfilled
1768 * simultaneously by different tiles in the range */
1769
1770 /* Initial values beyond the boundaries to avoid edge cases */
1771 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
1772 enum req_range covered_range = REQ_RANGE_TILE;
1773
1774#define EXTRACT_INFO(req) \
1775 if (req->present) { \
1776 if (req->source.kind == VUT_MINLATITUDE) { \
1777 /* present MinLatitude */ \
1778 minimum = MAX(minimum, req->source.value.latitude); \
1779 } else { \
1780 /* present MaxLatitude */ \
1781 maximum = MIN(maximum, req->source.value.latitude); \
1782 } \
1783 } else { \
1784 covered_range = MAX(covered_range, req->range); \
1785 if (req->source.kind == VUT_MINLATITUDE) { \
1786 /* negated MinLatitude */ \
1787 maximum = MIN(maximum, req->source.value.latitude - 1); \
1788 } else { \
1789 /* negated MaxLatitude */ \
1790 minimum = MAX(minimum, req->source.value.latitude + 1); \
1791 } \
1792 }
1793
1794 EXTRACT_INFO(req1);
1795 EXTRACT_INFO(req2);
1796
1797#undef EXTRACT_INFO
1798
1799 return (maximum < minimum
1800 && covered_range >= req1->range
1801 && covered_range >= req2->range);
1802 }
1803 break;
1804 case VUT_NATION:
1805 if (req2->source.kind == VUT_NATIONGROUP) {
1806 return nation_contra_group(req1, req2);
1807 }
1808
1809 /* No special knowledge. */
1810 return FALSE;
1811 break;
1812 case VUT_NATIONGROUP:
1813 if (req2->source.kind == VUT_NATION) {
1814 return nation_contra_group(req2, req1);
1815 }
1816
1817 /* No special knowledge. */
1818 return FALSE;
1819 break;
1820 case VUT_CITYTILE:
1821 if (req2->source.kind == VUT_CITYTILE) {
1822 return city_center_contra(req1, req2)
1823 || city_center_contra(req2, req1);
1824 } else if (req1->source.value.citytile == CITYT_CENTER
1825 && req2->source.kind == VUT_IMPROVEMENT
1826 && REQ_RANGE_TILE == req2->range
1827 && REQ_RANGE_TILE == req1->range
1828 && req2->present) {
1829 /* A building must be in a city */
1830 return !req1->present;
1831 }
1832
1833 return FALSE;
1834 default:
1835 /* No special knowledge exists. The requirements aren't the exact
1836 * opposite of each other per the initial check. */
1837 return FALSE;
1838 }
1839}
1840
1841/**********************************************************************/
1845 bool does_req_contradicts_reqs(const struct requirement *req,
1846 const struct requirement_vector *vec)
1847{
1848 /* If the requirement is contradicted by any requirement in the vector it
1849 * contradicts the entire requirement vector. */
1850 requirement_vector_iterate(vec, preq) {
1851 if (are_requirements_contradictions(req, preq)) {
1852 return TRUE;
1853 }
1854 } requirement_vector_iterate_end;
1855
1856 /* Not a singe requirement in the requirement vector is contradicted be
1857 * the specified requirement. */
1858 return FALSE;
1859}
1860
1861/**********************************************************************/
1864 static inline bool are_tiles_in_range(const struct tile *tile1,
1865 const struct tile *tile2,
1866 enum req_range range)
1867{
1868 switch (range) {
1869 case REQ_RANGE_ADJACENT:
1870 if (is_tiles_adjacent(tile1, tile2)) {
1871 return TRUE;
1872 }
1873 fc__fallthrough;
1874 case REQ_RANGE_TILE:
1875 return same_pos(tile1, tile2);
1876 case REQ_RANGE_CADJACENT:
1877 return map_distance(tile1, tile2) <= 1;
1878 case REQ_RANGE_CITY:
1879 case REQ_RANGE_TRADE_ROUTE:
1880 case REQ_RANGE_LOCAL:
1881 case REQ_RANGE_CONTINENT:
1882 case REQ_RANGE_PLAYER:
1883 case REQ_RANGE_TEAM:
1884 case REQ_RANGE_ALLIANCE:
1885 case REQ_RANGE_WORLD:
1886 case REQ_RANGE_COUNT:
1887 /* Invalid */
1888 fc_assert(FALSE);
1889 }
1890 return FALSE;
1891}
1892
1893/**********************************************************************/
1896 static inline bool players_in_same_range(const struct player *pplayer1,
1897 const struct player *pplayer2,
1898 enum req_range range)
1899{
1900 switch (range) {
1901 case REQ_RANGE_WORLD:
1902 return TRUE;
1903 case REQ_RANGE_ALLIANCE:
1904 return pplayers_allied(pplayer1, pplayer2);
1905 case REQ_RANGE_TEAM:
1906 return players_on_same_team(pplayer1, pplayer2);
1907 case REQ_RANGE_PLAYER:
1908 return pplayer1 == pplayer2;
1909 case REQ_RANGE_CONTINENT:
1910 case REQ_RANGE_TRADE_ROUTE:
1911 case REQ_RANGE_CITY:
1912 case REQ_RANGE_ADJACENT:
1913 case REQ_RANGE_CADJACENT:
1914 case REQ_RANGE_TILE:
1915 case REQ_RANGE_LOCAL:
1916 case REQ_RANGE_COUNT:
1917 break;
1918 }
1919
1920 fc_assert_msg(FALSE, "Invalid range %d.", range);
1921 return FALSE;
1922}
1923
1924#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
1925{ \
1926 fc_assert_ret_val(req != NULL, TRI_MAYBE); \
1927 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
1928 fc_assert(context != NULL); \
1929}
1930
1931/**********************************************************************/
1938static enum fc_tristate
1939is_none_req_active(const struct civ_map *nmap,
1940 const struct req_context *context,
1941 const struct player *other_player,
1942 const struct requirement *req)
1943{
1944 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NONE);
1945
1946 return TRI_YES;
1947}
1948
1949/**********************************************************************/
1953 static int num_world_buildings_total(const struct impr_type *building)
1954{
1955 if (is_great_wonder(building)) {
1956 return (great_wonder_is_built(building)
1957 || great_wonder_is_destroyed(building) ? 1 : 0);
1958 } else {
1959 log_error("World-ranged requirements are only supported for wonders.");
1960 return 0;
1961 }
1962}
1963
1964/**********************************************************************/
1967 static int num_world_buildings(const struct impr_type *building)
1968{
1969 if (is_great_wonder(building)) {
1970 return (great_wonder_is_built(building) ? 1 : 0);
1971 } else {
1972 log_error("World-ranged requirements are only supported for wonders.");
1973 return 0;
1974 }
1975}
1976
1977/**********************************************************************/
1988 static bool player_has_ever_built(const struct player *pplayer,
1989 const struct impr_type *building)
1990{
1991 if (is_wonder(building)) {
1992 return (wonder_is_built(pplayer, building)
1993 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
1994 } else {
1995 log_error("Player-ranged requirements are only supported for wonders.");
1996 return FALSE;
1997 }
1998}
1999
2000/**********************************************************************/
2003 static int num_player_buildings(const struct player *pplayer,
2004 const struct impr_type *building)
2005{
2006 if (is_wonder(building)) {
2007 return (wonder_is_built(pplayer, building) ? 1 : 0);
2008 } else {
2009 log_error("Player-ranged requirements are only supported for wonders.");
2010 return 0;
2011 }
2012}
2013
2014/**********************************************************************/
2017 static int num_continent_buildings(const struct player *pplayer,
2018 int continent,
2019 const struct impr_type *building)
2020{
2021 if (is_wonder(building)) {
2022 const struct city *pcity;
2023
2024 pcity = city_from_wonder(pplayer, building);
2025 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2026 return 1;
2027 }
2028 } else {
2029 log_error("Island-ranged requirements are only supported for wonders.");
2030 }
2031 return 0;
2032}
2033
2034/**********************************************************************/
2037 static int num_city_buildings(const struct city *pcity,
2038 const struct impr_type *building)
2039{
2040 return (city_has_building(pcity, building) ? 1 : 0);
2041}
2042
2043/**********************************************************************/
2050static enum fc_tristate
2051is_building_req_active(const struct civ_map *nmap,
2052 const struct req_context *context,
2053 const struct player *other_player,
2054 const struct requirement *req)
2055{
2056 const struct impr_type *building;
2057
2058 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT);
2059
2060 building = req->source.value.building;
2061
2062 /* Check if it's certain that the building is obsolete given the
2063 * specification we have */
2064 if (improvement_obsolete(context->player, building, context->city)) {
2065 return TRI_NO;
2066 }
2067
2068 if (req->survives) {
2069
2070 /* Check whether condition has ever held, using cached information. */
2071 switch (req->range) {
2072 case REQ_RANGE_WORLD:
2073 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2074 case REQ_RANGE_ALLIANCE:
2075 case REQ_RANGE_TEAM:
2076 if (context->player == NULL) {
2077 return TRI_MAYBE;
2078 }
2079 players_iterate_alive(plr2) {
2080 if (players_in_same_range(context->player, plr2, req->range)
2081 && player_has_ever_built(plr2, building)) {
2082 return TRI_YES;
2083 }
2084 } players_iterate_alive_end;
2085 return TRI_NO;
2086 case REQ_RANGE_PLAYER:
2087 if (context->player == NULL) {
2088 return TRI_MAYBE;
2089 }
2090 return BOOL_TO_TRISTATE(player_has_ever_built(context->player,
2091 building));
2092 case REQ_RANGE_CONTINENT:
2093 case REQ_RANGE_TRADE_ROUTE:
2094 case REQ_RANGE_CITY:
2095 case REQ_RANGE_LOCAL:
2096 case REQ_RANGE_TILE:
2097 case REQ_RANGE_CADJACENT:
2098 case REQ_RANGE_ADJACENT:
2099 /* There is no sources cache for this. */
2100 log_error("Surviving requirements are only supported at "
2101 "World/Alliance/Team/Player ranges.");
2102 return TRI_NO;
2103 case REQ_RANGE_COUNT:
2104 break;
2105 }
2106
2107 } else {
2108
2109 /* Non-surviving requirement. */
2110 switch (req->range) {
2111 case REQ_RANGE_WORLD:
2112 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2113 case REQ_RANGE_ALLIANCE:
2114 case REQ_RANGE_TEAM:
2115 if (context->player == NULL) {
2116 return TRI_MAYBE;
2117 }
2118 players_iterate_alive(plr2) {
2119 if (players_in_same_range(context->player, plr2, req->range)
2120 && num_player_buildings(plr2, building) > 0) {
2121 return TRI_YES;
2122 }
2123 } players_iterate_alive_end;
2124 return TRI_NO;
2125 case REQ_RANGE_PLAYER:
2126 if (context->player == NULL) {
2127 return TRI_MAYBE;
2128 }
2129 return BOOL_TO_TRISTATE(num_player_buildings(context->player,
2130 building)
2131 > 0);
2132 case REQ_RANGE_CONTINENT:
2133 /* At present, "Continent" effects can affect only
2134 * cities and units in cities. */
2135 if (context->player && context->city) {
2136 int continent = tile_continent(context->city->tile);
2137 return BOOL_TO_TRISTATE(num_continent_buildings(context->player,
2138 continent, building)
2139 > 0);
2140 } else {
2141 return TRI_MAYBE;
2142 }
2143 case REQ_RANGE_TRADE_ROUTE:
2144 if (context->city) {
2145 if (num_city_buildings(context->city, building) > 0) {
2146 return TRI_YES;
2147 } else {
2148 enum fc_tristate ret = TRI_NO;
2149
2150 trade_partners_iterate(context->city, trade_partner) {
2151 if (trade_partner == NULL) {
2152 ret = TRI_MAYBE;
2153 } else if (num_city_buildings(trade_partner, building) > 0) {
2154 return TRI_YES;
2155 }
2156 } trade_partners_iterate_end;
2157
2158 return ret;
2159 }
2160 } else {
2161 return TRI_MAYBE;
2162 }
2163 case REQ_RANGE_CITY:
2164 if (context->city) {
2165 return BOOL_TO_TRISTATE(num_city_buildings(context->city, building)
2166 > 0);
2167 } else {
2168 return TRI_MAYBE;
2169 }
2170 case REQ_RANGE_LOCAL:
2171 if (context->building) {
2172 if (context->building == building) {
2173 return TRI_YES;
2174 } else {
2175 return TRI_NO;
2176 }
2177 } else {
2178 /* TODO: other local targets */
2179 return TRI_MAYBE;
2180 }
2181 case REQ_RANGE_TILE:
2182 if (context->tile) {
2183 const struct city *pcity = tile_city(context->tile);
2184
2185 if (pcity) {
2186 return BOOL_TO_TRISTATE(num_city_buildings(pcity, building) > 0);
2187 } else {
2188 return TRI_NO;
2189 }
2190 } else {
2191 return TRI_MAYBE;
2192 }
2193 case REQ_RANGE_CADJACENT:
2194 case REQ_RANGE_ADJACENT:
2195 case REQ_RANGE_COUNT:
2196 break;
2197 }
2198
2199 }
2200
2201 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2202 return TRI_NO;
2203}
2204
2205/**********************************************************************/
2213static enum fc_tristate
2214is_buildinggenus_req_active(const struct civ_map *nmap,
2215 const struct req_context *context,
2216 const struct player *other_player,
2217 const struct requirement *req)
2218{
2219 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPR_GENUS);
2220
2221 return (context->building ? BOOL_TO_TRISTATE(
2222 context->building->genus
2223 == req->source.value.impr_genus)
2224 : TRI_MAYBE);
2225}
2226
2227/**********************************************************************/
2230 static enum fc_tristate is_buildingflag_in_city(const struct city *pcity,
2231 enum impr_flag_id flag)
2232{
2233 struct player *owner;
2234
2235 if (pcity == NULL) {
2236 return TRI_MAYBE;
2237 }
2238
2239 owner = city_owner(pcity);
2240 city_built_iterate(pcity, impr) {
2241 if (improvement_has_flag(impr, flag)
2242 && !improvement_obsolete(owner, impr, pcity)) {
2243 return TRI_YES;
2244 }
2245 } city_built_iterate_end;
2246
2247 return TRI_NO;
2248}
2249
2250/**********************************************************************/
2258static enum fc_tristate
2259is_buildingflag_req_active(const struct civ_map *nmap,
2260 const struct req_context *context,
2261 const struct player *other_player,
2262 const struct requirement *req)
2263{
2264 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPR_FLAG);
2265
2266 switch (req->range) {
2267 case REQ_RANGE_LOCAL:
2268 return (context->building
2269 ? BOOL_TO_TRISTATE(improvement_has_flag(context->building,
2270 req->source.value.impr_flag))
2271 : TRI_MAYBE);
2272 case REQ_RANGE_CITY:
2273 return is_buildingflag_in_city(context->city, req->source.value.impr_flag);
2274 case REQ_RANGE_TILE:
2275 if (context->tile == NULL) {
2276 return TRI_MAYBE;
2277 }
2278 return is_buildingflag_in_city(tile_city(context->tile),
2279 req->source.value.impr_flag);
2280 case REQ_RANGE_CADJACENT:
2281 case REQ_RANGE_ADJACENT:
2282 case REQ_RANGE_TRADE_ROUTE:
2283 case REQ_RANGE_CONTINENT:
2284 case REQ_RANGE_PLAYER:
2285 case REQ_RANGE_ALLIANCE:
2286 case REQ_RANGE_TEAM:
2287 case REQ_RANGE_WORLD:
2288 case REQ_RANGE_COUNT:
2289 break;
2290 }
2291
2292 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2293
2294 return TRI_MAYBE;
2295}
2296
2297/**********************************************************************/
2305static enum fc_tristate
2306is_plr_flag_req_active(const struct civ_map *nmap,
2307 const struct req_context *context,
2308 const struct player *other_player,
2309 const struct requirement *req)
2310{
2311 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_PLAYER_FLAG);
2312
2313 switch (req->range) {
2314 case REQ_RANGE_PLAYER:
2315 return (context->player != NULL
2316 ? BOOL_TO_TRISTATE(player_has_flag(context->player,
2317 req->source.value.plr_flag))
2318 : TRI_MAYBE);
2319 case REQ_RANGE_LOCAL:
2320 case REQ_RANGE_CITY:
2321 case REQ_RANGE_TILE:
2322 case REQ_RANGE_CADJACENT:
2323 case REQ_RANGE_ADJACENT:
2324 case REQ_RANGE_TRADE_ROUTE:
2325 case REQ_RANGE_CONTINENT:
2326 case REQ_RANGE_ALLIANCE:
2327 case REQ_RANGE_TEAM:
2328 case REQ_RANGE_WORLD:
2329 case REQ_RANGE_COUNT:
2330 break;
2331 }
2332
2333 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2334
2335 return TRI_MAYBE;
2336}
2337
2338/**********************************************************************/
2346static enum fc_tristate
2347is_plr_state_req_active(const struct civ_map *nmap,
2348 const struct req_context *context,
2349 const struct player *other_player,
2350 const struct requirement *req)
2351{
2352 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_PLAYER_STATE);
2353
2354 switch (req->range) {
2355 case REQ_RANGE_PLAYER:
2356 return (context->player != NULL
2357 ? BOOL_TO_TRISTATE(player_has_state(context->player,
2358 req->source.value.plrstate))
2359 : TRI_MAYBE);
2360 case REQ_RANGE_LOCAL:
2361 case REQ_RANGE_CITY:
2362 case REQ_RANGE_TILE:
2363 case REQ_RANGE_CADJACENT:
2364 case REQ_RANGE_ADJACENT:
2365 case REQ_RANGE_TRADE_ROUTE:
2366 case REQ_RANGE_CONTINENT:
2367 case REQ_RANGE_ALLIANCE:
2368 case REQ_RANGE_TEAM:
2369 case REQ_RANGE_WORLD:
2370 case REQ_RANGE_COUNT:
2371 break;
2372 }
2373
2374 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2375
2376 return TRI_MAYBE;
2377}
2378
2379/**********************************************************************/
2386static enum fc_tristate
2387is_tech_req_active(const struct civ_map *nmap,
2388 const struct req_context *context,
2389 const struct player *other_player,
2390 const struct requirement *req)
2391{
2392 Tech_type_id tech;
2393
2394 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ADVANCE);
2395
2396 tech = advance_number(req->source.value.advance);
2397
2398 if (req->survives) {
2399 fc_assert(req->range == REQ_RANGE_WORLD);
2400 return BOOL_TO_TRISTATE(game.info.global_advances[tech]);
2401 }
2402
2403 /* Not a 'surviving' requirement. */
2404 switch (req->range) {
2405 case REQ_RANGE_PLAYER:
2406 if (NULL != context->player) {
2407 return BOOL_TO_TRISTATE(TECH_KNOWN == research_invention_state
2408 (research_get(context->player), tech));
2409 } else {
2410 return TRI_MAYBE;
2411 }
2412 case REQ_RANGE_TEAM:
2413 case REQ_RANGE_ALLIANCE:
2414 case REQ_RANGE_WORLD:
2415 if (NULL == context->player) {
2416 return TRI_MAYBE;
2417 }
2418 players_iterate_alive(plr2) {
2419 if (players_in_same_range(context->player, plr2, req->range)) {
2420 if (research_invention_state(research_get(plr2), tech)
2421 == TECH_KNOWN) {
2422 return TRI_YES;
2423 }
2424 }
2425 } players_iterate_alive_end;
2426
2427 return TRI_NO;
2428 case REQ_RANGE_LOCAL:
2429 case REQ_RANGE_TILE:
2430 case REQ_RANGE_CADJACENT:
2431 case REQ_RANGE_ADJACENT:
2432 case REQ_RANGE_CITY:
2433 case REQ_RANGE_TRADE_ROUTE:
2434 case REQ_RANGE_CONTINENT:
2435 case REQ_RANGE_COUNT:
2436 break;
2437 }
2438
2439 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2440
2441 return TRI_MAYBE;
2442}
2443
2444/**********************************************************************/
2451static enum fc_tristate
2452is_techflag_req_active(const struct civ_map *nmap,
2453 const struct req_context *context,
2454 const struct player *other_player,
2455 const struct requirement *req)
2456{
2457 enum tech_flag_id techflag;
2458
2459 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TECHFLAG);
2460
2461 techflag = req->source.value.techflag;
2462
2463 switch (req->range) {
2464 case REQ_RANGE_PLAYER:
2465 if (NULL != context->player) {
2466 return BOOL_TO_TRISTATE(player_knows_techs_with_flag(context->player,
2467 techflag));
2468 } else {
2469 return TRI_MAYBE;
2470 }
2471 break;
2472 case REQ_RANGE_TEAM:
2473 case REQ_RANGE_ALLIANCE:
2474 if (NULL == context->player) {
2475 return TRI_MAYBE;
2476 }
2477 players_iterate_alive(plr2) {
2478 if (players_in_same_range(context->player, plr2, req->range)
2479 && player_knows_techs_with_flag(plr2, techflag)) {
2480 return TRI_YES;
2481 }
2482 } players_iterate_alive_end;
2483 return TRI_NO;
2484 case REQ_RANGE_WORLD:
2485 players_iterate(pplayer) {
2486 if (player_knows_techs_with_flag(pplayer, techflag)) {
2487 return TRI_YES;
2488 }
2489 } players_iterate_end;
2490
2491 return TRI_NO;
2492 case REQ_RANGE_LOCAL:
2493 case REQ_RANGE_TILE:
2494 case REQ_RANGE_CADJACENT:
2495 case REQ_RANGE_ADJACENT:
2496 case REQ_RANGE_CITY:
2497 case REQ_RANGE_TRADE_ROUTE:
2498 case REQ_RANGE_CONTINENT:
2499 case REQ_RANGE_COUNT:
2500 break;
2501 }
2502
2503 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2504
2505 return TRI_MAYBE;
2506}
2507
2508/**********************************************************************/
2515static enum fc_tristate
2516is_minculture_req_active(const struct civ_map *nmap,
2517 const struct req_context *context,
2518 const struct player *other_player,
2519 const struct requirement *req)
2520{
2521 int minculture;
2522
2523 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINCULTURE);
2524
2525 minculture = req->source.value.minculture;
2526
2527 switch (req->range) {
2528 case REQ_RANGE_CITY:
2529 if (!context->city) {
2530 return TRI_MAYBE;
2531 }
2532 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2533 case REQ_RANGE_TRADE_ROUTE:
2534 if (!context->city) {
2535 return TRI_MAYBE;
2536 }
2537 if (city_culture(context->city) >= minculture) {
2538 return TRI_YES;
2539 } else {
2540 enum fc_tristate ret = TRI_NO;
2541
2542 trade_partners_iterate(context->city, trade_partner) {
2543 if (trade_partner == NULL) {
2544 ret = TRI_MAYBE;
2545 } else if (city_culture(trade_partner) >= minculture) {
2546 return TRI_YES;
2547 }
2548 } trade_partners_iterate_end;
2549
2550 return ret;
2551 }
2552 case REQ_RANGE_PLAYER:
2553 case REQ_RANGE_TEAM:
2554 case REQ_RANGE_ALLIANCE:
2555 case REQ_RANGE_WORLD:
2556 if (NULL == context->player) {
2557 return TRI_MAYBE;
2558 }
2559 players_iterate_alive(plr2) {
2560 if (players_in_same_range(context->player, plr2, req->range)) {
2561 if (player_culture(plr2) >= minculture) {
2562 return TRI_YES;
2563 }
2564 }
2565 } players_iterate_alive_end;
2566 return TRI_NO;
2567 case REQ_RANGE_LOCAL:
2568 case REQ_RANGE_TILE:
2569 case REQ_RANGE_CADJACENT:
2570 case REQ_RANGE_ADJACENT:
2571 case REQ_RANGE_CONTINENT:
2572 case REQ_RANGE_COUNT:
2573 break;
2574 }
2575
2576 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2577
2578 return TRI_MAYBE;
2579}
2580
2581/**********************************************************************/
2589static enum fc_tristate
2590is_minforeignpct_req_active(const struct civ_map *nmap,
2591 const struct req_context *context,
2592 const struct player *other_player,
2593 const struct requirement *req)
2594{
2595 int min_foreign_pct, foreign_pct;
2596
2597 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINFOREIGNPCT);
2598
2599 min_foreign_pct = req->source.value.minforeignpct;
2600
2601 switch (req->range) {
2602 case REQ_RANGE_CITY:
2603 if (!context->city) {
2604 return TRI_MAYBE;
2605 }
2606 foreign_pct = citizens_nation_foreign(context->city) * 100
2607 / city_size_get(context->city);
2608 return BOOL_TO_TRISTATE(foreign_pct >= min_foreign_pct);
2609 case REQ_RANGE_TRADE_ROUTE:
2610 if (!context->city) {
2611 return TRI_MAYBE;
2612 }
2613 foreign_pct = citizens_nation_foreign(context->city) * 100
2614 / city_size_get(context->city);
2615 if (foreign_pct >= min_foreign_pct) {
2616 return TRI_YES;
2617 } else {
2618 enum fc_tristate ret = TRI_NO;
2619
2620 trade_partners_iterate(context->city, trade_partner) {
2621 if (trade_partner == NULL) {
2622 ret = TRI_MAYBE;
2623 } else {
2624 foreign_pct = citizens_nation_foreign(trade_partner) * 100
2625 / city_size_get(trade_partner);
2626 if (foreign_pct >= min_foreign_pct) {
2627 return TRI_YES;
2628 }
2629 }
2630 } trade_partners_iterate_end;
2631
2632 return ret;
2633 }
2634 case REQ_RANGE_PLAYER:
2635 case REQ_RANGE_TEAM:
2636 case REQ_RANGE_ALLIANCE:
2637 case REQ_RANGE_WORLD:
2638 case REQ_RANGE_LOCAL:
2639 case REQ_RANGE_TILE:
2640 case REQ_RANGE_CADJACENT:
2641 case REQ_RANGE_ADJACENT:
2642 case REQ_RANGE_CONTINENT:
2643 case REQ_RANGE_COUNT:
2644 break;
2645 }
2646
2647 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2648
2649 return TRI_MAYBE;
2650}
2651
2652/**********************************************************************/
2660static enum fc_tristate
2661is_maxunitsontile_req_active(const struct civ_map *nmap,
2662 const struct req_context *context,
2663 const struct player *other_player,
2664 const struct requirement *req)
2665{
2666 int max_units;
2667
2668 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MAXTILEUNITS);
2669
2670 max_units = req->source.value.max_tile_units;
2671
2672 /* TODO: if can't see V_INVIS -> TRI_MAYBE */
2673 switch (req->range) {
2674 case REQ_RANGE_TILE:
2675 if (!context->tile) {
2676 return TRI_MAYBE;
2677 }
2678 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
2679 case REQ_RANGE_CADJACENT:
2680 if (!context->tile) {
2681 return TRI_MAYBE;
2682 }
2683 if (unit_list_size(context->tile->units) <= max_units) {
2684 return TRI_YES;
2685 }
2686 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
2687 if (unit_list_size(adjc_tile->units) <= max_units) {
2688 return TRI_YES;
2689 }
2690 } cardinal_adjc_iterate_end;
2691 return TRI_NO;
2692 case REQ_RANGE_ADJACENT:
2693 if (!context->tile) {
2694 return TRI_MAYBE;
2695 }
2696 if (unit_list_size(context->tile->units) <= max_units) {
2697 return TRI_YES;
2698 }
2699 adjc_iterate(nmap, context->tile, adjc_tile) {
2700 if (unit_list_size(adjc_tile->units) <= max_units) {
2701 return TRI_YES;
2702 }
2703 } adjc_iterate_end;
2704 return TRI_NO;
2705 case REQ_RANGE_CITY:
2706 case REQ_RANGE_TRADE_ROUTE:
2707 case REQ_RANGE_CONTINENT:
2708 case REQ_RANGE_PLAYER:
2709 case REQ_RANGE_TEAM:
2710 case REQ_RANGE_ALLIANCE:
2711 case REQ_RANGE_WORLD:
2712 case REQ_RANGE_LOCAL:
2713 case REQ_RANGE_COUNT:
2714 break;
2715 }
2716
2717 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2718
2719 return TRI_MAYBE;
2720}
2721
2722/**********************************************************************/
2729static enum fc_tristate
2730is_extra_req_active(const struct civ_map *nmap,
2731 const struct req_context *context,
2732 const struct player *other_player,
2733 const struct requirement *req)
2734{
2735 const struct extra_type *pextra;
2736 enum fc_tristate ret;
2737
2738 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_EXTRA);
2739
2740 pextra = req->source.value.extra;
2741
2742 switch (req->range) {
2743 case REQ_RANGE_LOCAL:
2744 if (!context->extra) {
2745 return TRI_MAYBE;
2746 }
2747 return BOOL_TO_TRISTATE(context->extra == pextra);
2748 case REQ_RANGE_TILE:
2749 /* The requirement is filled if the tile has extra of requested type. */
2750 if (!context->tile) {
2751 return TRI_MAYBE;
2752 }
2753 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
2754 case REQ_RANGE_CADJACENT:
2755 if (!context->tile) {
2756 return TRI_MAYBE;
2757 }
2758 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2759 || is_extra_card_near(nmap, context->tile, pextra));
2760 case REQ_RANGE_ADJACENT:
2761 if (!context->tile) {
2762 return TRI_MAYBE;
2763 }
2764 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2765 || is_extra_near_tile(nmap, context->tile, pextra));
2766 case REQ_RANGE_CITY:
2767 if (!context->city) {
2768 return TRI_MAYBE;
2769 }
2770 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
2771 city_tile(context->city), ptile) {
2772 if (tile_has_extra(ptile, pextra)) {
2773 return TRI_YES;
2774 }
2775 } city_tile_iterate_end;
2776
2777 return TRI_NO;
2778
2779 case REQ_RANGE_TRADE_ROUTE:
2780 if (!context->city) {
2781 return TRI_MAYBE;
2782 }
2783 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
2784 city_tile(context->city), ptile) {
2785 if (tile_has_extra(ptile, pextra)) {
2786 return TRI_YES;
2787 }
2788 } city_tile_iterate_end;
2789
2790 ret = TRI_NO;
2791 trade_partners_iterate(context->city, trade_partner) {
2792 if (trade_partner == NULL) {
2793 ret = TRI_MAYBE;
2794 } else {
2795 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
2796 city_tile(trade_partner), ptile) {
2797 if (tile_has_extra(ptile, pextra)) {
2798 return TRI_YES;
2799 }
2800 } city_tile_iterate_end;
2801 }
2802 } trade_partners_iterate_end;
2803
2804 return ret;
2805
2806 case REQ_RANGE_CONTINENT:
2807 case REQ_RANGE_PLAYER:
2808 case REQ_RANGE_TEAM:
2809 case REQ_RANGE_ALLIANCE:
2810 case REQ_RANGE_WORLD:
2811 case REQ_RANGE_COUNT:
2812 break;
2813 }
2814
2815 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2816
2817 return TRI_MAYBE;
2818}
2819
2820/**********************************************************************/
2827static enum fc_tristate
2828is_good_req_active(const struct civ_map *nmap,
2829 const struct req_context *context,
2830 const struct player *other_player,
2831 const struct requirement *req)
2832{
2833 const struct goods_type *pgood;
2834
2835 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_GOOD);
2836
2837 pgood = req->source.value.good;
2838
2839 switch (req->range) {
2840 case REQ_RANGE_LOCAL:
2841 case REQ_RANGE_CITY:
2842 /* The requirement is filled if the city imports good of requested type. */
2843 if (!context->city) {
2844 return TRI_MAYBE;
2845 }
2846 return BOOL_TO_TRISTATE(city_receives_goods(context->city, pgood)
2847 || (goods_has_flag(pgood, GF_SELF_PROVIDED)
2848 && goods_can_be_provided(context->city, pgood, NULL)));
2849 case REQ_RANGE_TILE:
2850 case REQ_RANGE_CADJACENT:
2851 case REQ_RANGE_ADJACENT:
2852 case REQ_RANGE_TRADE_ROUTE:
2853 case REQ_RANGE_CONTINENT:
2854 case REQ_RANGE_PLAYER:
2855 case REQ_RANGE_TEAM:
2856 case REQ_RANGE_ALLIANCE:
2857 case REQ_RANGE_WORLD:
2858 case REQ_RANGE_COUNT:
2859 break;
2860 }
2861
2862 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2863
2864 return TRI_MAYBE;
2865}
2866
2867/**********************************************************************/
2874static enum fc_tristate
2875is_action_req_active(const struct civ_map *nmap,
2876 const struct req_context *context,
2877 const struct player *other_player,
2878 const struct requirement *req)
2879{
2880 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ACTION);
2881
2882 return BOOL_TO_TRISTATE(context->action
2883 && action_number(context->action)
2884 == action_number(req->source.value.action));
2885}
2886
2887/**********************************************************************/
2895static enum fc_tristate
2896is_outputtype_req_active(const struct civ_map *nmap,
2897 const struct req_context *context,
2898 const struct player *other_player,
2899 const struct requirement *req)
2900{
2901 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_OTYPE);
2902
2903 return BOOL_TO_TRISTATE(context->output
2904 && context->output->index
2905 == req->source.value.outputtype);
2906}
2907
2908/**********************************************************************/
2915static enum fc_tristate
2916is_specialist_req_active(const struct civ_map *nmap,
2917 const struct req_context *context,
2918 const struct player *other_player,
2919 const struct requirement *req)
2920{
2921 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_SPECIALIST);
2922
2923 return BOOL_TO_TRISTATE(context->specialist
2924 && context->specialist
2925 == req->source.value.specialist);
2926}
2927
2928/**********************************************************************/
2935static enum fc_tristate
2936is_terrain_req_active(const struct civ_map *nmap,
2937 const struct req_context *context,
2938 const struct player *other_player,
2939 const struct requirement *req)
2940{
2941 const struct terrain *pterrain;
2942
2943 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRAIN);
2944
2945 pterrain = req->source.value.terrain;
2946
2947 switch (req->range) {
2948 case REQ_RANGE_TILE:
2949 /* The requirement is filled if the tile has the terrain. */
2950 if (!context->tile) {
2951 return TRI_MAYBE;
2952 }
2953 return pterrain && tile_terrain(context->tile) == pterrain;
2954 case REQ_RANGE_CADJACENT:
2955 if (!context->tile) {
2956 return TRI_MAYBE;
2957 }
2958 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
2959 case REQ_RANGE_ADJACENT:
2960 if (!context->tile) {
2961 return TRI_MAYBE;
2962 }
2963 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
2964 case REQ_RANGE_CITY:
2965 if (!context->city) {
2966 return TRI_MAYBE;
2967 }
2968 if (pterrain != NULL) {
2969 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
2970 city_tile(context->city), ptile) {
2971 if (tile_terrain(ptile) == pterrain) {
2972 return TRI_YES;
2973 }
2974 } city_tile_iterate_end;
2975 }
2976 return TRI_NO;
2977 case REQ_RANGE_TRADE_ROUTE:
2978 if (!context->city) {
2979 return TRI_MAYBE;
2980 }
2981 if (pterrain != NULL) {
2982 enum fc_tristate ret;
2983
2984 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
2985 city_tile(context->city), ptile) {
2986 if (tile_terrain(ptile) == pterrain) {
2987 return TRI_YES;
2988 }
2989 } city_tile_iterate_end;
2990
2991 ret = TRI_NO;
2992 trade_partners_iterate(context->city, trade_partner) {
2993 if (trade_partner == NULL) {
2994 ret = TRI_MAYBE;
2995 } else {
2996 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
2997 city_tile(trade_partner), ptile) {
2998 if (tile_terrain(ptile) == pterrain) {
2999 return TRI_YES;
3000 }
3001 } city_tile_iterate_end;
3002 }
3003 } trade_partners_iterate_end;
3004
3005 return ret;
3006 }
3007
3008 return TRI_MAYBE;
3009 case REQ_RANGE_CONTINENT:
3010 case REQ_RANGE_PLAYER:
3011 case REQ_RANGE_TEAM:
3012 case REQ_RANGE_ALLIANCE:
3013 case REQ_RANGE_WORLD:
3014 case REQ_RANGE_LOCAL:
3015 case REQ_RANGE_COUNT:
3016 break;
3017 }
3018
3019 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3020
3021 return TRI_MAYBE;
3022}
3023
3024/**********************************************************************/
3032static enum fc_tristate
3033is_terrainclass_req_active(const struct civ_map *nmap,
3034 const struct req_context *context,
3035 const struct player *other_player,
3036 const struct requirement *req)
3037{
3038 enum terrain_class pclass;
3039 enum fc_tristate ret;
3040
3041 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRAINCLASS);
3042
3043 pclass = req->source.value.terrainclass;
3044
3045 switch (req->range) {
3046 case REQ_RANGE_TILE:
3047 /* The requirement is filled if the tile has the terrain of correct class. */
3048 if (!context->tile) {
3049 return TRI_MAYBE;
3050 }
3051 return BOOL_TO_TRISTATE(terrain_type_terrain_class(tile_terrain(context->tile)) == pclass);
3052 case REQ_RANGE_CADJACENT:
3053 if (!context->tile) {
3054 return TRI_MAYBE;
3055 }
3056 return BOOL_TO_TRISTATE(terrain_type_terrain_class(tile_terrain(context->tile)) == pclass
3057 || is_terrain_class_card_near(nmap, context->tile, pclass));
3058 case REQ_RANGE_ADJACENT:
3059 if (!context->tile) {
3060 return TRI_MAYBE;
3061 }
3062 return BOOL_TO_TRISTATE(terrain_type_terrain_class(tile_terrain(context->tile)) == pclass
3063 || is_terrain_class_near_tile(nmap, context->tile, pclass));
3064 case REQ_RANGE_CITY:
3065 if (!context->city) {
3066 return TRI_MAYBE;
3067 }
3068 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3069 city_tile(context->city), ptile) {
3070 const struct terrain *pterrain = tile_terrain(ptile);
3071
3072 if (pterrain != T_UNKNOWN
3073 && terrain_type_terrain_class(pterrain) == pclass) {
3074 return TRI_YES;
3075 }
3076 } city_tile_iterate_end;
3077
3078 return TRI_NO;
3079 case REQ_RANGE_TRADE_ROUTE:
3080 if (!context->city) {
3081 return TRI_MAYBE;
3082 }
3083 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3084 city_tile(context->city), ptile) {
3085 const struct terrain *pterrain = tile_terrain(ptile);
3086
3087 if (pterrain != T_UNKNOWN
3088 && terrain_type_terrain_class(pterrain) == pclass) {
3089 return TRI_YES;
3090 }
3091 } city_tile_iterate_end;
3092
3093 ret = TRI_NO;
3094 trade_partners_iterate(context->city, trade_partner) {
3095 if (trade_partner == NULL) {
3096 ret = TRI_MAYBE;
3097 } else {
3098 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3099 city_tile(trade_partner), ptile) {
3100 const struct terrain *pterrain = tile_terrain(ptile);
3101
3102 if (pterrain != T_UNKNOWN
3103 && terrain_type_terrain_class(pterrain) == pclass) {
3104 return TRI_YES;
3105 }
3106 } city_tile_iterate_end;
3107 }
3108 } trade_partners_iterate_end;
3109
3110 return ret;
3111 case REQ_RANGE_CONTINENT:
3112 case REQ_RANGE_PLAYER:
3113 case REQ_RANGE_TEAM:
3114 case REQ_RANGE_ALLIANCE:
3115 case REQ_RANGE_WORLD:
3116 case REQ_RANGE_LOCAL:
3117 case REQ_RANGE_COUNT:
3118 break;
3119 }
3120
3121 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3122
3123 return TRI_MAYBE;
3124}
3125
3126/**********************************************************************/
3134static enum fc_tristate
3135is_terrainflag_req_active(const struct civ_map *nmap,
3136 const struct req_context *context,
3137 const struct player *other_player,
3138 const struct requirement *req)
3139{
3140 enum terrain_flag_id terrflag;
3141 enum fc_tristate ret;
3142
3143 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRFLAG);
3144
3145 terrflag = req->source.value.terrainflag;
3146
3147 switch (req->range) {
3148 case REQ_RANGE_TILE:
3149 /* The requirement is fulfilled if the tile has a terrain with
3150 * correct flag. */
3151 if (!context->tile) {
3152 return TRI_MAYBE;
3153 }
3154 return BOOL_TO_TRISTATE(terrain_has_flag(tile_terrain(context->tile),
3155 terrflag));
3156 case REQ_RANGE_CADJACENT:
3157 if (!context->tile) {
3158 return TRI_MAYBE;
3159 }
3160 return BOOL_TO_TRISTATE(terrain_has_flag(tile_terrain(context->tile),
3161 terrflag)
3162 || is_terrain_flag_card_near(nmap, context->tile,
3163 terrflag));
3164 case REQ_RANGE_ADJACENT:
3165 if (!context->tile) {
3166 return TRI_MAYBE;
3167 }
3168 return BOOL_TO_TRISTATE(terrain_has_flag(tile_terrain(context->tile),
3169 terrflag)
3170 || is_terrain_flag_near_tile(nmap, context->tile,
3171 terrflag));
3172 case REQ_RANGE_CITY:
3173 if (!context->city) {
3174 return TRI_MAYBE;
3175 }
3176 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3177 city_tile(context->city), ptile) {
3178 const struct terrain *pterrain = tile_terrain(ptile);
3179
3180 if (pterrain != T_UNKNOWN
3181 && terrain_has_flag(pterrain, terrflag)) {
3182 return TRI_YES;
3183 }
3184 } city_tile_iterate_end;
3185
3186 return TRI_NO;
3187 case REQ_RANGE_TRADE_ROUTE:
3188 if (!context->city) {
3189 return TRI_MAYBE;
3190 }
3191 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3192 city_tile(context->city), ptile) {
3193 const struct terrain *pterrain = tile_terrain(ptile);
3194
3195 if (pterrain != T_UNKNOWN
3196 && terrain_has_flag(pterrain, terrflag)) {
3197 return TRI_YES;
3198 }
3199 } city_tile_iterate_end;
3200
3201 ret = TRI_NO;
3202 trade_partners_iterate(context->city, trade_partner) {
3203 if (trade_partner == NULL) {
3204 ret = TRI_MAYBE;
3205 } else {
3206 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3207 city_tile(trade_partner), ptile) {
3208 const struct terrain *pterrain = tile_terrain(ptile);
3209
3210 if (pterrain != T_UNKNOWN
3211 && terrain_has_flag(pterrain, terrflag)) {
3212 return TRI_YES;
3213 }
3214 } city_tile_iterate_end;
3215 }
3216 } trade_partners_iterate_end;
3217
3218 return ret;
3219 case REQ_RANGE_CONTINENT:
3220 case REQ_RANGE_PLAYER:
3221 case REQ_RANGE_TEAM:
3222 case REQ_RANGE_ALLIANCE:
3223 case REQ_RANGE_WORLD:
3224 case REQ_RANGE_LOCAL:
3225 case REQ_RANGE_COUNT:
3226 break;
3227 }
3228
3229 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3230
3231 return TRI_MAYBE;
3232}
3233
3234/**********************************************************************/
3241static enum fc_tristate
3242is_roadflag_req_active(const struct civ_map *nmap,
3243 const struct req_context *context,
3244 const struct player *other_player,
3245 const struct requirement *req)
3246{
3247 enum road_flag_id roadflag;
3248 enum fc_tristate ret;
3249
3250 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ROADFLAG);
3251
3252 roadflag = req->source.value.roadflag;
3253
3254 switch (req->range) {
3255 case REQ_RANGE_LOCAL:
3256 {
3257 if (!context->extra) {
3258 return TRI_MAYBE;
3259 }
3260 struct road_type *r = extra_road_get(context->extra);
3261
3262 return BOOL_TO_TRISTATE(
3263 r && road_has_flag(r, roadflag)
3264 );
3265 }
3266 case REQ_RANGE_TILE:
3267 /* The requirement is filled if the tile has a road with correct flag. */
3268 if (!context->tile) {
3269 return TRI_MAYBE;
3270 }
3271 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3272 case REQ_RANGE_CADJACENT:
3273 if (!context->tile) {
3274 return TRI_MAYBE;
3275 }
3276 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3277 || is_road_flag_card_near(nmap, context->tile,
3278 roadflag));
3279 case REQ_RANGE_ADJACENT:
3280 if (!context->tile) {
3281 return TRI_MAYBE;
3282 }
3283 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3284 || is_road_flag_near_tile(nmap, context->tile,
3285 roadflag));
3286 case REQ_RANGE_CITY:
3287 if (!context->city) {
3288 return TRI_MAYBE;
3289 }
3290 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3291 city_tile(context->city), ptile) {
3292 if (tile_has_road_flag(ptile, roadflag)) {
3293 return TRI_YES;
3294 }
3295 } city_tile_iterate_end;
3296
3297 return TRI_NO;
3298 case REQ_RANGE_TRADE_ROUTE:
3299 if (!context->city) {
3300 return TRI_MAYBE;
3301 }
3302 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3303 city_tile(context->city), ptile) {
3304 if (tile_has_road_flag(ptile, roadflag)) {
3305 return TRI_YES;
3306 }
3307 } city_tile_iterate_end;
3308
3309 ret = TRI_NO;
3310 trade_partners_iterate(context->city, trade_partner) {
3311 if (trade_partner == NULL) {
3312 ret = TRI_MAYBE;
3313 } else {
3314 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3315 city_tile(trade_partner), ptile) {
3316 if (tile_has_road_flag(ptile, roadflag)) {
3317 return TRI_YES;
3318 }
3319 } city_tile_iterate_end;
3320 }
3321 } trade_partners_iterate_end;
3322
3323 return ret;
3324 case REQ_RANGE_CONTINENT:
3325 case REQ_RANGE_PLAYER:
3326 case REQ_RANGE_TEAM:
3327 case REQ_RANGE_ALLIANCE:
3328 case REQ_RANGE_WORLD:
3329 case REQ_RANGE_COUNT:
3330 break;
3331 }
3332
3333 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3334
3335 return TRI_MAYBE;
3336}
3337
3338/**********************************************************************/
3345static enum fc_tristate
3346is_extraflag_req_active(const struct civ_map *nmap,
3347 const struct req_context *context,
3348 const struct player *other_player,
3349 const struct requirement *req)
3350{
3351 enum extra_flag_id extraflag;
3352 enum fc_tristate ret;
3353
3354 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_EXTRAFLAG);
3355
3356 extraflag = req->source.value.extraflag;
3357
3358 switch (req->range) {
3359 case REQ_RANGE_LOCAL:
3360 if (!context->extra) {
3361 return TRI_MAYBE;
3362 }
3363 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3364 case REQ_RANGE_TILE:
3365 /* The requirement is filled if the tile has an extra with correct flag. */
3366 if (!context->tile) {
3367 return TRI_MAYBE;
3368 }
3369 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3370 case REQ_RANGE_CADJACENT:
3371 if (!context->tile) {
3372 return TRI_MAYBE;
3373 }
3374 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3375 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3376 case REQ_RANGE_ADJACENT:
3377 if (!context->tile) {
3378 return TRI_MAYBE;
3379 }
3380 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3381 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3382 case REQ_RANGE_CITY:
3383 if (!context->city) {
3384 return TRI_MAYBE;
3385 }
3386 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3387 city_tile(context->city), ptile) {
3388 if (tile_has_extra_flag(ptile, extraflag)) {
3389 return TRI_YES;
3390 }
3391 } city_tile_iterate_end;
3392
3393 return TRI_NO;
3394 case REQ_RANGE_TRADE_ROUTE:
3395 if (!context->city) {
3396 return TRI_MAYBE;
3397 }
3398 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3399 city_tile(context->city), ptile) {
3400 if (tile_has_extra_flag(ptile, extraflag)) {
3401 return TRI_YES;
3402 }
3403 } city_tile_iterate_end;
3404
3405 ret = TRI_NO;
3406 trade_partners_iterate(context->city, trade_partner) {
3407 if (trade_partner == NULL) {
3408 ret = TRI_MAYBE;
3409 } else {
3410 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3411 city_tile(trade_partner), ptile) {
3412 if (tile_has_extra_flag(ptile, extraflag)) {
3413 return TRI_YES;
3414 }
3415 } city_tile_iterate_end;
3416 }
3417 } trade_partners_iterate_end;
3418
3419 return ret;
3420 case REQ_RANGE_CONTINENT:
3421 case REQ_RANGE_PLAYER:
3422 case REQ_RANGE_TEAM:
3423 case REQ_RANGE_ALLIANCE:
3424 case REQ_RANGE_WORLD:
3425 case REQ_RANGE_COUNT:
3426 break;
3427 }
3428
3429 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3430
3431 return TRI_MAYBE;
3432}
3433
3434/**********************************************************************/
3442static enum fc_tristate
3443is_terrainalter_req_active(const struct civ_map *nmap,
3444 const struct req_context *context,
3445 const struct player *other_player,
3446 const struct requirement *req)
3447{
3448 enum terrain_alteration alteration;
3449
3450 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRAINALTER);
3451
3452 alteration = req->source.value.terrainalter;
3453
3454 if (!context->tile) {
3455 return TRI_MAYBE;
3456 }
3457
3458 switch (req->range) {
3459 case REQ_RANGE_TILE:
3460 return BOOL_TO_TRISTATE(terrain_can_support_alteration(
3461 tile_terrain(context->tile), alteration));
3462 case REQ_RANGE_CADJACENT:
3463 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
3464 case REQ_RANGE_CITY:
3465 case REQ_RANGE_TRADE_ROUTE:
3466 case REQ_RANGE_CONTINENT:
3467 case REQ_RANGE_PLAYER:
3468 case REQ_RANGE_TEAM:
3469 case REQ_RANGE_ALLIANCE:
3470 case REQ_RANGE_WORLD:
3471 case REQ_RANGE_LOCAL:
3472 case REQ_RANGE_COUNT:
3473 break;
3474 }
3475
3476 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3477
3478 return TRI_MAYBE;
3479}
3480
3481/**********************************************************************/
3488static enum fc_tristate
3489is_gov_req_active(const struct civ_map *nmap,
3490 const struct req_context *context,
3491 const struct player *other_player,
3492 const struct requirement *req)
3493{
3494 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_GOVERNMENT);
3495
3496 if (context->player == NULL) {
3497 return TRI_MAYBE;
3498 } else {
3499 return BOOL_TO_TRISTATE(government_of_player(context->player)
3500 == req->source.value.govern);
3501 }
3502}
3503
3504/**********************************************************************/
3511static enum fc_tristate
3512is_style_req_active(const struct civ_map *nmap,
3513 const struct req_context *context,
3514 const struct player *other_player,
3515 const struct requirement *req)
3516{
3517 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_STYLE);
3518
3519 if (context->player == NULL) {
3520 return TRI_MAYBE;
3521 } else {
3522 return BOOL_TO_TRISTATE(context->player->style
3523 == req->source.value.style);
3524 }
3525}
3526
3527/**********************************************************************/
3534static enum fc_tristate
3535is_mintechs_req_active(const struct civ_map *nmap,
3536 const struct req_context *context,
3537 const struct player *other_player,
3538 const struct requirement *req)
3539{
3540 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINTECHS);
3541
3542 switch (req->range) {
3543 case REQ_RANGE_WORLD:
3544 /* "None" does not count */
3545 return ((game.info.global_advance_count - 1)
3546 >= req->source.value.min_techs);
3547 case REQ_RANGE_PLAYER:
3548 if (context->player == NULL) {
3549 return TRI_MAYBE;
3550 } else {
3551 /* "None" does not count */
3552 return BOOL_TO_TRISTATE(
3553 (research_get(context->player)->techs_researched - 1)
3554 >= req->source.value.min_techs
3555 );
3556 }
3557 default:
3558 return TRI_MAYBE;
3559 }
3560}
3561
3562/**********************************************************************/
3569static enum fc_tristate
3570is_ai_req_active(const struct civ_map *nmap,
3571 const struct req_context *context,
3572 const struct player *other_player,
3573 const struct requirement *req)
3574{
3575 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_AI_LEVEL);
3576
3577 if (context->player == NULL) {
3578 return TRI_MAYBE;
3579 } else {
3580 return BOOL_TO_TRISTATE(is_ai(context->player)
3581 && context->player->ai_common.skill_level
3582 == req->source.value.ai_level);
3583 }
3584}
3585
3586/**********************************************************************/
3593static enum fc_tristate
3594is_nation_req_active(const struct civ_map *nmap,
3595 const struct req_context *context,
3596 const struct player *other_player,
3597 const struct requirement *req)
3598{
3599 const struct nation_type *nation;
3600
3601 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NATION);
3602
3603 nation = req->source.value.nation;
3604
3605 switch (req->range) {
3606 case REQ_RANGE_PLAYER:
3607 if (context->player == NULL) {
3608 return TRI_MAYBE;
3609 }
3610 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
3611 case REQ_RANGE_TEAM:
3612 case REQ_RANGE_ALLIANCE:
3613 if (context->player == NULL) {
3614 return TRI_MAYBE;
3615 }
3616 players_iterate_alive(plr2) {
3617 if (players_in_same_range(context->player, plr2, req->range)) {
3618 if (nation_of_player(plr2) == nation) {
3619 return TRI_YES;
3620 }
3621 }
3622 } players_iterate_alive_end;
3623 return TRI_NO;
3624 case REQ_RANGE_WORLD:
3625 /* NB: if a player is ever removed outright from the game
3626 * (e.g. via /remove), rather than just dying, this 'survives'
3627 * requirement will stop being true for their nation.
3628 * create_command_newcomer() can also cause this to happen. */
3629 return BOOL_TO_TRISTATE(NULL != nation->player
3630 && (req->survives || nation->player->is_alive));
3631 case REQ_RANGE_LOCAL:
3632 case REQ_RANGE_TILE:
3633 case REQ_RANGE_CADJACENT:
3634 case REQ_RANGE_ADJACENT:
3635 case REQ_RANGE_CITY:
3636 case REQ_RANGE_TRADE_ROUTE:
3637 case REQ_RANGE_CONTINENT:
3638 case REQ_RANGE_COUNT:
3639 break;
3640 }
3641
3642 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3643
3644 return TRI_MAYBE;
3645}
3646
3647/**********************************************************************/
3655static enum fc_tristate
3656is_nationgroup_req_active(const struct civ_map *nmap,
3657 const struct req_context *context,
3658 const struct player *other_player,
3659 const struct requirement *req)
3660{
3661 const struct nation_group *ngroup;
3662
3663 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NATIONGROUP);
3664
3665 ngroup = req->source.value.nationgroup;
3666
3667 switch (req->range) {
3668 case REQ_RANGE_PLAYER:
3669 if (context->player == NULL) {
3670 return TRI_MAYBE;
3671 }
3672 return BOOL_TO_TRISTATE(nation_is_in_group(
3673 nation_of_player(context->player), ngroup));
3674 case REQ_RANGE_TEAM:
3675 case REQ_RANGE_ALLIANCE:
3676 case REQ_RANGE_WORLD:
3677 if (context->player == NULL) {
3678 return TRI_MAYBE;
3679 }
3680 players_iterate_alive(plr2) {
3681 if (players_in_same_range(context->player, plr2, req->range)) {
3682 if (nation_is_in_group(nation_of_player(plr2), ngroup)) {
3683 return TRI_YES;
3684 }
3685 }
3686 } players_iterate_alive_end;
3687 return TRI_NO;
3688 case REQ_RANGE_LOCAL:
3689 case REQ_RANGE_TILE:
3690 case REQ_RANGE_CADJACENT:
3691 case REQ_RANGE_ADJACENT:
3692 case REQ_RANGE_CITY:
3693 case REQ_RANGE_TRADE_ROUTE:
3694 case REQ_RANGE_CONTINENT:
3695 case REQ_RANGE_COUNT:
3696 break;
3697 }
3698
3699 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3700
3701 return TRI_MAYBE;
3702}
3703
3704/**********************************************************************/
3712static enum fc_tristate
3713is_nationality_req_active(const struct civ_map *nmap,
3714 const struct req_context *context,
3715 const struct player *other_player,
3716 const struct requirement *req)
3717{
3718 const struct nation_type *nationality;
3719 enum fc_tristate ret;
3720
3721 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NATIONALITY);
3722
3723 nationality = req->source.value.nationality;
3724
3725 switch (req->range) {
3726 case REQ_RANGE_CITY:
3727 if (context->city == NULL) {
3728 return TRI_MAYBE;
3729 }
3730 citizens_iterate(context->city, slot, count) {
3731 if (player_slot_get_player(slot)->nation == nationality) {
3732 return TRI_YES;
3733 }
3734 } citizens_iterate_end;
3735
3736 return TRI_NO;
3737 case REQ_RANGE_TRADE_ROUTE:
3738 if (context->city == NULL) {
3739 return TRI_MAYBE;
3740 }
3741 citizens_iterate(context->city, slot, count) {
3742 if (player_slot_get_player(slot)->nation == nationality) {
3743 return TRI_YES;
3744 }
3745 } citizens_iterate_end;
3746
3747 ret = TRI_NO;
3748 trade_partners_iterate(context->city, trade_partner) {
3749 if (trade_partner == NULL) {
3750 ret = TRI_MAYBE;
3751 } else {
3752 citizens_iterate(trade_partner, slot, count) {
3753 if (player_slot_get_player(slot)->nation == nationality) {
3754 return TRI_YES;
3755 }
3756 } citizens_iterate_end;
3757 }
3758 } trade_partners_iterate_end;
3759
3760 return ret;
3761 case REQ_RANGE_PLAYER:
3762 case REQ_RANGE_TEAM:
3763 case REQ_RANGE_ALLIANCE:
3764 case REQ_RANGE_WORLD:
3765 case REQ_RANGE_LOCAL:
3766 case REQ_RANGE_TILE:
3767 case REQ_RANGE_CADJACENT:
3768 case REQ_RANGE_ADJACENT:
3769 case REQ_RANGE_CONTINENT:
3770 case REQ_RANGE_COUNT:
3771 break;
3772 }
3773
3774 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3775
3776 return TRI_MAYBE;
3777}
3778
3779/**********************************************************************/
3787static enum fc_tristate
3788is_originalowner_req_active(const struct civ_map *nmap,
3789 const struct req_context *context,
3790 const struct player *other_player,
3791 const struct requirement *req)
3792{
3793 const struct nation_type *nation;
3794
3795 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ORIGINAL_OWNER);
3796
3797 nation = req->source.value.origowner;
3798
3799 switch (req->range) {
3800 case REQ_RANGE_CITY:
3801 if (context->city == NULL || context->city->original == NULL) {
3802 return TRI_MAYBE;
3803 }
3804 if (player_nation(context->city->original) == nation) {
3805 return TRI_YES;
3806 }
3807
3808 return TRI_NO;
3809 case REQ_RANGE_TRADE_ROUTE:
3810 case REQ_RANGE_PLAYER:
3811 case REQ_RANGE_TEAM:
3812 case REQ_RANGE_ALLIANCE:
3813 case REQ_RANGE_WORLD:
3814 case REQ_RANGE_LOCAL:
3815 case REQ_RANGE_TILE:
3816 case REQ_RANGE_CADJACENT:
3817 case REQ_RANGE_ADJACENT:
3818 case REQ_RANGE_CONTINENT:
3819 case REQ_RANGE_COUNT:
3820 break;
3821 }
3822
3823 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3824
3825 return TRI_MAYBE;
3826}
3827
3828/**********************************************************************/
3831 static enum fc_tristate is_diplrel_in_range(const struct player *target_player,
3832 const struct player *other_player,
3833 enum req_range range,
3834 int diplrel)
3835{
3836 switch (range) {
3837 case REQ_RANGE_PLAYER:
3838 if (target_player == NULL) {
3839 return TRI_MAYBE;
3840 }
3841 return BOOL_TO_TRISTATE(is_diplrel_to_other(target_player, diplrel));
3842 case REQ_RANGE_TEAM:
3843 case REQ_RANGE_ALLIANCE:
3844 case REQ_RANGE_WORLD:
3845 if (target_player == NULL) {
3846 return TRI_MAYBE;
3847 }
3848 players_iterate_alive(plr2) {
3849 if (players_in_same_range(target_player, plr2, range)) {
3850 if (is_diplrel_to_other(plr2, diplrel)) {
3851 return TRI_YES;
3852 }
3853 }
3854 } players_iterate_alive_end;
3855 return TRI_NO;
3856 case REQ_RANGE_LOCAL:
3857 if (target_player == NULL || other_player == NULL) {
3858 return TRI_MAYBE;
3859 }
3860 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
3861 case REQ_RANGE_TILE:
3862 case REQ_RANGE_CADJACENT:
3863 case REQ_RANGE_ADJACENT:
3864 case REQ_RANGE_CITY:
3865 case REQ_RANGE_TRADE_ROUTE:
3866 case REQ_RANGE_CONTINENT:
3867 case REQ_RANGE_COUNT:
3868 break;
3869 }
3870
3871 fc_assert_msg(FALSE, "Invalid range %d.", range);
3872
3873 return TRI_MAYBE;
3874}
3875
3876/**********************************************************************/
3883static enum fc_tristate
3884is_diplrel_req_active(const struct civ_map *nmap,
3885 const struct req_context *context,
3886 const struct player *other_player,
3887 const struct requirement *req)
3888{
3889 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL);
3890
3891 return is_diplrel_in_range(context->player, other_player, req->range,
3892 req->source.value.diplrel);
3893}
3894
3895/**********************************************************************/
3903static enum fc_tristate
3904is_diplrel_tile_req_active(const struct civ_map *nmap,
3905 const struct req_context *context,
3906 const struct player *other_player,
3907 const struct requirement *req)
3908{
3909 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_TILE);
3910
3911 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
3912 : NULL,
3913 context->player,
3914 req->range,
3915 req->source.value.diplrel);
3916}
3917
3918/**********************************************************************/
3927static enum fc_tristate
3928is_diplrel_tile_o_req_active(const struct civ_map *nmap,
3929 const struct req_context *context,
3930 const struct player *other_player,
3931 const struct requirement *req)
3932{
3933 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_TILE_O);
3934
3935 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
3936 : NULL,
3937 other_player,
3938 req->range,
3939 req->source.value.diplrel);
3940}
3941
3942/**********************************************************************/
3945static enum fc_tristate
3946is_diplrel_unitany_in_range(const struct tile *target_tile,
3947 const struct player *other_player,
3948 enum req_range range,
3949 int diplrel)
3950{
3951 enum fc_tristate out = TRI_NO;
3952
3953 if (target_tile == NULL) {
3954 return TRI_MAYBE;
3955 }
3956
3957 unit_list_iterate(target_tile->units, target_unit) {
3958 enum fc_tristate for_target_unit = is_diplrel_in_range(
3959 unit_owner(target_unit), other_player, range, diplrel);
3960
3961 out = fc_tristate_or(out, for_target_unit);
3962 } unit_list_iterate_end;
3963
3964 return out;
3965}
3966
3967/**********************************************************************/
3976static enum fc_tristate
3977is_diplrel_unitany_req_active(const struct civ_map *nmap,
3978 const struct req_context *context,
3979 const struct player *other_player,
3980 const struct requirement *req)
3981{
3982 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_UNITANY);
3983
3984 return is_diplrel_unitany_in_range(context->tile, context->player,
3985 req->range,
3986 req->source.value.diplrel);
3987}
3988
3989/**********************************************************************/
3998static enum fc_tristate
3999is_diplrel_unitany_o_req_active(const struct civ_map *nmap,
4000 const struct req_context *context,
4001 const struct player *other_player,
4002 const struct requirement *req)
4003{
4004 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_UNITANY_O);
4005
4006 return is_diplrel_unitany_in_range(context->tile, other_player,
4007 req->range,
4008 req->source.value.diplrel);
4009}
4010
4011/**********************************************************************/
4018static enum fc_tristate
4019is_unittype_req_active(const struct civ_map *nmap,
4020 const struct req_context *context,
4021 const struct player *other_player,
4022 const struct requirement *req)
4023{
4024 const struct unit_type *punittype;
4025
4026 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UTYPE);
4027
4028 punittype = req->source.value.utype;
4029
4030 if (req->range != REQ_RANGE_LOCAL) {
4031 return TRI_NO;
4032 }
4033 if (!context->unittype) {
4034 return TRI_MAYBE;
4035 }
4036
4037 return BOOL_TO_TRISTATE(context->unittype == punittype);
4038}
4039
4040/**********************************************************************/
4047static enum fc_tristate
4048is_unitflag_req_active(const struct civ_map *nmap,
4049 const struct req_context *context,
4050 const struct player *other_player,
4051 const struct requirement *req)
4052{
4053 enum unit_type_flag_id unitflag;
4054
4055 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UTFLAG);
4056
4057 unitflag = req->source.value.unitflag;
4058
4059 if (req->range != REQ_RANGE_LOCAL) {
4060 return TRI_NO;
4061 }
4062 if (!context->unittype) {
4063 return TRI_MAYBE;
4064 }
4065
4066 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4067}
4068
4069/**********************************************************************/
4076static enum fc_tristate
4077is_unitclass_req_active(const struct civ_map *nmap,
4078 const struct req_context *context,
4079 const struct player *other_player,
4080 const struct requirement *req)
4081{
4082 const struct unit_class *pclass;
4083
4084 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UCLASS);
4085
4086 pclass = req->source.value.uclass;
4087
4088 if (req->range != REQ_RANGE_LOCAL) {
4089 return TRI_NO;
4090 }
4091 if (!context->unittype) {
4092 return TRI_MAYBE;
4093 }
4094
4095 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4096}
4097
4098/**********************************************************************/
4106static enum fc_tristate
4107is_unitclassflag_req_active(const struct civ_map *nmap,
4108 const struct req_context *context,
4109 const struct player *other_player,
4110 const struct requirement *req)
4111{
4112 enum unit_class_flag_id ucflag;
4113
4114 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UCFLAG);
4115
4116 ucflag = req->source.value.unitclassflag;
4117
4118 if (req->range != REQ_RANGE_LOCAL) {
4119 return TRI_NO;
4120 }
4121 if (!context->unittype) {
4122 return TRI_MAYBE;
4123 }
4124
4125 return BOOL_TO_TRISTATE(uclass_has_flag(utype_class(context->unittype), ucflag));
4126}
4127
4128/**********************************************************************/
4135static enum fc_tristate
4136is_unitstate_req_active(const struct civ_map *nmap,
4137 const struct req_context *context,
4138 const struct player *other_player,
4139 const struct requirement *req)
4140{
4141 enum ustate_prop uprop;
4142
4143 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UNITSTATE);
4144
4145 uprop = req->source.value.unit_state;
4146
4147 fc_assert_ret_val_msg(req->range == REQ_RANGE_LOCAL, TRI_NO,
4148 "Unsupported range \"%s\"",
4149 req_range_name(req->range));
4150
4151 /* Could be asked with incomplete data.
4152 * is_req_active() will handle it based on prob_type. */
4153 if (context->unit == NULL) {
4154 return TRI_MAYBE;
4155 }
4156
4157 switch (uprop) {
4158 case USP_TRANSPORTED:
4159 return BOOL_TO_TRISTATE(context->unit->transporter != NULL);
4160 case USP_LIVABLE_TILE:
4161 return BOOL_TO_TRISTATE(
4162 can_unit_exist_at_tile(nmap, context->unit,
4163 unit_tile(context->unit)));
4164 break;
4165 case USP_TRANSPORTING:
4166 return BOOL_TO_TRISTATE(0 < get_transporter_occupancy(context->unit));
4167 case USP_HAS_HOME_CITY:
4168 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
4169 case USP_NATIVE_TILE:
4170 return BOOL_TO_TRISTATE(
4171 is_native_tile(unit_type_get(context->unit),
4172 unit_tile(context->unit)));
4173 break;
4174 case USP_NATIVE_EXTRA:
4175 return BOOL_TO_TRISTATE(
4176 tile_has_native_base(unit_tile(context->unit),
4177 unit_type_get(context->unit)));
4178 break;
4179 case USP_MOVED_THIS_TURN:
4180 return BOOL_TO_TRISTATE(context->unit->moved);
4181 case USP_COUNT:
4182 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
4183 /* Invalid property is unknowable. */
4184 return TRI_NO;
4185 }
4186
4187 /* Should never be reached */
4188 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
4189
4190 return TRI_NO;
4191}
4192
4193/**********************************************************************/
4200static enum fc_tristate
4201is_activity_req_active(const struct civ_map *nmap,
4202 const struct req_context *context,
4203 const struct player *other_player,
4204 const struct requirement *req)
4205{
4206 enum unit_activity activity;
4207
4208 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ACTIVITY);
4209
4210 activity = req->source.value.activity;
4211
4212 fc_assert_ret_val_msg(req->range == REQ_RANGE_LOCAL, TRI_NO,
4213 "Unsupported range \"%s\"",
4214 req_range_name(req->range));
4215
4216 if (context->unit == NULL) {
4217 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
4218 * it's the zero value that context has by default - so many callers
4219 * who meant not to set specific activity actually have ACTIVITY_IDLE
4220 * instead of ACTIVITY_LAST */
4221 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
4222 return BOOL_TO_TRISTATE(activity == context->activity);
4223 }
4224
4225 /* Could be asked with incomplete data.
4226 * is_req_active() will handle it based on prob_type. */
4227 return TRI_MAYBE;
4228 }
4229
4230 switch (context->unit->activity) {
4231 case ACTIVITY_IDLE:
4232 case ACTIVITY_SENTRY:
4233 case ACTIVITY_GOTO:
4234 case ACTIVITY_EXPLORE:
4235 /* Seen as idle. */
4236 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
4237 default:
4238 /* Handled below. */
4239 break;
4240 }
4241
4242 return BOOL_TO_TRISTATE(context->unit->activity == activity);
4243}
4244
4245/**********************************************************************/
4252static enum fc_tristate
4253is_minveteran_req_active(const struct civ_map *nmap,
4254 const struct req_context *context,
4255 const struct player *other_player,
4256 const struct requirement *req)
4257{
4258 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINVETERAN);
4259
4260 if (context->unit == NULL) {
4261 return TRI_MAYBE;
4262 } else {
4263 return BOOL_TO_TRISTATE(context->unit->veteran
4264 >= req->source.value.minveteran);
4265 }
4266}
4267
4268/**********************************************************************/
4276static enum fc_tristate
4277is_minmovefrags_req_active(const struct civ_map *nmap,
4278 const struct req_context *context,
4279 const struct player *other_player,
4280 const struct requirement *req)
4281{
4282 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINMOVES);
4283
4284 if (context->unit == NULL) {
4285 return TRI_MAYBE;
4286 } else {
4287 return BOOL_TO_TRISTATE(req->source.value.minmoves
4288 <= context->unit->moves_left);
4289 }
4290}
4291
4292/**********************************************************************/
4300static enum fc_tristate
4301is_minhitpoints_req_active(const struct civ_map *nmap,
4302 const struct req_context *context,
4303 const struct player *other_player,
4304 const struct requirement *req)
4305{
4306 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINHP);
4307
4308 if (context->unit == NULL) {
4309 return TRI_MAYBE;
4310 } else {
4311 return BOOL_TO_TRISTATE(req->source.value.min_hit_points
4312 <= context->unit->hp);
4313 }
4314}
4315
4316/**********************************************************************/
4323static enum fc_tristate
4324is_age_req_active(const struct civ_map *nmap,
4325 const struct req_context *context,
4326 const struct player *other_player,
4327 const struct requirement *req)
4328{
4329 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_AGE);
4330
4331 switch (req->range) {
4332 case REQ_RANGE_LOCAL:
4333 if (context->unit == NULL || !is_server()) {
4334 return TRI_MAYBE;
4335 } else {
4336 return BOOL_TO_TRISTATE(
4337 req->source.value.age <=
4338 game.info.turn - context->unit->birth_turn);
4339 }
4340 break;
4341 case REQ_RANGE_CITY:
4342 if (context->city == NULL) {
4343 return TRI_MAYBE;
4344 } else {
4345 return BOOL_TO_TRISTATE(
4346 req->source.value.age <=
4347 game.info.turn - context->city->turn_founded);
4348 }
4349 break;
4350 case REQ_RANGE_PLAYER:
4351 if (context->player == NULL) {
4352 return TRI_MAYBE;
4353 } else {
4354 return BOOL_TO_TRISTATE(req->source.value.age
4355 <= player_age(context->player));
4356 }
4357 break;
4358 default:
4359 return TRI_MAYBE;
4360 break;
4361 }
4362}
4363
4364/**********************************************************************/
4371static enum fc_tristate
4372is_form_age_req_active(const struct civ_map *nmap,
4373 const struct req_context *context,
4374 const struct player *other_player,
4375 const struct requirement *req)
4376{
4377 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_FORM_AGE);
4378
4379 switch (req->range) {
4380 case REQ_RANGE_LOCAL:
4381 if (context->unit == NULL || !is_server()) {
4382 return TRI_MAYBE;
4383 } else {
4384 return BOOL_TO_TRISTATE(
4385 req->source.value.form_age <=
4386 game.info.turn - context->unit->current_form_turn);
4387 }
4388 break;
4389 default:
4390 return TRI_MAYBE;
4391 break;
4392 }
4393}
4394
4395/**********************************************************************/
4398 static bool is_city_in_tile(const struct tile *ptile,
4399 const struct city *pcity)
4400{
4401 if (pcity == NULL) {
4402 return tile_city(ptile) != NULL;
4403 } else {
4404 return is_city_center(pcity, ptile);
4405 }
4406}
4407
4408/**********************************************************************/
4415static enum fc_tristate
4416is_citytile_req_active(const struct civ_map *nmap,
4417 const struct req_context *context,
4418 const struct player *other_player,
4419 const struct requirement *req)
4420{
4421 enum citytile_type citytile;
4422
4423 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_CITYTILE);
4424
4425 citytile = req->source.value.citytile;
4426
4427 fc_assert_ret_val(req_range_is_valid(req->range), TRI_MAYBE);
4428 if (context->tile == NULL) {
4429 return TRI_MAYBE;
4430 }
4431
4432 switch (citytile) {
4433 case CITYT_CENTER:
4434 switch (req->range) {
4435 case REQ_RANGE_TILE:
4436 return BOOL_TO_TRISTATE(is_city_in_tile(context->tile,
4437 context->city));
4438 case REQ_RANGE_CADJACENT:
4439 if (is_city_in_tile(context->tile, context->city)) {
4440 return TRI_YES;
4441 }
4442 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4443 if (is_city_in_tile(adjc_tile, context->city)) {
4444 return TRI_YES;
4445 }
4446 } cardinal_adjc_iterate_end;
4447
4448 return TRI_NO;
4449 case REQ_RANGE_ADJACENT:
4450 if (is_city_in_tile(context->tile, context->city)) {
4451 return TRI_YES;
4452 }
4453 adjc_iterate(nmap, context->tile, adjc_tile) {
4454 if (is_city_in_tile(adjc_tile, context->city)) {
4455 return TRI_YES;
4456 }
4457 } adjc_iterate_end;
4458
4459 return TRI_NO;
4460 case REQ_RANGE_CITY:
4461 case REQ_RANGE_TRADE_ROUTE:
4462 case REQ_RANGE_CONTINENT:
4463 case REQ_RANGE_PLAYER:
4464 case REQ_RANGE_TEAM:
4465 case REQ_RANGE_ALLIANCE:
4466 case REQ_RANGE_WORLD:
4467 case REQ_RANGE_LOCAL:
4468 case REQ_RANGE_COUNT:
4469 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4470 break;
4471 }
4472
4473 return TRI_MAYBE;
4474 case CITYT_CLAIMED:
4475 switch (req->range) {
4476 case REQ_RANGE_TILE:
4477 return BOOL_TO_TRISTATE(context->tile->owner != NULL);
4478 case REQ_RANGE_CADJACENT:
4479 if (context->tile->owner != NULL) {
4480 return TRI_YES;
4481 }
4482 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4483 if (adjc_tile->owner != NULL) {
4484 return TRI_YES;
4485 }
4486 } cardinal_adjc_iterate_end;
4487
4488 return TRI_NO;
4489 case REQ_RANGE_ADJACENT:
4490 if (context->tile->owner != NULL) {
4491 return TRI_YES;
4492 }
4493 adjc_iterate(nmap, context->tile, adjc_tile) {
4494 if (adjc_tile->owner != NULL) {
4495 return TRI_YES;
4496 }
4497 } adjc_iterate_end;
4498
4499 return TRI_NO;
4500 case REQ_RANGE_CITY:
4501 case REQ_RANGE_TRADE_ROUTE:
4502 case REQ_RANGE_CONTINENT:
4503 case REQ_RANGE_PLAYER:
4504 case REQ_RANGE_TEAM:
4505 case REQ_RANGE_ALLIANCE:
4506 case REQ_RANGE_WORLD:
4507 case REQ_RANGE_LOCAL:
4508 case REQ_RANGE_COUNT:
4509 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4510 break;
4511 }
4512
4513 return TRI_MAYBE;
4514 case CITYT_EXTRAS_OWNED:
4515 switch (req->range) {
4516 case REQ_RANGE_TILE:
4517 return BOOL_TO_TRISTATE(context->tile->extras_owner != NULL);
4518 case REQ_RANGE_CADJACENT:
4519 if (context->tile->extras_owner != NULL) {
4520 return TRI_YES;
4521 }
4522 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4523 if (adjc_tile->extras_owner != NULL) {
4524 return TRI_YES;
4525 }
4526 } cardinal_adjc_iterate_end;
4527
4528 return TRI_NO;
4529 case REQ_RANGE_ADJACENT:
4530 if (context->tile->extras_owner != NULL) {
4531 return TRI_YES;
4532 }
4533 adjc_iterate(nmap, context->tile, adjc_tile) {
4534 if (adjc_tile->extras_owner != NULL) {
4535 return TRI_YES;
4536 }
4537 } adjc_iterate_end;
4538
4539 return TRI_NO;
4540 case REQ_RANGE_CITY:
4541 case REQ_RANGE_TRADE_ROUTE:
4542 case REQ_RANGE_CONTINENT:
4543 case REQ_RANGE_PLAYER:
4544 case REQ_RANGE_TEAM:
4545 case REQ_RANGE_ALLIANCE:
4546 case REQ_RANGE_WORLD:
4547 case REQ_RANGE_LOCAL:
4548 case REQ_RANGE_COUNT:
4549 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4550 break;
4551 }
4552
4553 return TRI_MAYBE;
4554 case CITYT_WORKED:
4555 switch (req->range) {
4556 case REQ_RANGE_TILE:
4557 return BOOL_TO_TRISTATE(context->tile->worked != NULL);
4558 case REQ_RANGE_CADJACENT:
4559 if (context->tile->worked != NULL) {
4560 return TRI_YES;
4561 }
4562 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4563 if (adjc_tile->worked != NULL) {
4564 return TRI_YES;
4565 }
4566 } cardinal_adjc_iterate_end;
4567
4568 return TRI_NO;
4569 case REQ_RANGE_ADJACENT:
4570 if (context->tile->worked != NULL) {
4571 return TRI_YES;
4572 }
4573 adjc_iterate(nmap, context->tile, adjc_tile) {
4574 if (adjc_tile->worked != NULL) {
4575 return TRI_YES;
4576 }
4577 } adjc_iterate_end;
4578
4579 return TRI_NO;
4580 case REQ_RANGE_CITY:
4581 case REQ_RANGE_TRADE_ROUTE:
4582 case REQ_RANGE_CONTINENT:
4583 case REQ_RANGE_PLAYER:
4584 case REQ_RANGE_TEAM:
4585 case REQ_RANGE_ALLIANCE:
4586 case REQ_RANGE_WORLD:
4587 case REQ_RANGE_LOCAL:
4588 case REQ_RANGE_COUNT:
4589 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4590 break;
4591 }
4592
4593 return TRI_MAYBE;
4594 case CITYT_SAME_CONTINENT:
4595 {
4596 Continent_id cc;
4597 const struct tile *target_tile = context->tile, *cc_tile;
4598
4599 if (!context->city) {
4600 return TRI_MAYBE;
4601 }
4602 cc_tile = city_tile(context->city);
4603 if (!cc_tile) {
4604 /* Unplaced virtual city */
4605 return TRI_MAYBE;
4606 }
4607 cc = tile_continent(cc_tile);
4608 /* Note: No special treatment of 0 == cc here*/
4609 switch (req->range) {
4610 case REQ_RANGE_TILE:
4611 return BOOL_TO_TRISTATE(tile_continent(target_tile) == cc);
4612 case REQ_RANGE_CADJACENT:
4613 if (tile_continent(target_tile) == cc) {
4614 return TRI_YES;
4615 }
4616 cardinal_adjc_iterate(nmap, target_tile, adjc_tile) {
4617 if (tile_continent(adjc_tile) == cc) {
4618 return TRI_YES;
4619 }
4620 } cardinal_adjc_iterate_end;
4621
4622 return TRI_NO;
4623 case REQ_RANGE_ADJACENT:
4624 if (tile_continent(target_tile) == cc) {
4625 return TRI_YES;
4626 }
4627 adjc_iterate(nmap, target_tile, adjc_tile) {
4628 if (tile_continent(adjc_tile) == cc) {
4629 return TRI_YES;
4630 }
4631 } adjc_iterate_end;
4632
4633 return TRI_NO;
4634 case REQ_RANGE_CITY:
4635 case REQ_RANGE_TRADE_ROUTE:
4636 case REQ_RANGE_CONTINENT:
4637 case REQ_RANGE_PLAYER:
4638 case REQ_RANGE_TEAM:
4639 case REQ_RANGE_ALLIANCE:
4640 case REQ_RANGE_WORLD:
4641 case REQ_RANGE_LOCAL:
4642 case REQ_RANGE_COUNT:
4643 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4644 break;
4645 }
4646 }
4647
4648 return TRI_MAYBE;
4649 case CITYT_BORDERING_TCLASS_REGION:
4650 {
4651 int n = 0;
4652 Continent_id adjc_cont[8], cc;
4653 bool ukt = FALSE;
4654 const struct tile *target_tile = context->tile, *cc_tile;
4655
4656 if (!context->city) {
4657 return TRI_MAYBE;
4658 }
4659 cc_tile = city_tile(context->city);
4660 if (!cc_tile) {
4661 /* Unplaced virtual city */
4662 return TRI_MAYBE;
4663 }
4664 cc = tile_continent(cc_tile);
4665 if (!cc) {
4666 /* Don't know the city center terrain class.
4667 * Maybe, the city floats? Even if the rules prohibit it... */
4668 return TRI_MAYBE;
4669 }
4670 adjc_iterate(nmap, cc_tile, adjc_tile) {
4671 Continent_id tc = tile_continent(adjc_tile);
4672
4673 if (0 != tc) {
4674 bool seen = FALSE;
4675 int i = n;
4676
4677 if (tc == cc) {
4678 continue;
4679 }
4680 while (--i >= 0) {
4681 if (adjc_cont[i] == tc) {
4682 seen = TRUE;
4683 break;
4684 }
4685 }
4686 if (seen) {
4687 continue;
4688 }
4689 adjc_cont[n++] = tile_continent(adjc_tile);
4690 } else {
4691 /* Likely, it's a black tile in client and we don't know
4692 * We possibly can calculate, but keep it simple. */
4693 ukt = TRUE;
4694 }
4695 } adjc_iterate_end;
4696 if (0 == n) {
4697 return ukt ? TRI_MAYBE : TRI_NO;
4698 }
4699
4700 switch (req->range) {
4701 case REQ_RANGE_TILE:
4702 {
4703 Continent_id tc = tile_continent(target_tile);
4704
4705 if (cc == tc) {
4706 return TRI_NO;
4707 }
4708 if (0 == tc || ukt) {
4709 return TRI_MAYBE;
4710 }
4711 for (int i = 0; i < n; i++) {
4712 if (tc == adjc_cont[i]) {
4713 return TRI_YES;
4714 }
4715 }
4716 }
4717
4718 return TRI_NO;
4719 case REQ_RANGE_ADJACENT:
4720 if (ukt) {
4721 /* If ALL the tiles in range are on cc, we can say it's false */
4722 square_iterate(nmap, target_tile, 1, adjc_tile) {
4723 if (tile_continent(adjc_tile) != cc) {
4724 return TRI_MAYBE;
4725 }
4726 } square_iterate_end;
4727
4728 return TRI_NO;
4729 } else {
4730 square_iterate(nmap, target_tile, 1, adjc_tile) {
4731 Continent_id tc = tile_continent(adjc_tile);
4732
4733 if (0 == tc) {
4734 return TRI_MAYBE;
4735 }
4736 for (int i = 0; i < n; i++) {
4737 if (tc == adjc_cont[i]) {
4738 return TRI_YES;
4739 }
4740 }
4741 } square_iterate_end;
4742 }
4743
4744 return TRI_NO;
4745 case REQ_RANGE_CADJACENT:
4746 if (ukt) {
4747 /* If ALL the tiles in range are on cc, we can say it's false */
4748 circle_iterate(nmap, target_tile, 1, cadjc_tile) {
4749 if (tile_continent(cadjc_tile) != cc) {
4750 return TRI_MAYBE;
4751 }
4752 } circle_iterate_end;
4753 } else {
4754 circle_iterate(nmap, target_tile, 1, cadjc_tile) {
4755 Continent_id tc = tile_continent(cadjc_tile);
4756
4757 if (0 == tc) {
4758 return TRI_MAYBE;
4759 }
4760 for (int i = 0; i < n; i++) {
4761 if (tc == adjc_cont[i]) {
4762 return TRI_YES;
4763 }
4764 }
4765 } circle_iterate_end;
4766 }
4767
4768 return TRI_NO;
4769 case REQ_RANGE_CITY:
4770 case REQ_RANGE_TRADE_ROUTE:
4771 case REQ_RANGE_CONTINENT:
4772 case REQ_RANGE_PLAYER:
4773 case REQ_RANGE_TEAM:
4774 case REQ_RANGE_ALLIANCE:
4775 case REQ_RANGE_WORLD:
4776 case REQ_RANGE_LOCAL:
4777 case REQ_RANGE_COUNT:
4778 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4779 break;
4780 }
4781 }
4782
4783 return TRI_MAYBE;
4784 case CITYT_LAST:
4785 /* Handled below */
4786 break;
4787 }
4788
4789 /* Not implemented */
4790 log_error("is_req_active(): citytile %d not supported.",
4791 citytile);
4792 return TRI_MAYBE;
4793}
4794
4795/**********************************************************************/
4803static enum fc_tristate
4804is_citystatus_req_active(const struct civ_map *nmap,
4805 const struct req_context *context,
4806 const struct player *other_player,
4807 const struct requirement *req)
4808{
4809 enum citystatus_type citystatus;
4810
4811 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_CITYSTATUS);
4812
4813 citystatus = req->source.value.citystatus;
4814
4815 if (context->city == NULL) {
4816 return TRI_MAYBE;
4817 }
4818
4819 switch (citystatus) {
4820 case CITYS_OWNED_BY_ORIGINAL:
4821 switch (req->range) {
4822 case REQ_RANGE_CITY:
4823 if (context->city->original == NULL) {
4824 return TRI_MAYBE;
4825 }
4826 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
4827 case REQ_RANGE_TRADE_ROUTE:
4828 {
4829 enum fc_tristate ret;
4830
4831 if (city_owner(context->city) == context->city->original) {
4832 return TRI_YES;
4833 }
4834
4835 ret = TRI_NO;
4836 trade_partners_iterate(context->city, trade_partner) {
4837 if (trade_partner == NULL || trade_partner->original == NULL) {
4838 ret = TRI_MAYBE;
4839 } else if (city_owner(trade_partner) == trade_partner->original) {
4840 return TRI_YES;
4841 }
4842 } trade_partners_iterate_end;
4843
4844 return ret;
4845 }
4846 case REQ_RANGE_LOCAL:
4847 case REQ_RANGE_TILE:
4848 case REQ_RANGE_CADJACENT:
4849 case REQ_RANGE_ADJACENT:
4850 case REQ_RANGE_CONTINENT:
4851 case REQ_RANGE_PLAYER:
4852 case REQ_RANGE_TEAM:
4853 case REQ_RANGE_ALLIANCE:
4854 case REQ_RANGE_WORLD:
4855 case REQ_RANGE_COUNT:
4856 break;
4857 }
4858
4859 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
4860 req->range);
4861
4862 return TRI_MAYBE;
4863
4864 case CITYS_STARVED:
4865 switch (req->range) {
4866 case REQ_RANGE_CITY:
4867 return BOOL_TO_TRISTATE(context->city->had_famine);
4868 case REQ_RANGE_TRADE_ROUTE:
4869 {
4870 enum fc_tristate ret;
4871
4872 if (context->city->had_famine) {
4873 return TRI_YES;
4874 }
4875
4876 ret = TRI_NO;
4877 trade_partners_iterate(context->city, trade_partner) {
4878 if (trade_partner == NULL) {
4879 ret = TRI_MAYBE;
4880 } else if (trade_partner->had_famine) {
4881 return TRI_YES;
4882 }
4883 } trade_partners_iterate_end;
4884
4885 return ret;
4886 }
4887 case REQ_RANGE_LOCAL:
4888 case REQ_RANGE_TILE:
4889 case REQ_RANGE_CADJACENT:
4890 case REQ_RANGE_ADJACENT:
4891 case REQ_RANGE_CONTINENT:
4892 case REQ_RANGE_PLAYER:
4893 case REQ_RANGE_TEAM:
4894 case REQ_RANGE_ALLIANCE:
4895 case REQ_RANGE_WORLD:
4896 case REQ_RANGE_COUNT:
4897 break;
4898 }
4899
4900 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
4901 req->range);
4902
4903 return TRI_MAYBE;
4904
4905 case CITYS_DISORDER:
4906 switch (req->range) {
4907 case REQ_RANGE_CITY:
4908 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
4909 case REQ_RANGE_TRADE_ROUTE:
4910 {
4911 enum fc_tristate ret;
4912
4913 if (context->city->anarchy > 0) {
4914 return TRI_YES;
4915 }
4916
4917 ret = TRI_NO;
4918 trade_partners_iterate(context->city, trade_partner) {
4919 if (trade_partner == NULL) {
4920 ret = TRI_MAYBE;
4921 } else if (trade_partner->anarchy > 0) {
4922 return TRI_YES;
4923 }
4924 } trade_partners_iterate_end;
4925
4926 return ret;
4927 }
4928 case REQ_RANGE_LOCAL:
4929 case REQ_RANGE_TILE:
4930 case REQ_RANGE_CADJACENT:
4931 case REQ_RANGE_ADJACENT:
4932 case REQ_RANGE_CONTINENT:
4933 case REQ_RANGE_PLAYER:
4934 case REQ_RANGE_TEAM:
4935 case REQ_RANGE_ALLIANCE:
4936 case REQ_RANGE_WORLD:
4937 case REQ_RANGE_COUNT:
4938 break;
4939 }
4940
4941 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
4942 req->range);
4943
4944 return TRI_MAYBE;
4945
4946 case CITYS_CELEBRATION:
4947 switch (req->range) {
4948 case REQ_RANGE_CITY:
4949 return BOOL_TO_TRISTATE(context->city->rapture > 0);
4950 case REQ_RANGE_TRADE_ROUTE:
4951 {
4952 enum fc_tristate ret;
4953
4954 if (context->city->rapture > 0) {
4955 return TRI_YES;
4956 }
4957
4958 ret = TRI_NO;
4959 trade_partners_iterate(context->city, trade_partner) {
4960 if (trade_partner == NULL) {
4961 ret = TRI_MAYBE;
4962 } else if (trade_partner->rapture > 0) {
4963 return TRI_YES;
4964 }
4965 } trade_partners_iterate_end;
4966
4967 return ret;
4968 }
4969 case REQ_RANGE_LOCAL:
4970 case REQ_RANGE_TILE:
4971 case REQ_RANGE_CADJACENT:
4972 case REQ_RANGE_ADJACENT:
4973 case REQ_RANGE_CONTINENT:
4974 case REQ_RANGE_PLAYER:
4975 case REQ_RANGE_TEAM:
4976 case REQ_RANGE_ALLIANCE:
4977 case REQ_RANGE_WORLD:
4978 case REQ_RANGE_COUNT:
4979 break;
4980 }
4981
4982 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
4983 req->range);
4984
4985 return TRI_MAYBE;
4986
4987 case CITYS_TRANSFERRED:
4988 switch (req->range) {
4989 case REQ_RANGE_CITY:
4990 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
4991 case REQ_RANGE_TRADE_ROUTE:
4992 {
4993 enum fc_tristate ret;
4994
4995 if (context->city->acquire_t != CACQ_FOUNDED) {
4996 return TRI_YES;
4997 }
4998
4999 ret = TRI_NO;
5000 trade_partners_iterate(context->city, trade_partner) {
5001 if (trade_partner == NULL) {
5002 ret = TRI_MAYBE;
5003 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
5004 return TRI_YES;
5005 }
5006 } trade_partners_iterate_end;
5007
5008 return ret;
5009 }
5010 case REQ_RANGE_LOCAL:
5011 case REQ_RANGE_TILE:
5012 case REQ_RANGE_CADJACENT:
5013 case REQ_RANGE_ADJACENT:
5014 case REQ_RANGE_CONTINENT:
5015 case REQ_RANGE_PLAYER:
5016 case REQ_RANGE_TEAM:
5017 case REQ_RANGE_ALLIANCE:
5018 case REQ_RANGE_WORLD:
5019 case REQ_RANGE_COUNT:
5020 break;
5021 }
5022
5023 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
5024 req->range);
5025
5026 return TRI_MAYBE;
5027
5028 case CITYS_LAST:
5029 break;
5030 }
5031
5032 /* Not implemented */
5033 log_error("is_req_active(): citystatus %d not supported.",
5034 citystatus);
5035
5036 return TRI_MAYBE;
5037}
5038
5039/**********************************************************************/
5046static enum fc_tristate
5047is_minsize_req_active(const struct civ_map *nmap,
5048 const struct req_context *context,
5049 const struct player *other_player,
5050 const struct requirement *req)
5051{
5052 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINSIZE);
5053
5054 if (context->city == NULL) {
5055 return TRI_MAYBE;
5056 } else {
5057 if (req->range == REQ_RANGE_TRADE_ROUTE) {
5058 enum fc_tristate ret;
5059
5060 if (city_size_get(context->city) >= req->source.value.minsize) {
5061 return TRI_YES;
5062 }
5063
5064 ret = TRI_NO;
5065 trade_partners_iterate(context->city, trade_partner) {
5066 if (trade_partner == NULL) {
5067 ret = TRI_MAYBE;
5068 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
5069 return TRI_YES;
5070 }
5071 } trade_partners_iterate_end;
5072
5073 return ret;
5074 } else {
5075 return BOOL_TO_TRISTATE(city_size_get(context->city)
5076 >= req->source.value.minsize);
5077 }
5078 }
5079}
5080
5081/**********************************************************************/
5088static enum fc_tristate
5089is_counter_req_active(const struct civ_map *nmap,
5090 const struct req_context *context,
5091 const struct player *other_player,
5092 const struct requirement *req)
5093{
5094 const struct counter *count;
5095
5096 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_COUNTER);
5097
5098 count = req->source.value.counter;
5099
5100 if (NULL == context->city) {
5101 return TRI_MAYBE;
5102 }
5103 return BOOL_TO_TRISTATE(count->checkpoint <=
5104 context->city->counter_values[
5105 counter_index(count)]);
5106}
5107
5108/**********************************************************************/
5116static enum fc_tristate
5117is_achievement_req_active(const struct civ_map *nmap,
5118 const struct req_context *context,
5119 const struct player *other_player,
5120 const struct requirement *req)
5121{
5122 const struct achievement *achievement;
5123
5124 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ACHIEVEMENT);
5125
5126 achievement = req->source.value.achievement;
5127
5128 if (req->range == REQ_RANGE_WORLD) {
5129 return BOOL_TO_TRISTATE(achievement_claimed(achievement));
5130 } else if (context->player == NULL) {
5131 return TRI_MAYBE;
5132 } else if (req->range == REQ_RANGE_ALLIANCE
5133 || req->range == REQ_RANGE_TEAM) {
5134 players_iterate_alive(plr2) {
5135 if (players_in_same_range(context->player, plr2, req->range)
5136 && achievement_player_has(achievement, plr2)) {
5137 return TRI_YES;
5138 }
5139 } players_iterate_alive_end;
5140 return TRI_NO;
5141 } else if (req->range == REQ_RANGE_PLAYER) {
5142 if (achievement_player_has(achievement, context->player)) {
5143 return TRI_YES;
5144 } else {
5145 return TRI_NO;
5146 }
5147 }
5148
5149 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
5150
5151 return TRI_MAYBE;
5152}
5153
5154/**********************************************************************/
5162static enum fc_tristate
5163is_latitude_req_active(const struct civ_map *nmap,
5164 const struct req_context *context,
5165 const struct player *other_player,
5166 const struct requirement *req)
5167{
5168 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
5169
5170 fc_assert_ret_val(req != NULL, TRI_MAYBE);
5171 fc_assert(context != NULL);
5172
5173 switch (req->source.kind) {
5174 case VUT_MINLATITUDE:
5175 min = req->source.value.latitude;
5176 break;
5177 case VUT_MAXLATITUDE:
5178 max = req->source.value.latitude;
5179 break;
5180 default:
5181 fc_assert(req->source.kind == VUT_MINLATITUDE
5182 || req->source.kind == VUT_MAXLATITUDE);
5183 break;
5184 }
5185
5186 switch (req->range) {
5187 case REQ_RANGE_WORLD:
5188 return BOOL_TO_TRISTATE(min <= MAP_MAX_REAL_LATITUDE(wld.map)
5189 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
5190
5191 case REQ_RANGE_TILE:
5192 if (context->tile == NULL) {
5193 return TRI_MAYBE;
5194 } else {
5195 int tile_lat = map_signed_latitude(context->tile);
5196
5197 return BOOL_TO_TRISTATE(min <= tile_lat && max >= tile_lat);
5198 }
5199
5200 case REQ_RANGE_CADJACENT:
5201 if (context->tile == NULL) {
5202 return TRI_MAYBE;
5203 }
5204
5205 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
5206 int tile_lat = map_signed_latitude(adjc_tile);
5207
5208 if (min <= tile_lat && max >= tile_lat) {
5209 return TRI_YES;
5210 }
5211 } cardinal_adjc_iterate_end;
5212 return TRI_NO;
5213
5214 case REQ_RANGE_ADJACENT:
5215 if (!context->tile) {
5216 return TRI_MAYBE;
5217 }
5218
5219 adjc_iterate(nmap, context->tile, adjc_tile) {
5220 int tile_lat = map_signed_latitude(adjc_tile);
5221
5222 if (min <= tile_lat && max >= tile_lat) {
5223 return TRI_YES;
5224 }
5225 } adjc_iterate_end;
5226 return TRI_NO;
5227
5228 case REQ_RANGE_CITY:
5229 case REQ_RANGE_TRADE_ROUTE:
5230 case REQ_RANGE_CONTINENT:
5231 case REQ_RANGE_PLAYER:
5232 case REQ_RANGE_TEAM:
5233 case REQ_RANGE_ALLIANCE:
5234 case REQ_RANGE_LOCAL:
5235 case REQ_RANGE_COUNT:
5236 break;
5237 }
5238
5239 fc_assert_msg(FALSE,
5240 "Illegal range %d for latitude requirement.", req->range);
5241
5242 return TRI_MAYBE;
5243}
5244
5245/**********************************************************************/
5252static enum fc_tristate
5253is_minyear_req_active(const struct civ_map *nmap,
5254 const struct req_context *context,
5255 const struct player *other_player,
5256 const struct requirement *req)
5257{
5258 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINYEAR);
5259
5260 return BOOL_TO_TRISTATE(game.info.year >= req->source.value.minyear);
5261}
5262
5263/**********************************************************************/
5270static enum fc_tristate
5271is_mincalfrag_req_active(const struct civ_map *nmap,
5272 const struct req_context *context,
5273 const struct player *other_player,
5274 const struct requirement *req)
5275{
5276 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINCALFRAG);
5277
5278 return BOOL_TO_TRISTATE(game.info.fragment_count
5279 >= req->source.value.mincalfrag);
5280}
5281
5282/**********************************************************************/
5289static enum fc_tristate
5290is_topology_req_active(const struct civ_map *nmap,
5291 const struct req_context *context,
5292 const struct player *other_player,
5293 const struct requirement *req)
5294{
5295 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TOPO);
5296
5297 return BOOL_TO_TRISTATE(
5298 current_topo_has_flag(req->source.value.topo_property));
5299}
5300
5301/**********************************************************************/
5308static enum fc_tristate
5309is_wrap_req_active(const struct civ_map *nmap,
5310 const struct req_context *context,
5311 const struct player *other_player,
5312 const struct requirement *req)
5313{
5314 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_WRAP);
5315
5316 return BOOL_TO_TRISTATE(
5317 current_wrap_has_flag(req->source.value.wrap_property));
5318}
5319
5320/**********************************************************************/
5328static enum fc_tristate
5329is_serversetting_req_active(const struct civ_map *nmap,
5330 const struct req_context *context,
5331 const struct player *other_player,
5332 const struct requirement *req)
5333{
5334 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_SERVERSETTING);
5335
5336 return BOOL_TO_TRISTATE(ssetv_setting_has_value(
5337 req->source.value.ssetval));
5338}
5339
5340/* Not const for potential ruleset-related adjustment */
5341 static struct req_def req_definitions[VUT_COUNT] = {
5342 [VUT_NONE] = {is_none_req_active, REQUCH_YES},
5343
5344 /* Alphabetical order of enum constant */
5345 [VUT_ACHIEVEMENT] = {is_achievement_req_active, REQUCH_YES, REQUC_PRESENT},
5346 [VUT_ACTION] = {is_action_req_active, REQUCH_YES},
5347 [VUT_ACTIVITY] = {is_activity_req_active, REQUCH_NO},
5348 [VUT_ADVANCE] = {is_tech_req_active, REQUCH_NO},
5349 [VUT_AGE] = {is_age_req_active, REQUCH_YES, REQUC_PRESENT},
5350 [VUT_FORM_AGE] = {is_form_age_req_active, REQUCH_YES, REQUC_PRESENT},
5351 [VUT_AI_LEVEL] = {is_ai_req_active, REQUCH_HACK},
5352 [VUT_CITYSTATUS] = {is_citystatus_req_active, REQUCH_NO, REQUC_CITYSTATUS},
5353 [VUT_CITYTILE] = {is_citytile_req_active, REQUCH_NO, REQUC_CITYTILE},
5354 [VUT_COUNTER] = {is_counter_req_active, REQUCH_NO},
5355 [VUT_DIPLREL] = {is_diplrel_req_active, REQUCH_NO},
5356 [VUT_DIPLREL_TILE] = {is_diplrel_tile_req_active, REQUCH_NO},
5357 [VUT_DIPLREL_TILE_O] = {is_diplrel_tile_o_req_active, REQUCH_NO},
5358 [VUT_DIPLREL_UNITANY] = {is_diplrel_unitany_req_active, REQUCH_NO},
5359 [VUT_DIPLREL_UNITANY_O] = {is_diplrel_unitany_o_req_active, REQUCH_NO},
5360 [VUT_EXTRA] = {is_extra_req_active, REQUCH_NO, REQUC_LOCAL},
5361 [VUT_EXTRAFLAG] = {is_extraflag_req_active, REQUCH_NO, REQUC_LOCAL},
5362 [VUT_GOOD] = {is_good_req_active, REQUCH_NO},
5363 [VUT_GOVERNMENT] = {is_gov_req_active, REQUCH_NO},
5364 [VUT_IMPROVEMENT] = {is_building_req_active, REQUCH_NO, REQUC_IMPR},
5365 [VUT_IMPR_GENUS] = {is_buildinggenus_req_active, REQUCH_YES},
5366 [VUT_IMPR_FLAG] = {is_buildingflag_req_active, REQUCH_YES},
5367 [VUT_PLAYER_FLAG] = {is_plr_flag_req_active, REQUCH_NO},
5368 [VUT_PLAYER_STATE] = {is_plr_state_req_active, REQUCH_NO},
5369 [VUT_MAXLATITUDE] = {is_latitude_req_active, REQUCH_YES},
5370 [VUT_MAXTILEUNITS] = {is_maxunitsontile_req_active, REQUCH_NO},
5371 [VUT_MINCALFRAG] = {is_mincalfrag_req_active, REQUCH_NO},
5372 [VUT_MINCULTURE] = {is_minculture_req_active, REQUCH_NO},
5373 [VUT_MINFOREIGNPCT] = {is_minforeignpct_req_active, REQUCH_NO},
5374 [VUT_MINHP] = {is_minhitpoints_req_active, REQUCH_NO},
5375 [VUT_MINLATITUDE] = {is_latitude_req_active, REQUCH_NO},
5376 [VUT_MINMOVES] = {is_minmovefrags_req_active, REQUCH_NO},
5377 [VUT_MINSIZE] = {is_minsize_req_active, REQUCH_NO},
5378 [VUT_MINTECHS] = {is_mintechs_req_active, REQUCH_ACT, REQUC_WORLD},
5379 [VUT_MINVETERAN] = {is_minveteran_req_active, REQUCH_SCRIPTS, REQUC_PRESENT},
5380 [VUT_MINYEAR] = {is_minyear_req_active, REQUCH_HACK, REQUC_PRESENT},
5381 [VUT_NATION] = {is_nation_req_active, REQUCH_HACK, REQUC_NALLY},
5382 [VUT_NATIONALITY] = {is_nationality_req_active, REQUCH_NO},
5383 [VUT_NATIONGROUP] = {is_nationgroup_req_active, REQUCH_HACK, REQUC_NALLY},
5384 [VUT_ORIGINAL_OWNER] = {is_originalowner_req_active, REQUCH_HACK},
5385 [VUT_OTYPE] = {is_outputtype_req_active, REQUCH_YES},
5386 [VUT_ROADFLAG] = {is_roadflag_req_active, REQUCH_NO, REQUC_LOCAL},
5387 [VUT_SERVERSETTING] = {is_serversetting_req_active, REQUCH_HACK},
5388 [VUT_SPECIALIST] = {is_specialist_req_active, REQUCH_YES},
5389 [VUT_STYLE] = {is_style_req_active, REQUCH_HACK},
5390 [VUT_TECHFLAG] = {is_techflag_req_active, REQUCH_NO},
5391 [VUT_TERRAIN] = {is_terrain_req_active, REQUCH_NO},
5392 [VUT_TERRAINALTER] = {is_terrainalter_req_active, REQUCH_NO},
5393 [VUT_TERRAINCLASS] = {is_terrainclass_req_active, REQUCH_NO},
5394 [VUT_TERRFLAG] = {is_terrainflag_req_active, REQUCH_NO},
5395 [VUT_TOPO] = {is_topology_req_active, REQUCH_YES},
5396 [VUT_WRAP] = {is_wrap_req_active, REQUCH_YES},
5397 [VUT_UCFLAG] = {is_unitclassflag_req_active, REQUCH_YES},
5398 [VUT_UCLASS] = {is_unitclass_req_active, REQUCH_YES},
5399 [VUT_UNITSTATE] = {is_unitstate_req_active, REQUCH_NO},
5400 [VUT_UTFLAG] = {is_unitflag_req_active, REQUCH_YES},
5401 [VUT_UTYPE] = {is_unittype_req_active, REQUCH_YES}
5402};
5403
5404/**********************************************************************/
5416 bool is_req_active(const struct req_context *context,
5417 const struct player *other_player,
5418 const struct requirement *req,
5419 const enum req_problem_type prob_type)
5420{
5421 const struct civ_map *nmap = &(wld.map);
5422 enum fc_tristate eval = tri_req_present(nmap, context, other_player, req);
5423
5424 if (eval == TRI_MAYBE) {
5425 if (prob_type == RPT_POSSIBLE) {
5426 return TRUE;
5427 } else {
5428 return FALSE;
5429 }
5430 }
5431 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
5432}
5433
5434/**********************************************************************/
5442static
5443 enum fc_tristate tri_req_present(const struct civ_map *nmap,
5444 const struct req_context *context,
5445 const struct player *other_player,
5446 const struct requirement *req)
5447{
5448 if (context == NULL) {
5449 context = req_context_empty();
5450 }
5451
5452 if (req->source.kind >= VUT_COUNT) {
5453 log_error("tri_req_present(): invalid source kind %d.",
5454 req->source.kind);
5455 return TRI_NO;
5456 }
5457
5458 fc_assert_ret_val(req_definitions[req->source.kind].cb != NULL, TRI_NO);
5459
5460 return req_definitions[req->source.kind].cb(nmap, context,
5461 other_player, req);
5462}
5463
5464/**********************************************************************/
5472 enum fc_tristate tri_req_active(const struct req_context *context,
5473 const struct player *other_player,
5474 const struct requirement *req)
5475{
5476 const struct civ_map *nmap = &(wld.map);
5477 enum fc_tristate eval = tri_req_present(nmap, context, other_player, req);
5478
5479 if (!req->present) {
5480 if (TRI_NO == eval) {
5481 return TRI_YES;
5482 }
5483 if (TRI_YES == eval) {
5484 return TRI_NO;
5485 }
5486 }
5487
5488 return eval;
5489}
5490
5491/**********************************************************************/
5505 bool are_reqs_active(const struct req_context *context,
5506 const struct player *other_player,
5507 const struct requirement_vector *reqs,
5508 const enum req_problem_type prob_type)
5509{
5510 requirement_vector_iterate(reqs, preq) {
5511 if (!is_req_active(context, other_player, preq, prob_type)) {
5512 return FALSE;
5513 }
5514 } requirement_vector_iterate_end;
5515
5516 return TRUE;
5517}
5518
5519/**********************************************************************/
5523 bool are_reqs_active_ranges(const enum req_range min_range,
5524 const enum req_range max_range,
5525 const struct req_context *context,
5526 const struct player *other_player,
5527 const struct requirement_vector *reqs,
5528 const enum req_problem_type prob_type)
5529{
5530 requirement_vector_iterate(reqs, preq) {
5531 if (preq->range >= min_range && preq->range <= max_range) {
5532 if (!is_req_active(context, other_player, preq, prob_type)) {
5533 return FALSE;
5534 }
5535 }
5536 } requirement_vector_iterate_end;
5537
5538 return TRUE;
5539}
5540
5541/**********************************************************************/
5547enum fc_tristate
5548tri_req_active_turns(int pass, int period,
5549 const struct req_context *context,
5550 const struct player *other_player,
5551 const struct requirement *req)
5552{
5553 /* FIXME: doubles code from calendar.c */
5554 int ypt = get_world_bonus(EFT_TURN_YEARS);
5555 int fpt = get_world_bonus(EFT_TURN_FRAGMENTS);
5556 int fragment = game.info.fragment_count;
5557 int fragment1 = fragment; /* if fragments don't advance */
5558 int year_inc, year_inc1;
5559 const int slowdown = (victory_enabled(VC_SPACERACE)
5560 ? get_world_bonus(EFT_SLOW_DOWN_TIMELINE) : 0);
5561 bool present, present1;
5562
5563 fc_assert(pass >= 0 && period >= 0);
5564 if (slowdown >= 3) {
5565 if (ypt > 1) {
5566 ypt = 1;
5567 }
5568 } else if (slowdown >= 2) {
5569 if (ypt > 2) {
5570 ypt = 2;
5571 }
5572 } else if (slowdown >= 1) {
5573 if (ypt > 5) {
5574 ypt = 5;
5575 }
5576 }
5577 year_inc = ypt * pass;
5578 year_inc1 = year_inc + ypt * period;
5579 if (game.calendar.calendar_fragments) {
5580 int fragment_years;
5581
5582 fragment += fpt * pass;
5583 fragment_years = fragment / game.calendar.calendar_fragments;
5584 year_inc += fragment_years;
5585 fragment -= fragment_years * game.calendar.calendar_fragments;
5586 fragment1 = fragment + fpt * period;
5587 fragment_years += fragment1 / game.calendar.calendar_fragments;
5588 year_inc1 += fragment_years;
5589 fragment1 -= fragment_years * game.calendar.calendar_fragments;
5590 }
5591 if (game.calendar.calendar_skip_0 && game.info.year < 0) {
5592 if (year_inc + game.info.year >= 0) {
5593 year_inc++;
5594 year_inc1++;
5595 } else if (year_inc1 + game.info.year >= 0) {
5596 year_inc1++;
5597 }
5598 }
5599
5600 switch (req->source.kind) {
5601 case VUT_AGE:
5602 switch (req->range) {
5603 case REQ_RANGE_LOCAL:
5604 if (context->unit == NULL || !is_server()) {
5605 return TRI_MAYBE;
5606 } else {
5607 int ua = game.info.turn + pass - context->unit->birth_turn;
5608
5609 present = req->source.value.age <= ua;
5610 present1 = req->source.value.age <= ua + period;
5611 }
5612 break;
5613 case REQ_RANGE_CITY:
5614 if (context->city == NULL) {
5615 return TRI_MAYBE;
5616 } else {
5617 int ca = game.info.turn + pass - context->city->turn_founded;
5618
5619 present = req->source.value.age <= ca;
5620 present1 = req->source.value.age <= ca + period;
5621 }
5622 break;
5623 case REQ_RANGE_PLAYER:
5624 if (context->player == NULL) {
5625 return TRI_MAYBE;
5626 } else {
5627 present = req->source.value.age
5628 <= player_age(context->player) + pass;
5629 present1 = req->source.value.age
5630 <= player_age(context->player) + pass + period;
5631 }
5632 break;
5633 default:
5634 return TRI_MAYBE;
5635 }
5636 break;
5637 case VUT_FORM_AGE:
5638 if (context->unit == NULL || !is_server()) {
5639 return TRI_MAYBE;
5640 } else {
5641 int ua = game.info.turn + pass - context->unit->current_form_turn;
5642
5643 present = req->source.value.form_age <= ua;
5644 present1 = req->source.value.form_age <= ua + period;
5645 }
5646 break;
5647 case VUT_MINYEAR:
5648 present = game.info.year + year_inc >= req->source.value.minyear;
5649 present1 = game.info.year + year_inc1 >= req->source.value.minyear;
5650 break;
5651 case VUT_MINCALFRAG:
5652 if (game.calendar.calendar_fragments <= period) {
5653 /* Hope that the requirement is valid and fragments advance fine */
5654 return TRI_YES;
5655 }
5656 present = fragment >= req->source.value.mincalfrag;
5657 present1 = fragment1 >= req->source.value.mincalfrag;
5658 break;
5659 default:
5660 /* No special handling invented */
5661 return tri_req_active(context, other_player, req);
5662 }
5663 return BOOL_TO_TRISTATE(req->present
5664 ? present || present1 : !(present && present1));
5665}
5666
5667/**********************************************************************/
5672 enum fc_tristate default_tester_cb
5673 (const struct req_context *context,
5674 const struct player *other_player,
5675 const struct requirement *req,
5676 void *data, int n_data)
5677{
5678 int i;
5679
5680 fc_assert_ret_val(data || n_data == 0, TRI_NO);
5681
5682 for (i = 0; i < n_data; i++) {
5683 if (are_requirements_contradictions(&((struct requirement *) data)[i],
5684 req)) {
5685 return TRI_NO;
5686 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
5687 return TRI_YES;
5688 }
5689 }
5690
5691 return tri_req_active(context, other_player, req);
5692}
5693
5694/**********************************************************************/
5700enum fc_tristate
5701 tri_reqs_cb_active(const struct req_context *context,
5702 const struct player *other_player,
5703 const struct requirement_vector *reqs,
5704 struct requirement_vector *maybe_reqs,
5705 req_tester_cb tester,
5706 void *data, int n_data)
5707{
5708 bool active = TRUE;
5709 bool certain = TRUE;
5710
5711 fc_assert_ret_val(NULL != tester, TRI_NO);
5712 requirement_vector_iterate(reqs, preq) {
5713 switch(tester(context, other_player, preq,
5714 data, n_data)) {
5715 case TRI_NO:
5716 active = FALSE;
5717 certain = TRUE;
5718 break;
5719 case TRI_YES:
5720 break;
5721 case TRI_MAYBE:
5722 certain = FALSE;
5723 if (maybe_reqs) {
5724 requirement_vector_append(maybe_reqs, *preq);
5725 }
5726 break;
5727 default:
5728 fc_assert(FALSE);
5729 active = FALSE;
5730 }
5731 if (!active) {
5732 break;
5733 }
5734 } requirement_vector_iterate_end;
5735
5736 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
5737}
5738
5739/**********************************************************************/
5747enum req_unchanging_status
5748 is_req_unchanging(const struct req_context *context,
5749 const struct requirement *req)
5750{
5751 enum req_unchanging_status s;
5752 const struct civ_map *nmap = &(wld.map);
5753
5754 fc_assert_ret_val(req, REQUCH_NO);
5755 fc_assert_ret_val_msg(universals_n_is_valid(req->source.kind), REQUCH_NO,
5756 "Invalid source kind %d.", req->source.kind);
5757 s = req_definitions[req->source.kind].unchanging;
5758
5759 if (req->survives) {
5760 /* Special case for surviving requirements */
5761 /* Buildings may obsolete even here */
5762 if (VUT_IMPROVEMENT == req->source.kind) {
5763 const struct impr_type *b = req->source.value.building;
5764
5765 if (can_improvement_go_obsolete(b)) {
5766 if (improvement_obsolete(context->player, b, context->city)) {
5767 /* FIXME: sometimes can unobsolete, but considering it
5768 * may sometimes put the function on endless recursion */
5769 return REQUCH_ACT; /* Mostly about techs */
5770 } else {
5771 /* NOTE: may obsoletion reqs be unchanging? Hardly but why not. */
5772 return REQUCH_NO;
5773 }
5774 }
5775 }
5776 s = unchanging_present(nmap, s, context, req);
5777 if (s != REQUCH_NO) {
5778 return unchanging_noally(nmap, s, context, req);
5779 }
5780 } else {
5781 req_unchanging_cond_cb cond
5782 = req_definitions[req->source.kind].unchanging_cond;
5783
5784 if (cond) {
5785 return cond(nmap, s, context, req);
5786 }
5787 }
5788
5789 return s;
5790}
5791
5792/**********************************************************************/
5795enum req_unchanging_status
5796 is_req_preventing(const struct req_context *context,
5797 const struct player *other_player,
5798 const struct requirement *req,
5799 enum req_problem_type prob_type)
5800{
5801 enum req_unchanging_status u = is_req_unchanging(context, req);
5802
5803 if (REQUCH_NO != u) {
5804 /* presence is precalculated */
5805 bool auto_present = (req->survives
5806 && !(VUT_IMPROVEMENT == req->source.kind
5807 && can_improvement_go_obsolete(req->source.value.building)))
5808 || REQUC_PRESENT == req_definitions[req->source.kind].unchanging_cond
5809 || REQUC_WORLD == req_definitions[req->source.kind].unchanging_cond;
5810
5811 if (auto_present ? req->present
5812 : is_req_active(context, other_player, req, RPT_POSSIBLE)) {
5813 /* Unchanging but does not block */
5814 return REQUCH_NO;
5815 }
5816 }
5817
5818 return u;
5819}
5820
5821/**********************************************************************/
5825 bool is_req_in_vec(const struct requirement *req,
5826 const struct requirement_vector *vec)
5827{
5828 requirement_vector_iterate(vec, preq) {
5829 if (are_requirements_equal(req, preq)) {
5830 return TRUE;
5831 }
5832 } requirement_vector_iterate_end;
5833
5834 return FALSE;
5835}
5836
5837/**********************************************************************/
5843 bool req_vec_wants_type(const struct requirement_vector *reqs,
5844 enum universals_n kind)
5845{
5846 requirement_vector_iterate(reqs, preq) {
5847 if (preq->present && preq->source.kind == kind) {
5848 return TRUE;
5849 }
5850 } requirement_vector_iterate_end;
5851 return FALSE;
5852}
5853
5854/**********************************************************************/
5862 bool universal_never_there(const struct universal *source)
5863{
5864 switch (source->kind) {
5865 case VUT_ACTION:
5866 return !action_is_in_use(source->value.action);
5867 case VUT_UTFLAG:
5868 return !utype_flag_is_in_use(source->value.unitflag);
5869 case VUT_UCFLAG:
5870 return !uclass_flag_is_in_use(source->value.unitclassflag);
5871 case VUT_EXTRAFLAG:
5872 return !extra_flag_is_in_use(source->value.extraflag);
5873 case VUT_MINLATITUDE:
5874 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
5875 case VUT_MAXLATITUDE:
5876 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
5877 case VUT_COUNTER:
5878 case VUT_OTYPE:
5879 case VUT_SPECIALIST:
5880 case VUT_AI_LEVEL:
5881 case VUT_CITYTILE:
5882 case VUT_CITYSTATUS:
5883 case VUT_STYLE:
5884 case VUT_TOPO:
5885 case VUT_WRAP:
5886 case VUT_SERVERSETTING:
5887 case VUT_NATION:
5888 case VUT_NATIONGROUP:
5889 case VUT_ADVANCE:
5890 case VUT_TECHFLAG:
5891 case VUT_GOVERNMENT:
5892 case VUT_ACHIEVEMENT:
5893 case VUT_IMPROVEMENT:
5894 case VUT_IMPR_GENUS:
5895 case VUT_IMPR_FLAG:
5896 case VUT_PLAYER_FLAG:
5897 case VUT_PLAYER_STATE:
5898 case VUT_MINSIZE:
5899 case VUT_MINCULTURE:
5900 case VUT_MINFOREIGNPCT:
5901 case VUT_MINTECHS:
5902 case VUT_NATIONALITY:
5903 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
5904 case VUT_DIPLREL:
5905 case VUT_DIPLREL_TILE:
5906 case VUT_DIPLREL_TILE_O:
5907 case VUT_DIPLREL_UNITANY:
5908 case VUT_DIPLREL_UNITANY_O:
5909 case VUT_MAXTILEUNITS:
5910 case VUT_UTYPE:
5911 case VUT_UCLASS:
5912 case VUT_MINVETERAN:
5913 case VUT_UNITSTATE:
5914 case VUT_ACTIVITY:
5915 case VUT_MINMOVES:
5916 case VUT_MINHP:
5917 case VUT_AGE:
5918 case VUT_FORM_AGE:
5919 case VUT_ROADFLAG:
5920 case VUT_MINCALFRAG:
5921 case VUT_TERRAIN:
5922 case VUT_EXTRA:
5923 case VUT_GOOD:
5924 case VUT_TERRAINCLASS:
5925 case VUT_TERRFLAG:
5926 case VUT_TERRAINALTER:
5927 case VUT_MINYEAR:
5928 case VUT_NONE:
5929 case VUT_COUNT:
5930 /* Not implemented. */
5931 break;
5932 }
5933
5934 return FALSE;
5935}
5936
5937/**********************************************************************/
5944 bool req_is_impossible_to_fulfill(const struct requirement *req)
5945{
5946 /* Not known to be impossible to fulfill */
5947 return req->present && universal_never_there(&req->source);
5948}
5949
5950/**********************************************************************/
5957 bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
5958{
5959 requirement_vector_iterate(reqs, preq) {
5960 if (req_is_impossible_to_fulfill(preq)) {
5961 return TRUE;
5962 }
5963 } requirement_vector_iterate_end;
5964
5965 /* Not known to be impossible to fulfill */
5966 return FALSE;
5967}
5968
5969/**********************************************************************/
5976 req_vec_num_in_item
5977req_vec_vector_number(const void *parent_item,
5978 const struct requirement_vector *vec)
5979{
5980 if (vec) {
5981 return 0;
5982 } else {
5983 return -1;
5984 }
5985}
5986
5987/********************************************************************/
5995struct requirement_vector *
5996req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
5997{
5998 fc_assert_ret_val(number == 0, NULL);
5999 return (struct requirement_vector *)parent_item;
6000}
6001
6002/**********************************************************************/
6012 const char *req_vec_change_translation(const struct req_vec_change *change,
6013 const requirement_vector_namer namer)
6014{
6015 const char *req_vec_description;
6016 static char buf[MAX_LEN_NAME * 3];
6017 struct astring astr;
6018
6019 fc_assert_ret_val(change, NULL);
6020 fc_assert_ret_val(req_vec_change_operation_is_valid(change->operation),
6021 NULL);
6022
6023 /* Get rid of the previous. */
6024 buf[0] = '\0';
6025
6026 if (namer == NULL) {
6027 /* TRANS: default description of a requirement vector
6028 * (used in ruledit) */
6029 req_vec_description = _("the requirement vector");
6030 } else {
6031 req_vec_description = namer(change->vector_number);
6032 }
6033
6034 switch (change->operation) {
6035 case RVCO_REMOVE:
6036 fc_snprintf(buf, sizeof(buf),
6037 /* TRANS: remove a requirement from a requirement vector
6038 * (in ruledit).
6039 * The first %s is the operation.
6040 * The second %s is the requirement.
6041 * The third %s is a description of the requirement vector,
6042 * like "actor_reqs" */
6043 _("%s %s from %s"),
6044 req_vec_change_operation_name(change->operation),
6045 req_to_fstring(&change->req, &astr),
6046 req_vec_description);
6047 astr_free(&astr);
6048 break;
6049 case RVCO_APPEND:
6050 fc_snprintf(buf, sizeof(buf),
6051 /* TRANS: append a requirement to a requirement vector
6052 * (in ruledit).
6053 * The first %s is the operation.
6054 * The second %s is the requirement.
6055 * The third %s is a description of the requirement vector,
6056 * like "actor_reqs" */
6057 _("%s %s to %s"),
6058 req_vec_change_operation_name(change->operation),
6059 req_to_fstring(&change->req, &astr),
6060 req_vec_description);
6061 astr_free(&astr);
6062 break;
6063 case RVCO_NOOP:
6064 fc_snprintf(buf, sizeof(buf),
6065 /* TRANS: do nothing to a requirement vector (in ruledit).
6066 * The first %s is a description of the requirement vector,
6067 * like "actor_reqs" */
6068 _("Do nothing to %s"), req_vec_description);
6069 break;
6070 }
6071
6072 return buf;
6073}
6074
6075/**********************************************************************/
6085 bool req_vec_change_apply(const struct req_vec_change *modification,
6086 requirement_vector_by_number getter,
6087 const void *parent_item)
6088{
6089 struct requirement_vector *target
6090 = getter(parent_item, modification->vector_number);
6091 int i = 0;
6092
6093 switch (modification->operation) {
6094 case RVCO_APPEND:
6095 requirement_vector_append(target, modification->req);
6096 return TRUE;
6097 case RVCO_REMOVE:
6098 requirement_vector_iterate(target, preq) {
6099 if (are_requirements_equal(&modification->req, preq)) {
6100 requirement_vector_remove(target, i);
6101 return TRUE;
6102 }
6103 i++;
6104 } requirement_vector_iterate_end;
6105 return FALSE;
6106 case RVCO_NOOP:
6107 return FALSE;
6108 }
6109
6110 return FALSE;
6111}
6112
6113/**********************************************************************/
6122struct req_vec_problem *
6123req_vec_problem_new_transl(int num_suggested_solutions,
6124 const char *description,
6125 const char *description_translated)
6126{
6127 struct req_vec_problem *out;
6128 int i;
6129
6130 out = fc_malloc(sizeof(*out));
6131
6132 fc_strlcpy(out->description, description, sizeof(out->description));
6133 fc_strlcpy(out->description_translated, _(description_translated),
6134 sizeof(out->description_translated));
6135
6136 out->num_suggested_solutions = num_suggested_solutions;
6137 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
6138 * sizeof(struct req_vec_change));
6139 for (i = 0; i < out->num_suggested_solutions; i++) {
6140 /* No suggestions are ready yet. */
6141 out->suggested_solutions[i].operation = RVCO_NOOP;
6142 out->suggested_solutions[i].vector_number = -1;
6143 out->suggested_solutions[i].req.source.kind = VUT_NONE;
6144 }
6145
6146 return out;
6147}
6148
6149/**********************************************************************/
6157 struct req_vec_problem *req_vec_problem_new(int num_suggested_solutions,
6158 const char *descr, ...)
6159{
6160 char description[500];
6161 char description_translated[500];
6162 va_list ap;
6163
6164 va_start(ap, descr);
6165 fc_vsnprintf(description, sizeof(description), descr, ap);
6166 va_end(ap);
6167
6168 va_start(ap, descr);
6169 fc_vsnprintf(description_translated, sizeof(description_translated),
6170 _(descr), ap);
6171 va_end(ap);
6172
6173 return req_vec_problem_new_transl(num_suggested_solutions,
6174 description, description_translated);
6175}
6176
6177/**********************************************************************/
6182 void req_vec_problem_free(struct req_vec_problem *issue)
6183{
6184 FC_FREE(issue->suggested_solutions);
6185 issue->num_suggested_solutions = 0;
6186
6187 FC_FREE(issue);
6188}
6189
6190/**********************************************************************/
6201struct req_vec_problem *
6202req_vec_get_first_contradiction(const struct requirement_vector *vec,
6203 requirement_vector_number get_num,
6204 const void *parent_item)
6205{
6206 int i, j;
6207 req_vec_num_in_item vec_num;
6208
6209 if (vec == NULL || requirement_vector_size(vec) == 0) {
6210 /* No vector. */
6211 return NULL;
6212 }
6213
6214 if (get_num == NULL || parent_item == NULL) {
6215 vec_num = 0;
6216 } else {
6217 vec_num = get_num(parent_item, vec);
6218 }
6219
6220 /* Look for contradictions */
6221 for (i = 0; i < requirement_vector_size(vec); i++) {
6222 struct requirement *preq = requirement_vector_get(vec, i);
6223 for (j = 0; j < requirement_vector_size(vec); j++) {
6224 struct requirement *nreq = requirement_vector_get(vec, j);
6225
6226 if (are_requirements_contradictions(preq, nreq)) {
6227 struct req_vec_problem *problem;
6228 struct astring astr;
6229 struct astring nastr;
6230
6231 problem = req_vec_problem_new(2,
6232 N_("Requirements {%s} and {%s} contradict each other."),
6233 req_to_fstring(preq, &astr), req_to_fstring(nreq, &nastr));
6234
6235 astr_free(&astr);
6236 astr_free(&nastr);
6237
6238 /* The solution is to remove one of the contradictions. */
6239 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6240 problem->suggested_solutions[0].vector_number = vec_num;
6241 problem->suggested_solutions[0].req = *preq;
6242
6243 problem->suggested_solutions[1].operation = RVCO_REMOVE;
6244 problem->suggested_solutions[1].vector_number = vec_num;
6245 problem->suggested_solutions[1].req = *nreq;
6246
6247 /* Only the first contradiction is reported. */
6248 return problem;
6249 }
6250 }
6251 }
6252
6253 return NULL;
6254}
6255
6256/**********************************************************************/
6266struct req_vec_problem *
6267req_vec_suggest_repair(const struct requirement_vector *vec,
6268 requirement_vector_number get_num,
6269 const void *parent_item)
6270{
6271 /* Check for self contradictins. */
6272 return req_vec_get_first_contradiction(vec, get_num, parent_item);
6273}
6274
6275/**********************************************************************/
6287struct req_vec_problem *
6288req_vec_get_first_missing_univ(const struct requirement_vector *vec,
6289 requirement_vector_number get_num,
6290 const void *parent_item)
6291{
6292 int i;
6293 req_vec_num_in_item vec_num;
6294 struct req_vec_problem *problem = NULL;
6295
6296 if (vec == NULL || requirement_vector_size(vec) == 0) {
6297 /* No vector. */
6298 return NULL;
6299 }
6300
6301 if (get_num == NULL || parent_item == NULL) {
6302 vec_num = 0;
6303 } else {
6304 vec_num = get_num(parent_item, vec);
6305 }
6306
6307 /* Look for contradictions */
6308 for (i = 0; i < requirement_vector_size(vec); i++) {
6309 struct requirement *preq = requirement_vector_get(vec, i);
6310
6311 if (universal_never_there(&preq->source)) {
6312 struct astring astr;
6313
6314 if (preq->present) {
6315 /* The requirement vector can never be fulfilled. Removing the
6316 * requirement makes it possible to fulfill it. This is a rule
6317 * change and shouldn't be "fixed" without thinking. Don't offer any
6318 * automatic solution to prevent mindless "fixes". */
6319 /* TRANS: ruledit warns a user about an unused requirement vector
6320 * that never can be fulfilled because it asks for something that
6321 * never will be there. */
6322 if (problem == NULL) {
6323 problem = req_vec_problem_new(0,
6324 N_("Requirement {%s} requires %s but it will never be"
6325 " there."),
6326 req_to_fstring(preq, &astr), universal_rule_name(&preq->source));
6327 astr_free(&astr);
6328 }
6329
6330 /* Continue to check if other problems have a solution proposal,
6331 * and prefer to return those. */
6332 continue;
6333 }
6334
6335 if (problem != NULL) {
6336 /* Free previous one (one with no solution proposals) */
6337 req_vec_problem_free(problem);
6338 }
6339
6340 problem = req_vec_problem_new(1,
6341 N_("Requirement {%s} mentions %s but it will never be there."),
6342 req_to_fstring(preq, &astr), universal_rule_name(&preq->source));
6343
6344 astr_free(&astr);
6345
6346 /* The solution is to remove the reference to the missing
6347 * universal. */
6348 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6349 problem->suggested_solutions[0].vector_number = vec_num;
6350 problem->suggested_solutions[0].req = *preq;
6351
6352 /* Only the first missing universal is reported. */
6353 return problem;
6354 }
6355 }
6356
6357 return problem;
6358}
6359
6360/**********************************************************************/
6372struct req_vec_problem *
6373req_vec_get_first_redundant_req(const struct requirement_vector *vec,
6374 requirement_vector_number get_num,
6375 const void *parent_item)
6376{
6377 int i, j;
6378 req_vec_num_in_item vec_num;
6379
6380 if (vec == NULL || requirement_vector_size(vec) == 0) {
6381 /* No vector. */
6382 return NULL;
6383 }
6384
6385 if (get_num == NULL || parent_item == NULL) {
6386 vec_num = 0;
6387 } else {
6388 vec_num = get_num(parent_item, vec);
6389 }
6390
6391 /* Look for repeated requirements */
6392 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
6393 struct requirement *preq = requirement_vector_get(vec, i);
6394 for (j = i + 1; j < requirement_vector_size(vec); j++) {
6395 struct requirement *nreq = requirement_vector_get(vec, j);
6396
6397 if (are_requirements_equal(preq, nreq)) {
6398 struct req_vec_problem *problem;
6399 struct astring astr;
6400 struct astring nastr;
6401
6402 problem = req_vec_problem_new(2,
6403 N_("Requirements {%s} and {%s} are the same."),
6404 req_to_fstring(preq, &astr), req_to_fstring(nreq, &nastr));
6405
6406 astr_free(&astr);
6407 astr_free(&nastr);
6408
6409 /* The solution is to remove one of the redundant requirements. */
6410 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6411 problem->suggested_solutions[0].vector_number = vec_num;
6412 problem->suggested_solutions[0].req = *preq;
6413
6414 problem->suggested_solutions[1].operation = RVCO_REMOVE;
6415 problem->suggested_solutions[1].vector_number = vec_num;
6416 problem->suggested_solutions[1].req = *nreq;
6417
6418 /* Only the first redundancy is reported. */
6419 return problem;
6420 }
6421 }
6422 }
6423
6424 return NULL;
6425}
6426
6427/**********************************************************************/
6438struct req_vec_problem *
6439req_vec_suggest_improvement(const struct requirement_vector *vec,
6440 requirement_vector_number get_num,
6441 const void *parent_item)
6442{
6443 struct req_vec_problem *out;
6444
6445 out = req_vec_suggest_repair(vec, get_num, parent_item);
6446 if (out != NULL) {
6447 /* A bug, not just a potential improvement */
6448 return out;
6449 }
6450
6451 /* Check if a universal that never will appear in the game is checked. */
6452 out = req_vec_get_first_missing_univ(vec, get_num, parent_item);
6453 if (out != NULL) {
6454 return out;
6455 }
6456
6457 /* Check if a requirement is redundant. */
6458 out = req_vec_get_first_redundant_req(vec, get_num, parent_item);
6459 return out;
6460}
6461
6462/**********************************************************************/
6466 bool are_universals_equal(const struct universal *psource1,
6467 const struct universal *psource2)
6468{
6469 if (psource1->kind != psource2->kind) {
6470 return FALSE;
6471 }
6472 switch (psource1->kind) {
6473 case VUT_NONE:
6474 return TRUE;
6475 case VUT_COUNTER:
6476 return psource1->value.counter == psource2->value.counter;
6477 case VUT_ADVANCE:
6478 return psource1->value.advance == psource2->value.advance;
6479 case VUT_TECHFLAG:
6480 return psource1->value.techflag == psource2->value.techflag;
6481 case VUT_GOVERNMENT:
6482 return psource1->value.govern == psource2->value.govern;
6483 case VUT_ACHIEVEMENT:
6484 return psource1->value.achievement == psource2->value.achievement;
6485 case VUT_STYLE:
6486 return psource1->value.style == psource2->value.style;
6487 case VUT_IMPROVEMENT:
6488 return psource1->value.building == psource2->value.building;
6489 case VUT_IMPR_GENUS:
6490 return psource1->value.impr_genus == psource2->value.impr_genus;
6491 case VUT_IMPR_FLAG:
6492 return psource1->value.impr_flag == psource2->value.impr_flag;
6493 case VUT_PLAYER_FLAG:
6494 return psource1->value.plr_flag == psource2->value.plr_flag;
6495 case VUT_PLAYER_STATE:
6496 return psource1->value.plrstate == psource2->value.plrstate;
6497 case VUT_EXTRA:
6498 return psource1->value.extra == psource2->value.extra;
6499 case VUT_GOOD:
6500 return psource1->value.good == psource2->value.good;
6501 case VUT_TERRAIN:
6502 return psource1->value.terrain == psource2->value.terrain;
6503 case VUT_TERRFLAG:
6504 return psource1->value.terrainflag == psource2->value.terrainflag;
6505 case VUT_NATION:
6506 return psource1->value.nation == psource2->value.nation;
6507 case VUT_NATIONGROUP:
6508 return psource1->value.nationgroup == psource2->value.nationgroup;
6509 case VUT_NATIONALITY:
6510 return psource1->value.nationality == psource2->value.nationality;
6511 case VUT_ORIGINAL_OWNER:
6512 return psource1->value.origowner == psource2->value.origowner;
6513 case VUT_DIPLREL:
6514 case VUT_DIPLREL_TILE:
6515 case VUT_DIPLREL_TILE_O:
6516 case VUT_DIPLREL_UNITANY:
6517 case VUT_DIPLREL_UNITANY_O:
6518 return psource1->value.diplrel == psource2->value.diplrel;
6519 case VUT_UTYPE:
6520 return psource1->value.utype == psource2->value.utype;
6521 case VUT_UTFLAG:
6522 return psource1->value.unitflag == psource2->value.unitflag;
6523 case VUT_UCLASS:
6524 return psource1->value.uclass == psource2->value.uclass;
6525 case VUT_UCFLAG:
6526 return psource1->value.unitclassflag == psource2->value.unitclassflag;
6527 case VUT_MINVETERAN:
6528 return psource1->value.minveteran == psource2->value.minveteran;
6529 case VUT_UNITSTATE:
6530 return psource1->value.unit_state == psource2->value.unit_state;
6531 case VUT_ACTIVITY:
6532 return psource1->value.activity == psource2->value.activity;
6533 case VUT_MINMOVES:
6534 return psource1->value.minmoves == psource2->value.minmoves;
6535 case VUT_MINHP:
6536 return psource1->value.min_hit_points == psource2->value.min_hit_points;
6537 case VUT_AGE:
6538 return psource1->value.age == psource2->value.age;
6539 case VUT_FORM_AGE:
6540 return psource1->value.form_age == psource2->value.form_age;
6541 case VUT_MINTECHS:
6542 return psource1->value.min_techs == psource2->value.min_techs;
6543 case VUT_ACTION:
6544 return (action_number(psource1->value.action)
6545 == action_number(psource2->value.action));
6546 case VUT_OTYPE:
6547 return psource1->value.outputtype == psource2->value.outputtype;
6548 case VUT_SPECIALIST:
6549 return psource1->value.specialist == psource2->value.specialist;
6550 case VUT_MINSIZE:
6551 return psource1->value.minsize == psource2->value.minsize;
6552 case VUT_MINCULTURE:
6553 return psource1->value.minculture == psource2->value.minculture;
6554 case VUT_MINFOREIGNPCT:
6555 return psource1->value.minforeignpct == psource2->value.minforeignpct;
6556 case VUT_AI_LEVEL:
6557 return psource1->value.ai_level == psource2->value.ai_level;
6558 case VUT_MAXTILEUNITS:
6559 return psource1->value.max_tile_units == psource2->value.max_tile_units;
6560 case VUT_TERRAINCLASS:
6561 return psource1->value.terrainclass == psource2->value.terrainclass;
6562 case VUT_ROADFLAG:
6563 return psource1->value.roadflag == psource2->value.roadflag;
6564 case VUT_EXTRAFLAG:
6565 return psource1->value.extraflag == psource2->value.extraflag;
6566 case VUT_MINYEAR:
6567 return psource1->value.minyear == psource2->value.minyear;
6568 case VUT_MINCALFRAG:
6569 return psource1->value.mincalfrag == psource2->value.mincalfrag;
6570 case VUT_TOPO:
6571 return psource1->value.topo_property == psource2->value.topo_property;
6572 case VUT_WRAP:
6573 return psource1->value.wrap_property == psource2->value.wrap_property;
6574 case VUT_SERVERSETTING:
6575 return psource1->value.ssetval == psource2->value.ssetval;
6576 case VUT_TERRAINALTER:
6577 return psource1->value.terrainalter == psource2->value.terrainalter;
6578 case VUT_CITYTILE:
6579 return psource1->value.citytile == psource2->value.citytile;
6580 case VUT_CITYSTATUS:
6581 return psource1->value.citystatus == psource2->value.citystatus;
6582 case VUT_MINLATITUDE:
6583 case VUT_MAXLATITUDE:
6584 return psource1->value.latitude == psource2->value.latitude;
6585 case VUT_COUNT:
6586 break;
6587 }
6588
6589 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
6590 return FALSE;
6591}
6592
6593/**********************************************************************/
6597 const char *universal_rule_name(const struct universal *psource)
6598{
6599 static char buffer[10];
6600
6601 switch (psource->kind) {
6602 case VUT_NONE:
6603 return "(none)";
6604 case VUT_COUNTER:
6605 return counter_rule_name(psource->value.counter);
6606 case VUT_CITYTILE:
6607 return citytile_type_name(psource->value.citytile);
6608 case VUT_CITYSTATUS:
6609 return citystatus_type_name(psource->value.citystatus);
6610 case VUT_MINYEAR:
6611 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
6612
6613 return buffer;
6614 case VUT_MINCALFRAG:
6615 /* Rule name is 0-based number, not pretty name from ruleset */
6616 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
6617
6618 return buffer;
6619 case VUT_TOPO:
6620 return topo_flag_name(psource->value.topo_property);
6621 case VUT_WRAP:
6622 return wrap_flag_name(psource->value.wrap_property);
6623 case VUT_SERVERSETTING:
6624 return ssetv_rule_name(psource->value.ssetval);
6625 case VUT_ADVANCE:
6626 return advance_rule_name(psource->value.advance);
6627 case VUT_TECHFLAG:
6628 return tech_flag_id_name(psource->value.techflag);
6629 case VUT_GOVERNMENT:
6630 return government_rule_name(psource->value.govern);
6631 case VUT_ACHIEVEMENT:
6632 return achievement_rule_name(psource->value.achievement);
6633 case VUT_STYLE:
6634 return style_rule_name(psource->value.style);
6635 case VUT_IMPROVEMENT:
6636 return improvement_rule_name(psource->value.building);
6637 case VUT_IMPR_GENUS:
6638 return impr_genus_id_name(psource->value.impr_genus);
6639 case VUT_IMPR_FLAG:
6640 return impr_flag_id_name(psource->value.impr_flag);
6641 case VUT_PLAYER_FLAG:
6642 return plr_flag_id_name(psource->value.plr_flag);
6643 case VUT_PLAYER_STATE:
6644 return plrstate_type_name(psource->value.plrstate);
6645 case VUT_EXTRA:
6646 return extra_rule_name(psource->value.extra);
6647 case VUT_GOOD:
6648 return goods_rule_name(psource->value.good);
6649 case VUT_TERRAIN:
6650 return terrain_rule_name(psource->value.terrain);
6651 case VUT_TERRFLAG:
6652 return terrain_flag_id_name(psource->value.terrainflag);
6653 case VUT_NATION:
6654 return nation_rule_name(psource->value.nation);
6655 case VUT_NATIONGROUP:
6656 return nation_group_rule_name(psource->value.nationgroup);
6657 case VUT_DIPLREL:
6658 case VUT_DIPLREL_TILE:
6659 case VUT_DIPLREL_TILE_O:
6660 case VUT_DIPLREL_UNITANY:
6661 case VUT_DIPLREL_UNITANY_O:
6662 return diplrel_rule_name(psource->value.diplrel);
6663 case VUT_NATIONALITY:
6664 return nation_rule_name(psource->value.nationality);
6665 case VUT_ORIGINAL_OWNER:
6666 return nation_rule_name(psource->value.origowner);
6667 case VUT_UTYPE:
6668 return utype_rule_name(psource->value.utype);
6669 case VUT_UTFLAG:
6670 return unit_type_flag_id_name(psource->value.unitflag);
6671 case VUT_UCLASS:
6672 return uclass_rule_name(psource->value.uclass);
6673 case VUT_UCFLAG:
6674 return unit_class_flag_id_name(psource->value.unitclassflag);
6675 case VUT_MINVETERAN:
6676 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
6677
6678 return buffer;
6679 case VUT_UNITSTATE:
6680 return ustate_prop_name(psource->value.unit_state);
6681 case VUT_ACTIVITY:
6682 return unit_activity_name(psource->value.activity);
6683 case VUT_MINMOVES:
6684 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
6685
6686 return buffer;
6687 case VUT_MINHP:
6688 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
6689
6690 return buffer;
6691 case VUT_AGE:
6692 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
6693
6694 return buffer;
6695 case VUT_FORM_AGE:
6696 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
6697
6698 return buffer;
6699 case VUT_MINTECHS:
6700 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
6701
6702 return buffer;
6703 case VUT_ACTION:
6704 return action_rule_name(psource->value.action);
6705 case VUT_OTYPE:
6706 return get_output_identifier(psource->value.outputtype);
6707 case VUT_SPECIALIST:
6708 return specialist_rule_name(psource->value.specialist);
6709 case VUT_MINSIZE:
6710 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
6711
6712 return buffer;
6713 case VUT_MINCULTURE:
6714 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
6715
6716 return buffer;
6717 case VUT_MINFOREIGNPCT:
6718 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
6719
6720 return buffer;
6721 case VUT_AI_LEVEL:
6722 return ai_level_name(psource->value.ai_level);
6723 case VUT_MAXTILEUNITS:
6724 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_units);
6725 return buffer;
6726 case VUT_TERRAINCLASS:
6727 return terrain_class_name(psource->value.terrainclass);
6728 case VUT_ROADFLAG:
6729 return road_flag_id_name(psource->value.roadflag);
6730 case VUT_EXTRAFLAG:
6731 return extra_flag_id_name(psource->value.extraflag);
6732 case VUT_TERRAINALTER:
6733 return terrain_alteration_name(psource->value.terrainalter);
6734 case VUT_MINLATITUDE:
6735 case VUT_MAXLATITUDE:
6736 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
6737
6738 return buffer;
6739 case VUT_COUNT:
6740 break;
6741 }
6742
6743 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
6744 return NULL;
6745}
6746
6747/**********************************************************************/
6755 const char *universal_name_translation(const struct universal *psource,
6756 char *buf, size_t bufsz)
6757{
6758 buf[0] = '\0'; /* to be safe. */
6759 switch (psource->kind) {
6760 case VUT_NONE:
6761 /* TRANS: missing value */
6762 fc_strlcat(buf, _("(none)"), bufsz);
6763 return buf;
6764 case VUT_ADVANCE:
6765 fc_strlcat(buf, advance_name_translation(psource->value.advance), bufsz);
6766 return buf;
6767 case VUT_COUNTER:
6768 fc_strlcat(buf, counter_name_translation(psource->value.counter), bufsz);
6769 return buf;
6770 case VUT_TECHFLAG:
6771 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
6772 tech_flag_id_translated_name(psource->value.techflag));
6773 return buf;
6774 case VUT_GOVERNMENT:
6775 fc_strlcat(buf, government_name_translation(psource->value.govern),
6776 bufsz);
6777 return buf;
6778 case VUT_ACHIEVEMENT:
6779 fc_strlcat(buf, achievement_name_translation(psource->value.achievement),
6780 bufsz);
6781 return buf;
6782 case VUT_STYLE:
6783 fc_strlcat(buf, style_name_translation(psource->value.style),
6784 bufsz);
6785 return buf;
6786 case VUT_IMPROVEMENT:
6787 fc_strlcat(buf, improvement_name_translation(psource->value.building),
6788 bufsz);
6789 return buf;
6790 case VUT_IMPR_GENUS:
6791 fc_strlcat(buf,
6792 impr_genus_id_translated_name(psource->value.impr_genus),
6793 bufsz);
6794 return buf;
6795 case VUT_IMPR_FLAG:
6796 fc_strlcat(buf,
6797 impr_flag_id_translated_name(psource->value.impr_flag),
6798 bufsz);
6799 return buf;
6800 case VUT_PLAYER_FLAG:
6801 fc_strlcat(buf,
6802 plr_flag_id_translated_name(psource->value.plr_flag),
6803 bufsz);
6804 return buf;
6805 case VUT_PLAYER_STATE:
6806 fc_strlcat(buf,
6807 plrstate_type_translated_name(psource->value.plrstate),
6808 bufsz);
6809 return buf;
6810 case VUT_EXTRA:
6811 fc_strlcat(buf, extra_name_translation(psource->value.extra), bufsz);
6812 return buf;
6813 case VUT_GOOD:
6814 fc_strlcat(buf, goods_name_translation(psource->value.good), bufsz);
6815 return buf;
6816 case VUT_TERRAIN:
6817 fc_strlcat(buf, terrain_name_translation(psource->value.terrain), bufsz);
6818 return buf;
6819 case VUT_NATION:
6820 fc_strlcat(buf, nation_adjective_translation(psource->value.nation),
6821 bufsz);
6822 return buf;
6823 case VUT_NATIONGROUP:
6824 fc_strlcat(buf, nation_group_name_translation(psource->value.nationgroup),
6825 bufsz);
6826 return buf;
6827 case VUT_NATIONALITY:
6828 cat_snprintf(buf, bufsz, _("%s citizens"),
6829 nation_adjective_translation(psource->value.nationality));
6830 return buf;
6831 case VUT_ORIGINAL_OWNER:
6832 /* TRANS: Keep short. City founding nation. */
6833 cat_snprintf(buf, bufsz, _("%s original owner"),
6834 nation_adjective_translation(psource->value.origowner));
6835 return buf;
6836 case VUT_DIPLREL:
6837 case VUT_DIPLREL_TILE:
6838 case VUT_DIPLREL_TILE_O:
6839 case VUT_DIPLREL_UNITANY:
6840 case VUT_DIPLREL_UNITANY_O:
6841 fc_strlcat(buf, diplrel_name_translation(psource->value.diplrel),
6842 bufsz);
6843 return buf;
6844 case VUT_UTYPE:
6845 fc_strlcat(buf, utype_name_translation(psource->value.utype), bufsz);
6846 return buf;
6847 case VUT_UTFLAG:
6848 cat_snprintf(buf, bufsz,
6849 /* TRANS: Unit type flag */
6850 Q_("?utflag:\"%s\" units"),
6851 unit_type_flag_id_translated_name(
6852 psource->value.unitflag));
6853 return buf;
6854 case VUT_UCLASS:
6855 cat_snprintf(buf, bufsz,
6856 /* TRANS: Unit class */
6857 _("%s units"),
6858 uclass_name_translation(psource->value.uclass));
6859 return buf;
6860 case VUT_UCFLAG:
6861 cat_snprintf(buf, bufsz,
6862 /* TRANS: Unit class flag */
6863 Q_("?ucflag:\"%s\" units"),
6864 unit_class_flag_id_translated_name(
6865 psource->value.unitclassflag));
6866 return buf;
6867 case VUT_MINVETERAN:
6868 /* FIXME */
6869 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
6870 psource->value.minveteran);
6871 return buf;
6872 case VUT_UNITSTATE:
6873 switch (psource->value.unit_state) {
6874 case USP_TRANSPORTED:
6875 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
6876 cat_snprintf(buf, bufsz, _("Transported"));
6877 break;
6878 case USP_LIVABLE_TILE:
6879 cat_snprintf(buf, bufsz,
6880 /* TRANS: unit state. (appears in strings like
6881 * "Missile+On livable tile") */
6882 _("On livable tile"));
6883 break;
6884 case USP_TRANSPORTING:
6885 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
6886 cat_snprintf(buf, bufsz, _("Transporting"));
6887 break;
6888 case USP_HAS_HOME_CITY:
6889 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
6890 cat_snprintf(buf, bufsz, _("Has a home city"));
6891 break;
6892 case USP_NATIVE_TILE:
6893 cat_snprintf(buf, bufsz,
6894 /* TRANS: unit state. (appears in strings like
6895 * "Missile+On native tile") */
6896 _("On native tile"));
6897 break;
6898 case USP_NATIVE_EXTRA:
6899 cat_snprintf(buf, bufsz,
6900 /* TRANS: unit state. (appears in strings like
6901 * "Missile+In native extra") */
6902 _("In native extra"));
6903 break;
6904 case USP_MOVED_THIS_TURN:
6905 /* TRANS: unit state. (appears in strings like
6906 * "Missile+Has moved this turn") */
6907 cat_snprintf(buf, bufsz, _("Has moved this turn"));
6908 break;
6909 case USP_COUNT:
6910 fc_assert_msg(psource->value.unit_state != USP_COUNT,
6911 "Invalid unit state property.");
6912 break;
6913 }
6914 return buf;
6915 case VUT_ACTIVITY:
6916 cat_snprintf(buf, bufsz, _("%s activity"),
6917 Q_(unit_activity_name(psource->value.activity)));
6918 return buf;
6919 case VUT_MINMOVES:
6920 /* TRANS: Minimum unit movement points left for requirement to be met
6921 * (%s is a string like "1" or "2 1/3") */
6922 cat_snprintf(buf, bufsz, _("%s MP"),
6923 move_points_text(psource->value.minmoves, TRUE));
6924 return buf;
6925 case VUT_MINHP:
6926 /* TRANS: HP = hit points */
6927 cat_snprintf(buf, bufsz, _("%d HP"),
6928 psource->value.min_hit_points);
6929 return buf;
6930 case VUT_AGE:
6931 cat_snprintf(buf, bufsz, _("Age %d"),
6932 psource->value.age);
6933 return buf;
6934 case VUT_FORM_AGE:
6935 cat_snprintf(buf, bufsz, _("Form age %d"),
6936 psource->value.form_age);
6937 return buf;
6938 case VUT_MINTECHS:
6939 cat_snprintf(buf, bufsz, _("%d Techs"),
6940 psource->value.min_techs);
6941 return buf;
6942 case VUT_ACTION:
6943 fc_strlcat(buf, action_name_translation(psource->value.action),
6944 bufsz);
6945 return buf;
6946 case VUT_OTYPE:
6947 /* FIXME */
6948 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
6949 return buf;
6950 case VUT_SPECIALIST:
6951 fc_strlcat(buf, specialist_plural_translation(psource->value.specialist),
6952 bufsz);
6953 return buf;
6954 case VUT_MINSIZE:
6955 cat_snprintf(buf, bufsz, _("Size %d"),
6956 psource->value.minsize);
6957 return buf;
6958 case VUT_MINCULTURE:
6959 cat_snprintf(buf, bufsz, _("Culture %d"),
6960 psource->value.minculture);
6961 return buf;
6962 case VUT_MINFOREIGNPCT:
6963 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
6964 psource->value.minforeignpct);
6965 return buf;
6966 case VUT_AI_LEVEL:
6967 /* TRANS: "Hard AI" */
6968 cat_snprintf(buf, bufsz, _("%s AI"),
6969 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
6970 return buf;
6971 case VUT_MAXTILEUNITS:
6972 /* TRANS: here <= means 'less than or equal' */
6973 cat_snprintf(buf, bufsz, PL_("<=%d unit",
6974 "<=%d units", psource->value.max_tile_units),
6975 psource->value.max_tile_units);
6976 return buf;
6977 case VUT_TERRAINCLASS:
6978 /* TRANS: Terrain class: "Land terrain" */
6979 cat_snprintf(buf, bufsz, _("%s terrain"),
6980 terrain_class_name_translation(psource->value.terrainclass));
6981 return buf;
6982 case VUT_TERRFLAG:
6983 cat_snprintf(buf, bufsz,
6984 /* TRANS: Terrain flag */
6985 Q_("?terrflag:\"%s\" terrain"),
6986 terrain_flag_id_translated_name(
6987 psource->value.terrainflag));
6988 return buf;
6989 case VUT_ROADFLAG:
6990 cat_snprintf(buf, bufsz,
6991 /* TRANS: Road flag */
6992 Q_("?roadflag:\"%s\" road"),
6993 road_flag_id_translated_name(psource->value.roadflag));
6994 return buf;
6995 case VUT_EXTRAFLAG:
6996 cat_snprintf(buf, bufsz,
6997 /* TRANS: Extra flag */
6998 Q_("?extraflag:\"%s\" extra"),
6999 extra_flag_id_translated_name(psource->value.extraflag));
7000 return buf;
7001 case VUT_MINYEAR:
7002 cat_snprintf(buf, bufsz, _("After %s"),
7003 textyear(psource->value.minyear));
7004 return buf;
7005 case VUT_MINCALFRAG:
7006 /* TRANS: here >= means 'greater than or equal'.
7007 * %s identifies a calendar fragment (may be bare number). */
7008 cat_snprintf(buf, bufsz, _(">=%s"),
7009 textcalfrag(psource->value.mincalfrag));
7010 return buf;
7011 case VUT_TOPO:
7012 /* TRANS: topology flag name ("Hex", "ISO") */
7013 cat_snprintf(buf, bufsz, _("%s map"),
7014 _(topo_flag_name(psource->value.topo_property)));
7015 return buf;
7016 case VUT_WRAP:
7017 /* TRANS: wrap flag name ("WrapX", "WrapY") */
7018 cat_snprintf(buf, bufsz, _("%s map"),
7019 _(wrap_flag_name(psource->value.wrap_property)));
7020 return buf;
7021 case VUT_SERVERSETTING:
7022 fc_strlcat(buf, ssetv_human_readable(psource->value.ssetval, TRUE),
7023 bufsz);
7024 return buf;
7025 case VUT_TERRAINALTER:
7026 /* TRANS: "Irrigation possible" */
7027 cat_snprintf(buf, bufsz, _("%s possible"),
7028 Q_(terrain_alteration_name(psource->value.terrainalter)));
7029 return buf;
7030 case VUT_CITYTILE:
7031 switch (psource->value.citytile) {
7032 case CITYT_CENTER:
7033 fc_strlcat(buf, _("City center"), bufsz);
7034 break;
7035 case CITYT_CLAIMED:
7036 fc_strlcat(buf, _("Tile claimed"), bufsz);
7037 break;
7038 case CITYT_EXTRAS_OWNED:
7039 fc_strlcat(buf, _("Extras owned"), bufsz);
7040 break;
7041 case CITYT_WORKED:
7042 fc_strlcat(buf, _("Worked tile"), bufsz);
7043 break;
7044 case CITYT_SAME_CONTINENT:
7045 fc_strlcat(buf, _("Same continent tile"), bufsz);
7046 break;
7047 case CITYT_BORDERING_TCLASS_REGION:
7048 /* TRANS: Short for "a tile of other terrain class mass near city" */
7049 fc_strlcat(buf, _("Port reachable tile"), bufsz);
7050 break;
7051 case CITYT_LAST:
7052 fc_assert(psource->value.citytile != CITYT_LAST);
7053 fc_strlcat(buf, "error", bufsz);
7054 break;
7055 }
7056 return buf;
7057 case VUT_CITYSTATUS:
7058 switch (psource->value.citystatus) {
7059 case CITYS_OWNED_BY_ORIGINAL:
7060 fc_strlcat(buf, _("Owned by original"), bufsz);
7061 break;
7062 case CITYS_STARVED:
7063 fc_strlcat(buf, _("Starved"), bufsz);
7064 break;
7065 case CITYS_DISORDER:
7066 fc_strlcat(buf, _("Disorder"), bufsz);
7067 break;
7068 case CITYS_CELEBRATION:
7069 fc_strlcat(buf, _("Celebration"), bufsz);
7070 break;
7071 case CITYS_TRANSFERRED:
7072 /* TRANS: CityStatus value - city has changed hands */
7073 fc_strlcat(buf, _("Transferred"), bufsz);
7074 break;
7075 case CITYS_LAST:
7076 fc_assert(psource->value.citystatus != CITYS_LAST);
7077 fc_strlcat(buf, "error", bufsz);
7078 break;
7079 }
7080 return buf;
7081 case VUT_MINLATITUDE:
7082 /* TRANS: here >= means 'greater than or equal'. */
7083 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
7084 psource->value.latitude);
7085 return buf;
7086 case VUT_MAXLATITUDE:
7087 /* TRANS: here <= means 'less than or equal'. */
7088 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
7089 psource->value.latitude);
7090 return buf;
7091 case VUT_COUNT:
7092 break;
7093 }
7094
7095 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
7096 return buf;
7097}
7098
7099/**********************************************************************/
7102 const char *universal_type_rule_name(const struct universal *psource)
7103{
7104 return universals_n_name(psource->kind);
7105}
7106
7107/**********************************************************************/
7110 int universal_build_shield_cost(const struct city *pcity,
7111 const struct universal *target)
7112{
7113 switch (target->kind) {
7114 case VUT_IMPROVEMENT:
7115 return impr_build_shield_cost(pcity, target->value.building);
7116 case VUT_UTYPE:
7117 return utype_build_shield_cost(pcity, NULL, target->value.utype);
7118 default:
7119 break;
7120 }
7121 return FC_INFINITY;
7122}
7123
7124/**********************************************************************/
7129 bool universal_replace_in_req_vec(struct requirement_vector *reqs,
7130 const struct universal *to_replace,
7131 const struct universal *replacement)
7132{
7133 bool changed = FALSE;
7134
7135 requirement_vector_iterate(reqs, preq) {
7136 if (universal_is_mentioned_by_requirement(preq, to_replace)) {
7137 preq->source = *replacement;
7138 changed = TRUE;
7139 }
7140 } requirement_vector_iterate_end;
7141
7142 return changed;
7143}
7144
7145/**********************************************************************/
7149 bool universal_is_mentioned_by_requirements(
7150 const struct requirement_vector *reqs,
7151 const struct universal *psource)
7152{
7153 requirement_vector_iterate(reqs, preq) {
7154 if (universal_is_mentioned_by_requirement(preq, psource)) {
7155 return TRUE;
7156 }
7157 } requirement_vector_iterate_end;
7158
7159 return FALSE;
7160}
7161
7162/**********************************************************************/
7171 bool universals_mean_unfulfilled(struct requirement_vector *reqs,
7172 struct universal *unis,
7173 size_t n_unis)
7174{
7175 int i;
7176
7177 for (i = 0; i < n_unis; i++) {
7178 if (!universal_fulfills_requirements(FALSE, reqs, &unis[i])) {
7179 /* This universal makes it impossible to fulfill the specified
7180 * requirement vector */
7181 return TRUE;
7182 }
7183 }
7184
7185 /* No specified universal is known to guarantee that the requirement
7186 * vector never will be fulfilled. */
7187 return FALSE;
7188}
7189
7190/**********************************************************************/
7204 bool universals_say_everything(struct requirement_vector *reqs,
7205 struct universal *unis,
7206 size_t n_unis)
7207{
7208 requirement_vector_iterate(reqs, preq) {
7209 int i;
7210 bool req_mentioned_a_source = FALSE;
7211
7212 for (i = 0; i < n_unis; i++) {
7213 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
7214 case ITF_NO:
7215 case ITF_YES:
7216 /* this req matched this source */
7217 req_mentioned_a_source = TRUE;
7218 break;
7219 case ITF_NOT_APPLICABLE:
7220 /* Not a mention. */
7221 break;
7222 }
7223 }
7224
7225 if (!req_mentioned_a_source) {
7226 /* A requirement not relevant to any of the specified universals was
7227 * found in the requirement vector. */
7228 return FALSE;
7229 }
7230 } requirement_vector_iterate_end;
7231
7232 /* No requirement not relevant to any of the specified universals was
7233 * found in the requirement vector. */
7234 return TRUE;
7235}
7236
7237/**********************************************************************/
7240enum req_item_found
7241universal_fulfills_requirement(const struct requirement *preq,
7242 const struct universal *source)
7243{
7244 fc_assert_ret_val_msg(universal_found_function[source->kind],
7245 ITF_NOT_APPLICABLE,
7246 "No req item found function for %s",
7247 universal_type_rule_name(source));
7248
7249 return (*universal_found_function[source->kind])(preq, source);
7250}
7251
7252/**********************************************************************/
7262 bool universal_fulfills_requirements(bool check_necessary,
7263 const struct requirement_vector *reqs,
7264 const struct universal *source)
7265{
7266 bool necessary = FALSE;
7267
7268 fc_assert_ret_val_msg(universal_found_function[source->kind],
7269 !check_necessary,
7270 "No req item found function for %s",
7271 universal_type_rule_name(source));
7272
7273 requirement_vector_iterate(reqs, preq) {
7274 switch ((*universal_found_function[source->kind])(preq, source)) {
7275 case ITF_NOT_APPLICABLE:
7276 continue;
7277 case ITF_NO:
7278 if (preq->present) {
7279 return FALSE;
7280 }
7281 break;
7282 case ITF_YES:
7283 if (preq->present) {
7284 necessary = TRUE;
7285 } else {
7286 return FALSE;
7287 }
7288 break;
7289 }
7290 } requirement_vector_iterate_end;
7291
7292 return (!check_necessary || necessary);
7293}
7294
7295/**********************************************************************/
7299 bool universal_is_relevant_to_requirement(const struct requirement *req,
7300 const struct universal *source)
7301{
7302 switch (universal_fulfills_requirement(req, source)) {
7303 case ITF_NOT_APPLICABLE:
7304 return FALSE;
7305 case ITF_NO:
7306 case ITF_YES:
7307 return TRUE;
7308 }
7309
7310 log_error("Unhandled item_found value");
7311 return FALSE;
7312}
7313
7314/**********************************************************************/
7317 static enum req_item_found nation_found(const struct requirement *preq,
7318 const struct universal *source)
7319{
7320 fc_assert(source->value.nation);
7321
7322 switch (preq->source.kind) {
7323 case VUT_NATION:
7324 return preq->source.value.nation == source->value.nation ? ITF_YES
7325 : ITF_NO;
7326 case VUT_NATIONGROUP:
7327 return nation_is_in_group(source->value.nation,
7328 preq->source.value.nationgroup) ? ITF_YES
7329 : ITF_NO;
7330 default:
7331 break;
7332 }
7333
7334 return ITF_NOT_APPLICABLE;
7335}
7336
7337/**********************************************************************/
7340 static enum req_item_found government_found(const struct requirement *preq,
7341 const struct universal *source)
7342{
7343 fc_assert(source->value.govern);
7344
7345 if (preq->source.kind == VUT_GOVERNMENT) {
7346 return preq->source.value.govern == source->value.govern ? ITF_YES
7347 : ITF_NO;
7348 }
7349
7350 return ITF_NOT_APPLICABLE;
7351}
7352
7353/**********************************************************************/
7356 static enum req_item_found improvement_found(const struct requirement *preq,
7357 const struct universal *source)
7358{
7359 fc_assert(source->value.building);
7360
7361 /* We only ever return ITF_YES, because requiring a different
7362 * improvement does not mean that the improvement under consideration
7363 * cannot fulfill the requirements. This is necessary to allow
7364 * requirement vectors to specify multiple required improvements. */
7365
7366 switch (preq->source.kind) {
7367 case VUT_IMPROVEMENT:
7368 if (source->value.building == preq->source.value.building) {
7369 return ITF_YES;
7370 }
7371 break;
7372 case VUT_IMPR_GENUS:
7373 if (source->value.building->genus == preq->source.value.impr_genus) {
7374 return ITF_YES;
7375 }
7376 break;
7377 case VUT_IMPR_FLAG:
7378 if (improvement_has_flag(source->value.building,
7379 preq->source.value.impr_flag)) {
7380 return ITF_YES;
7381 }
7382 break;
7383 default:
7384 break;
7385 }
7386
7387 return ITF_NOT_APPLICABLE;
7388}
7389
7390/**********************************************************************/
7393 static enum req_item_found unit_class_found(const struct requirement *preq,
7394 const struct universal *source)
7395{
7396 fc_assert(source->value.uclass);
7397
7398 switch (preq->source.kind) {
7399 case VUT_UCLASS:
7400 return source->value.uclass == preq->source.value.uclass ? ITF_YES
7401 : ITF_NO;
7402 case VUT_UCFLAG:
7403 return uclass_has_flag(source->value.uclass,
7404 preq->source.value.unitclassflag) ? ITF_YES
7405 : ITF_NO;
7406
7407 default:
7408 /* Not found and not relevant. */
7409 return ITF_NOT_APPLICABLE;
7410 };
7411}
7412
7413/**********************************************************************/
7416 static enum req_item_found unit_type_found(const struct requirement *preq,
7417 const struct universal *source)
7418{
7419 fc_assert(source->value.utype);
7420
7421 switch (preq->source.kind) {
7422 case VUT_UTYPE:
7423 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
7424 case VUT_UCLASS:
7425 return utype_class(source->value.utype) == preq->source.value.uclass
7426 ? ITF_YES : ITF_NO;
7427 case VUT_UTFLAG:
7428 return utype_has_flag(source->value.utype,
7429 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
7430 case VUT_UCFLAG:
7431 return uclass_has_flag(utype_class(source->value.utype),
7432 preq->source.value.unitclassflag) ? ITF_YES
7433 : ITF_NO;
7434 default:
7435 /* Not found and not relevant. */
7436 return ITF_NOT_APPLICABLE;
7437 };
7438}
7439
7440/**********************************************************************/
7443static enum req_item_found
7444unit_activity_found(const struct requirement *preq,
7445 const struct universal *source)
7446{
7447 fc_assert_ret_val(unit_activity_is_valid(source->value.activity),
7448 ITF_NOT_APPLICABLE);
7449
7450 switch (preq->source.kind) {
7451 case VUT_ACTIVITY:
7452 return source->value.activity == preq->source.value.activity ? ITF_YES
7453 : ITF_NO;
7454 default:
7455 /* Not found and not relevant. */
7456 return ITF_NOT_APPLICABLE;
7457 };
7458}
7459
7460/**********************************************************************/
7463 static enum req_item_found terrain_type_found(const struct requirement *preq,
7464 const struct universal *source)
7465{
7466 fc_assert(source->value.terrain);
7467
7468 switch (preq->source.kind) {
7469 case VUT_TERRAIN:
7470 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
7471 case VUT_TERRAINCLASS:
7472 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
7473 ? ITF_YES : ITF_NO;
7474 case VUT_TERRFLAG:
7475 return terrain_has_flag(source->value.terrain,
7476 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
7477 case VUT_TERRAINALTER:
7478 return (terrain_can_support_alteration(source->value.terrain,
7479 preq->source.value.terrainalter)
7480 ? ITF_YES : ITF_NO);
7481 default:
7482 /* Not found and not relevant. */
7483 return ITF_NOT_APPLICABLE;
7484 };
7485}
7486
7487/**********************************************************************/
7490 static enum req_item_found city_tile_found(const struct requirement *preq,
7491 const struct universal *source)
7492{
7493 fc_assert_ret_val(citytile_type_is_valid(source->value.citytile),
7494 ITF_NOT_APPLICABLE);
7495
7496 switch (preq->source.kind) {
7497 case VUT_CITYTILE:
7498 return (source->value.citytile == preq->source.value.citytile
7499 ? ITF_YES
7500 /* The presence of one tile state doesn't block another */
7501 : ITF_NOT_APPLICABLE);
7502 default:
7503 /* Not found and not relevant. */
7504 return ITF_NOT_APPLICABLE;
7505 };
7506}
7507
7508/**********************************************************************/
7511 static enum req_item_found extra_type_found(const struct requirement *preq,
7512 const struct universal *source)
7513{
7514 fc_assert(source->value.extra);
7515
7516 switch (preq->source.kind) {
7517 case VUT_EXTRA:
7518 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
7519 case VUT_EXTRAFLAG:
7520 return extra_has_flag(source->value.extra,
7521 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
7522 case VUT_ROADFLAG:
7523 {
7524 struct road_type *r = extra_road_get(source->value.extra);
7525 return r && road_has_flag(r, preq->source.value.roadflag)
7526 ? ITF_YES : ITF_NO;
7527 }
7528 default:
7529 /* Not found and not relevant. */
7530 return ITF_NOT_APPLICABLE;
7531 }
7532}
7533
7534/**********************************************************************/
7537 static enum req_item_found action_found(const struct requirement *preq,
7538 const struct universal *source)
7539{
7540 fc_assert(source->value.action);
7541
7542 if (preq->source.kind == VUT_ACTION) {
7543 return preq->source.value.action == source->value.action ? ITF_YES
7544 : ITF_NO;
7545 }
7546
7547 return ITF_NOT_APPLICABLE;
7548}
7549
7550/**********************************************************************/
7553 static enum req_item_found diplrel_found(const struct requirement *preq,
7554 const struct universal *source)
7555{
7556 fc_assert_ret_val((source->kind == VUT_DIPLREL
7557 || source->kind == VUT_DIPLREL_TILE
7558 || source->kind == VUT_DIPLREL_TILE_O
7559 || source->kind == VUT_DIPLREL_UNITANY
7560 || source->kind == VUT_DIPLREL_UNITANY_O),
7561 ITF_NOT_APPLICABLE);
7562
7563 if (preq->source.kind == source->kind) {
7564 if (preq->source.value.diplrel == source->value.diplrel) {
7565 /* The diplrel itself. */
7566 return ITF_YES;
7567 }
7568 if (preq->source.value.diplrel == DRO_FOREIGN
7569 && source->value.diplrel < DS_LAST) {
7570 /* All diplstate_type values are to foreigners. */
7571 return ITF_YES;
7572 }
7573 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
7574 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
7575 /* A real embassy is an embassy. */
7576 return ITF_YES;
7577 }
7578 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
7579 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
7580 /* A real embassy is an embassy. */
7581 return ITF_YES;
7582 }
7583 if (preq->source.value.diplrel < DS_LAST
7584 && source->value.diplrel < DS_LAST
7585 && preq->range == REQ_RANGE_LOCAL) {
7586 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
7587 ITF_YES);
7588 /* Can only have one diplstate_type to a specific player. */
7589 return ITF_NO;
7590 }
7591 /* Can't say this diplrel blocks the other diplrel. */
7592 return ITF_NOT_APPLICABLE;
7593 }
7594
7595 /* Not relevant. */
7596 return ITF_NOT_APPLICABLE;
7597}
7598
7599/**********************************************************************/
7602 static enum req_item_found output_type_found(const struct requirement *preq,
7603 const struct universal *source)
7604{
7605 switch (preq->source.kind) {
7606 case VUT_OTYPE:
7607 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
7608 : ITF_NO;
7609 default:
7610 /* Not found and not relevant. */
7611 return ITF_NOT_APPLICABLE;
7612 }
7613}
7614
7615/**********************************************************************/
7618 static enum req_item_found ustate_found(const struct requirement *preq,
7619 const struct universal *source)
7620{
7621 if (preq->range != REQ_RANGE_LOCAL) {
7622 return ITF_NOT_APPLICABLE;
7623 }
7624
7625 if (preq->source.kind == VUT_UNITSTATE) {
7626 switch (source->value.unit_state) {
7627 case USP_TRANSPORTED:
7628 case USP_TRANSPORTING:
7629 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
7630 case USP_LIVABLE_TILE:
7631 case USP_NATIVE_TILE:
7632 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
7633 * UTYF_COAST_STRICT. */
7634 case USP_HAS_HOME_CITY:
7635 case USP_NATIVE_EXTRA:
7636 case USP_MOVED_THIS_TURN:
7637 if (source->value.unit_state == preq->source.value.unit_state) {
7638 /* The other unit states doesn't contradict */
7639 return ITF_YES;
7640 }
7641 break;
7642 case USP_COUNT:
7643 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
7644 ITF_NOT_APPLICABLE);
7645 }
7646 }
7647
7648 /* Not found and not relevant. */
7649 return ITF_NOT_APPLICABLE;
7650}
7651
7652/**********************************************************************/
7655 void universal_found_functions_init(void)
7656{
7657 universal_found_function[VUT_GOVERNMENT] = &government_found;
7658 universal_found_function[VUT_NATION] = &nation_found;
7659 universal_found_function[VUT_IMPROVEMENT] = &improvement_found;
7660 universal_found_function[VUT_UCLASS] = &unit_class_found;
7661 universal_found_function[VUT_UTYPE] = &unit_type_found;
7662 universal_found_function[VUT_ACTIVITY] = &unit_activity_found;
7663 universal_found_function[VUT_TERRAIN] = &terrain_type_found;
7664 universal_found_function[VUT_CITYTILE] = &city_tile_found;
7665 universal_found_function[VUT_EXTRA] = &extra_type_found;
7666 universal_found_function[VUT_OTYPE] = &output_type_found;
7667 universal_found_function[VUT_ACTION] = &action_found;
7668 universal_found_function[VUT_DIPLREL] = &diplrel_found;
7669 universal_found_function[VUT_DIPLREL_TILE] = &diplrel_found;
7670 universal_found_function[VUT_DIPLREL_TILE_O] = &diplrel_found;
7671 universal_found_function[VUT_DIPLREL_UNITANY] = &diplrel_found;
7672 universal_found_function[VUT_DIPLREL_UNITANY_O] = &diplrel_found;
7673 universal_found_function[VUT_UNITSTATE] = &ustate_found;
7674}
7675
7676/**********************************************************************/
7684 int requirement_kind_ereq(const int value,
7685 const enum req_range range,
7686 const bool present,
7687 const int max_value)
7688{
7689 /* The enumerators in each range starts with present for every possible
7690 * value followed by !present for every possible value. */
7691 const int pres_start = (present ? 0 : max_value);
7692
7693 /* The enumerators for every range follows all the positions of the
7694 * previous range(s). */
7695 const int range_start = ((max_value - 1) * 2) * range;
7696
7697 return range_start + pres_start + value;
7698}
achievement_player_has
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
Definition achievements.c:364
achievement_by_number
struct achievement * achievement_by_number(int id)
Definition achievements.c:96
achievement_number
int achievement_number(const struct achievement *pach)
Definition achievements.c:76
achievement_rule_name
const char * achievement_rule_name(struct achievement *pach)
Definition achievements.c:114
achievement_by_rule_name
struct achievement * achievement_by_rule_name(const char *name)
Definition achievements.c:123
achievement_name_translation
const char * achievement_name_translation(struct achievement *pach)
Definition achievements.c:106
achievement_claimed
bool achievement_claimed(const struct achievement *pach)
Definition achievements.c:377
achievements.h
action_name_translation
const char * action_name_translation(const struct action *action)
Definition actions.c:1982
action_is_in_use
bool action_is_in_use(struct action *paction)
Definition actions.c:6400
action_by_rule_name
struct action * action_by_rule_name(const char *name)
Definition actions.c:1831
action_rule_name
const char * action_rule_name(const struct action *action)
Definition actions.c:1968
action_number
int action_number(const struct action *action)
Definition actions.c:1960
action_by_number
static struct action * action_by_number(action_id act_id)
Definition actions.h:633
astr_free
void astr_free(struct astring *astr)
Definition astring.c:153
astr_set
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:267
astr_init
void astr_init(struct astring *astr)
Definition astring.c:144
n
#define n
Definition astring.c:77
astring.h
astr_str
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
textcalfrag
const char * textcalfrag(int frag)
Definition calendar.c:101
textyear
const char * textyear(int year)
Definition calendar.c:120
calendar.h
citizens_nation_foreign
citizens citizens_nation_foreign(const struct city *pcity)
Definition citizens.c:91
citizens.h
citizens_iterate_end
#define citizens_iterate_end
Definition citizens.h:54
citizens_iterate
#define citizens_iterate(_pcity, _pslot, _nationality)
Definition citizens.h:48
city_has_building
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:1231
output_type_by_identifier
Output_type_id output_type_by_identifier(const char *id)
Definition city.c:646
get_output_identifier
const char * get_output_identifier(Output_type_id output)
Definition city.c:618
get_output_name
const char * get_output_name(Output_type_id output)
Definition city.c:628
city_map_radius_sq_get
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:136
city_tile
#define city_tile(_pcity_)
Definition city.h:564
city_size_get
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
city_owner
#define city_owner(_pcity_)
Definition city.h:563
is_city_center
static bool is_city_center(const struct city *pcity, const struct tile *ptile)
Definition city.h:856
city_tile_iterate
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:230
city_tile_iterate_end
#define city_tile_iterate_end
Definition city.h:238
city_built_iterate
#define city_built_iterate(_pcity, _p)
Definition city.h:822
city_built_iterate_end
#define city_built_iterate_end
Definition city.h:828
incite_cost
char * incite_cost
Definition comments.c:74
counter_index
int counter_index(const struct counter *pcount)
Definition counters.c:174
counter_name_translation
const char * counter_name_translation(const struct counter *counter)
Definition counters.c:157
counter_by_rule_name
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:115
counter_rule_name
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:165
counter_by_id
struct counter * counter_by_id(int id)
Definition counters.c:82
counter_id
int counter_id(struct counter *pcount)
Definition counters.c:105
counters.h
city_culture
int city_culture(const struct city *pcity)
Definition culture.c:29
player_culture
int player_culture(const struct player *plr)
Definition culture.c:46
culture.h
target_unit
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:56
target_tile
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:57
reqs
struct @21::@22 reqs
get_world_bonus
int get_world_bonus(enum effect_type effect_type)
Definition effects.c:816
extra_type_by_rule_name
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
extra_flag_is_in_use
bool extra_flag_is_in_use(enum extra_flag_id id)
Definition extras.c:987
is_extra_flag_near_tile
bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:890
is_extra_flag_card_near
bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:870
is_extra_near_tile
bool is_extra_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:379
extra_number
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
extra_has_flag
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:861
is_extra_card_near
bool is_extra_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:363
extra_by_number
struct extra_type * extra_by_number(int id)
Definition extras.c:183
extra_rule_name
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
extra_name_translation
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:194
extra_road_get
#define extra_road_get(_e_)
Definition extras.h:191
is_server
static bool is_server(void)
Definition fc_interface.h:69
Tech_type_id
int Tech_type_id
Definition fc_types.h:380
req_problem_type
req_problem_type
Definition fc_types.h:702
RPT_POSSIBLE
@ RPT_POSSIBLE
Definition fc_types.h:703
MAX_LEN_NAME
#define MAX_LEN_NAME
Definition fc_types.h:66
VC_SPACERACE
@ VC_SPACERACE
Definition fc_types.h:1272
O_LAST
@ O_LAST
Definition fc_types.h:101
Continent_id
signed short Continent_id
Definition fc_types.h:375
fcintl.h
Q_
#define Q_(String)
Definition fcintl.h:70
PL_
#define PL_(String1, String2, n)
Definition fcintl.h:71
_
#define _(String)
Definition fcintl.h:67
N_
#define N_(String)
Definition fcintl.h:69
game
struct civ_game game
Definition game.c:62
wld
struct world wld
Definition game.c:63
game.h
government_name_translation
const char * government_name_translation(const struct government *pgovern)
Definition government.c:143
government_by_number
struct government * government_by_number(const Government_type_id gov)
Definition government.c:103
government_of_player
struct government * government_of_player(const struct player *pplayer)
Definition government.c:114
government_number
Government_type_id government_number(const struct government *pgovern)
Definition government.c:91
government_rule_name
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
government_by_rule_name
struct government * government_by_rule_name(const char *name)
Definition government.c:55
government.h
owner
struct city * owner
Definition citydlg.c:220
source
static GtkWidget * source
Definition gotodlg.c:58
type
GType type
Definition repodlgs.c:1313
bufsz
static const int bufsz
Definition helpdlg.c:70
improvement_by_number
struct impr_type * improvement_by_number(const Impr_type_id id)
Definition improvement.c:194
great_wonder_is_built
bool great_wonder_is_built(const struct impr_type *pimprove)
Definition improvement.c:982
great_wonder_is_destroyed
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
Definition improvement.c:993
wonder_is_lost
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
Definition improvement.c:863
wonder_is_built
bool wonder_is_built(const struct player *pplayer, const struct impr_type *pimprove)
Definition improvement.c:876
improvement_number
Impr_type_id improvement_number(const struct impr_type *pimprove)
Definition improvement.c:184
can_improvement_go_obsolete
bool can_improvement_go_obsolete(const struct impr_type *pimprove)
Definition improvement.c:403
improvement_rule_name
const char * improvement_rule_name(const struct impr_type *pimprove)
Definition improvement.c:252
city_from_wonder
struct city * city_from_wonder(const struct player *pplayer, const struct impr_type *pimprove)
Definition improvement.c:891
impr_build_shield_cost
int impr_build_shield_cost(const struct city *pcity, const struct impr_type *pimprove)
Definition improvement.c:294
is_wonder
bool is_wonder(const struct impr_type *pimprove)
Definition improvement.c:343
is_great_wonder
bool is_great_wonder(const struct impr_type *pimprove)
Definition improvement.c:772
improvement_obsolete
bool improvement_obsolete(const struct player *pplayer, const struct impr_type *pimprove, const struct city *pcity)
Definition improvement.c:411
improvement_has_flag
bool improvement_has_flag(const struct impr_type *pimprove, enum impr_flag_id flag)
Definition improvement.c:383
improvement_by_rule_name
struct impr_type * improvement_by_rule_name(const char *name)
Definition improvement.c:367
improvement_name_translation
const char * improvement_name_translation(const struct impr_type *pimprove)
Definition improvement.c:243
great_wonder_is_available
bool great_wonder_is_available(const struct impr_type *pimprove)
Definition improvement.c:1004
improvement.h
log.h
fc_assert_msg
#define fc_assert_msg(condition, message,...)
Definition log.h:181
fc_assert
#define fc_assert(condition)
Definition log.h:176
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
log_error
#define log_error(message,...)
Definition log.h:103
fc_assert_ret_val_msg
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition log.h:208
is_tiles_adjacent
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:931
map_signed_latitude
int map_signed_latitude(const struct tile *ptile)
Definition map.c:1550
same_pos
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:940
map_distance
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:654
map.h
current_topo_has_flag
#define current_topo_has_flag(flag)
Definition map.h:48
MAP_MAX_LATITUDE
#define MAP_MAX_LATITUDE
Definition map.h:574
adjc_iterate_end
#define adjc_iterate_end
Definition map.h:433
MAP_MAX_REAL_LATITUDE
#define MAP_MAX_REAL_LATITUDE(_nmap)
Definition map.h:586
square_iterate
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:391
cardinal_adjc_iterate_end
#define cardinal_adjc_iterate_end
Definition map.h:459
adjc_iterate
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:428
square_iterate_end
#define square_iterate_end
Definition map.h:394
cardinal_adjc_iterate
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:455
circle_iterate
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:401
current_wrap_has_flag
#define current_wrap_has_flag(flag)
Definition map.h:51
MAP_MIN_REAL_LATITUDE
#define MAP_MIN_REAL_LATITUDE(_nmap)
Definition map.h:588
circle_iterate_end
#define circle_iterate_end
Definition map.h:404
FC_FREE
#define FC_FREE(ptr)
Definition mem.h:41
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
move_points_text
const char * move_points_text(int mp, bool reduce)
Definition movement.c:1015
can_unit_exist_at_tile
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:319
is_native_tile
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:331
movement.h
nation_group_by_rule_name
struct nation_group * nation_group_by_rule_name(const char *name)
Definition nation.c:1021
nation_rule_name
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
nation_number
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:486
nation_adjective_translation
const char * nation_adjective_translation(const struct nation_type *pnation)
Definition nation.c:149
nation_by_number
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:475
nation_group_rule_name
const char * nation_group_rule_name(const struct nation_group *pgroup)
Definition nation.c:1079
nation_of_player
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
nation_is_in_group
bool nation_is_in_group(const struct nation_type *pnation, const struct nation_group *pgroup)
Definition nation.c:1099
nation_group_name_translation
const char * nation_group_name_translation(const struct nation_group *pgroup)
Definition nation.c:1090
nation_by_rule_name
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
nation_group_by_number
struct nation_group * nation_group_by_number(int id)
Definition nation.c:1004
nation_group_number
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:952
nation.h
NO_NATION_SELECTED
#define NO_NATION_SELECTED
Definition nation.h:30
player_knows_techs_with_flag
bool player_knows_techs_with_flag(const struct player *pplayer, enum tech_flag_id flag)
Definition player.c:1328
player_has_state
bool player_has_state(const struct player *pplayer, enum plrstate_type state)
Definition player.c:1998
diplrel_req_contradicts
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Definition player.c:1823
diplrel_by_rule_name
int diplrel_by_rule_name(const char *value)
Definition player.c:1581
players_on_same_team
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1476
is_diplrel_to_other
bool is_diplrel_to_other(const struct player *pplayer, int diplrel)
Definition player.c:1562
player_has_flag
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1990
diplrel_name_translation
const char * diplrel_name_translation(int value)
Definition player.c:1627
is_diplrel_between
bool is_diplrel_between(const struct player *player1, const struct player *player2, int diplrel)
Definition player.c:1512
player_age
int player_age(const struct player *pplayer)
Definition player.c:954
pplayers_allied
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1405
player_slot_get_player
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:437
diplrel_rule_name
const char * diplrel_rule_name(int value)
Definition player.c:1615
player.h
players_iterate_end
#define players_iterate_end
Definition player.h:537
players_iterate
#define players_iterate(_pplayer)
Definition player.h:532
player_nation
#define player_nation(_plr_)
Definition player.h:406
is_ai
#define is_ai(plr)
Definition player.h:230
players_iterate_alive_end
#define players_iterate_alive_end
Definition player.h:547
players_iterate_alive
#define players_iterate_alive(_pplayer)
Definition player.h:542
is_latitude_req_active
static enum fc_tristate is_latitude_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
Definition requirements.c:5163
terrain_type_found
static enum req_item_found terrain_type_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7463
universal_never_there
bool universal_never_there(const struct universal *source)
Definition requirements.c:5862
is_topology_req_active
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)
Definition requirements.c:5290
is_diplrel_unitany_req_active
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)
Definition requirements.c:3977
universal_is_relevant_to_requirement
bool universal_is_relevant_to_requirement(const struct requirement *req, const struct universal *source)
Definition requirements.c:7299
EXTRACT_INFO
#define EXTRACT_INFO(req)
is_req_in_vec
bool is_req_in_vec(const struct requirement *req, const struct requirement_vector *vec)
Definition requirements.c:5825
num_city_buildings
static int num_city_buildings(const struct city *pcity, const struct impr_type *building)
Definition requirements.c:2037
universal_build_shield_cost
int universal_build_shield_cost(const struct city *pcity, const struct universal *target)
Definition requirements.c:7110
city_tile_found
static enum req_item_found city_tile_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7490
req_vec_get_first_contradiction
struct req_vec_problem * req_vec_get_first_contradiction(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
Definition requirements.c:6202
universal_found_function
static universal_found universal_found_function[VUT_COUNT]
Definition requirements.c:52
unchanging_local
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)
Definition requirements.c:77
REQUC_CITYSTATUS
#define REQUC_CITYSTATUS
Definition requirements.c:183
req_context_empty
const struct req_context * req_context_empty(void)
Definition requirements.c:1000
unit_type_found
static enum req_item_found unit_type_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7416
is_mincalfrag_req_active
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)
Definition requirements.c:5271
universal_extraction
void universal_extraction(const struct universal *source, int *kind, int *value)
Definition requirements.c:862
num_player_buildings
static int num_player_buildings(const struct player *pplayer, const struct impr_type *building)
Definition requirements.c:2003
is_extraflag_req_active
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)
Definition requirements.c:3346
is_minforeignpct_req_active
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)
Definition requirements.c:2590
num_continent_buildings
static int num_continent_buildings(const struct player *pplayer, int continent, const struct impr_type *building)
Definition requirements.c:2017
tri_req_present
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)
Definition requirements.c:5443
req_to_fstring
const char * req_to_fstring(const struct requirement *req, struct astring *astr)
Definition requirements.c:1015
is_style_req_active
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)
Definition requirements.c:3512
req_vec_vector_number
req_vec_num_in_item req_vec_vector_number(const void *parent_item, const struct requirement_vector *vec)
Definition requirements.c:5977
present_implies_not_present
static bool present_implies_not_present(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1608
is_roadflag_req_active
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)
Definition requirements.c:3242
req_vec_by_number
struct requirement_vector * req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
Definition requirements.c:5996
universal_fulfills_requirements
bool universal_fulfills_requirements(bool check_necessary, const struct requirement_vector *reqs, const struct universal *source)
Definition requirements.c:7262
activity_is_valid_in_requirement
static bool activity_is_valid_in_requirement(enum unit_activity act)
Definition requirements.c:255
is_specialist_req_active
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)
Definition requirements.c:2916
unchanging_noally
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)
Definition requirements.c:122
is_minveteran_req_active
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)
Definition requirements.c:4253
is_unitstate_req_active
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)
Definition requirements.c:4136
req_vec_change_apply
bool req_vec_change_apply(const struct req_vec_change *modification, requirement_vector_by_number getter, const void *parent_item)
Definition requirements.c:6085
universal_copy
void universal_copy(struct universal *dst, const struct universal *src)
Definition requirements.c:852
unchanging_building
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)
Definition requirements.c:191
are_requirements_equal
bool are_requirements_equal(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1450
extra_type_found
static enum req_item_found extra_type_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7511
is_diplrel_unitany_in_range
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)
Definition requirements.c:3946
are_reqs_active_ranges
bool are_reqs_active_ranges(const enum req_range min_range, const enum req_range max_range, const struct req_context *context, const struct player *other_player, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
Definition requirements.c:5523
is_buildingflag_req_active
static enum fc_tristate is_buildingflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
Definition requirements.c:2259
is_nation_req_active
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)
Definition requirements.c:3594
is_req_active
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)
Definition requirements.c:5416
is_buildinggenus_req_active
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)
Definition requirements.c:2214
req_vec_change_translation
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
Definition requirements.c:6012
is_diplrel_req_active
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)
Definition requirements.c:3884
req_from_str
struct requirement req_from_str(const char *type, const char *range, bool survives, bool present, bool quiet, const char *value)
Definition requirements.c:1037
req_vec_suggest_repair
struct req_vec_problem * req_vec_suggest_repair(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
Definition requirements.c:6267
universal_value_from_str
void universal_value_from_str(struct universal *source, const char *value)
Definition requirements.c:280
is_buildingflag_in_city
static enum fc_tristate is_buildingflag_in_city(const struct city *pcity, enum impr_flag_id flag)
Definition requirements.c:2230
req_get_values
void req_get_values(const struct requirement *req, int *type, int *range, bool *survives, bool *present, bool *quiet, int *value)
Definition requirements.c:1422
req_from_values
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
Definition requirements.c:1403
are_reqs_active
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)
Definition requirements.c:5505
universal_rule_name
const char * universal_rule_name(const struct universal *psource)
Definition requirements.c:6597
is_ai_req_active
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)
Definition requirements.c:3570
unchanging_present
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)
Definition requirements.c:90
is_plr_flag_req_active
static enum fc_tristate is_plr_flag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
Definition requirements.c:2306
is_citytile_req_active
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)
Definition requirements.c:4416
is_nationality_req_active
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)
Definition requirements.c:3713
is_activity_req_active
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)
Definition requirements.c:4201
universal_replace_in_req_vec
bool universal_replace_in_req_vec(struct requirement_vector *reqs, const struct universal *to_replace, const struct universal *replacement)
Definition requirements.c:7129
is_wrap_req_active
static enum fc_tristate is_wrap_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
Definition requirements.c:5309
action_found
static enum req_item_found action_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7537
default_tester_cb
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)
Definition requirements.c:5673
are_requirements_contradictions
bool are_requirements_contradictions(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1666
tri_req_active_turns
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)
Definition requirements.c:5548
is_diplrel_unitany_o_req_active
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)
Definition requirements.c:3999
REQUC_IMPR
#define REQUC_IMPR
Definition requirements.c:221
req_vec_problem_new
struct req_vec_problem * req_vec_problem_new(int num_suggested_solutions, const char *descr,...)
Definition requirements.c:6157
is_form_age_req_active
static enum fc_tristate is_form_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
Definition requirements.c:4372
is_diplrel_in_range
static enum fc_tristate is_diplrel_in_range(const struct player *target_player, const struct player *other_player, enum req_range range, int diplrel)
Definition requirements.c:3831
is_counter_req_active
static enum fc_tristate is_counter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
Definition requirements.c:5089
is_none_req_active
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)
Definition requirements.c:1939
universal_is_legal_in_requirement
bool universal_is_legal_in_requirement(const struct universal *univ)
Definition requirements.c:267
is_maxunitsontile_req_active
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)
Definition requirements.c:2661
requirement_kind_ereq
int requirement_kind_ereq(const int value, const enum req_range range, const bool present, const int max_value)
Definition requirements.c:7684
is_terrain_req_active
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)
Definition requirements.c:2936
req_vec_problem_free
void req_vec_problem_free(struct req_vec_problem *issue)
Definition requirements.c:6182
req_definitions
static struct req_def req_definitions[VUT_COUNT]
Definition requirements.c:5341
impr_contra_flag
static bool impr_contra_flag(const struct requirement *impr_req, const struct requirement *flag_req)
Definition requirements.c:1507
improvement_found
static enum req_item_found improvement_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7356
req_vec_get_first_missing_univ
struct req_vec_problem * req_vec_get_first_missing_univ(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
Definition requirements.c:6288
is_gov_req_active
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)
Definition requirements.c:3489
is_terrainalter_req_active
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)
Definition requirements.c:3443
is_tech_req_active
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)
Definition requirements.c:2387
is_good_req_active
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)
Definition requirements.c:2828
players_in_same_range
static bool players_in_same_range(const struct player *pplayer1, const struct player *pplayer2, enum req_range range)
Definition requirements.c:1896
universal_found
enum req_item_found(* universal_found)(const struct requirement *, const struct universal *)
Definition requirements.c:50
universal_by_number
struct universal universal_by_number(const enum universals_n kind, const int value)
Definition requirements.c:621
is_achievement_req_active
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)
Definition requirements.c:5117
universal_fulfills_requirement
enum req_item_found universal_fulfills_requirement(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7241
is_building_req_active
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)
Definition requirements.c:2051
city_center_contra
static bool city_center_contra(const struct requirement *cc_req, const struct requirement *ct_req)
Definition requirements.c:1565
is_unitclassflag_req_active
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)
Definition requirements.c:4107
ustate_found
static enum req_item_found ustate_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7618
req_vec_wants_type
bool req_vec_wants_type(const struct requirement_vector *reqs, enum universals_n kind)
Definition requirements.c:5843
num_world_buildings_total
static int num_world_buildings_total(const struct impr_type *building)
Definition requirements.c:1953
unchanging_citytile
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)
Definition requirements.c:145
tri_reqs_cb_active
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)
Definition requirements.c:5701
output_type_found
static enum req_item_found output_type_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7602
is_minhitpoints_req_active
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)
Definition requirements.c:4301
req_vec_get_first_redundant_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)
Definition requirements.c:6373
is_age_req_active
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)
Definition requirements.c:4324
is_nationgroup_req_active
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)
Definition requirements.c:3656
is_city_in_tile
static bool is_city_in_tile(const struct tile *ptile, const struct city *pcity)
Definition requirements.c:4398
is_req_active_cb
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)
Definition requirements.c:62
is_originalowner_req_active
static enum fc_tristate is_originalowner_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
Definition requirements.c:3788
is_plr_state_req_active
static enum fc_tristate is_plr_state_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
Definition requirements.c:2347
does_req_contradicts_reqs
bool does_req_contradicts_reqs(const struct requirement *req, const struct requirement_vector *vec)
Definition requirements.c:1845
government_found
static enum req_item_found government_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7340
unchanging_world
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)
Definition requirements.c:106
is_serversetting_req_active
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)
Definition requirements.c:5329
is_action_req_active
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)
Definition requirements.c:2875
are_universals_equal
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
Definition requirements.c:6466
req_vec_problem_new_transl
struct req_vec_problem * req_vec_problem_new_transl(int num_suggested_solutions, const char *description, const char *description_translated)
Definition requirements.c:6123
REQUC_NALLY
#define REQUC_NALLY
Definition requirements.c:139
unit_activity_found
static enum req_item_found unit_activity_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7444
is_mintechs_req_active
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)
Definition requirements.c:3535
is_unitclass_req_active
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)
Definition requirements.c:4077
tri_req_active
enum fc_tristate tri_req_active(const struct req_context *context, const struct player *other_player, const struct requirement *req)
Definition requirements.c:5472
is_terrainflag_req_active
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)
Definition requirements.c:3135
REQUC_LOCAL
#define REQUC_LOCAL
Definition requirements.c:84
universals_say_everything
bool universals_say_everything(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
Definition requirements.c:7204
is_extra_req_active
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)
Definition requirements.c:2730
nation_found
static enum req_item_found nation_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7317
REQUC_WORLD
#define REQUC_WORLD
Definition requirements.c:115
universal_type_rule_name
const char * universal_type_rule_name(const struct universal *psource)
Definition requirements.c:7102
REQUC_PRESENT
#define REQUC_PRESENT
Definition requirements.c:100
universal_found_functions_init
void universal_found_functions_init(void)
Definition requirements.c:7655
unit_class_found
static enum req_item_found unit_class_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7393
IS_REQ_ACTIVE_VARIANT_ASSERT
#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind)
Definition requirements.c:1924
universal_number
int universal_number(const struct universal *source)
Definition requirements.c:872
is_outputtype_req_active
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)
Definition requirements.c:2896
universal_is_mentioned_by_requirements
bool universal_is_mentioned_by_requirements(const struct requirement_vector *reqs, const struct universal *psource)
Definition requirements.c:7149
REQUC_CITYTILE
#define REQUC_CITYTILE
Definition requirements.c:162
is_minsize_req_active
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)
Definition requirements.c:5047
is_diplrel_tile_o_req_active
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)
Definition requirements.c:3928
diplrel_found
static enum req_item_found diplrel_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7553
req_vec_is_impossible_to_fulfill
bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
Definition requirements.c:5957
is_unitflag_req_active
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)
Definition requirements.c:4048
req_implies_req
bool req_implies_req(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1649
req_copy
void req_copy(struct requirement *dst, const struct requirement *src)
Definition requirements.c:1437
is_req_unchanging
enum req_unchanging_status is_req_unchanging(const struct req_context *context, const struct requirement *req)
Definition requirements.c:5748
is_techflag_req_active
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)
Definition requirements.c:2452
player_has_ever_built
static bool player_has_ever_built(const struct player *pplayer, const struct impr_type *building)
Definition requirements.c:1988
is_terrainclass_req_active
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)
Definition requirements.c:3033
is_req_preventing
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)
Definition requirements.c:5796
nation_contra_group
static bool nation_contra_group(const struct requirement *nation_req, const struct requirement *group_req)
Definition requirements.c:1539
req_is_impossible_to_fulfill
bool req_is_impossible_to_fulfill(const struct requirement *req)
Definition requirements.c:5944
are_tiles_in_range
static bool are_tiles_in_range(const struct tile *tile1, const struct tile *tile2, enum req_range range)
Definition requirements.c:1864
is_minyear_req_active
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)
Definition requirements.c:5253
are_requirements_opposites
static bool are_requirements_opposites(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1462
num_world_buildings
static int num_world_buildings(const struct impr_type *building)
Definition requirements.c:1967
is_minmovefrags_req_active
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)
Definition requirements.c:4277
is_diplrel_tile_req_active
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)
Definition requirements.c:3904
unchanging_citystatus
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)
Definition requirements.c:168
is_minculture_req_active
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)
Definition requirements.c:2516
universal_name_translation
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
Definition requirements.c:6755
universal_by_rule_name
struct universal universal_by_rule_name(const char *kind, const char *value)
Definition requirements.c:236
is_citystatus_req_active
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)
Definition requirements.c:4804
universals_mean_unfulfilled
bool universals_mean_unfulfilled(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
Definition requirements.c:7171
req_vec_suggest_improvement
struct req_vec_problem * req_vec_suggest_improvement(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
Definition requirements.c:6439
impr_contra_genus
static bool impr_contra_genus(const struct requirement *impr_req, const struct requirement *genus_req)
Definition requirements.c:1475
is_unittype_req_active
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)
Definition requirements.c:4019
requirements.h
requirement_diplrel_ereq
#define requirement_diplrel_ereq(_id_, _range_, _present_)
Definition requirements.h:449
req_vec_num_in_item
signed char req_vec_num_in_item
req_vec_num_in_item a requirement vectors number in an item.
Definition requirements.h:237
requirement_vector_number
req_vec_num_in_item(* requirement_vector_number)(const void *parent_item, const struct requirement_vector *vec)
Definition requirements.h:248
requirement_vector_namer
const char *(* requirement_vector_namer)(req_vec_num_in_item number)
Definition requirements.h:270
universal_is_mentioned_by_requirement
#define universal_is_mentioned_by_requirement(preq, psource)
Definition requirements.h:371
req_unchanging_cond_cb
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)
Definition requirements.h:131
req_tester_cb
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)
Definition requirements.h:193
requirement_vector_iterate_end
#define requirement_vector_iterate_end
Definition requirements.h:94
universal_by_number
struct universal universal_by_number(const enum universals_n kind, const int value)
Definition requirements.c:621
requirement_vector_by_number
struct requirement_vector *(* requirement_vector_by_number)(const void *parent_item, req_vec_num_in_item number)
Definition requirements.h:260
requirement_vector_iterate
#define requirement_vector_iterate(req_vec, preq)
Definition requirements.h:92
req_item_found
req_item_found
Definition requirements.h:378
ITF_NO
@ ITF_NO
Definition requirements.h:378
ITF_YES
@ ITF_YES
Definition requirements.h:378
ITF_NOT_APPLICABLE
@ ITF_NOT_APPLICABLE
Definition requirements.h:378
req_unchanging_status
req_unchanging_status
Definition requirements.h:116
REQUCH_ACT
@ REQUCH_ACT
Definition requirements.h:120
REQUCH_NO
@ REQUCH_NO
Definition requirements.h:117
REQUCH_SCRIPTS
@ REQUCH_SCRIPTS
Definition requirements.h:122
REQUCH_YES
@ REQUCH_YES
Definition requirements.h:124
REQUCH_HACK
@ REQUCH_HACK
Definition requirements.h:123
REQUCH_CTRL
@ REQUCH_CTRL
Definition requirements.h:118
research_get
struct research * research_get(const struct player *pplayer)
Definition research.c:128
research_invention_state
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:619
research.h
road_has_flag
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Definition road.c:410
is_road_flag_near_tile
bool is_road_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:440
is_road_flag_card_near
bool is_road_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum road_flag_id flag)
Definition road.c:419
road.h
ssetv_setting_has_value
bool ssetv_setting_has_value(ssetv val)
Definition server_settings.c:201
ssetv_by_rule_name
ssetv ssetv_by_rule_name(const char *name)
Definition server_settings.c:153
ssetv_rule_name
const char * ssetv_rule_name(ssetv val)
Definition server_settings.c:169
ssetv_human_readable
const char * ssetv_human_readable(ssetv val, bool present)
Definition server_settings.c:181
server_settings.h
SSETV_NONE
#define SSETV_NONE
Definition server_settings.h:43
fc_tristate_or
enum fc_tristate fc_tristate_or(enum fc_tristate one, enum fc_tristate two)
Definition shared.c:140
fc_tristate
fc_tristate
Definition shared.h:46
TRI_YES
@ TRI_YES
Definition shared.h:46
TRI_NO
@ TRI_NO
Definition shared.h:46
TRI_MAYBE
@ TRI_MAYBE
Definition shared.h:46
BOOL_TO_TRISTATE
#define BOOL_TO_TRISTATE(tri)
Definition shared.h:47
FC_INFINITY
#define FC_INFINITY
Definition shared.h:36
specialist_by_rule_name
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c:112
specialist_by_number
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:100
specialist_number
Specialist_type_id specialist_number(const struct specialist *sp)
Definition specialist.c:91
specialist_rule_name
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
specialist_plural_translation
const char * specialist_plural_translation(const struct specialist *sp)
Definition specialist.c:155
specialist.h
achievement
Definition achievements.h:26
astring
Definition astring.h:36
city
Definition city.h:320
city::tile
struct tile * tile
Definition city.h:322
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_game::calendar
struct packet_calendar_info calendar
Definition game.h:90
civ_map
Definition map_types.h:71
counter
Definition counters.h:27
counter::checkpoint
int checkpoint
Definition counters.h:33
extra_type
Definition extras.h:88
goods_type
Definition traderoutes.h:183
impr_type
Definition improvement.h:50
nation_group
Definition nation.h:167
nation_type
Definition nation.h:98
nation_type::player
struct player * player
Definition nation.h:118
packet_calendar_info::calendar_skip_0
bool calendar_skip_0
Definition packets_gen.h:259
packet_calendar_info::calendar_fragments
int calendar_fragments
Definition packets_gen.h:257
packet_game_info::global_advances
bool global_advances[A_LAST]
Definition packets_gen.h:162
packet_game_info::fragment_count
int fragment_count
Definition packets_gen.h:246
packet_game_info::turn
int turn
Definition packets_gen.h:241
packet_game_info::year
int year
Definition packets_gen.h:243
packet_game_info::global_advance_count
int global_advance_count
Definition packets_gen.h:161
player
Definition player.h:247
player::is_alive
bool is_alive
Definition player.h:266
range
Definition unittype.c:879
req_context
Definition requirements.h:100
req_def
Definition requirements.c:223
req_def::unchanging
enum req_unchanging_status unchanging
Definition requirements.c:225
req_def::unchanging_cond
req_unchanging_cond_cb unchanging_cond
Definition requirements.c:226
req_def::cb
const is_req_active_cb cb
Definition requirements.c:224
req_vec_change
Definition requirements.h:288
req_vec_change::vector_number
req_vec_num_in_item vector_number
Definition requirements.h:292
req_vec_change::operation
enum req_vec_change_operation operation
Definition requirements.h:289
req_vec_change::req
struct requirement req
Definition requirements.h:290
req_vec_problem
Definition requirements.h:295
req_vec_problem::num_suggested_solutions
int num_suggested_solutions
Definition requirements.h:301
req_vec_problem::description
char description[500]
Definition requirements.h:298
req_vec_problem::description_translated
char description_translated[500]
Definition requirements.h:299
requirement
Definition requirements.h:81
requirement::quiet
bool quiet
Definition requirements.h:86
requirement::survives
bool survives
Definition requirements.h:84
requirement::present
bool present
Definition requirements.h:85
requirement::range
enum req_range range
Definition requirements.h:83
requirement::source
struct universal source
Definition requirements.h:82
research::techs_researched
int techs_researched
Definition research.h:42
road_type
Definition road.h:71
terrain
Definition terrain.h:182
tile
Definition tile.h:50
unit_class
Definition unittype.h:149
unit_type
Definition unittype.h:500
unit::tile
struct tile * tile
Definition unit.h:140
universal
Definition fc_types.h:901
universal::kind
enum universals_n kind
Definition fc_types.h:903
universal::value
universals_u value
Definition fc_types.h:902
world::map
struct civ_map map
Definition world_object.h:38
style_by_rule_name
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
style_by_number
struct nation_style * style_by_number(int id)
Definition style.c:88
style_name_translation
const char * style_name_translation(const struct nation_style *pstyle)
Definition style.c:99
style_rule_name
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:108
style_number
int style_number(const struct nation_style *pstyle)
Definition style.c:68
style.h
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
fc_strlcpy
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:791
fc_strcasecmp
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
fc_strlcat
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:836
cat_snprintf
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
fc_vsnprintf
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:900
support.h
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
bool
#define bool
Definition support.h:71
fc__fallthrough
#define fc__fallthrough
Definition support.h:119
advance_by_number
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
advance_name_translation
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:290
advance_rule_name
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:299
advance_by_rule_name
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
advance_number
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
terrain_by_rule_name
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:186
is_terrain_class_near_tile
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:612
is_terrain_class_card_near
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:591
terrain_class_name_translation
const char * terrain_class_name_translation(enum terrain_class tclass)
Definition terrain.c:661
terrain_name_translation
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:238
terrain_by_number
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:156
terrain_can_support_alteration
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Definition terrain.c:673
is_terrain_card_near
bool is_terrain_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:327
terrain_rule_name
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
terrain_type_terrain_class
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:582
is_terrain_flag_near_tile
bool is_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:458
terrain_number
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:147
is_terrain_flag_card_near
bool is_terrain_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:438
is_terrain_near_tile
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:348
T_UNKNOWN
#define T_UNKNOWN
Definition terrain.h:57
terrain_has_flag
#define terrain_has_flag(terr, flag)
Definition terrain.h:283
tile_has_extra_flag
bool tile_has_extra_flag(const struct tile *ptile, enum extra_flag_id flag)
Definition tile.c:886
tile_has_native_base
bool tile_has_native_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:324
tile_has_road_flag
bool tile_has_road_flag(const struct tile *ptile, enum road_flag_id flag)
Definition tile.c:868
tile_city
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
tile_terrain
#define tile_terrain(_tile)
Definition tile.h:110
tile_continent
#define tile_continent(_tile)
Definition tile.h:92
tile_has_extra
#define tile_has_extra(ptile, pextra)
Definition tile.h:147
tile_owner
#define tile_owner(_tile)
Definition tile.h:96
goods_number
Goods_type_id goods_number(const struct goods_type *pgood)
Definition traderoutes.c:581
goods_has_flag
bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
Definition traderoutes.c:668
goods_by_rule_name
struct goods_type * goods_by_rule_name(const char *name)
Definition traderoutes.c:631
goods_rule_name
const char * goods_rule_name(struct goods_type *pgood)
Definition traderoutes.c:622
goods_name_translation
const char * goods_name_translation(struct goods_type *pgood)
Definition traderoutes.c:614
goods_by_number
struct goods_type * goods_by_number(Goods_type_id id)
Definition traderoutes.c:604
goods_can_be_provided
bool goods_can_be_provided(const struct city *pcity, const struct goods_type *pgood, struct unit *punit)
Definition traderoutes.c:676
city_receives_goods
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
Definition traderoutes.c:694
trade_partners_iterate_end
#define trade_partners_iterate_end
Definition traderoutes.h:166
trade_partners_iterate
#define trade_partners_iterate(c, p)
Definition traderoutes.h:161
universals_u::utype
const struct unit_type * utype
Definition fc_types.h:724
universals_u::unitflag
int unitflag
Definition fc_types.h:745
universals_u::min_techs
int min_techs
Definition fc_types.h:763
universals_u::mincalfrag
int mincalfrag
Definition fc_types.h:740
universals_u::diplrel
int diplrel
Definition fc_types.h:750
universals_u::style
struct nation_style * style
Definition fc_types.h:728
universals_u::ai_level
enum ai_level ai_level
Definition fc_types.h:732
universals_u::specialist
struct specialist * specialist
Definition fc_types.h:721
universals_u::impr_genus
enum impr_genus_id impr_genus
Definition fc_types.h:754
universals_u::citytile
enum citytile_type citytile
Definition fc_types.h:733
universals_u::nationgroup
struct nation_group * nationgroup
Definition fc_types.h:727
universals_u::extra
struct extra_type * extra
Definition fc_types.h:725
universals_u::wrap_property
enum wrap_flag wrap_property
Definition fc_types.h:767
universals_u::plrstate
enum plrstate_type plrstate
Definition fc_types.h:735
universals_u::nation
struct nation_type * nation
Definition fc_types.h:718
universals_u::minmoves
int minmoves
Definition fc_types.h:757
universals_u::terrainclass
int terrainclass
Definition fc_types.h:742
universals_u::unitclassflag
int unitclassflag
Definition fc_types.h:744
universals_u::govern
struct government * govern
Definition fc_types.h:716
universals_u::origowner
struct nation_type * origowner
Definition fc_types.h:720
universals_u::age
int age
Definition fc_types.h:761
universals_u::minsize
int minsize
Definition fc_types.h:736
universals_u::impr_flag
enum impr_flag_id impr_flag
Definition fc_types.h:755
universals_u::max_tile_units
int max_tile_units
Definition fc_types.h:758
universals_u::terrainalter
int terrainalter
Definition fc_types.h:743
universals_u::minculture
int minculture
Definition fc_types.h:737
universals_u::citystatus
enum citystatus_type citystatus
Definition fc_types.h:734
universals_u::minforeignpct
int minforeignpct
Definition fc_types.h:738
universals_u::building
const struct impr_type * building
Definition fc_types.h:717
universals_u::achievement
struct achievement * achievement
Definition fc_types.h:726
universals_u::ssetval
ssetv ssetval
Definition fc_types.h:768
universals_u::techflag
int techflag
Definition fc_types.h:747
universals_u::advance
struct advance * advance
Definition fc_types.h:714
universals_u::activity
enum unit_activity activity
Definition fc_types.h:753
universals_u::good
struct goods_type * good
Definition fc_types.h:730
universals_u::terrain
struct terrain * terrain
Definition fc_types.h:722
universals_u::terrainflag
int terrainflag
Definition fc_types.h:746
universals_u::unit_state
enum ustate_prop unit_state
Definition fc_types.h:752
universals_u::minveteran
int minveteran
Definition fc_types.h:759
universals_u::extraflag
int extraflag
Definition fc_types.h:749
universals_u::outputtype
Output_type_id outputtype
Definition fc_types.h:741
universals_u::roadflag
int roadflag
Definition fc_types.h:748
universals_u::topo_property
enum topo_flag topo_property
Definition fc_types.h:766
universals_u::latitude
int latitude
Definition fc_types.h:764
universals_u::counter
struct counter * counter
Definition fc_types.h:715
universals_u::min_hit_points
int min_hit_points
Definition fc_types.h:760
universals_u::uclass
struct unit_class * uclass
Definition fc_types.h:723
universals_u::nationality
struct nation_type * nationality
Definition fc_types.h:719
universals_u::minyear
int minyear
Definition fc_types.h:739
universals_u::action
struct action * action
Definition fc_types.h:729
universals_u::form_age
int form_age
Definition fc_types.h:762
universals_u::plr_flag
enum plr_flag_id plr_flag
Definition fc_types.h:756
get_transporter_occupancy
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1779
unit_tile
#define unit_tile(_pu)
Definition unit.h:390
unit_owner
#define unit_owner(_pu)
Definition unit.h:389
unit_list_iterate
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
unit_list_iterate_end
#define unit_list_iterate_end
Definition unitlist.h:33
uclass_name_translation
const char * uclass_name_translation(const struct unit_class *pclass)
Definition unittype.c:1632
unit_type_get
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
unit_type_by_rule_name
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1767
uclass_flag_is_in_use
bool uclass_flag_is_in_use(enum unit_class_flag_id ucflag)
Definition unittype.c:2967
uclass_by_number
struct unit_class * uclass_by_number(const Unit_Class_id id)
Definition unittype.c:2476
utype_rule_name
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1578
utype_by_number
struct unit_type * utype_by_number(const Unit_type_id id)
Definition unittype.c:112
uclass_rule_name
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1641
utype_number
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:100
unit_class_by_rule_name
struct unit_class * unit_class_by_rule_name(const char *s)
Definition unittype.c:1784
utype_flag_is_in_use
bool utype_flag_is_in_use(enum unit_type_flag_id uflag)
Definition unittype.c:2986
utype_build_shield_cost
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1438
uclass_number
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2467
utype_name_translation
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
uclass_has_flag
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:766
utype_class
#define utype_class(_t_)
Definition unittype.h:749
utype_has_flag
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:617
victory_enabled
bool victory_enabled(enum victory_condition_type victory)
Definition victory.c:26
victory.h