Freeciv-3.3: /fast/freeciv/nightly/main/common/requirements.c Source File

Freeciv-3.3

Loading...
Searching...
No Matches
requirements.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2004 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17#include <stdarg.h>
18
19/* utility */
20#include "astring.h"
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "achievements.h"
27#include "calendar.h"
28#include "citizens.h"
29#include "counters.h"
30#include "culture.h"
31#include "game.h"
32#include "government.h"
33#include "improvement.h"
34#include "movement.h"
35#include "nation.h"
36#include "player.h"
37#include "map.h"
38#include "research.h"
39#include "road.h"
40#include "server_settings.h"
41#include "specialist.h"
42#include "style.h"
43#include "victory.h" /* victory_enabled() */
44
45#include "requirements.h"
46
47/************************************************************************
48 Container for req_item_found functions
49************************************************************************/
50typedef enum req_item_found (*universal_found)(const struct requirement *,
51 const struct universal *);
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_MINCITIES:
474 source->value.min_cities = atoi(value);
475 if (source->value.min_cities > 0) {
476 return;
477 }
478 break;
479 case VUT_ACTION:
480 source->value.action = action_by_rule_name(value);
481 if (source->value.action != NULL) {
482 return;
483 }
484 break;
485 case VUT_OTYPE:
486 source->value.outputtype = output_type_by_identifier(value);
487 if (source->value.outputtype != O_LAST) {
488 return;
489 }
490 break;
491 case VUT_SPECIALIST:
492 source->value.specialist = specialist_by_rule_name(value);
493 if (source->value.specialist) {
494 return;
495 }
496 break;
497 case VUT_MINSIZE:
498 source->value.minsize = atoi(value);
499 if (source->value.minsize > 0) {
500 return;
501 }
502 break;
503 case VUT_MINCULTURE:
504 source->value.minculture = atoi(value);
505 if (source->value.minculture > 0) {
506 return;
507 }
508 break;
509 case VUT_MINFOREIGNPCT:
510 source->value.minforeignpct = atoi(value);
511 if (source->value.minforeignpct > 0) {
512 return;
513 }
514 break;
515 case VUT_AI_LEVEL:
516 source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
517 if (ai_level_is_valid(source->value.ai_level)) {
518 return;
519 }
520 break;
521 case VUT_MAXTILEUNITS:
522 source->value.max_tile_units = atoi(value);
523 if (0 <= source->value.max_tile_units) {
524 return;
525 }
526 break;
527 case VUT_TERRAINCLASS:
528 source->value.terrainclass
529 = terrain_class_by_name(value, fc_strcasecmp);
530 if (terrain_class_is_valid(source->value.terrainclass)) {
531 return;
532 }
533 break;
534 case VUT_ROADFLAG:
535 source->value.roadflag = road_flag_id_by_name(value, fc_strcasecmp);
536 if (road_flag_id_is_valid(source->value.roadflag)) {
537 return;
538 }
539 break;
540 case VUT_EXTRAFLAG:
541 source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
542 if (extra_flag_id_is_valid(source->value.extraflag)) {
543 return;
544 }
545 break;
546 case VUT_MINYEAR:
547 source->value.minyear = atoi(value);
548 return;
549 case VUT_MINCALFRAG:
550 /* Rule names are 0-based numbers, not pretty names from ruleset */
551 source->value.mincalfrag = atoi(value);
552 if (source->value.mincalfrag >= 0) {
553 /* More range checking done later, in sanity_check_req_individual() */
554 return;
555 }
556 break;
557 case VUT_TOPO:
558 source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
559 if (topo_flag_is_valid(source->value.topo_property)) {
560 return;
561 }
562 break;
563 case VUT_WRAP:
564 source->value.wrap_property = wrap_flag_by_name(value, fc_strcasecmp);
565 if (wrap_flag_is_valid(source->value.wrap_property)) {
566 return;
567 }
568 break;
569 case VUT_SERVERSETTING:
570 source->value.ssetval = ssetv_by_rule_name(value);
571 if (source->value.ssetval != SSETV_NONE) {
572 return;
573 }
574 break;
575 case VUT_TERRAINALTER:
576 source->value.terrainalter
577 = terrain_alteration_by_name(value, fc_strcasecmp);
578 if (terrain_alteration_is_valid(source->value.terrainalter)) {
579 return;
580 }
581 break;
582 case VUT_CITYTILE:
583 source->value.citytile = citytile_type_by_name(value, fc_strcasecmp);
584 if (source->value.citytile != CITYT_LAST) {
585 return;
586 }
587 break;
588 case VUT_CITYSTATUS:
589 source->value.citystatus = citystatus_type_by_name(value, fc_strcasecmp);
590 if (source->value.citystatus != CITYS_LAST) {
591 return;
592 }
593 break;
594 case VUT_PLAYER_STATE:
595 source->value.plrstate = plrstate_type_by_name(value, fc_strcasecmp);
596 if (source->value.plrstate != PLRS_LAST) {
597 return;
598 }
599 break;
600 case VUT_MINLATITUDE:
601 case VUT_MAXLATITUDE:
602 source->value.latitude = atoi(value);
603 if (source->value.latitude >= -MAP_MAX_LATITUDE
604 && source->value.latitude <= MAP_MAX_LATITUDE) {
605 return;
606 }
607 break;
608 case VUT_COUNTER:
609 source->value.counter = counter_by_rule_name(value);
610 if (source->value.counter != NULL) {
611 return;
612 }
613 break;
614 case VUT_COUNT:
615 break;
616 }
617
618 /* If we reach here there's been an error. */
619 source->kind = universals_n_invalid();
620}
621
622/**********************************************************************/
627 struct universal universal_by_number(const enum universals_n kind,
628 const int value)
629{
630 struct universal source;
631
632 source.kind = kind;
633
634 switch (source.kind) {
635 case VUT_NONE:
636 /* Avoid compiler warning about unitialized source.value */
637 source.value.advance = NULL;
638
639 return source;
640 case VUT_ADVANCE:
641 source.value.advance = advance_by_number(value);
642 if (source.value.advance != NULL) {
643 return source;
644 }
645 break;
646 case VUT_TECHFLAG:
647 source.value.techflag = value;
648 return source;
649 case VUT_GOVERNMENT:
650 source.value.govern = government_by_number(value);
651 if (source.value.govern != NULL) {
652 return source;
653 }
654 break;
655 case VUT_ACHIEVEMENT:
656 source.value.achievement = achievement_by_number(value);
657 if (source.value.achievement != NULL) {
658 return source;
659 }
660 break;
661 case VUT_STYLE:
662 source.value.style = style_by_number(value);
663 if (source.value.style != NULL) {
664 return source;
665 }
666 break;
667 case VUT_IMPROVEMENT:
668 source.value.building = improvement_by_number(value);
669 if (source.value.building != NULL) {
670 return source;
671 }
672 break;
673 case VUT_IMPR_GENUS:
674 source.value.impr_genus = value;
675 return source;
676 case VUT_IMPR_FLAG:
677 source.value.impr_flag = value;
678 return source;
679 case VUT_PLAYER_FLAG:
680 source.value.plr_flag = value;
681 return source;
682 case VUT_EXTRA:
683 source.value.extra = extra_by_number(value);
684 return source;
685 case VUT_GOOD:
686 source.value.good = goods_by_number(value);
687 return source;
688 case VUT_TERRAIN:
689 source.value.terrain = terrain_by_number(value);
690 if (source.value.terrain != NULL) {
691 return source;
692 }
693 break;
694 case VUT_TERRFLAG:
695 source.value.terrainflag = value;
696 return source;
697 case VUT_NATION:
698 source.value.nation = nation_by_number(value);
699 if (source.value.nation != NULL) {
700 return source;
701 }
702 break;
703 case VUT_NATIONGROUP:
704 source.value.nationgroup = nation_group_by_number(value);
705 if (source.value.nationgroup != NULL) {
706 return source;
707 }
708 break;
709 case VUT_DIPLREL:
710 case VUT_DIPLREL_TILE:
711 case VUT_DIPLREL_TILE_O:
712 case VUT_DIPLREL_UNITANY:
713 case VUT_DIPLREL_UNITANY_O:
714 source.value.diplrel = value;
715 if (source.value.diplrel != diplrel_other_invalid()) {
716 return source;
717 }
718 break;
719 case VUT_NATIONALITY:
720 source.value.nationality = nation_by_number(value);
721 if (source.value.nationality != NULL) {
722 return source;
723 }
724 break;
725 case VUT_ORIGINAL_OWNER:
726 source.value.origowner = nation_by_number(value);
727 if (source.value.origowner != NULL) {
728 return source;
729 }
730 break;
731 case VUT_UTYPE:
732 source.value.utype = utype_by_number(value);
733 if (source.value.utype != NULL) {
734 return source;
735 }
736 break;
737 case VUT_UTFLAG:
738 source.value.unitflag = value;
739 return source;
740 case VUT_UCLASS:
741 source.value.uclass = uclass_by_number(value);
742 if (source.value.uclass != NULL) {
743 return source;
744 }
745 break;
746 case VUT_UCFLAG:
747 source.value.unitclassflag = value;
748 return source;
749 case VUT_MINVETERAN:
750 source.value.minveteran = value;
751 return source;
752 case VUT_UNITSTATE:
753 source.value.unit_state = value;
754 return source;
755 case VUT_ACTIVITY:
756 source.value.activity = value;
757 return source;
758 case VUT_MINMOVES:
759 source.value.minmoves = value;
760 return source;
761 case VUT_MINHP:
762 source.value.min_hit_points = value;
763 return source;
764 case VUT_AGE:
765 source.value.age = value;
766 return source;
767 case VUT_FORM_AGE:
768 source.value.form_age = value;
769 return source;
770 case VUT_MINTECHS:
771 source.value.min_techs = value;
772 return source;
773 case VUT_MINCITIES:
774 source.value.min_cities = value;
775 return source;
776 case VUT_ACTION:
777 source.value.action = action_by_number(value);
778 if (source.value.action != NULL) {
779 return source;
780 }
781 break;
782 case VUT_OTYPE:
783 source.value.outputtype = value;
784 return source;
785 case VUT_SPECIALIST:
786 source.value.specialist = specialist_by_number(value);
787 return source;
788 case VUT_MINSIZE:
789 source.value.minsize = value;
790 return source;
791 case VUT_MINCULTURE:
792 source.value.minculture = value;
793 return source;
794 case VUT_MINFOREIGNPCT:
795 source.value.minforeignpct = value;
796 return source;
797 case VUT_AI_LEVEL:
798 source.value.ai_level = value;
799 return source;
800 case VUT_MAXTILEUNITS:
801 source.value.max_tile_units = value;
802 return source;
803 case VUT_TERRAINCLASS:
804 source.value.terrainclass = value;
805 return source;
806 case VUT_ROADFLAG:
807 source.value.roadflag = value;
808 return source;
809 case VUT_EXTRAFLAG:
810 source.value.extraflag = value;
811 return source;
812 case VUT_MINYEAR:
813 source.value.minyear = value;
814 return source;
815 case VUT_MINCALFRAG:
816 source.value.mincalfrag = value;
817 return source;
818 case VUT_TOPO:
819 source.value.topo_property = value;
820 return source;
821 case VUT_WRAP:
822 source.value.wrap_property = value;
823 return source;
824 case VUT_SERVERSETTING:
825 source.value.ssetval = value;
826 return source;
827 case VUT_TERRAINALTER:
828 source.value.terrainalter = value;
829 return source;
830 case VUT_CITYTILE:
831 source.value.citytile = value;
832 return source;
833 case VUT_CITYSTATUS:
834 source.value.citystatus = value;
835 return source;
836 case VUT_PLAYER_STATE:
837 source.value.plrstate = value;
838 return source;
839 case VUT_COUNTER:
840 source.value.counter = counter_by_id(value);
841 return source;
842 case VUT_MINLATITUDE:
843 case VUT_MAXLATITUDE:
844 source.value.latitude = value;
845 return source;
846 case VUT_COUNT:
847 break;
848 }
849
850 /* If we reach here there's been an error. */
851 source.kind = universals_n_invalid();
852 /* Avoid compiler warning about unitialized source.value */
853 source.value.advance = NULL;
854
855 return source;
856}
857
858/**********************************************************************/
861 void universal_copy(struct universal *dst, const struct universal *src)
862{
863 dst->value = src->value;
864 dst->kind = src->kind;
865}
866
867/**********************************************************************/
871 void universal_extraction(const struct universal *source,
872 int *kind, int *value)
873{
874 *kind = source->kind;
875 *value = universal_number(source);
876}
877
878/**********************************************************************/
881 int universal_number(const struct universal *source)
882{
883 switch (source->kind) {
884 case VUT_NONE:
885 return 0;
886 case VUT_ADVANCE:
887 return advance_number(source->value.advance);
888 case VUT_TECHFLAG:
889 return source->value.techflag;
890 case VUT_GOVERNMENT:
891 return government_number(source->value.govern);
892 case VUT_ACHIEVEMENT:
893 return achievement_number(source->value.achievement);
894 case VUT_STYLE:
895 return style_number(source->value.style);
896 case VUT_IMPROVEMENT:
897 return improvement_number(source->value.building);
898 case VUT_IMPR_GENUS:
899 return source->value.impr_genus;
900 case VUT_IMPR_FLAG:
901 return source->value.impr_flag;
902 case VUT_PLAYER_FLAG:
903 return source->value.plr_flag;
904 case VUT_EXTRA:
905 return extra_number(source->value.extra);
906 case VUT_GOOD:
907 return goods_number(source->value.good);
908 case VUT_TERRAIN:
909 return terrain_number(source->value.terrain);
910 case VUT_TERRFLAG:
911 return source->value.terrainflag;
912 case VUT_NATION:
913 return nation_number(source->value.nation);
914 case VUT_NATIONGROUP:
915 return nation_group_number(source->value.nationgroup);
916 case VUT_NATIONALITY:
917 return nation_number(source->value.nationality);
918 case VUT_ORIGINAL_OWNER:
919 return nation_number(source->value.origowner);
920 case VUT_DIPLREL:
921 case VUT_DIPLREL_TILE:
922 case VUT_DIPLREL_TILE_O:
923 case VUT_DIPLREL_UNITANY:
924 case VUT_DIPLREL_UNITANY_O:
925 return source->value.diplrel;
926 case VUT_UTYPE:
927 return utype_number(source->value.utype);
928 case VUT_UTFLAG:
929 return source->value.unitflag;
930 case VUT_UCLASS:
931 return uclass_number(source->value.uclass);
932 case VUT_UCFLAG:
933 return source->value.unitclassflag;
934 case VUT_MINVETERAN:
935 return source->value.minveteran;
936 case VUT_UNITSTATE:
937 return source->value.unit_state;
938 case VUT_ACTIVITY:
939 return source->value.activity;
940 case VUT_MINMOVES:
941 return source->value.minmoves;
942 case VUT_MINHP:
943 return source->value.min_hit_points;
944 case VUT_AGE:
945 return source->value.age;
946 case VUT_FORM_AGE:
947 return source->value.form_age;
948 case VUT_MINTECHS:
949 return source->value.min_techs;
950 case VUT_MINCITIES:
951 return source->value.min_cities;
952 case VUT_ACTION:
953 return action_number(source->value.action);
954 case VUT_OTYPE:
955 return source->value.outputtype;
956 case VUT_SPECIALIST:
957 return specialist_number(source->value.specialist);
958 case VUT_MINSIZE:
959 return source->value.minsize;
960 case VUT_MINCULTURE:
961 return source->value.minculture;
962 case VUT_MINFOREIGNPCT:
963 return source->value.minforeignpct;
964 case VUT_AI_LEVEL:
965 return source->value.ai_level;
966 case VUT_MAXTILEUNITS:
967 return source->value.max_tile_units;
968 case VUT_TERRAINCLASS:
969 return source->value.terrainclass;
970 case VUT_ROADFLAG:
971 return source->value.roadflag;
972 case VUT_EXTRAFLAG:
973 return source->value.extraflag;
974 case VUT_MINYEAR:
975 return source->value.minyear;
976 case VUT_MINCALFRAG:
977 return source->value.mincalfrag;
978 case VUT_TOPO:
979 return source->value.topo_property;
980 case VUT_WRAP:
981 return source->value.wrap_property;
982 case VUT_SERVERSETTING:
983 return source->value.ssetval;
984 case VUT_TERRAINALTER:
985 return source->value.terrainalter;
986 case VUT_CITYTILE:
987 return source->value.citytile;
988 case VUT_CITYSTATUS:
989 return source->value.citystatus;
990 case VUT_PLAYER_STATE:
991 return source->value.plrstate;
992 case VUT_COUNTER:
993 return counter_id(source->value.counter);
994 case VUT_MINLATITUDE:
995 case VUT_MAXLATITUDE:
996 return source->value.latitude;
997 case VUT_COUNT:
998 break;
999 }
1000
1001 /* If we reach here there's been an error. */
1002 fc_assert_msg(FALSE, "universal_number(): invalid source kind %d.",
1003 source->kind);
1004 return 0;
1005}
1006
1007
1008/**********************************************************************/
1011 const struct req_context *req_context_empty(void)
1012{
1013 static const struct req_context empty = {};
1014 return &empty;
1015}
1016
1017
1018/**********************************************************************/
1026 const char *req_to_fstring(const struct requirement *req,
1027 struct astring *astr)
1028{
1029 astr_init(astr);
1030
1031 astr_set(astr, "%s%s %s %s%s",
1032 req->survives ? "surviving " : "",
1033 req_range_name(req->range),
1034 universal_type_rule_name(&req->source),
1035 req->present ? "" : "!",
1036 universal_rule_name(&req->source));
1037
1038 return astr_str(astr);
1039}
1040
1041/**********************************************************************/
1048 struct requirement req_from_str(const char *type, const char *range,
1049 bool survives, bool present, bool quiet,
1050 const char *value)
1051{
1052 struct requirement req;
1053 bool invalid;
1054 const char *error = NULL;
1055
1056 req.source = universal_by_rule_name(type, value);
1057
1058 invalid = !universals_n_is_valid(req.source.kind);
1059 if (invalid) {
1060 error = "bad type or name";
1061 } else {
1062 /* Scan the range string to find the range. If no range is given a
1063 * default fallback is used rather than giving an error. */
1064 if (range != NULL) {
1065 req.range = req_range_by_name(range, fc_strcasecmp);
1066 if (!req_range_is_valid(req.range)) {
1067 invalid = TRUE;
1068 }
1069 } else {
1070 switch (req.source.kind) {
1071 case VUT_NONE:
1072 case VUT_COUNT:
1073 break;
1074 case VUT_IMPROVEMENT:
1075 case VUT_IMPR_GENUS:
1076 case VUT_IMPR_FLAG:
1077 case VUT_UTYPE:
1078 case VUT_UTFLAG:
1079 case VUT_UCLASS:
1080 case VUT_UCFLAG:
1081 case VUT_MINVETERAN:
1082 case VUT_UNITSTATE:
1083 case VUT_ACTIVITY:
1084 case VUT_MINMOVES:
1085 case VUT_MINHP:
1086 case VUT_AGE:
1087 case VUT_FORM_AGE:
1088 case VUT_ACTION:
1089 case VUT_OTYPE:
1090 case VUT_SPECIALIST:
1091 case VUT_DIPLREL_TILE_O:
1092 case VUT_DIPLREL_UNITANY_O:
1093 req.range = REQ_RANGE_LOCAL;
1094 break;
1095 case VUT_EXTRA:
1096 case VUT_ROADFLAG:
1097 case VUT_EXTRAFLAG:
1098 /* Keep old behavior */
1099 req.range = REQ_RANGE_TILE;
1100 break;
1101 case VUT_TERRAIN:
1102 case VUT_TERRFLAG:
1103 case VUT_TERRAINCLASS:
1104 case VUT_TERRAINALTER:
1105 case VUT_CITYTILE:
1106 case VUT_MAXTILEUNITS:
1107 case VUT_MINLATITUDE:
1108 case VUT_MAXLATITUDE:
1109 req.range = REQ_RANGE_TILE;
1110 break;
1111 case VUT_COUNTER:
1112 case VUT_MINSIZE:
1113 case VUT_MINCULTURE:
1114 case VUT_MINFOREIGNPCT:
1115 case VUT_NATIONALITY:
1116 case VUT_ORIGINAL_OWNER:
1117 case VUT_CITYSTATUS:
1118 case VUT_GOOD:
1119 req.range = REQ_RANGE_CITY;
1120 break;
1121 case VUT_GOVERNMENT:
1122 case VUT_ACHIEVEMENT:
1123 case VUT_STYLE:
1124 case VUT_ADVANCE:
1125 case VUT_TECHFLAG:
1126 case VUT_NATION:
1127 case VUT_NATIONGROUP:
1128 case VUT_DIPLREL:
1129 case VUT_DIPLREL_TILE:
1130 case VUT_DIPLREL_UNITANY:
1131 case VUT_AI_LEVEL:
1132 case VUT_PLAYER_FLAG:
1133 case VUT_PLAYER_STATE:
1134 case VUT_MINCITIES:
1135 req.range = REQ_RANGE_PLAYER;
1136 break;
1137 case VUT_MINYEAR:
1138 case VUT_MINCALFRAG:
1139 case VUT_TOPO:
1140 case VUT_WRAP:
1141 case VUT_MINTECHS:
1142 case VUT_SERVERSETTING:
1143 req.range = REQ_RANGE_WORLD;
1144 break;
1145 }
1146 }
1147
1148 req.survives = survives;
1149 req.present = present;
1150 req.quiet = quiet;
1151
1152 /* These checks match what combinations are supported inside
1153 * is_req_active(). However, it's only possible to do basic checks,
1154 * not anything that might depend on the rest of the ruleset which
1155 * might not have been loaded yet. */
1156 switch (req.source.kind) {
1157 case VUT_TERRAIN:
1158 case VUT_TERRAINCLASS:
1159 case VUT_TERRFLAG:
1160 invalid = (req.range != REQ_RANGE_TILE
1161 && req.range != REQ_RANGE_CADJACENT
1162 && req.range != REQ_RANGE_ADJACENT
1163 && req.range != REQ_RANGE_CITY
1164 && req.range != REQ_RANGE_TRADE_ROUTE);
1165 break;
1166 case VUT_EXTRA:
1167 case VUT_ROADFLAG:
1168 case VUT_EXTRAFLAG:
1169 invalid = (req.range > REQ_RANGE_TRADE_ROUTE);
1170 break;
1171 case VUT_ADVANCE:
1172 case VUT_TECHFLAG:
1173 case VUT_ACHIEVEMENT:
1174 case VUT_MINTECHS:
1175 invalid = (req.range < REQ_RANGE_PLAYER);
1176 break;
1177 case VUT_GOVERNMENT:
1178 case VUT_AI_LEVEL:
1179 case VUT_STYLE:
1180 case VUT_MINCITIES:
1181 invalid = (req.range != REQ_RANGE_PLAYER);
1182 break;
1183 case VUT_MINSIZE:
1184 case VUT_MINFOREIGNPCT:
1185 case VUT_NATIONALITY:
1186 case VUT_CITYSTATUS:
1187 invalid = (req.range != REQ_RANGE_CITY
1188 && req.range != REQ_RANGE_TRADE_ROUTE);
1189 break;
1190 case VUT_GOOD:
1191 case VUT_ORIGINAL_OWNER:
1192 invalid = (req.range != REQ_RANGE_CITY);
1193 break;
1194 case VUT_MINCULTURE:
1195 invalid = (req.range != REQ_RANGE_CITY
1196 && req.range != REQ_RANGE_TRADE_ROUTE
1197 && req.range != REQ_RANGE_PLAYER
1198 && req.range != REQ_RANGE_TEAM
1199 && req.range != REQ_RANGE_ALLIANCE
1200 && req.range != REQ_RANGE_WORLD);
1201 break;
1202 case VUT_DIPLREL:
1203 invalid = (req.range != REQ_RANGE_LOCAL
1204 && req.range != REQ_RANGE_PLAYER
1205 && req.range != REQ_RANGE_TEAM
1206 && req.range != REQ_RANGE_ALLIANCE
1207 && req.range != REQ_RANGE_WORLD)
1208 /* Non local foreign makes no sense. */
1209 || (req.source.value.diplrel == DRO_FOREIGN
1210 && req.range != REQ_RANGE_LOCAL);
1211 break;
1212 case VUT_DIPLREL_TILE:
1213 invalid = (req.range != REQ_RANGE_LOCAL
1214 && req.range != REQ_RANGE_PLAYER
1215 && req.range != REQ_RANGE_TEAM
1216 && req.range != REQ_RANGE_ALLIANCE)
1217 /* Non local foreign makes no sense. */
1218 || (req.source.value.diplrel == DRO_FOREIGN
1219 && req.range != REQ_RANGE_LOCAL);
1220 break;
1221 case VUT_DIPLREL_TILE_O:
1222 invalid = (req.range != REQ_RANGE_LOCAL);
1223 break;
1224 case VUT_DIPLREL_UNITANY:
1225 invalid = (req.range != REQ_RANGE_LOCAL
1226 && req.range != REQ_RANGE_PLAYER
1227 && req.range != REQ_RANGE_TEAM
1228 && req.range != REQ_RANGE_ALLIANCE)
1229 /* Non local foreign makes no sense. */
1230 || (req.source.value.diplrel == DRO_FOREIGN
1231 && req.range != REQ_RANGE_LOCAL);
1232 break;
1233 case VUT_DIPLREL_UNITANY_O:
1234 invalid = (req.range != REQ_RANGE_LOCAL);
1235 break;
1236 case VUT_NATION:
1237 case VUT_NATIONGROUP:
1238 invalid = (req.range != REQ_RANGE_PLAYER
1239 && req.range != REQ_RANGE_TEAM
1240 && req.range != REQ_RANGE_ALLIANCE
1241 && req.range != REQ_RANGE_WORLD);
1242 break;
1243 case VUT_UCFLAG:
1244 case VUT_MINVETERAN:
1245 case VUT_UNITSTATE:
1246 case VUT_ACTIVITY:
1247 case VUT_MINMOVES:
1248 case VUT_MINHP:
1249 case VUT_ACTION:
1250 case VUT_OTYPE:
1251 case VUT_SPECIALIST:
1252 invalid = (req.range != REQ_RANGE_LOCAL);
1253 break;
1254 case VUT_UTYPE:
1255 case VUT_UTFLAG:
1256 case VUT_UCLASS:
1257 invalid = (req.range != REQ_RANGE_LOCAL
1258 && req.range != REQ_RANGE_TILE
1259 && req.range != REQ_RANGE_CADJACENT
1260 && req.range != REQ_RANGE_ADJACENT);
1261 break;
1262 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1263 invalid = (req.range != REQ_RANGE_TILE);
1264 break;
1265 case VUT_CITYTILE:
1266 case VUT_MAXTILEUNITS:
1267 invalid = (req.range != REQ_RANGE_TILE
1268 && req.range != REQ_RANGE_CADJACENT
1269 && req.range != REQ_RANGE_ADJACENT);
1270 break;
1271 case VUT_MINLATITUDE:
1272 case VUT_MAXLATITUDE:
1273 invalid = (req.range != REQ_RANGE_TILE
1274 && req.range != REQ_RANGE_CADJACENT
1275 && req.range != REQ_RANGE_ADJACENT
1276 && req.range != REQ_RANGE_WORLD)
1277 /* Avoid redundancy at tile range: no negated requirements
1278 * that could be emulated by a present requirement of the
1279 * other type */
1280 || (req.range == REQ_RANGE_TILE && !req.present);
1281 break;
1282 case VUT_MINYEAR:
1283 case VUT_MINCALFRAG:
1284 case VUT_TOPO:
1285 case VUT_WRAP:
1286 case VUT_SERVERSETTING:
1287 invalid = (req.range != REQ_RANGE_WORLD);
1288 break;
1289 case VUT_AGE:
1290 /* FIXME: could support TRADE_ROUTE, TEAM, etc */
1291 invalid = (req.range != REQ_RANGE_LOCAL
1292 && req.range != REQ_RANGE_CITY
1293 && req.range != REQ_RANGE_PLAYER);
1294 break;
1295 case VUT_FORM_AGE:
1296 invalid = (req.range != REQ_RANGE_LOCAL);
1297 break;
1298 case VUT_IMPR_GENUS:
1299 /* TODO: Support other ranges too. */
1300 invalid = (req.range != REQ_RANGE_LOCAL);
1301 break;
1302 case VUT_IMPR_FLAG:
1303 invalid = (req.range != REQ_RANGE_LOCAL
1304 && req.range != REQ_RANGE_TILE
1305 && req.range != REQ_RANGE_CITY);
1306 break;
1307 case VUT_COUNTER:
1308 invalid = req.range != REQ_RANGE_CITY;
1309 break;
1310 case VUT_PLAYER_FLAG:
1311 case VUT_PLAYER_STATE:
1312 invalid = (req.range != REQ_RANGE_PLAYER);
1313 break;
1314 case VUT_IMPROVEMENT:
1315 /* Valid ranges depend on the building genus (wonder/improvement),
1316 * which might not have been loaded from the ruleset yet.
1317 * So we allow anything here, and do a proper check once ruleset
1318 * loading is complete, in sanity_check_req_individual(). */
1319 case VUT_NONE:
1320 invalid = FALSE;
1321 break;
1322 case VUT_COUNT:
1323 break;
1324 }
1325 if (invalid) {
1326 error = "bad range";
1327 }
1328 }
1329
1330 if (!invalid) {
1331 /* Check 'survives'. */
1332 switch (req.source.kind) {
1333 case VUT_IMPROVEMENT:
1334 /* See buildings_in_range(). */
1335 invalid = survives && req.range <= REQ_RANGE_CONTINENT;
1336 break;
1337 case VUT_NATION:
1338 case VUT_ADVANCE:
1339 invalid = survives && req.range != REQ_RANGE_WORLD;
1340 break;
1341 case VUT_COUNTER:
1342 case VUT_IMPR_GENUS:
1343 case VUT_IMPR_FLAG:
1344 case VUT_PLAYER_FLAG:
1345 case VUT_PLAYER_STATE:
1346 case VUT_GOVERNMENT:
1347 case VUT_TERRAIN:
1348 case VUT_UTYPE:
1349 case VUT_UTFLAG:
1350 case VUT_UCLASS:
1351 case VUT_UCFLAG:
1352 case VUT_MINVETERAN:
1353 case VUT_UNITSTATE:
1354 case VUT_ACTIVITY:
1355 case VUT_MINMOVES:
1356 case VUT_MINHP:
1357 case VUT_AGE:
1358 case VUT_FORM_AGE:
1359 case VUT_ACTION:
1360 case VUT_OTYPE:
1361 case VUT_SPECIALIST:
1362 case VUT_MINSIZE:
1363 case VUT_MINCULTURE:
1364 case VUT_MINFOREIGNPCT:
1365 case VUT_AI_LEVEL:
1366 case VUT_TERRAINCLASS:
1367 case VUT_MINYEAR:
1368 case VUT_MINCALFRAG:
1369 case VUT_TOPO:
1370 case VUT_WRAP:
1371 case VUT_SERVERSETTING:
1372 case VUT_TERRAINALTER:
1373 case VUT_CITYTILE:
1374 case VUT_CITYSTATUS:
1375 case VUT_TERRFLAG:
1376 case VUT_NATIONALITY:
1377 case VUT_ORIGINAL_OWNER:
1378 case VUT_ROADFLAG:
1379 case VUT_EXTRAFLAG:
1380 case VUT_EXTRA:
1381 case VUT_GOOD:
1382 case VUT_TECHFLAG:
1383 case VUT_ACHIEVEMENT:
1384 case VUT_NATIONGROUP:
1385 case VUT_STYLE:
1386 case VUT_DIPLREL:
1387 case VUT_DIPLREL_TILE:
1388 case VUT_DIPLREL_TILE_O:
1389 case VUT_DIPLREL_UNITANY:
1390 case VUT_DIPLREL_UNITANY_O:
1391 case VUT_MAXTILEUNITS:
1392 case VUT_MINTECHS:
1393 case VUT_MINCITIES:
1394 case VUT_MINLATITUDE:
1395 case VUT_MAXLATITUDE:
1396 /* Most requirements don't support 'survives'. */
1397 invalid = survives;
1398 break;
1399 case VUT_NONE:
1400 case VUT_COUNT:
1401 break;
1402 }
1403 if (invalid) {
1404 error = "bad 'survives'";
1405 }
1406 }
1407
1408 if (invalid) {
1409 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1410 type, range, survives ? "survives" : "",
1411 present ? "present" : "", value, error);
1412 req.source.kind = universals_n_invalid();
1413 }
1414
1415 return req;
1416}
1417
1418/**********************************************************************/
1422 struct requirement req_from_values(int type, int range,
1423 bool survives, bool present, bool quiet,
1424 int value)
1425{
1426 struct requirement req;
1427
1428 req.source = universal_by_number(type, value);
1429 req.range = range;
1430 req.survives = survives;
1431 req.present = present;
1432 req.quiet = quiet;
1433
1434 return req;
1435}
1436
1437/**********************************************************************/
1441 void req_get_values(const struct requirement *req,
1442 int *type, int *range,
1443 bool *survives, bool *present, bool *quiet,
1444 int *value)
1445{
1446 universal_extraction(&req->source, type, value);
1447 *range = req->range;
1448 *survives = req->survives;
1449 *present = req->present;
1450 *quiet = req->quiet;
1451}
1452
1453/**********************************************************************/
1456 void req_copy(struct requirement *dst, const struct requirement *src)
1457{
1458 universal_copy(&(dst->source), &(src->source));
1459 dst->range = src->range;
1460 dst->survives = src->survives;
1461 dst->present = src->present;
1462 dst->quiet = src->quiet;
1463}
1464
1465/**********************************************************************/
1469 bool are_requirements_equal(const struct requirement *req1,
1470 const struct requirement *req2)
1471{
1472 return (are_universals_equal(&req1->source, &req2->source)
1473 && req1->range == req2->range
1474 && req1->survives == req2->survives
1475 && req1->present == req2->present);
1476}
1477
1478/**********************************************************************/
1481 static bool are_requirements_opposites(const struct requirement *req1,
1482 const struct requirement *req2)
1483{
1484 return (are_universals_equal(&req1->source, &req2->source)
1485 && req1->range == req2->range
1486 && req1->survives == req2->survives
1487 && req1->present != req2->present);
1488}
1489
1490/**********************************************************************/
1494 static bool impr_contra_genus(const struct requirement *impr_req,
1495 const struct requirement *genus_req)
1496{
1497 /* The input is sane. */
1498 fc_assert_ret_val(impr_req->source.kind == VUT_IMPROVEMENT, FALSE);
1499 fc_assert_ret_val(genus_req->source.kind == VUT_IMPR_GENUS, FALSE);
1500
1501 if (impr_req->range == REQ_RANGE_LOCAL
1502 && genus_req->range == REQ_RANGE_LOCAL) {
1503 /* Applies to the same target building. */
1504
1505 if (impr_req->present && !genus_req->present) {
1506 /* The target building can't not have the genus it has. */
1507 return (impr_req->source.value.building->genus
1508 == genus_req->source.value.impr_genus);
1509 }
1510
1511 if (impr_req->present && genus_req->present) {
1512 /* The target building can't have another genus than it has. */
1513 return (impr_req->source.value.building->genus
1514 != genus_req->source.value.impr_genus);
1515 }
1516 }
1517
1518 /* No special knowledge. */
1519 return FALSE;
1520}
1521
1522/**********************************************************************/
1526 static bool impr_contra_flag(const struct requirement *impr_req,
1527 const struct requirement *flag_req)
1528{
1529 /* The input is sane. */
1530 fc_assert_ret_val(impr_req->source.kind == VUT_IMPROVEMENT, FALSE);
1531 fc_assert_ret_val(flag_req->source.kind == VUT_IMPR_FLAG, FALSE);
1532
1533 if (impr_req->range == REQ_RANGE_LOCAL
1534 && flag_req->range == REQ_RANGE_LOCAL) {
1535 /* Applies to the same target building. */
1536
1537 if (impr_req->present && !flag_req->present) {
1538 /* The target building can't not have the flag it has. */
1539 return improvement_has_flag(impr_req->source.value.building,
1540 flag_req->source.value.impr_flag);
1541 }
1542
1543 if (impr_req->present && flag_req->present) {
1544 /* The target building can't have another flag than it has. */
1545 return !improvement_has_flag(impr_req->source.value.building,
1546 flag_req->source.value.impr_flag);
1547 }
1548 }
1549
1550 /* No special knowledge. */
1551 return FALSE;
1552}
1553
1554/**********************************************************************/
1558 static bool nation_contra_group(const struct requirement *nation_req,
1559 const struct requirement *group_req)
1560{
1561 /* The input is sane. */
1562 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1563 fc_assert_ret_val(group_req->source.kind == VUT_NATIONGROUP, FALSE);
1564
1565 if (nation_req->range == REQ_RANGE_PLAYER
1566 && group_req->range == REQ_RANGE_PLAYER) {
1567 /* Applies to the same target building. */
1568
1569 if (nation_req->present && !group_req->present) {
1570 /* The target nation can't be in the group. */
1571 return nation_is_in_group(nation_req->source.value.nation,
1572 group_req->source.value.nationgroup);
1573 }
1574 }
1575
1576 /* No special knowledge. */
1577 return FALSE;
1578}
1579
1580/**********************************************************************/
1584 static bool city_center_contra(const struct requirement *cc_req,
1585 const struct requirement *ct_req)
1586{
1587 /* The input is sane. */
1588 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1589 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1590
1591 if (cc_req->source.value.citytile == CITYT_CENTER
1592 && cc_req->present && cc_req->range <= ct_req->range) {
1593 switch (ct_req->source.value.citytile) {
1594 case CITYT_CENTER:
1595 case CITYT_CLAIMED:
1596 case CITYT_EXTRAS_OWNED:
1597 case CITYT_WORKED:
1598 case CITYT_SAME_CONTINENT:
1599 /* Should be always on city center */
1600 return !ct_req->present;
1601 case CITYT_BORDERING_TCLASS_REGION:
1602 /* Handled later */
1603 break;
1604 case CITYT_LAST:
1605 /* Error */
1606 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1607 }
1608 }
1609 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1610 || cc_req->source.value.citytile == CITYT_CENTER)
1611 && ct_req->source.value.citytile
1612 == CITYT_BORDERING_TCLASS_REGION
1613 && REQ_RANGE_TILE == cc_req->range
1614 && REQ_RANGE_TILE == ct_req->range) {
1615 /* Can't coexist */
1616 return cc_req->present ? ct_req->present : !ct_req->present;
1617 }
1618
1619 return FALSE;
1620}
1621
1622/**********************************************************************/
1627 static bool present_implies_not_present(const struct requirement *req1,
1628 const struct requirement *req2)
1629{
1630 const struct requirement *absent, *present;
1631
1632 if (req1->present == req2->present) {
1633 /* Can't use the knowledge in universal_found_function when both are
1634 * required to be absent or when both are required to be present.
1635 * It is no contradiction to require !Spy unit and !Missile unit class.
1636 * It is no contradiction to require River and Irrigation at the same
1637 * tile. */
1638 return FALSE;
1639 }
1640
1641 if (req1->present) {
1642 absent = req2;
1643 present = req1;
1644 } else {
1645 absent = req1;
1646 present = req2;
1647 }
1648
1649 if (!universal_found_function[present->source.kind]) {
1650 /* No knowledge to exploit. */
1651 return FALSE;
1652 }
1653
1654 if (present->range != absent->range) {
1655 /* Larger ranges are not always strict supersets of smaller ranges.
1656 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1657 * but not in Trade Route. */
1658 return FALSE;
1659 }
1660
1661 return ITF_YES == universal_fulfills_requirement(absent,
1662 &present->source);
1663}
1664
1665/**********************************************************************/
1668 bool req_implies_req(const struct requirement *req1,
1669 const struct requirement *req2)
1670{
1671 struct requirement nreq2;
1672
1673 req_copy(&nreq2, req2);
1674 nreq2.present = !nreq2.present;
1675 return are_requirements_contradictions(req1, &nreq2);
1676}
1677
1678/**********************************************************************/
1685 bool are_requirements_contradictions(const struct requirement *req1,
1686 const struct requirement *req2)
1687{
1688 if (are_requirements_opposites(req1, req2)) {
1689 /* The exact opposite. */
1690 return TRUE;
1691 }
1692
1693 if (present_implies_not_present(req1, req2)) {
1694 return TRUE;
1695 }
1696
1697 switch (req1->source.kind) {
1698 case VUT_IMPROVEMENT:
1699 if (req2->source.kind == VUT_IMPR_GENUS) {
1700 return impr_contra_genus(req1, req2);
1701 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1702 return impr_contra_flag(req1, req2);
1703 } else if (req2->source.kind == VUT_CITYTILE
1704 && req2->source.value.citytile == CITYT_CENTER
1705 && REQ_RANGE_TILE == req2->range
1706 && REQ_RANGE_TILE == req1->range
1707 && req1->present) {
1708 /* A building must be in a city */
1709 return !req2->present;
1710 }
1711
1712 /* No special knowledge. */
1713 return FALSE;
1714 case VUT_IMPR_GENUS:
1715 if (req2->source.kind == VUT_IMPROVEMENT) {
1716 return impr_contra_genus(req2, req1);
1717 }
1718
1719 /* No special knowledge. */
1720 return FALSE;
1721 case VUT_IMPR_FLAG:
1722 if (req2->source.kind == VUT_IMPROVEMENT) {
1723 return impr_contra_flag(req2, req1);
1724 }
1725
1726 /* No special knowledge. */
1727 return FALSE;
1728 case VUT_DIPLREL:
1729 case VUT_DIPLREL_TILE:
1730 case VUT_DIPLREL_TILE_O:
1731 case VUT_DIPLREL_UNITANY:
1732 case VUT_DIPLREL_UNITANY_O:
1733 if (req2->source.kind != req1->source.kind) {
1734 /* Finding contradictions across requirement kinds aren't supported
1735 * for DiplRel requirements. */
1736 return FALSE;
1737 } else {
1738 /* Use the special knowledge about DiplRel requirements to find
1739 * contradictions. */
1740
1741 bv_diplrel_all_reqs req1_contra;
1742 int req2_pos;
1743
1744 req1_contra = diplrel_req_contradicts(req1);
1745 req2_pos = requirement_diplrel_ereq(req2->source.value.diplrel,
1746 req2->range,
1747 req2->present);
1748
1749 return BV_ISSET(req1_contra, req2_pos);
1750 }
1751 break;
1752 case VUT_MINMOVES:
1753 if (req2->source.kind != VUT_MINMOVES) {
1754 /* Finding contradictions across requirement kinds aren't supported
1755 * for MinMoveFrags requirements. */
1756 return FALSE;
1757 } else if (req1->present == req2->present) {
1758 /* No contradiction possible. */
1759 return FALSE;
1760 } else {
1761 /* Number of move fragments left can't be larger than the number
1762 * required to be present and smaller than the number required to not
1763 * be present when the number required to be present is smaller than
1764 * the number required to not be present. */
1765 if (req1->present) {
1766 return req1->source.value.minmoves >= req2->source.value.minmoves;
1767 } else {
1768 return req1->source.value.minmoves <= req2->source.value.minmoves;
1769 }
1770 }
1771 break;
1772 case VUT_MINLATITUDE:
1773 case VUT_MAXLATITUDE:
1774 if (req2->source.kind != VUT_MINLATITUDE
1775 && req2->source.kind != VUT_MAXLATITUDE) {
1776 /* Finding contradictions across requirement kinds other than each
1777 * other is not supported for MinLatitude and MaxLatitude. */
1778 return FALSE;
1779 } else {
1780 /* For a contradiction, we need
1781 * - a minimum (present MinLatitude or negated MaxLatitude)
1782 * - a maximum (negated MinLatitude or present MaxLatitude)
1783 * - the maximum to be less than the minimum
1784 * - a requirement at the larger range that applies to the entire
1785 * range (i.e. a negated requirement, unless the range is Tile)
1786 * Otherwise, the two requirements could still be fulfilled
1787 * simultaneously by different tiles in the range */
1788
1789 /* Initial values beyond the boundaries to avoid edge cases */
1790 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
1791 enum req_range covered_range = REQ_RANGE_TILE;
1792
1793#define EXTRACT_INFO(req) \
1794 if (req->present) { \
1795 if (req->source.kind == VUT_MINLATITUDE) { \
1796 /* present MinLatitude */ \
1797 minimum = MAX(minimum, req->source.value.latitude); \
1798 } else { \
1799 /* present MaxLatitude */ \
1800 maximum = MIN(maximum, req->source.value.latitude); \
1801 } \
1802 } else { \
1803 covered_range = MAX(covered_range, req->range); \
1804 if (req->source.kind == VUT_MINLATITUDE) { \
1805 /* negated MinLatitude */ \
1806 maximum = MIN(maximum, req->source.value.latitude - 1); \
1807 } else { \
1808 /* negated MaxLatitude */ \
1809 minimum = MAX(minimum, req->source.value.latitude + 1); \
1810 } \
1811 }
1812
1813 EXTRACT_INFO(req1);
1814 EXTRACT_INFO(req2);
1815
1816#undef EXTRACT_INFO
1817
1818 return (maximum < minimum
1819 && covered_range >= req1->range
1820 && covered_range >= req2->range);
1821 }
1822 break;
1823 case VUT_NATION:
1824 if (req2->source.kind == VUT_NATIONGROUP) {
1825 return nation_contra_group(req1, req2);
1826 }
1827
1828 /* No special knowledge. */
1829 return FALSE;
1830 break;
1831 case VUT_NATIONGROUP:
1832 if (req2->source.kind == VUT_NATION) {
1833 return nation_contra_group(req2, req1);
1834 }
1835
1836 /* No special knowledge. */
1837 return FALSE;
1838 break;
1839 case VUT_CITYTILE:
1840 if (req2->source.kind == VUT_CITYTILE) {
1841 return city_center_contra(req1, req2)
1842 || city_center_contra(req2, req1);
1843 } else if (req1->source.value.citytile == CITYT_CENTER
1844 && req2->source.kind == VUT_IMPROVEMENT
1845 && REQ_RANGE_TILE == req2->range
1846 && REQ_RANGE_TILE == req1->range
1847 && req2->present) {
1848 /* A building must be in a city */
1849 return !req1->present;
1850 }
1851
1852 return FALSE;
1853 default:
1854 /* No special knowledge exists. The requirements aren't the exact
1855 * opposite of each other per the initial check. */
1856 return FALSE;
1857 }
1858}
1859
1860/**********************************************************************/
1864 bool does_req_contradicts_reqs(const struct requirement *req,
1865 const struct requirement_vector *vec)
1866{
1867 /* If the requirement is contradicted by any requirement in the vector it
1868 * contradicts the entire requirement vector. */
1869 requirement_vector_iterate(vec, preq) {
1870 if (are_requirements_contradictions(req, preq)) {
1871 return TRUE;
1872 }
1873 } requirement_vector_iterate_end;
1874
1875 /* Not a singe requirement in the requirement vector is contradicted be
1876 * the specified requirement. */
1877 return FALSE;
1878}
1879
1880/**********************************************************************/
1883 static inline bool are_tiles_in_range(const struct tile *tile1,
1884 const struct tile *tile2,
1885 enum req_range range)
1886{
1887 switch (range) {
1888 case REQ_RANGE_ADJACENT:
1889 if (is_tiles_adjacent(tile1, tile2)) {
1890 return TRUE;
1891 }
1892 fc__fallthrough;
1893 case REQ_RANGE_TILE:
1894 return same_pos(tile1, tile2);
1895 case REQ_RANGE_CADJACENT:
1896 return map_distance(tile1, tile2) <= 1;
1897 case REQ_RANGE_CITY:
1898 case REQ_RANGE_TRADE_ROUTE:
1899 case REQ_RANGE_LOCAL:
1900 case REQ_RANGE_CONTINENT:
1901 case REQ_RANGE_PLAYER:
1902 case REQ_RANGE_TEAM:
1903 case REQ_RANGE_ALLIANCE:
1904 case REQ_RANGE_WORLD:
1905 case REQ_RANGE_COUNT:
1906 /* Invalid */
1907 fc_assert(FALSE);
1908 }
1909 return FALSE;
1910}
1911
1912/**********************************************************************/
1915 static inline bool players_in_same_range(const struct player *pplayer1,
1916 const struct player *pplayer2,
1917 enum req_range range)
1918{
1919 switch (range) {
1920 case REQ_RANGE_WORLD:
1921 return TRUE;
1922 case REQ_RANGE_ALLIANCE:
1923 return pplayers_allied(pplayer1, pplayer2);
1924 case REQ_RANGE_TEAM:
1925 return players_on_same_team(pplayer1, pplayer2);
1926 case REQ_RANGE_PLAYER:
1927 return pplayer1 == pplayer2;
1928 case REQ_RANGE_CONTINENT:
1929 case REQ_RANGE_TRADE_ROUTE:
1930 case REQ_RANGE_CITY:
1931 case REQ_RANGE_ADJACENT:
1932 case REQ_RANGE_CADJACENT:
1933 case REQ_RANGE_TILE:
1934 case REQ_RANGE_LOCAL:
1935 case REQ_RANGE_COUNT:
1936 break;
1937 }
1938
1939 fc_assert_msg(FALSE, "Invalid range %d.", range);
1940 return FALSE;
1941}
1942
1943#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
1944{ \
1945 fc_assert_ret_val(req != NULL, TRI_MAYBE); \
1946 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
1947 fc_assert(context != NULL); \
1948}
1949
1950/**********************************************************************/
1957static enum fc_tristate
1958is_none_req_active(const struct civ_map *nmap,
1959 const struct req_context *context,
1960 const struct player *other_player,
1961 const struct requirement *req)
1962{
1963 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NONE);
1964
1965 return TRI_YES;
1966}
1967
1968/**********************************************************************/
1972 static int num_world_buildings_total(const struct impr_type *building)
1973{
1974 if (is_great_wonder(building)) {
1975 return (great_wonder_is_built(building)
1976 || great_wonder_is_destroyed(building) ? 1 : 0);
1977 } else {
1978 log_error("World-ranged requirements are only supported for wonders.");
1979 return 0;
1980 }
1981}
1982
1983/**********************************************************************/
1986 static int num_world_buildings(const struct impr_type *building)
1987{
1988 if (is_great_wonder(building)) {
1989 return (great_wonder_is_built(building) ? 1 : 0);
1990 } else {
1991 log_error("World-ranged requirements are only supported for wonders.");
1992 return 0;
1993 }
1994}
1995
1996/**********************************************************************/
2007 static bool player_has_ever_built(const struct player *pplayer,
2008 const struct impr_type *building)
2009{
2010 if (is_wonder(building)) {
2011 return (wonder_is_built(pplayer, building)
2012 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2013 } else {
2014 log_error("Player-ranged requirements are only supported for wonders.");
2015 return FALSE;
2016 }
2017}
2018
2019/**********************************************************************/
2022 static int num_player_buildings(const struct player *pplayer,
2023 const struct impr_type *building)
2024{
2025 if (is_wonder(building)) {
2026 return (wonder_is_built(pplayer, building) ? 1 : 0);
2027 } else {
2028 log_error("Player-ranged requirements are only supported for wonders.");
2029 return 0;
2030 }
2031}
2032
2033/**********************************************************************/
2036 static int num_continent_buildings(const struct player *pplayer,
2037 int continent,
2038 const struct impr_type *building)
2039{
2040 if (is_wonder(building)) {
2041 const struct city *pcity;
2042
2043 pcity = city_from_wonder(pplayer, building);
2044 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2045 return 1;
2046 }
2047 } else {
2048 log_error("Island-ranged requirements are only supported for wonders.");
2049 }
2050 return 0;
2051}
2052
2053/**********************************************************************/
2060static enum fc_tristate
2061is_building_req_active(const struct civ_map *nmap,
2062 const struct req_context *context,
2063 const struct player *other_player,
2064 const struct requirement *req)
2065{
2066 const struct impr_type *building;
2067
2068 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT);
2069
2070 building = req->source.value.building;
2071
2072 /* Check if it's certain that the building is obsolete given the
2073 * specification we have */
2074 if (improvement_obsolete(context->player, building, context->city)) {
2075 return TRI_NO;
2076 }
2077
2078 if (req->survives) {
2079
2080 /* Check whether condition has ever held, using cached information. */
2081 switch (req->range) {
2082 case REQ_RANGE_WORLD:
2083 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2084 case REQ_RANGE_ALLIANCE:
2085 case REQ_RANGE_TEAM:
2086 if (context->player == NULL) {
2087 return TRI_MAYBE;
2088 }
2089 players_iterate_alive(plr2) {
2090 if (players_in_same_range(context->player, plr2, req->range)
2091 && player_has_ever_built(plr2, building)) {
2092 return TRI_YES;
2093 }
2094 } players_iterate_alive_end;
2095 return TRI_NO;
2096 case REQ_RANGE_PLAYER:
2097 if (context->player == NULL) {
2098 return TRI_MAYBE;
2099 }
2100 return BOOL_TO_TRISTATE(player_has_ever_built(context->player,
2101 building));
2102 case REQ_RANGE_CONTINENT:
2103 case REQ_RANGE_TRADE_ROUTE:
2104 case REQ_RANGE_CITY:
2105 case REQ_RANGE_LOCAL:
2106 case REQ_RANGE_TILE:
2107 case REQ_RANGE_CADJACENT:
2108 case REQ_RANGE_ADJACENT:
2109 /* There is no sources cache for this. */
2110 log_error("Surviving requirements are only supported at "
2111 "World/Alliance/Team/Player ranges.");
2112 return TRI_NO;
2113 case REQ_RANGE_COUNT:
2114 break;
2115 }
2116
2117 } else {
2118
2119 /* Non-surviving requirement. */
2120 switch (req->range) {
2121 case REQ_RANGE_WORLD:
2122 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2123 case REQ_RANGE_ALLIANCE:
2124 case REQ_RANGE_TEAM:
2125 if (context->player == NULL) {
2126 return TRI_MAYBE;
2127 }
2128 players_iterate_alive(plr2) {
2129 if (players_in_same_range(context->player, plr2, req->range)
2130 && num_player_buildings(plr2, building) > 0) {
2131 return TRI_YES;
2132 }
2133 } players_iterate_alive_end;
2134 return TRI_NO;
2135 case REQ_RANGE_PLAYER:
2136 if (context->player == NULL) {
2137 return TRI_MAYBE;
2138 }
2139 return BOOL_TO_TRISTATE(num_player_buildings(context->player,
2140 building)
2141 > 0);
2142 case REQ_RANGE_CONTINENT:
2143 /* At present, "Continent" effects can affect only
2144 * cities and units in cities. */
2145 if (context->player && context->city) {
2146 int continent = tile_continent(context->city->tile);
2147 return BOOL_TO_TRISTATE(num_continent_buildings(context->player,
2148 continent, building)
2149 > 0);
2150 } else {
2151 return TRI_MAYBE;
2152 }
2153 case REQ_RANGE_TRADE_ROUTE:
2154 if (context->city) {
2155 if (city_has_building(context->city, building)) {
2156 return TRI_YES;
2157 } else {
2158 enum fc_tristate ret = TRI_NO;
2159
2160 trade_partners_iterate(context->city, trade_partner) {
2161 if (trade_partner == NULL) {
2162 ret = TRI_MAYBE;
2163 } else if (city_has_building(trade_partner, building)) {
2164 return TRI_YES;
2165 }
2166 } trade_partners_iterate_end;
2167
2168 return ret;
2169 }
2170 } else {
2171 return TRI_MAYBE;
2172 }
2173 case REQ_RANGE_CITY:
2174 if (context->city) {
2175 return BOOL_TO_TRISTATE(city_has_building(context->city, building));
2176 } else {
2177 return TRI_MAYBE;
2178 }
2179 case REQ_RANGE_LOCAL:
2180 if (context->building) {
2181 if (context->building == building) {
2182 return TRI_YES;
2183 } else {
2184 return TRI_NO;
2185 }
2186 } else {
2187 /* TODO: other local targets */
2188 return TRI_MAYBE;
2189 }
2190 case REQ_RANGE_TILE:
2191 if (context->tile) {
2192 const struct city *pcity = tile_city(context->tile);
2193
2194 if (pcity) {
2195 return BOOL_TO_TRISTATE(city_has_building(pcity, building));
2196 } else {
2197 return TRI_NO;
2198 }
2199 } else {
2200 return TRI_MAYBE;
2201 }
2202 case REQ_RANGE_CADJACENT:
2203 case REQ_RANGE_ADJACENT:
2204 case REQ_RANGE_COUNT:
2205 break;
2206 }
2207
2208 }
2209
2210 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2211 return TRI_NO;
2212}
2213
2214/**********************************************************************/
2222static enum fc_tristate
2223is_buildinggenus_req_active(const struct civ_map *nmap,
2224 const struct req_context *context,
2225 const struct player *other_player,
2226 const struct requirement *req)
2227{
2228 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPR_GENUS);
2229
2230 return (context->building ? BOOL_TO_TRISTATE(
2231 context->building->genus
2232 == req->source.value.impr_genus)
2233 : TRI_MAYBE);
2234}
2235
2236/**********************************************************************/
2239 static enum fc_tristate is_buildingflag_in_city(const struct city *pcity,
2240 enum impr_flag_id flag)
2241{
2242 struct player *owner;
2243
2244 if (pcity == NULL) {
2245 return TRI_MAYBE;
2246 }
2247
2248 owner = city_owner(pcity);
2249 city_built_iterate(pcity, impr) {
2250 if (improvement_has_flag(impr, flag)
2251 && !improvement_obsolete(owner, impr, pcity)) {
2252 return TRI_YES;
2253 }
2254 } city_built_iterate_end;
2255
2256 return TRI_NO;
2257}
2258
2259/**********************************************************************/
2267static enum fc_tristate
2268is_buildingflag_req_active(const struct civ_map *nmap,
2269 const struct req_context *context,
2270 const struct player *other_player,
2271 const struct requirement *req)
2272{
2273 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPR_FLAG);
2274
2275 switch (req->range) {
2276 case REQ_RANGE_LOCAL:
2277 return (context->building
2278 ? BOOL_TO_TRISTATE(improvement_has_flag(context->building,
2279 req->source.value.impr_flag))
2280 : TRI_MAYBE);
2281 case REQ_RANGE_CITY:
2282 return is_buildingflag_in_city(context->city, req->source.value.impr_flag);
2283 case REQ_RANGE_TILE:
2284 if (context->tile == NULL) {
2285 return TRI_MAYBE;
2286 }
2287 return is_buildingflag_in_city(tile_city(context->tile),
2288 req->source.value.impr_flag);
2289 case REQ_RANGE_CADJACENT:
2290 case REQ_RANGE_ADJACENT:
2291 case REQ_RANGE_TRADE_ROUTE:
2292 case REQ_RANGE_CONTINENT:
2293 case REQ_RANGE_PLAYER:
2294 case REQ_RANGE_ALLIANCE:
2295 case REQ_RANGE_TEAM:
2296 case REQ_RANGE_WORLD:
2297 case REQ_RANGE_COUNT:
2298 break;
2299 }
2300
2301 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2302
2303 return TRI_MAYBE;
2304}
2305
2306/**********************************************************************/
2314static enum fc_tristate
2315is_plr_flag_req_active(const struct civ_map *nmap,
2316 const struct req_context *context,
2317 const struct player *other_player,
2318 const struct requirement *req)
2319{
2320 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_PLAYER_FLAG);
2321
2322 switch (req->range) {
2323 case REQ_RANGE_PLAYER:
2324 return (context->player != NULL
2325 ? BOOL_TO_TRISTATE(player_has_flag(context->player,
2326 req->source.value.plr_flag))
2327 : TRI_MAYBE);
2328 case REQ_RANGE_LOCAL:
2329 case REQ_RANGE_CITY:
2330 case REQ_RANGE_TILE:
2331 case REQ_RANGE_CADJACENT:
2332 case REQ_RANGE_ADJACENT:
2333 case REQ_RANGE_TRADE_ROUTE:
2334 case REQ_RANGE_CONTINENT:
2335 case REQ_RANGE_ALLIANCE:
2336 case REQ_RANGE_TEAM:
2337 case REQ_RANGE_WORLD:
2338 case REQ_RANGE_COUNT:
2339 break;
2340 }
2341
2342 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2343
2344 return TRI_MAYBE;
2345}
2346
2347/**********************************************************************/
2355static enum fc_tristate
2356is_plr_state_req_active(const struct civ_map *nmap,
2357 const struct req_context *context,
2358 const struct player *other_player,
2359 const struct requirement *req)
2360{
2361 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_PLAYER_STATE);
2362
2363 switch (req->range) {
2364 case REQ_RANGE_PLAYER:
2365 return (context->player != NULL
2366 ? BOOL_TO_TRISTATE(player_has_state(context->player,
2367 req->source.value.plrstate))
2368 : TRI_MAYBE);
2369 case REQ_RANGE_LOCAL:
2370 case REQ_RANGE_CITY:
2371 case REQ_RANGE_TILE:
2372 case REQ_RANGE_CADJACENT:
2373 case REQ_RANGE_ADJACENT:
2374 case REQ_RANGE_TRADE_ROUTE:
2375 case REQ_RANGE_CONTINENT:
2376 case REQ_RANGE_ALLIANCE:
2377 case REQ_RANGE_TEAM:
2378 case REQ_RANGE_WORLD:
2379 case REQ_RANGE_COUNT:
2380 break;
2381 }
2382
2383 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2384
2385 return TRI_MAYBE;
2386}
2387
2388/**********************************************************************/
2395static enum fc_tristate
2396is_tech_req_active(const struct civ_map *nmap,
2397 const struct req_context *context,
2398 const struct player *other_player,
2399 const struct requirement *req)
2400{
2401 Tech_type_id tech;
2402
2403 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ADVANCE);
2404
2405 tech = advance_number(req->source.value.advance);
2406
2407 if (req->survives) {
2408 fc_assert(req->range == REQ_RANGE_WORLD);
2409 return BOOL_TO_TRISTATE(game.info.global_advances[tech]);
2410 }
2411
2412 /* Not a 'surviving' requirement. */
2413 switch (req->range) {
2414 case REQ_RANGE_PLAYER:
2415 if (NULL != context->player) {
2416 return BOOL_TO_TRISTATE(TECH_KNOWN == research_invention_state
2417 (research_get(context->player), tech));
2418 } else {
2419 return TRI_MAYBE;
2420 }
2421 case REQ_RANGE_TEAM:
2422 case REQ_RANGE_ALLIANCE:
2423 case REQ_RANGE_WORLD:
2424 if (NULL == context->player) {
2425 return TRI_MAYBE;
2426 }
2427 players_iterate_alive(plr2) {
2428 if (players_in_same_range(context->player, plr2, req->range)) {
2429 if (research_invention_state(research_get(plr2), tech)
2430 == TECH_KNOWN) {
2431 return TRI_YES;
2432 }
2433 }
2434 } players_iterate_alive_end;
2435
2436 return TRI_NO;
2437 case REQ_RANGE_LOCAL:
2438 case REQ_RANGE_TILE:
2439 case REQ_RANGE_CADJACENT:
2440 case REQ_RANGE_ADJACENT:
2441 case REQ_RANGE_CITY:
2442 case REQ_RANGE_TRADE_ROUTE:
2443 case REQ_RANGE_CONTINENT:
2444 case REQ_RANGE_COUNT:
2445 break;
2446 }
2447
2448 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2449
2450 return TRI_MAYBE;
2451}
2452
2453/**********************************************************************/
2460static enum fc_tristate
2461is_techflag_req_active(const struct civ_map *nmap,
2462 const struct req_context *context,
2463 const struct player *other_player,
2464 const struct requirement *req)
2465{
2466 enum tech_flag_id techflag;
2467
2468 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TECHFLAG);
2469
2470 techflag = req->source.value.techflag;
2471
2472 switch (req->range) {
2473 case REQ_RANGE_PLAYER:
2474 if (NULL != context->player) {
2475 return BOOL_TO_TRISTATE(player_knows_techs_with_flag(context->player,
2476 techflag));
2477 } else {
2478 return TRI_MAYBE;
2479 }
2480 break;
2481 case REQ_RANGE_TEAM:
2482 case REQ_RANGE_ALLIANCE:
2483 if (NULL == context->player) {
2484 return TRI_MAYBE;
2485 }
2486 players_iterate_alive(plr2) {
2487 if (players_in_same_range(context->player, plr2, req->range)
2488 && player_knows_techs_with_flag(plr2, techflag)) {
2489 return TRI_YES;
2490 }
2491 } players_iterate_alive_end;
2492 return TRI_NO;
2493 case REQ_RANGE_WORLD:
2494 players_iterate(pplayer) {
2495 if (player_knows_techs_with_flag(pplayer, techflag)) {
2496 return TRI_YES;
2497 }
2498 } players_iterate_end;
2499
2500 return TRI_NO;
2501 case REQ_RANGE_LOCAL:
2502 case REQ_RANGE_TILE:
2503 case REQ_RANGE_CADJACENT:
2504 case REQ_RANGE_ADJACENT:
2505 case REQ_RANGE_CITY:
2506 case REQ_RANGE_TRADE_ROUTE:
2507 case REQ_RANGE_CONTINENT:
2508 case REQ_RANGE_COUNT:
2509 break;
2510 }
2511
2512 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2513
2514 return TRI_MAYBE;
2515}
2516
2517/**********************************************************************/
2524static enum fc_tristate
2525is_minculture_req_active(const struct civ_map *nmap,
2526 const struct req_context *context,
2527 const struct player *other_player,
2528 const struct requirement *req)
2529{
2530 int minculture;
2531
2532 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINCULTURE);
2533
2534 minculture = req->source.value.minculture;
2535
2536 switch (req->range) {
2537 case REQ_RANGE_CITY:
2538 if (!context->city) {
2539 return TRI_MAYBE;
2540 }
2541 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2542 case REQ_RANGE_TRADE_ROUTE:
2543 if (!context->city) {
2544 return TRI_MAYBE;
2545 }
2546 if (city_culture(context->city) >= minculture) {
2547 return TRI_YES;
2548 } else {
2549 enum fc_tristate ret = TRI_NO;
2550
2551 trade_partners_iterate(context->city, trade_partner) {
2552 if (trade_partner == NULL) {
2553 ret = TRI_MAYBE;
2554 } else if (city_culture(trade_partner) >= minculture) {
2555 return TRI_YES;
2556 }
2557 } trade_partners_iterate_end;
2558
2559 return ret;
2560 }
2561 case REQ_RANGE_PLAYER:
2562 case REQ_RANGE_TEAM:
2563 case REQ_RANGE_ALLIANCE:
2564 case REQ_RANGE_WORLD:
2565 if (NULL == context->player) {
2566 return TRI_MAYBE;
2567 }
2568 players_iterate_alive(plr2) {
2569 if (players_in_same_range(context->player, plr2, req->range)) {
2570 if (player_culture(plr2) >= minculture) {
2571 return TRI_YES;
2572 }
2573 }
2574 } players_iterate_alive_end;
2575 return TRI_NO;
2576 case REQ_RANGE_LOCAL:
2577 case REQ_RANGE_TILE:
2578 case REQ_RANGE_CADJACENT:
2579 case REQ_RANGE_ADJACENT:
2580 case REQ_RANGE_CONTINENT:
2581 case REQ_RANGE_COUNT:
2582 break;
2583 }
2584
2585 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2586
2587 return TRI_MAYBE;
2588}
2589
2590/**********************************************************************/
2598static enum fc_tristate
2599is_minforeignpct_req_active(const struct civ_map *nmap,
2600 const struct req_context *context,
2601 const struct player *other_player,
2602 const struct requirement *req)
2603{
2604 int min_foreign_pct, foreign_pct;
2605
2606 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINFOREIGNPCT);
2607
2608 min_foreign_pct = req->source.value.minforeignpct;
2609
2610 switch (req->range) {
2611 case REQ_RANGE_CITY:
2612 if (!context->city) {
2613 return TRI_MAYBE;
2614 }
2615 foreign_pct = citizens_nation_foreign(context->city) * 100
2616 / city_size_get(context->city);
2617 return BOOL_TO_TRISTATE(foreign_pct >= min_foreign_pct);
2618 case REQ_RANGE_TRADE_ROUTE:
2619 if (!context->city) {
2620 return TRI_MAYBE;
2621 }
2622 foreign_pct = citizens_nation_foreign(context->city) * 100
2623 / city_size_get(context->city);
2624 if (foreign_pct >= min_foreign_pct) {
2625 return TRI_YES;
2626 } else {
2627 enum fc_tristate ret = TRI_NO;
2628
2629 trade_partners_iterate(context->city, trade_partner) {
2630 if (trade_partner == NULL) {
2631 ret = TRI_MAYBE;
2632 } else {
2633 foreign_pct = citizens_nation_foreign(trade_partner) * 100
2634 / city_size_get(trade_partner);
2635 if (foreign_pct >= min_foreign_pct) {
2636 return TRI_YES;
2637 }
2638 }
2639 } trade_partners_iterate_end;
2640
2641 return ret;
2642 }
2643 case REQ_RANGE_PLAYER:
2644 case REQ_RANGE_TEAM:
2645 case REQ_RANGE_ALLIANCE:
2646 case REQ_RANGE_WORLD:
2647 case REQ_RANGE_LOCAL:
2648 case REQ_RANGE_TILE:
2649 case REQ_RANGE_CADJACENT:
2650 case REQ_RANGE_ADJACENT:
2651 case REQ_RANGE_CONTINENT:
2652 case REQ_RANGE_COUNT:
2653 break;
2654 }
2655
2656 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2657
2658 return TRI_MAYBE;
2659}
2660
2661/**********************************************************************/
2669static enum fc_tristate
2670is_maxunitsontile_req_active(const struct civ_map *nmap,
2671 const struct req_context *context,
2672 const struct player *other_player,
2673 const struct requirement *req)
2674{
2675 int max_units;
2676
2677 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MAXTILEUNITS);
2678
2679 max_units = req->source.value.max_tile_units;
2680
2681 /* TODO: if can't see V_INVIS -> TRI_MAYBE */
2682 switch (req->range) {
2683 case REQ_RANGE_TILE:
2684 if (!context->tile) {
2685 return TRI_MAYBE;
2686 }
2687 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
2688 case REQ_RANGE_CADJACENT:
2689 if (!context->tile) {
2690 return TRI_MAYBE;
2691 }
2692 if (unit_list_size(context->tile->units) <= max_units) {
2693 return TRI_YES;
2694 }
2695 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
2696 if (unit_list_size(adjc_tile->units) <= max_units) {
2697 return TRI_YES;
2698 }
2699 } cardinal_adjc_iterate_end;
2700 return TRI_NO;
2701 case REQ_RANGE_ADJACENT:
2702 if (!context->tile) {
2703 return TRI_MAYBE;
2704 }
2705 if (unit_list_size(context->tile->units) <= max_units) {
2706 return TRI_YES;
2707 }
2708 adjc_iterate(nmap, context->tile, adjc_tile) {
2709 if (unit_list_size(adjc_tile->units) <= max_units) {
2710 return TRI_YES;
2711 }
2712 } adjc_iterate_end;
2713 return TRI_NO;
2714 case REQ_RANGE_CITY:
2715 case REQ_RANGE_TRADE_ROUTE:
2716 case REQ_RANGE_CONTINENT:
2717 case REQ_RANGE_PLAYER:
2718 case REQ_RANGE_TEAM:
2719 case REQ_RANGE_ALLIANCE:
2720 case REQ_RANGE_WORLD:
2721 case REQ_RANGE_LOCAL:
2722 case REQ_RANGE_COUNT:
2723 break;
2724 }
2725
2726 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2727
2728 return TRI_MAYBE;
2729}
2730
2731/**********************************************************************/
2738static enum fc_tristate
2739is_extra_req_active(const struct civ_map *nmap,
2740 const struct req_context *context,
2741 const struct player *other_player,
2742 const struct requirement *req)
2743{
2744 const struct extra_type *pextra;
2745 enum fc_tristate ret;
2746
2747 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_EXTRA);
2748
2749 pextra = req->source.value.extra;
2750
2751 switch (req->range) {
2752 case REQ_RANGE_LOCAL:
2753 if (!context->extra) {
2754 return TRI_MAYBE;
2755 }
2756 return BOOL_TO_TRISTATE(context->extra == pextra);
2757 case REQ_RANGE_TILE:
2758 /* The requirement is filled if the tile has extra of requested type. */
2759 if (!context->tile) {
2760 return TRI_MAYBE;
2761 }
2762 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
2763 case REQ_RANGE_CADJACENT:
2764 if (!context->tile) {
2765 return TRI_MAYBE;
2766 }
2767 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2768 || is_extra_card_near(nmap, context->tile, pextra));
2769 case REQ_RANGE_ADJACENT:
2770 if (!context->tile) {
2771 return TRI_MAYBE;
2772 }
2773 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2774 || is_extra_near_tile(nmap, context->tile, pextra));
2775 case REQ_RANGE_CITY:
2776 if (!context->city) {
2777 return TRI_MAYBE;
2778 }
2779 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
2780 city_tile(context->city), ptile) {
2781 if (tile_has_extra(ptile, pextra)) {
2782 return TRI_YES;
2783 }
2784 } city_tile_iterate_end;
2785
2786 return TRI_NO;
2787
2788 case REQ_RANGE_TRADE_ROUTE:
2789 if (!context->city) {
2790 return TRI_MAYBE;
2791 }
2792 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
2793 city_tile(context->city), ptile) {
2794 if (tile_has_extra(ptile, pextra)) {
2795 return TRI_YES;
2796 }
2797 } city_tile_iterate_end;
2798
2799 ret = TRI_NO;
2800 trade_partners_iterate(context->city, trade_partner) {
2801 if (trade_partner == NULL) {
2802 ret = TRI_MAYBE;
2803 } else {
2804 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
2805 city_tile(trade_partner), ptile) {
2806 if (tile_has_extra(ptile, pextra)) {
2807 return TRI_YES;
2808 }
2809 } city_tile_iterate_end;
2810 }
2811 } trade_partners_iterate_end;
2812
2813 return ret;
2814
2815 case REQ_RANGE_CONTINENT:
2816 case REQ_RANGE_PLAYER:
2817 case REQ_RANGE_TEAM:
2818 case REQ_RANGE_ALLIANCE:
2819 case REQ_RANGE_WORLD:
2820 case REQ_RANGE_COUNT:
2821 break;
2822 }
2823
2824 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2825
2826 return TRI_MAYBE;
2827}
2828
2829/**********************************************************************/
2836static enum fc_tristate
2837is_good_req_active(const struct civ_map *nmap,
2838 const struct req_context *context,
2839 const struct player *other_player,
2840 const struct requirement *req)
2841{
2842 const struct goods_type *pgood;
2843
2844 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_GOOD);
2845
2846 pgood = req->source.value.good;
2847
2848 switch (req->range) {
2849 case REQ_RANGE_LOCAL:
2850 case REQ_RANGE_CITY:
2851 /* The requirement is filled if the city imports good of requested type. */
2852 if (!context->city) {
2853 return TRI_MAYBE;
2854 }
2855 return BOOL_TO_TRISTATE(city_receives_goods(context->city, pgood)
2856 || (goods_has_flag(pgood, GF_SELF_PROVIDED)
2857 && goods_can_be_provided(context->city, pgood, NULL)));
2858 case REQ_RANGE_TILE:
2859 case REQ_RANGE_CADJACENT:
2860 case REQ_RANGE_ADJACENT:
2861 case REQ_RANGE_TRADE_ROUTE:
2862 case REQ_RANGE_CONTINENT:
2863 case REQ_RANGE_PLAYER:
2864 case REQ_RANGE_TEAM:
2865 case REQ_RANGE_ALLIANCE:
2866 case REQ_RANGE_WORLD:
2867 case REQ_RANGE_COUNT:
2868 break;
2869 }
2870
2871 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2872
2873 return TRI_MAYBE;
2874}
2875
2876/**********************************************************************/
2883static enum fc_tristate
2884is_action_req_active(const struct civ_map *nmap,
2885 const struct req_context *context,
2886 const struct player *other_player,
2887 const struct requirement *req)
2888{
2889 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ACTION);
2890
2891 if (context->action) {
2892 return BOOL_TO_TRISTATE(action_number(context->action)
2893 == action_number(req->source.value.action));
2894 }
2895
2896 if (context->unit != nullptr && context->unit->action != ACTION_NONE) {
2897 log_normal("Unit action %s", action_id_rule_name(context->unit->action));
2898 return BOOL_TO_TRISTATE(context->unit->action
2899 == action_number(req->source.value.action));
2900 }
2901
2902 return TRI_NO;
2903}
2904
2905/**********************************************************************/
2913static enum fc_tristate
2914is_outputtype_req_active(const struct civ_map *nmap,
2915 const struct req_context *context,
2916 const struct player *other_player,
2917 const struct requirement *req)
2918{
2919 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_OTYPE);
2920
2921 return BOOL_TO_TRISTATE(context->output
2922 && context->output->index
2923 == req->source.value.outputtype);
2924}
2925
2926/**********************************************************************/
2933static enum fc_tristate
2934is_specialist_req_active(const struct civ_map *nmap,
2935 const struct req_context *context,
2936 const struct player *other_player,
2937 const struct requirement *req)
2938{
2939 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_SPECIALIST);
2940
2941 return BOOL_TO_TRISTATE(context->specialist
2942 && context->specialist
2943 == req->source.value.specialist);
2944}
2945
2946/**********************************************************************/
2953static enum fc_tristate
2954is_terrain_req_active(const struct civ_map *nmap,
2955 const struct req_context *context,
2956 const struct player *other_player,
2957 const struct requirement *req)
2958{
2959 const struct terrain *pterrain;
2960
2961 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRAIN);
2962
2963 pterrain = req->source.value.terrain;
2964
2965 switch (req->range) {
2966 case REQ_RANGE_TILE:
2967 /* The requirement is filled if the tile has the terrain. */
2968 if (!context->tile) {
2969 return TRI_MAYBE;
2970 }
2971 return pterrain && tile_terrain(context->tile) == pterrain;
2972 case REQ_RANGE_CADJACENT:
2973 if (!context->tile) {
2974 return TRI_MAYBE;
2975 }
2976 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
2977 case REQ_RANGE_ADJACENT:
2978 if (!context->tile) {
2979 return TRI_MAYBE;
2980 }
2981 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
2982 case REQ_RANGE_CITY:
2983 if (!context->city) {
2984 return TRI_MAYBE;
2985 }
2986 if (pterrain != NULL) {
2987 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
2988 city_tile(context->city), ptile) {
2989 if (tile_terrain(ptile) == pterrain) {
2990 return TRI_YES;
2991 }
2992 } city_tile_iterate_end;
2993 }
2994 return TRI_NO;
2995 case REQ_RANGE_TRADE_ROUTE:
2996 if (!context->city) {
2997 return TRI_MAYBE;
2998 }
2999 if (pterrain != NULL) {
3000 enum fc_tristate ret;
3001
3002 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3003 city_tile(context->city), ptile) {
3004 if (tile_terrain(ptile) == pterrain) {
3005 return TRI_YES;
3006 }
3007 } city_tile_iterate_end;
3008
3009 ret = TRI_NO;
3010 trade_partners_iterate(context->city, trade_partner) {
3011 if (trade_partner == NULL) {
3012 ret = TRI_MAYBE;
3013 } else {
3014 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3015 city_tile(trade_partner), ptile) {
3016 if (tile_terrain(ptile) == pterrain) {
3017 return TRI_YES;
3018 }
3019 } city_tile_iterate_end;
3020 }
3021 } trade_partners_iterate_end;
3022
3023 return ret;
3024 }
3025
3026 return TRI_MAYBE;
3027 case REQ_RANGE_CONTINENT:
3028 case REQ_RANGE_PLAYER:
3029 case REQ_RANGE_TEAM:
3030 case REQ_RANGE_ALLIANCE:
3031 case REQ_RANGE_WORLD:
3032 case REQ_RANGE_LOCAL:
3033 case REQ_RANGE_COUNT:
3034 break;
3035 }
3036
3037 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3038
3039 return TRI_MAYBE;
3040}
3041
3042/**********************************************************************/
3050static enum fc_tristate
3051is_terrainclass_req_active(const struct civ_map *nmap,
3052 const struct req_context *context,
3053 const struct player *other_player,
3054 const struct requirement *req)
3055{
3056 enum terrain_class pclass;
3057 enum fc_tristate ret;
3058
3059 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRAINCLASS);
3060
3061 pclass = req->source.value.terrainclass;
3062
3063 switch (req->range) {
3064 case REQ_RANGE_TILE:
3065 /* The requirement is filled if the tile has the terrain of correct class. */
3066 if (!context->tile) {
3067 return TRI_MAYBE;
3068 }
3069 return BOOL_TO_TRISTATE(terrain_type_terrain_class(tile_terrain(context->tile)) == pclass);
3070 case REQ_RANGE_CADJACENT:
3071 if (!context->tile) {
3072 return TRI_MAYBE;
3073 }
3074 return BOOL_TO_TRISTATE(terrain_type_terrain_class(tile_terrain(context->tile)) == pclass
3075 || is_terrain_class_card_near(nmap, context->tile, pclass));
3076 case REQ_RANGE_ADJACENT:
3077 if (!context->tile) {
3078 return TRI_MAYBE;
3079 }
3080 return BOOL_TO_TRISTATE(terrain_type_terrain_class(tile_terrain(context->tile)) == pclass
3081 || is_terrain_class_near_tile(nmap, context->tile, pclass));
3082 case REQ_RANGE_CITY:
3083 if (!context->city) {
3084 return TRI_MAYBE;
3085 }
3086 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3087 city_tile(context->city), ptile) {
3088 const struct terrain *pterrain = tile_terrain(ptile);
3089
3090 if (pterrain != T_UNKNOWN
3091 && terrain_type_terrain_class(pterrain) == pclass) {
3092 return TRI_YES;
3093 }
3094 } city_tile_iterate_end;
3095
3096 return TRI_NO;
3097 case REQ_RANGE_TRADE_ROUTE:
3098 if (!context->city) {
3099 return TRI_MAYBE;
3100 }
3101 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3102 city_tile(context->city), ptile) {
3103 const struct terrain *pterrain = tile_terrain(ptile);
3104
3105 if (pterrain != T_UNKNOWN
3106 && terrain_type_terrain_class(pterrain) == pclass) {
3107 return TRI_YES;
3108 }
3109 } city_tile_iterate_end;
3110
3111 ret = TRI_NO;
3112 trade_partners_iterate(context->city, trade_partner) {
3113 if (trade_partner == NULL) {
3114 ret = TRI_MAYBE;
3115 } else {
3116 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3117 city_tile(trade_partner), ptile) {
3118 const struct terrain *pterrain = tile_terrain(ptile);
3119
3120 if (pterrain != T_UNKNOWN
3121 && terrain_type_terrain_class(pterrain) == pclass) {
3122 return TRI_YES;
3123 }
3124 } city_tile_iterate_end;
3125 }
3126 } trade_partners_iterate_end;
3127
3128 return ret;
3129 case REQ_RANGE_CONTINENT:
3130 case REQ_RANGE_PLAYER:
3131 case REQ_RANGE_TEAM:
3132 case REQ_RANGE_ALLIANCE:
3133 case REQ_RANGE_WORLD:
3134 case REQ_RANGE_LOCAL:
3135 case REQ_RANGE_COUNT:
3136 break;
3137 }
3138
3139 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3140
3141 return TRI_MAYBE;
3142}
3143
3144/**********************************************************************/
3152static enum fc_tristate
3153is_terrainflag_req_active(const struct civ_map *nmap,
3154 const struct req_context *context,
3155 const struct player *other_player,
3156 const struct requirement *req)
3157{
3158 enum terrain_flag_id terrflag;
3159 enum fc_tristate ret;
3160
3161 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRFLAG);
3162
3163 terrflag = req->source.value.terrainflag;
3164
3165 switch (req->range) {
3166 case REQ_RANGE_TILE:
3167 /* The requirement is fulfilled if the tile has a terrain with
3168 * correct flag. */
3169 if (!context->tile) {
3170 return TRI_MAYBE;
3171 }
3172 return BOOL_TO_TRISTATE(terrain_has_flag(tile_terrain(context->tile),
3173 terrflag));
3174 case REQ_RANGE_CADJACENT:
3175 if (!context->tile) {
3176 return TRI_MAYBE;
3177 }
3178 return BOOL_TO_TRISTATE(terrain_has_flag(tile_terrain(context->tile),
3179 terrflag)
3180 || is_terrain_flag_card_near(nmap, context->tile,
3181 terrflag));
3182 case REQ_RANGE_ADJACENT:
3183 if (!context->tile) {
3184 return TRI_MAYBE;
3185 }
3186 return BOOL_TO_TRISTATE(terrain_has_flag(tile_terrain(context->tile),
3187 terrflag)
3188 || is_terrain_flag_near_tile(nmap, context->tile,
3189 terrflag));
3190 case REQ_RANGE_CITY:
3191 if (!context->city) {
3192 return TRI_MAYBE;
3193 }
3194 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3195 city_tile(context->city), ptile) {
3196 const struct terrain *pterrain = tile_terrain(ptile);
3197
3198 if (pterrain != T_UNKNOWN
3199 && terrain_has_flag(pterrain, terrflag)) {
3200 return TRI_YES;
3201 }
3202 } city_tile_iterate_end;
3203
3204 return TRI_NO;
3205 case REQ_RANGE_TRADE_ROUTE:
3206 if (!context->city) {
3207 return TRI_MAYBE;
3208 }
3209 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3210 city_tile(context->city), ptile) {
3211 const struct terrain *pterrain = tile_terrain(ptile);
3212
3213 if (pterrain != T_UNKNOWN
3214 && terrain_has_flag(pterrain, terrflag)) {
3215 return TRI_YES;
3216 }
3217 } city_tile_iterate_end;
3218
3219 ret = TRI_NO;
3220 trade_partners_iterate(context->city, trade_partner) {
3221 if (trade_partner == NULL) {
3222 ret = TRI_MAYBE;
3223 } else {
3224 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3225 city_tile(trade_partner), ptile) {
3226 const struct terrain *pterrain = tile_terrain(ptile);
3227
3228 if (pterrain != T_UNKNOWN
3229 && terrain_has_flag(pterrain, terrflag)) {
3230 return TRI_YES;
3231 }
3232 } city_tile_iterate_end;
3233 }
3234 } trade_partners_iterate_end;
3235
3236 return ret;
3237 case REQ_RANGE_CONTINENT:
3238 case REQ_RANGE_PLAYER:
3239 case REQ_RANGE_TEAM:
3240 case REQ_RANGE_ALLIANCE:
3241 case REQ_RANGE_WORLD:
3242 case REQ_RANGE_LOCAL:
3243 case REQ_RANGE_COUNT:
3244 break;
3245 }
3246
3247 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3248
3249 return TRI_MAYBE;
3250}
3251
3252/**********************************************************************/
3259static enum fc_tristate
3260is_roadflag_req_active(const struct civ_map *nmap,
3261 const struct req_context *context,
3262 const struct player *other_player,
3263 const struct requirement *req)
3264{
3265 enum road_flag_id roadflag;
3266 enum fc_tristate ret;
3267
3268 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ROADFLAG);
3269
3270 roadflag = req->source.value.roadflag;
3271
3272 switch (req->range) {
3273 case REQ_RANGE_LOCAL:
3274 {
3275 if (!context->extra) {
3276 return TRI_MAYBE;
3277 }
3278 struct road_type *r = extra_road_get(context->extra);
3279
3280 return BOOL_TO_TRISTATE(
3281 r && road_has_flag(r, roadflag)
3282 );
3283 }
3284 case REQ_RANGE_TILE:
3285 /* The requirement is filled if the tile has a road with correct flag. */
3286 if (!context->tile) {
3287 return TRI_MAYBE;
3288 }
3289 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3290 case REQ_RANGE_CADJACENT:
3291 if (!context->tile) {
3292 return TRI_MAYBE;
3293 }
3294 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3295 || is_road_flag_card_near(nmap, context->tile,
3296 roadflag));
3297 case REQ_RANGE_ADJACENT:
3298 if (!context->tile) {
3299 return TRI_MAYBE;
3300 }
3301 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3302 || is_road_flag_near_tile(nmap, context->tile,
3303 roadflag));
3304 case REQ_RANGE_CITY:
3305 if (!context->city) {
3306 return TRI_MAYBE;
3307 }
3308 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3309 city_tile(context->city), ptile) {
3310 if (tile_has_road_flag(ptile, roadflag)) {
3311 return TRI_YES;
3312 }
3313 } city_tile_iterate_end;
3314
3315 return TRI_NO;
3316 case REQ_RANGE_TRADE_ROUTE:
3317 if (!context->city) {
3318 return TRI_MAYBE;
3319 }
3320 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3321 city_tile(context->city), ptile) {
3322 if (tile_has_road_flag(ptile, roadflag)) {
3323 return TRI_YES;
3324 }
3325 } city_tile_iterate_end;
3326
3327 ret = TRI_NO;
3328 trade_partners_iterate(context->city, trade_partner) {
3329 if (trade_partner == NULL) {
3330 ret = TRI_MAYBE;
3331 } else {
3332 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3333 city_tile(trade_partner), ptile) {
3334 if (tile_has_road_flag(ptile, roadflag)) {
3335 return TRI_YES;
3336 }
3337 } city_tile_iterate_end;
3338 }
3339 } trade_partners_iterate_end;
3340
3341 return ret;
3342 case REQ_RANGE_CONTINENT:
3343 case REQ_RANGE_PLAYER:
3344 case REQ_RANGE_TEAM:
3345 case REQ_RANGE_ALLIANCE:
3346 case REQ_RANGE_WORLD:
3347 case REQ_RANGE_COUNT:
3348 break;
3349 }
3350
3351 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3352
3353 return TRI_MAYBE;
3354}
3355
3356/**********************************************************************/
3363static enum fc_tristate
3364is_extraflag_req_active(const struct civ_map *nmap,
3365 const struct req_context *context,
3366 const struct player *other_player,
3367 const struct requirement *req)
3368{
3369 enum extra_flag_id extraflag;
3370 enum fc_tristate ret;
3371
3372 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_EXTRAFLAG);
3373
3374 extraflag = req->source.value.extraflag;
3375
3376 switch (req->range) {
3377 case REQ_RANGE_LOCAL:
3378 if (!context->extra) {
3379 return TRI_MAYBE;
3380 }
3381 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3382 case REQ_RANGE_TILE:
3383 /* The requirement is filled if the tile has an extra with correct flag. */
3384 if (!context->tile) {
3385 return TRI_MAYBE;
3386 }
3387 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3388 case REQ_RANGE_CADJACENT:
3389 if (!context->tile) {
3390 return TRI_MAYBE;
3391 }
3392 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3393 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3394 case REQ_RANGE_ADJACENT:
3395 if (!context->tile) {
3396 return TRI_MAYBE;
3397 }
3398 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3399 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3400 case REQ_RANGE_CITY:
3401 if (!context->city) {
3402 return TRI_MAYBE;
3403 }
3404 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3405 city_tile(context->city), ptile) {
3406 if (tile_has_extra_flag(ptile, extraflag)) {
3407 return TRI_YES;
3408 }
3409 } city_tile_iterate_end;
3410
3411 return TRI_NO;
3412 case REQ_RANGE_TRADE_ROUTE:
3413 if (!context->city) {
3414 return TRI_MAYBE;
3415 }
3416 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3417 city_tile(context->city), ptile) {
3418 if (tile_has_extra_flag(ptile, extraflag)) {
3419 return TRI_YES;
3420 }
3421 } city_tile_iterate_end;
3422
3423 ret = TRI_NO;
3424 trade_partners_iterate(context->city, trade_partner) {
3425 if (trade_partner == NULL) {
3426 ret = TRI_MAYBE;
3427 } else {
3428 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3429 city_tile(trade_partner), ptile) {
3430 if (tile_has_extra_flag(ptile, extraflag)) {
3431 return TRI_YES;
3432 }
3433 } city_tile_iterate_end;
3434 }
3435 } trade_partners_iterate_end;
3436
3437 return ret;
3438 case REQ_RANGE_CONTINENT:
3439 case REQ_RANGE_PLAYER:
3440 case REQ_RANGE_TEAM:
3441 case REQ_RANGE_ALLIANCE:
3442 case REQ_RANGE_WORLD:
3443 case REQ_RANGE_COUNT:
3444 break;
3445 }
3446
3447 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3448
3449 return TRI_MAYBE;
3450}
3451
3452/**********************************************************************/
3460static enum fc_tristate
3461is_terrainalter_req_active(const struct civ_map *nmap,
3462 const struct req_context *context,
3463 const struct player *other_player,
3464 const struct requirement *req)
3465{
3466 enum terrain_alteration alteration;
3467
3468 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRAINALTER);
3469
3470 alteration = req->source.value.terrainalter;
3471
3472 if (!context->tile) {
3473 return TRI_MAYBE;
3474 }
3475
3476 switch (req->range) {
3477 case REQ_RANGE_TILE:
3478 return BOOL_TO_TRISTATE(terrain_can_support_alteration(
3479 tile_terrain(context->tile), alteration));
3480 case REQ_RANGE_CADJACENT:
3481 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
3482 case REQ_RANGE_CITY:
3483 case REQ_RANGE_TRADE_ROUTE:
3484 case REQ_RANGE_CONTINENT:
3485 case REQ_RANGE_PLAYER:
3486 case REQ_RANGE_TEAM:
3487 case REQ_RANGE_ALLIANCE:
3488 case REQ_RANGE_WORLD:
3489 case REQ_RANGE_LOCAL:
3490 case REQ_RANGE_COUNT:
3491 break;
3492 }
3493
3494 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3495
3496 return TRI_MAYBE;
3497}
3498
3499/**********************************************************************/
3506static enum fc_tristate
3507is_gov_req_active(const struct civ_map *nmap,
3508 const struct req_context *context,
3509 const struct player *other_player,
3510 const struct requirement *req)
3511{
3512 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_GOVERNMENT);
3513
3514 if (context->player == NULL) {
3515 return TRI_MAYBE;
3516 } else {
3517 return BOOL_TO_TRISTATE(government_of_player(context->player)
3518 == req->source.value.govern);
3519 }
3520}
3521
3522/**********************************************************************/
3529static enum fc_tristate
3530is_style_req_active(const struct civ_map *nmap,
3531 const struct req_context *context,
3532 const struct player *other_player,
3533 const struct requirement *req)
3534{
3535 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_STYLE);
3536
3537 if (context->player == NULL) {
3538 return TRI_MAYBE;
3539 } else {
3540 return BOOL_TO_TRISTATE(context->player->style
3541 == req->source.value.style);
3542 }
3543}
3544
3545/**********************************************************************/
3552static enum fc_tristate
3553is_mintechs_req_active(const struct civ_map *nmap,
3554 const struct req_context *context,
3555 const struct player *other_player,
3556 const struct requirement *req)
3557{
3558 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINTECHS);
3559
3560 switch (req->range) {
3561 case REQ_RANGE_WORLD:
3562 /* "None" does not count */
3563 return ((game.info.global_advance_count - 1)
3564 >= req->source.value.min_techs);
3565 case REQ_RANGE_PLAYER:
3566 if (context->player == NULL) {
3567 return TRI_MAYBE;
3568 } else {
3569 /* "None" does not count */
3570 return BOOL_TO_TRISTATE(
3571 (research_get(context->player)->techs_researched - 1)
3572 >= req->source.value.min_techs
3573 );
3574 }
3575 default:
3576 return TRI_MAYBE;
3577 }
3578}
3579
3580/**********************************************************************/
3587static enum fc_tristate
3588is_mincities_req_active(const struct civ_map *nmap,
3589 const struct req_context *context,
3590 const struct player *other_player,
3591 const struct requirement *req)
3592{
3593 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINCITIES);
3594
3595 switch (req->range) {
3596 case REQ_RANGE_PLAYER:
3597 if (context->player == NULL) {
3598 return TRI_MAYBE;
3599 } else {
3600 /* "None" does not count */
3601 return BOOL_TO_TRISTATE(
3602 city_list_size(context->player->cities)
3603 >= req->source.value.min_cities
3604 );
3605 }
3606 default:
3607 return TRI_MAYBE;
3608 }
3609}
3610
3611/**********************************************************************/
3618static enum fc_tristate
3619is_ai_req_active(const struct civ_map *nmap,
3620 const struct req_context *context,
3621 const struct player *other_player,
3622 const struct requirement *req)
3623{
3624 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_AI_LEVEL);
3625
3626 if (context->player == NULL) {
3627 return TRI_MAYBE;
3628 } else {
3629 return BOOL_TO_TRISTATE(is_ai(context->player)
3630 && context->player->ai_common.skill_level
3631 == req->source.value.ai_level);
3632 }
3633}
3634
3635/**********************************************************************/
3642static enum fc_tristate
3643is_nation_req_active(const struct civ_map *nmap,
3644 const struct req_context *context,
3645 const struct player *other_player,
3646 const struct requirement *req)
3647{
3648 const struct nation_type *nation;
3649
3650 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NATION);
3651
3652 nation = req->source.value.nation;
3653
3654 switch (req->range) {
3655 case REQ_RANGE_PLAYER:
3656 if (context->player == NULL) {
3657 return TRI_MAYBE;
3658 }
3659 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
3660 case REQ_RANGE_TEAM:
3661 case REQ_RANGE_ALLIANCE:
3662 if (context->player == NULL) {
3663 return TRI_MAYBE;
3664 }
3665 players_iterate_alive(plr2) {
3666 if (players_in_same_range(context->player, plr2, req->range)) {
3667 if (nation_of_player(plr2) == nation) {
3668 return TRI_YES;
3669 }
3670 }
3671 } players_iterate_alive_end;
3672 return TRI_NO;
3673 case REQ_RANGE_WORLD:
3674 /* NB: if a player is ever removed outright from the game
3675 * (e.g. via /remove), rather than just dying, this 'survives'
3676 * requirement will stop being true for their nation.
3677 * create_command_newcomer() can also cause this to happen. */
3678 return BOOL_TO_TRISTATE(NULL != nation->player
3679 && (req->survives || nation->player->is_alive));
3680 case REQ_RANGE_LOCAL:
3681 case REQ_RANGE_TILE:
3682 case REQ_RANGE_CADJACENT:
3683 case REQ_RANGE_ADJACENT:
3684 case REQ_RANGE_CITY:
3685 case REQ_RANGE_TRADE_ROUTE:
3686 case REQ_RANGE_CONTINENT:
3687 case REQ_RANGE_COUNT:
3688 break;
3689 }
3690
3691 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3692
3693 return TRI_MAYBE;
3694}
3695
3696/**********************************************************************/
3704static enum fc_tristate
3705is_nationgroup_req_active(const struct civ_map *nmap,
3706 const struct req_context *context,
3707 const struct player *other_player,
3708 const struct requirement *req)
3709{
3710 const struct nation_group *ngroup;
3711
3712 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NATIONGROUP);
3713
3714 ngroup = req->source.value.nationgroup;
3715
3716 switch (req->range) {
3717 case REQ_RANGE_PLAYER:
3718 if (context->player == NULL) {
3719 return TRI_MAYBE;
3720 }
3721 return BOOL_TO_TRISTATE(nation_is_in_group(
3722 nation_of_player(context->player), ngroup));
3723 case REQ_RANGE_TEAM:
3724 case REQ_RANGE_ALLIANCE:
3725 case REQ_RANGE_WORLD:
3726 if (context->player == NULL) {
3727 return TRI_MAYBE;
3728 }
3729 players_iterate_alive(plr2) {
3730 if (players_in_same_range(context->player, plr2, req->range)) {
3731 if (nation_is_in_group(nation_of_player(plr2), ngroup)) {
3732 return TRI_YES;
3733 }
3734 }
3735 } players_iterate_alive_end;
3736 return TRI_NO;
3737 case REQ_RANGE_LOCAL:
3738 case REQ_RANGE_TILE:
3739 case REQ_RANGE_CADJACENT:
3740 case REQ_RANGE_ADJACENT:
3741 case REQ_RANGE_CITY:
3742 case REQ_RANGE_TRADE_ROUTE:
3743 case REQ_RANGE_CONTINENT:
3744 case REQ_RANGE_COUNT:
3745 break;
3746 }
3747
3748 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3749
3750 return TRI_MAYBE;
3751}
3752
3753/**********************************************************************/
3761static enum fc_tristate
3762is_nationality_req_active(const struct civ_map *nmap,
3763 const struct req_context *context,
3764 const struct player *other_player,
3765 const struct requirement *req)
3766{
3767 const struct nation_type *nationality;
3768 enum fc_tristate ret;
3769
3770 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NATIONALITY);
3771
3772 nationality = req->source.value.nationality;
3773
3774 switch (req->range) {
3775 case REQ_RANGE_CITY:
3776 if (context->city == NULL) {
3777 return TRI_MAYBE;
3778 }
3779 citizens_iterate(context->city, slot, count) {
3780 if (player_slot_get_player(slot)->nation == nationality) {
3781 return TRI_YES;
3782 }
3783 } citizens_iterate_end;
3784
3785 return TRI_NO;
3786 case REQ_RANGE_TRADE_ROUTE:
3787 if (context->city == NULL) {
3788 return TRI_MAYBE;
3789 }
3790 citizens_iterate(context->city, slot, count) {
3791 if (player_slot_get_player(slot)->nation == nationality) {
3792 return TRI_YES;
3793 }
3794 } citizens_iterate_end;
3795
3796 ret = TRI_NO;
3797 trade_partners_iterate(context->city, trade_partner) {
3798 if (trade_partner == NULL) {
3799 ret = TRI_MAYBE;
3800 } else {
3801 citizens_iterate(trade_partner, slot, count) {
3802 if (player_slot_get_player(slot)->nation == nationality) {
3803 return TRI_YES;
3804 }
3805 } citizens_iterate_end;
3806 }
3807 } trade_partners_iterate_end;
3808
3809 return ret;
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/**********************************************************************/
3836static enum fc_tristate
3837is_originalowner_req_active(const struct civ_map *nmap,
3838 const struct req_context *context,
3839 const struct player *other_player,
3840 const struct requirement *req)
3841{
3842 const struct nation_type *nation;
3843
3844 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ORIGINAL_OWNER);
3845
3846 nation = req->source.value.origowner;
3847
3848 switch (req->range) {
3849 case REQ_RANGE_CITY:
3850 if (context->city == NULL || context->city->original == NULL) {
3851 return TRI_MAYBE;
3852 }
3853 if (player_nation(context->city->original) == nation) {
3854 return TRI_YES;
3855 }
3856
3857 return TRI_NO;
3858 case REQ_RANGE_TRADE_ROUTE:
3859 case REQ_RANGE_PLAYER:
3860 case REQ_RANGE_TEAM:
3861 case REQ_RANGE_ALLIANCE:
3862 case REQ_RANGE_WORLD:
3863 case REQ_RANGE_LOCAL:
3864 case REQ_RANGE_TILE:
3865 case REQ_RANGE_CADJACENT:
3866 case REQ_RANGE_ADJACENT:
3867 case REQ_RANGE_CONTINENT:
3868 case REQ_RANGE_COUNT:
3869 break;
3870 }
3871
3872 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3873
3874 return TRI_MAYBE;
3875}
3876
3877/**********************************************************************/
3880 static enum fc_tristate is_diplrel_in_range(const struct player *target_player,
3881 const struct player *other_player,
3882 enum req_range range,
3883 int diplrel)
3884{
3885 switch (range) {
3886 case REQ_RANGE_PLAYER:
3887 if (target_player == NULL) {
3888 return TRI_MAYBE;
3889 }
3890 return BOOL_TO_TRISTATE(is_diplrel_to_other(target_player, diplrel));
3891 case REQ_RANGE_TEAM:
3892 case REQ_RANGE_ALLIANCE:
3893 case REQ_RANGE_WORLD:
3894 if (target_player == NULL) {
3895 return TRI_MAYBE;
3896 }
3897 players_iterate_alive(plr2) {
3898 if (players_in_same_range(target_player, plr2, range)) {
3899 if (is_diplrel_to_other(plr2, diplrel)) {
3900 return TRI_YES;
3901 }
3902 }
3903 } players_iterate_alive_end;
3904 return TRI_NO;
3905 case REQ_RANGE_LOCAL:
3906 if (target_player == NULL || other_player == NULL) {
3907 return TRI_MAYBE;
3908 }
3909 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
3910 case REQ_RANGE_TILE:
3911 case REQ_RANGE_CADJACENT:
3912 case REQ_RANGE_ADJACENT:
3913 case REQ_RANGE_CITY:
3914 case REQ_RANGE_TRADE_ROUTE:
3915 case REQ_RANGE_CONTINENT:
3916 case REQ_RANGE_COUNT:
3917 break;
3918 }
3919
3920 fc_assert_msg(FALSE, "Invalid range %d.", range);
3921
3922 return TRI_MAYBE;
3923}
3924
3925/**********************************************************************/
3932static enum fc_tristate
3933is_diplrel_req_active(const struct civ_map *nmap,
3934 const struct req_context *context,
3935 const struct player *other_player,
3936 const struct requirement *req)
3937{
3938 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL);
3939
3940 return is_diplrel_in_range(context->player, other_player, req->range,
3941 req->source.value.diplrel);
3942}
3943
3944/**********************************************************************/
3952static enum fc_tristate
3953is_diplrel_tile_req_active(const struct civ_map *nmap,
3954 const struct req_context *context,
3955 const struct player *other_player,
3956 const struct requirement *req)
3957{
3958 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_TILE);
3959
3960 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
3961 : NULL,
3962 context->player,
3963 req->range,
3964 req->source.value.diplrel);
3965}
3966
3967/**********************************************************************/
3976static enum fc_tristate
3977is_diplrel_tile_o_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_TILE_O);
3983
3984 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
3985 : NULL,
3986 other_player,
3987 req->range,
3988 req->source.value.diplrel);
3989}
3990
3991/**********************************************************************/
3994static enum fc_tristate
3995is_diplrel_unitany_in_range(const struct tile *target_tile,
3996 const struct player *other_player,
3997 enum req_range range,
3998 int diplrel)
3999{
4000 enum fc_tristate out = TRI_NO;
4001
4002 if (target_tile == NULL) {
4003 return TRI_MAYBE;
4004 }
4005
4006 unit_list_iterate(target_tile->units, target_unit) {
4007 enum fc_tristate for_target_unit = is_diplrel_in_range(
4008 unit_owner(target_unit), other_player, range, diplrel);
4009
4010 out = fc_tristate_or(out, for_target_unit);
4011 } unit_list_iterate_end;
4012
4013 return out;
4014}
4015
4016/**********************************************************************/
4025static enum fc_tristate
4026is_diplrel_unitany_req_active(const struct civ_map *nmap,
4027 const struct req_context *context,
4028 const struct player *other_player,
4029 const struct requirement *req)
4030{
4031 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_UNITANY);
4032
4033 return is_diplrel_unitany_in_range(context->tile, context->player,
4034 req->range,
4035 req->source.value.diplrel);
4036}
4037
4038/**********************************************************************/
4047static enum fc_tristate
4048is_diplrel_unitany_o_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 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_UNITANY_O);
4054
4055 return is_diplrel_unitany_in_range(context->tile, other_player,
4056 req->range,
4057 req->source.value.diplrel);
4058}
4059
4060/**********************************************************************/
4067static enum fc_tristate
4068is_unittype_req_active(const struct civ_map *nmap,
4069 const struct req_context *context,
4070 const struct player *other_player,
4071 const struct requirement *req)
4072{
4073 const struct unit_type *punittype;
4074
4075 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UTYPE);
4076
4077 punittype = req->source.value.utype;
4078
4079 switch (req->range) {
4080 case REQ_RANGE_LOCAL:
4081 if (!context->unittype) {
4082 return TRI_MAYBE;
4083 }
4084 return BOOL_TO_TRISTATE(context->unittype == punittype);
4085 case REQ_RANGE_TILE:
4086 case REQ_RANGE_CADJACENT:
4087 case REQ_RANGE_ADJACENT:
4088 if (context->tile == nullptr) {
4089 return TRI_MAYBE;
4090 }
4091
4092 unit_list_iterate(context->tile->units, punit) {
4093 if (punit->utype == punittype) {
4094 return TRI_YES;
4095 }
4096 } unit_list_iterate_end;
4097
4098 if (req->range == REQ_RANGE_TILE) {
4099 return TRI_NO;
4100 }
4101
4102 if (req->range == REQ_RANGE_CADJACENT) {
4103 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4104 unit_list_iterate(adjc_tile->units, punit) {
4105 if (punit->utype == punittype) {
4106 return TRI_YES;
4107 }
4108 } unit_list_iterate_end;
4109 } cardinal_adjc_iterate_end;
4110 } else {
4111 fc_assert(req->range == REQ_RANGE_ADJACENT);
4112
4113 adjc_iterate(nmap, context->tile, adjc_tile) {
4114 unit_list_iterate(adjc_tile->units, punit) {
4115 if (punit->utype == punittype) {
4116 return TRI_YES;
4117 }
4118 } unit_list_iterate_end;
4119 } adjc_iterate_end;
4120 }
4121
4122 return TRI_NO;
4123
4124 case REQ_RANGE_CITY:
4125 case REQ_RANGE_TRADE_ROUTE:
4126 case REQ_RANGE_CONTINENT:
4127 case REQ_RANGE_PLAYER:
4128 case REQ_RANGE_TEAM:
4129 case REQ_RANGE_ALLIANCE:
4130 case REQ_RANGE_WORLD:
4131 case REQ_RANGE_COUNT:
4132 fc_assert(FALSE);
4133 break;
4134 }
4135
4136 return TRI_NO;
4137}
4138
4139/**********************************************************************/
4146static enum fc_tristate
4147is_unitflag_req_active(const struct civ_map *nmap,
4148 const struct req_context *context,
4149 const struct player *other_player,
4150 const struct requirement *req)
4151{
4152 enum unit_type_flag_id unitflag;
4153
4154 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UTFLAG);
4155
4156 unitflag = req->source.value.unitflag;
4157
4158 switch (req->range) {
4159 case REQ_RANGE_LOCAL:
4160 if (!context->unittype) {
4161 return TRI_MAYBE;
4162 }
4163 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4164 case REQ_RANGE_TILE:
4165 case REQ_RANGE_CADJACENT:
4166 case REQ_RANGE_ADJACENT:
4167 if (context->tile == nullptr) {
4168 return TRI_MAYBE;
4169 }
4170
4171 unit_list_iterate(context->tile->units, punit) {
4172 if (unit_has_type_flag(punit, unitflag)) {
4173 return TRI_YES;
4174 }
4175 } unit_list_iterate_end;
4176
4177 if (req->range == REQ_RANGE_TILE) {
4178 return TRI_NO;
4179 }
4180
4181 if (req->range == REQ_RANGE_CADJACENT) {
4182 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4183 unit_list_iterate(adjc_tile->units, punit) {
4184 if (unit_has_type_flag(punit, unitflag)) {
4185 return TRI_YES;
4186 }
4187 } unit_list_iterate_end;
4188 } cardinal_adjc_iterate_end;
4189 } else {
4190 fc_assert(req->range == REQ_RANGE_ADJACENT);
4191
4192 adjc_iterate(nmap, context->tile, adjc_tile) {
4193 unit_list_iterate(adjc_tile->units, punit) {
4194 if (unit_has_type_flag(punit, unitflag)) {
4195 return TRI_YES;
4196 }
4197 } unit_list_iterate_end;
4198 } adjc_iterate_end;
4199 }
4200
4201 return TRI_NO;
4202
4203 case REQ_RANGE_CITY:
4204 case REQ_RANGE_TRADE_ROUTE:
4205 case REQ_RANGE_CONTINENT:
4206 case REQ_RANGE_PLAYER:
4207 case REQ_RANGE_TEAM:
4208 case REQ_RANGE_ALLIANCE:
4209 case REQ_RANGE_WORLD:
4210 case REQ_RANGE_COUNT:
4211 fc_assert(FALSE);
4212 break;
4213 }
4214
4215 return TRI_NO;
4216}
4217
4218/**********************************************************************/
4225static enum fc_tristate
4226is_unitclass_req_active(const struct civ_map *nmap,
4227 const struct req_context *context,
4228 const struct player *other_player,
4229 const struct requirement *req)
4230{
4231 const struct unit_class *pclass;
4232
4233 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UCLASS);
4234
4235 pclass = req->source.value.uclass;
4236
4237 switch (req->range) {
4238 case REQ_RANGE_LOCAL:
4239 if (!context->unittype) {
4240 return TRI_MAYBE;
4241 }
4242 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4243 case REQ_RANGE_TILE:
4244 case REQ_RANGE_CADJACENT:
4245 case REQ_RANGE_ADJACENT:
4246 if (context->tile == nullptr) {
4247 return TRI_MAYBE;
4248 }
4249
4250 unit_list_iterate(context->tile->units, punit) {
4251 if (unit_class_get(punit) == pclass) {
4252 return TRI_YES;
4253 }
4254 } unit_list_iterate_end;
4255
4256 if (req->range == REQ_RANGE_TILE) {
4257 return TRI_NO;
4258 }
4259
4260 if (req->range == REQ_RANGE_CADJACENT) {
4261 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4262 unit_list_iterate(adjc_tile->units, punit) {
4263 if (unit_class_get(punit) == pclass) {
4264 return TRI_YES;
4265 }
4266 } unit_list_iterate_end;
4267 } cardinal_adjc_iterate_end;
4268 } else {
4269 fc_assert(req->range == REQ_RANGE_ADJACENT);
4270
4271 adjc_iterate(nmap, context->tile, adjc_tile) {
4272 unit_list_iterate(adjc_tile->units, punit) {
4273 if (unit_class_get(punit) == pclass) {
4274 return TRI_YES;
4275 }
4276 } unit_list_iterate_end;
4277 } adjc_iterate_end;
4278 }
4279
4280 return TRI_NO;
4281
4282 case REQ_RANGE_CITY:
4283 case REQ_RANGE_TRADE_ROUTE:
4284 case REQ_RANGE_CONTINENT:
4285 case REQ_RANGE_PLAYER:
4286 case REQ_RANGE_TEAM:
4287 case REQ_RANGE_ALLIANCE:
4288 case REQ_RANGE_WORLD:
4289 case REQ_RANGE_COUNT:
4290 fc_assert(FALSE);
4291 break;
4292 }
4293
4294 return TRI_NO;
4295}
4296
4297/**********************************************************************/
4305static enum fc_tristate
4306is_unitclassflag_req_active(const struct civ_map *nmap,
4307 const struct req_context *context,
4308 const struct player *other_player,
4309 const struct requirement *req)
4310{
4311 enum unit_class_flag_id ucflag;
4312
4313 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UCFLAG);
4314
4315 ucflag = req->source.value.unitclassflag;
4316
4317 if (req->range != REQ_RANGE_LOCAL) {
4318 return TRI_NO;
4319 }
4320 if (!context->unittype) {
4321 return TRI_MAYBE;
4322 }
4323
4324 return BOOL_TO_TRISTATE(uclass_has_flag(utype_class(context->unittype), ucflag));
4325}
4326
4327/**********************************************************************/
4334static enum fc_tristate
4335is_unitstate_req_active(const struct civ_map *nmap,
4336 const struct req_context *context,
4337 const struct player *other_player,
4338 const struct requirement *req)
4339{
4340 enum ustate_prop uprop;
4341
4342 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UNITSTATE);
4343
4344 uprop = req->source.value.unit_state;
4345
4346 fc_assert_ret_val_msg(req->range == REQ_RANGE_LOCAL, TRI_NO,
4347 "Unsupported range \"%s\"",
4348 req_range_name(req->range));
4349
4350 /* Could be asked with incomplete data.
4351 * is_req_active() will handle it based on prob_type. */
4352 if (context->unit == NULL) {
4353 return TRI_MAYBE;
4354 }
4355
4356 switch (uprop) {
4357 case USP_TRANSPORTED:
4358 return BOOL_TO_TRISTATE(context->unit->transporter != NULL);
4359 case USP_LIVABLE_TILE:
4360 return BOOL_TO_TRISTATE(
4361 can_unit_exist_at_tile(nmap, context->unit,
4362 unit_tile(context->unit)));
4363 break;
4364 case USP_TRANSPORTING:
4365 return BOOL_TO_TRISTATE(0 < get_transporter_occupancy(context->unit));
4366 case USP_HAS_HOME_CITY:
4367 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
4368 case USP_NATIVE_TILE:
4369 return BOOL_TO_TRISTATE(
4370 is_native_tile(unit_type_get(context->unit),
4371 unit_tile(context->unit)));
4372 break;
4373 case USP_NATIVE_EXTRA:
4374 return BOOL_TO_TRISTATE(
4375 tile_has_native_base(unit_tile(context->unit),
4376 unit_type_get(context->unit)));
4377 break;
4378 case USP_MOVED_THIS_TURN:
4379 return BOOL_TO_TRISTATE(context->unit->moved);
4380 case USP_COUNT:
4381 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
4382 /* Invalid property is unknowable. */
4383 return TRI_NO;
4384 }
4385
4386 /* Should never be reached */
4387 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
4388
4389 return TRI_NO;
4390}
4391
4392/**********************************************************************/
4399static enum fc_tristate
4400is_activity_req_active(const struct civ_map *nmap,
4401 const struct req_context *context,
4402 const struct player *other_player,
4403 const struct requirement *req)
4404{
4405 enum unit_activity activity;
4406
4407 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ACTIVITY);
4408
4409 activity = req->source.value.activity;
4410
4411 fc_assert_ret_val_msg(req->range == REQ_RANGE_LOCAL, TRI_NO,
4412 "Unsupported range \"%s\"",
4413 req_range_name(req->range));
4414
4415 if (context->unit == NULL) {
4416 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
4417 * it's the zero value that context has by default - so many callers
4418 * who meant not to set specific activity actually have ACTIVITY_IDLE
4419 * instead of ACTIVITY_LAST */
4420 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
4421 return BOOL_TO_TRISTATE(activity == context->activity);
4422 }
4423
4424 /* Could be asked with incomplete data.
4425 * is_req_active() will handle it based on prob_type. */
4426 return TRI_MAYBE;
4427 }
4428
4429 switch (context->unit->activity) {
4430 case ACTIVITY_IDLE:
4431 case ACTIVITY_SENTRY:
4432 case ACTIVITY_GOTO:
4433 case ACTIVITY_EXPLORE:
4434 /* Seen as idle. */
4435 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
4436 default:
4437 /* Handled below. */
4438 break;
4439 }
4440
4441 return BOOL_TO_TRISTATE(context->unit->activity == activity);
4442}
4443
4444/**********************************************************************/
4451static enum fc_tristate
4452is_minveteran_req_active(const struct civ_map *nmap,
4453 const struct req_context *context,
4454 const struct player *other_player,
4455 const struct requirement *req)
4456{
4457 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINVETERAN);
4458
4459 if (context->unit == NULL) {
4460 return TRI_MAYBE;
4461 } else {
4462 return BOOL_TO_TRISTATE(context->unit->veteran
4463 >= req->source.value.minveteran);
4464 }
4465}
4466
4467/**********************************************************************/
4475static enum fc_tristate
4476is_minmovefrags_req_active(const struct civ_map *nmap,
4477 const struct req_context *context,
4478 const struct player *other_player,
4479 const struct requirement *req)
4480{
4481 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINMOVES);
4482
4483 if (context->unit == NULL) {
4484 return TRI_MAYBE;
4485 } else {
4486 return BOOL_TO_TRISTATE(req->source.value.minmoves
4487 <= context->unit->moves_left);
4488 }
4489}
4490
4491/**********************************************************************/
4499static enum fc_tristate
4500is_minhitpoints_req_active(const struct civ_map *nmap,
4501 const struct req_context *context,
4502 const struct player *other_player,
4503 const struct requirement *req)
4504{
4505 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINHP);
4506
4507 if (context->unit == NULL) {
4508 return TRI_MAYBE;
4509 } else {
4510 return BOOL_TO_TRISTATE(req->source.value.min_hit_points
4511 <= context->unit->hp);
4512 }
4513}
4514
4515/**********************************************************************/
4522static enum fc_tristate
4523is_age_req_active(const struct civ_map *nmap,
4524 const struct req_context *context,
4525 const struct player *other_player,
4526 const struct requirement *req)
4527{
4528 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_AGE);
4529
4530 switch (req->range) {
4531 case REQ_RANGE_LOCAL:
4532 if (context->unit == NULL || !is_server()) {
4533 return TRI_MAYBE;
4534 } else {
4535 return BOOL_TO_TRISTATE(
4536 req->source.value.age <=
4537 game.info.turn - context->unit->birth_turn);
4538 }
4539 break;
4540 case REQ_RANGE_CITY:
4541 if (context->city == NULL) {
4542 return TRI_MAYBE;
4543 } else {
4544 return BOOL_TO_TRISTATE(
4545 req->source.value.age <=
4546 game.info.turn - context->city->turn_founded);
4547 }
4548 break;
4549 case REQ_RANGE_PLAYER:
4550 if (context->player == NULL) {
4551 return TRI_MAYBE;
4552 } else {
4553 return BOOL_TO_TRISTATE(req->source.value.age
4554 <= player_age(context->player));
4555 }
4556 break;
4557 default:
4558 return TRI_MAYBE;
4559 break;
4560 }
4561}
4562
4563/**********************************************************************/
4570static enum fc_tristate
4571is_form_age_req_active(const struct civ_map *nmap,
4572 const struct req_context *context,
4573 const struct player *other_player,
4574 const struct requirement *req)
4575{
4576 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_FORM_AGE);
4577
4578 switch (req->range) {
4579 case REQ_RANGE_LOCAL:
4580 if (context->unit == NULL || !is_server()) {
4581 return TRI_MAYBE;
4582 } else {
4583 return BOOL_TO_TRISTATE(
4584 req->source.value.form_age <=
4585 game.info.turn - context->unit->current_form_turn);
4586 }
4587 break;
4588 default:
4589 return TRI_MAYBE;
4590 break;
4591 }
4592}
4593
4594/**********************************************************************/
4597 static bool is_city_in_tile(const struct tile *ptile,
4598 const struct city *pcity)
4599{
4600 if (pcity == NULL) {
4601 return tile_city(ptile) != NULL;
4602 } else {
4603 return is_city_center(pcity, ptile);
4604 }
4605}
4606
4607/**********************************************************************/
4614static enum fc_tristate
4615is_citytile_req_active(const struct civ_map *nmap,
4616 const struct req_context *context,
4617 const struct player *other_player,
4618 const struct requirement *req)
4619{
4620 enum citytile_type citytile;
4621
4622 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_CITYTILE);
4623
4624 citytile = req->source.value.citytile;
4625
4626 fc_assert_ret_val(req_range_is_valid(req->range), TRI_MAYBE);
4627 if (context->tile == NULL) {
4628 return TRI_MAYBE;
4629 }
4630
4631 switch (citytile) {
4632 case CITYT_CENTER:
4633 switch (req->range) {
4634 case REQ_RANGE_TILE:
4635 return BOOL_TO_TRISTATE(is_city_in_tile(context->tile,
4636 context->city));
4637 case REQ_RANGE_CADJACENT:
4638 if (is_city_in_tile(context->tile, context->city)) {
4639 return TRI_YES;
4640 }
4641 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4642 if (is_city_in_tile(adjc_tile, context->city)) {
4643 return TRI_YES;
4644 }
4645 } cardinal_adjc_iterate_end;
4646
4647 return TRI_NO;
4648 case REQ_RANGE_ADJACENT:
4649 if (is_city_in_tile(context->tile, context->city)) {
4650 return TRI_YES;
4651 }
4652 adjc_iterate(nmap, context->tile, adjc_tile) {
4653 if (is_city_in_tile(adjc_tile, context->city)) {
4654 return TRI_YES;
4655 }
4656 } adjc_iterate_end;
4657
4658 return TRI_NO;
4659 case REQ_RANGE_CITY:
4660 case REQ_RANGE_TRADE_ROUTE:
4661 case REQ_RANGE_CONTINENT:
4662 case REQ_RANGE_PLAYER:
4663 case REQ_RANGE_TEAM:
4664 case REQ_RANGE_ALLIANCE:
4665 case REQ_RANGE_WORLD:
4666 case REQ_RANGE_LOCAL:
4667 case REQ_RANGE_COUNT:
4668 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4669 break;
4670 }
4671
4672 return TRI_MAYBE;
4673 case CITYT_CLAIMED:
4674 switch (req->range) {
4675 case REQ_RANGE_TILE:
4676 return BOOL_TO_TRISTATE(context->tile->owner != NULL);
4677 case REQ_RANGE_CADJACENT:
4678 if (context->tile->owner != NULL) {
4679 return TRI_YES;
4680 }
4681 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4682 if (adjc_tile->owner != NULL) {
4683 return TRI_YES;
4684 }
4685 } cardinal_adjc_iterate_end;
4686
4687 return TRI_NO;
4688 case REQ_RANGE_ADJACENT:
4689 if (context->tile->owner != NULL) {
4690 return TRI_YES;
4691 }
4692 adjc_iterate(nmap, context->tile, adjc_tile) {
4693 if (adjc_tile->owner != NULL) {
4694 return TRI_YES;
4695 }
4696 } adjc_iterate_end;
4697
4698 return TRI_NO;
4699 case REQ_RANGE_CITY:
4700 case REQ_RANGE_TRADE_ROUTE:
4701 case REQ_RANGE_CONTINENT:
4702 case REQ_RANGE_PLAYER:
4703 case REQ_RANGE_TEAM:
4704 case REQ_RANGE_ALLIANCE:
4705 case REQ_RANGE_WORLD:
4706 case REQ_RANGE_LOCAL:
4707 case REQ_RANGE_COUNT:
4708 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4709 break;
4710 }
4711
4712 return TRI_MAYBE;
4713 case CITYT_EXTRAS_OWNED:
4714 switch (req->range) {
4715 case REQ_RANGE_TILE:
4716 return BOOL_TO_TRISTATE(context->tile->extras_owner != NULL);
4717 case REQ_RANGE_CADJACENT:
4718 if (context->tile->extras_owner != NULL) {
4719 return TRI_YES;
4720 }
4721 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4722 if (adjc_tile->extras_owner != NULL) {
4723 return TRI_YES;
4724 }
4725 } cardinal_adjc_iterate_end;
4726
4727 return TRI_NO;
4728 case REQ_RANGE_ADJACENT:
4729 if (context->tile->extras_owner != NULL) {
4730 return TRI_YES;
4731 }
4732 adjc_iterate(nmap, context->tile, adjc_tile) {
4733 if (adjc_tile->extras_owner != NULL) {
4734 return TRI_YES;
4735 }
4736 } adjc_iterate_end;
4737
4738 return TRI_NO;
4739 case REQ_RANGE_CITY:
4740 case REQ_RANGE_TRADE_ROUTE:
4741 case REQ_RANGE_CONTINENT:
4742 case REQ_RANGE_PLAYER:
4743 case REQ_RANGE_TEAM:
4744 case REQ_RANGE_ALLIANCE:
4745 case REQ_RANGE_WORLD:
4746 case REQ_RANGE_LOCAL:
4747 case REQ_RANGE_COUNT:
4748 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4749 break;
4750 }
4751
4752 return TRI_MAYBE;
4753 case CITYT_WORKED:
4754 switch (req->range) {
4755 case REQ_RANGE_TILE:
4756 return BOOL_TO_TRISTATE(context->tile->worked != NULL);
4757 case REQ_RANGE_CADJACENT:
4758 if (context->tile->worked != NULL) {
4759 return TRI_YES;
4760 }
4761 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4762 if (adjc_tile->worked != NULL) {
4763 return TRI_YES;
4764 }
4765 } cardinal_adjc_iterate_end;
4766
4767 return TRI_NO;
4768 case REQ_RANGE_ADJACENT:
4769 if (context->tile->worked != NULL) {
4770 return TRI_YES;
4771 }
4772 adjc_iterate(nmap, context->tile, adjc_tile) {
4773 if (adjc_tile->worked != NULL) {
4774 return TRI_YES;
4775 }
4776 } adjc_iterate_end;
4777
4778 return TRI_NO;
4779 case REQ_RANGE_CITY:
4780 case REQ_RANGE_TRADE_ROUTE:
4781 case REQ_RANGE_CONTINENT:
4782 case REQ_RANGE_PLAYER:
4783 case REQ_RANGE_TEAM:
4784 case REQ_RANGE_ALLIANCE:
4785 case REQ_RANGE_WORLD:
4786 case REQ_RANGE_LOCAL:
4787 case REQ_RANGE_COUNT:
4788 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4789 break;
4790 }
4791
4792 return TRI_MAYBE;
4793 case CITYT_SAME_CONTINENT:
4794 {
4795 Continent_id cc;
4796 const struct tile *target_tile = context->tile, *cc_tile;
4797
4798 if (!context->city) {
4799 return TRI_MAYBE;
4800 }
4801 cc_tile = city_tile(context->city);
4802 if (!cc_tile) {
4803 /* Unplaced virtual city */
4804 return TRI_MAYBE;
4805 }
4806 cc = tile_continent(cc_tile);
4807 /* Note: No special treatment of 0 == cc here*/
4808 switch (req->range) {
4809 case REQ_RANGE_TILE:
4810 return BOOL_TO_TRISTATE(tile_continent(target_tile) == cc);
4811 case REQ_RANGE_CADJACENT:
4812 if (tile_continent(target_tile) == cc) {
4813 return TRI_YES;
4814 }
4815 cardinal_adjc_iterate(nmap, target_tile, adjc_tile) {
4816 if (tile_continent(adjc_tile) == cc) {
4817 return TRI_YES;
4818 }
4819 } cardinal_adjc_iterate_end;
4820
4821 return TRI_NO;
4822 case REQ_RANGE_ADJACENT:
4823 if (tile_continent(target_tile) == cc) {
4824 return TRI_YES;
4825 }
4826 adjc_iterate(nmap, target_tile, adjc_tile) {
4827 if (tile_continent(adjc_tile) == cc) {
4828 return TRI_YES;
4829 }
4830 } adjc_iterate_end;
4831
4832 return TRI_NO;
4833 case REQ_RANGE_CITY:
4834 case REQ_RANGE_TRADE_ROUTE:
4835 case REQ_RANGE_CONTINENT:
4836 case REQ_RANGE_PLAYER:
4837 case REQ_RANGE_TEAM:
4838 case REQ_RANGE_ALLIANCE:
4839 case REQ_RANGE_WORLD:
4840 case REQ_RANGE_LOCAL:
4841 case REQ_RANGE_COUNT:
4842 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4843 break;
4844 }
4845 }
4846
4847 return TRI_MAYBE;
4848 case CITYT_BORDERING_TCLASS_REGION:
4849 {
4850 int n = 0;
4851 Continent_id adjc_cont[8], cc;
4852 bool ukt = FALSE;
4853 const struct tile *target_tile = context->tile, *cc_tile;
4854
4855 if (!context->city) {
4856 return TRI_MAYBE;
4857 }
4858 cc_tile = city_tile(context->city);
4859 if (!cc_tile) {
4860 /* Unplaced virtual city */
4861 return TRI_MAYBE;
4862 }
4863 cc = tile_continent(cc_tile);
4864 if (!cc) {
4865 /* Don't know the city center terrain class.
4866 * Maybe, the city floats? Even if the rules prohibit it... */
4867 return TRI_MAYBE;
4868 }
4869 adjc_iterate(nmap, cc_tile, adjc_tile) {
4870 Continent_id tc = tile_continent(adjc_tile);
4871
4872 if (0 != tc) {
4873 bool seen = FALSE;
4874 int i = n;
4875
4876 if (tc == cc) {
4877 continue;
4878 }
4879 while (--i >= 0) {
4880 if (adjc_cont[i] == tc) {
4881 seen = TRUE;
4882 break;
4883 }
4884 }
4885 if (seen) {
4886 continue;
4887 }
4888 adjc_cont[n++] = tile_continent(adjc_tile);
4889 } else {
4890 /* Likely, it's a black tile in client and we don't know
4891 * We possibly can calculate, but keep it simple. */
4892 ukt = TRUE;
4893 }
4894 } adjc_iterate_end;
4895 if (0 == n) {
4896 return ukt ? TRI_MAYBE : TRI_NO;
4897 }
4898
4899 switch (req->range) {
4900 case REQ_RANGE_TILE:
4901 {
4902 Continent_id tc = tile_continent(target_tile);
4903
4904 if (cc == tc) {
4905 return TRI_NO;
4906 }
4907 if (0 == tc || ukt) {
4908 return TRI_MAYBE;
4909 }
4910 for (int i = 0; i < n; i++) {
4911 if (tc == adjc_cont[i]) {
4912 return TRI_YES;
4913 }
4914 }
4915 }
4916
4917 return TRI_NO;
4918 case REQ_RANGE_ADJACENT:
4919 if (ukt) {
4920 /* If ALL the tiles in range are on cc, we can say it's false */
4921 square_iterate(nmap, target_tile, 1, adjc_tile) {
4922 if (tile_continent(adjc_tile) != cc) {
4923 return TRI_MAYBE;
4924 }
4925 } square_iterate_end;
4926
4927 return TRI_NO;
4928 } else {
4929 square_iterate(nmap, target_tile, 1, adjc_tile) {
4930 Continent_id tc = tile_continent(adjc_tile);
4931
4932 if (0 == tc) {
4933 return TRI_MAYBE;
4934 }
4935 for (int i = 0; i < n; i++) {
4936 if (tc == adjc_cont[i]) {
4937 return TRI_YES;
4938 }
4939 }
4940 } square_iterate_end;
4941 }
4942
4943 return TRI_NO;
4944 case REQ_RANGE_CADJACENT:
4945 if (ukt) {
4946 /* If ALL the tiles in range are on cc, we can say it's false */
4947 circle_iterate(nmap, target_tile, 1, cadjc_tile) {
4948 if (tile_continent(cadjc_tile) != cc) {
4949 return TRI_MAYBE;
4950 }
4951 } circle_iterate_end;
4952 } else {
4953 circle_iterate(nmap, target_tile, 1, cadjc_tile) {
4954 Continent_id tc = tile_continent(cadjc_tile);
4955
4956 if (0 == tc) {
4957 return TRI_MAYBE;
4958 }
4959 for (int i = 0; i < n; i++) {
4960 if (tc == adjc_cont[i]) {
4961 return TRI_YES;
4962 }
4963 }
4964 } circle_iterate_end;
4965 }
4966
4967 return TRI_NO;
4968 case REQ_RANGE_CITY:
4969 case REQ_RANGE_TRADE_ROUTE:
4970 case REQ_RANGE_CONTINENT:
4971 case REQ_RANGE_PLAYER:
4972 case REQ_RANGE_TEAM:
4973 case REQ_RANGE_ALLIANCE:
4974 case REQ_RANGE_WORLD:
4975 case REQ_RANGE_LOCAL:
4976 case REQ_RANGE_COUNT:
4977 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4978 break;
4979 }
4980 }
4981
4982 return TRI_MAYBE;
4983 case CITYT_LAST:
4984 /* Handled below */
4985 break;
4986 }
4987
4988 /* Not implemented */
4989 log_error("is_req_active(): citytile %d not supported.",
4990 citytile);
4991 return TRI_MAYBE;
4992}
4993
4994/**********************************************************************/
5002static enum fc_tristate
5003is_citystatus_req_active(const struct civ_map *nmap,
5004 const struct req_context *context,
5005 const struct player *other_player,
5006 const struct requirement *req)
5007{
5008 enum citystatus_type citystatus;
5009
5010 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_CITYSTATUS);
5011
5012 citystatus = req->source.value.citystatus;
5013
5014 if (context->city == NULL) {
5015 return TRI_MAYBE;
5016 }
5017
5018 switch (citystatus) {
5019 case CITYS_OWNED_BY_ORIGINAL:
5020 switch (req->range) {
5021 case REQ_RANGE_CITY:
5022 if (context->city->original == NULL) {
5023 return TRI_MAYBE;
5024 }
5025 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
5026 case REQ_RANGE_TRADE_ROUTE:
5027 {
5028 enum fc_tristate ret;
5029
5030 if (city_owner(context->city) == context->city->original) {
5031 return TRI_YES;
5032 }
5033
5034 ret = TRI_NO;
5035 trade_partners_iterate(context->city, trade_partner) {
5036 if (trade_partner == NULL || trade_partner->original == NULL) {
5037 ret = TRI_MAYBE;
5038 } else if (city_owner(trade_partner) == trade_partner->original) {
5039 return TRI_YES;
5040 }
5041 } trade_partners_iterate_end;
5042
5043 return ret;
5044 }
5045 case REQ_RANGE_LOCAL:
5046 case REQ_RANGE_TILE:
5047 case REQ_RANGE_CADJACENT:
5048 case REQ_RANGE_ADJACENT:
5049 case REQ_RANGE_CONTINENT:
5050 case REQ_RANGE_PLAYER:
5051 case REQ_RANGE_TEAM:
5052 case REQ_RANGE_ALLIANCE:
5053 case REQ_RANGE_WORLD:
5054 case REQ_RANGE_COUNT:
5055 break;
5056 }
5057
5058 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
5059 req->range);
5060
5061 return TRI_MAYBE;
5062
5063 case CITYS_STARVED:
5064 switch (req->range) {
5065 case REQ_RANGE_CITY:
5066 return BOOL_TO_TRISTATE(context->city->had_famine);
5067 case REQ_RANGE_TRADE_ROUTE:
5068 {
5069 enum fc_tristate ret;
5070
5071 if (context->city->had_famine) {
5072 return TRI_YES;
5073 }
5074
5075 ret = TRI_NO;
5076 trade_partners_iterate(context->city, trade_partner) {
5077 if (trade_partner == NULL) {
5078 ret = TRI_MAYBE;
5079 } else if (trade_partner->had_famine) {
5080 return TRI_YES;
5081 }
5082 } trade_partners_iterate_end;
5083
5084 return ret;
5085 }
5086 case REQ_RANGE_LOCAL:
5087 case REQ_RANGE_TILE:
5088 case REQ_RANGE_CADJACENT:
5089 case REQ_RANGE_ADJACENT:
5090 case REQ_RANGE_CONTINENT:
5091 case REQ_RANGE_PLAYER:
5092 case REQ_RANGE_TEAM:
5093 case REQ_RANGE_ALLIANCE:
5094 case REQ_RANGE_WORLD:
5095 case REQ_RANGE_COUNT:
5096 break;
5097 }
5098
5099 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
5100 req->range);
5101
5102 return TRI_MAYBE;
5103
5104 case CITYS_DISORDER:
5105 switch (req->range) {
5106 case REQ_RANGE_CITY:
5107 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
5108 case REQ_RANGE_TRADE_ROUTE:
5109 {
5110 enum fc_tristate ret;
5111
5112 if (context->city->anarchy > 0) {
5113 return TRI_YES;
5114 }
5115
5116 ret = TRI_NO;
5117 trade_partners_iterate(context->city, trade_partner) {
5118 if (trade_partner == NULL) {
5119 ret = TRI_MAYBE;
5120 } else if (trade_partner->anarchy > 0) {
5121 return TRI_YES;
5122 }
5123 } trade_partners_iterate_end;
5124
5125 return ret;
5126 }
5127 case REQ_RANGE_LOCAL:
5128 case REQ_RANGE_TILE:
5129 case REQ_RANGE_CADJACENT:
5130 case REQ_RANGE_ADJACENT:
5131 case REQ_RANGE_CONTINENT:
5132 case REQ_RANGE_PLAYER:
5133 case REQ_RANGE_TEAM:
5134 case REQ_RANGE_ALLIANCE:
5135 case REQ_RANGE_WORLD:
5136 case REQ_RANGE_COUNT:
5137 break;
5138 }
5139
5140 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
5141 req->range);
5142
5143 return TRI_MAYBE;
5144
5145 case CITYS_CELEBRATION:
5146 switch (req->range) {
5147 case REQ_RANGE_CITY:
5148 return BOOL_TO_TRISTATE(context->city->rapture > 0);
5149 case REQ_RANGE_TRADE_ROUTE:
5150 {
5151 enum fc_tristate ret;
5152
5153 if (context->city->rapture > 0) {
5154 return TRI_YES;
5155 }
5156
5157 ret = TRI_NO;
5158 trade_partners_iterate(context->city, trade_partner) {
5159 if (trade_partner == NULL) {
5160 ret = TRI_MAYBE;
5161 } else if (trade_partner->rapture > 0) {
5162 return TRI_YES;
5163 }
5164 } trade_partners_iterate_end;
5165
5166 return ret;
5167 }
5168 case REQ_RANGE_LOCAL:
5169 case REQ_RANGE_TILE:
5170 case REQ_RANGE_CADJACENT:
5171 case REQ_RANGE_ADJACENT:
5172 case REQ_RANGE_CONTINENT:
5173 case REQ_RANGE_PLAYER:
5174 case REQ_RANGE_TEAM:
5175 case REQ_RANGE_ALLIANCE:
5176 case REQ_RANGE_WORLD:
5177 case REQ_RANGE_COUNT:
5178 break;
5179 }
5180
5181 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
5182 req->range);
5183
5184 return TRI_MAYBE;
5185
5186 case CITYS_TRANSFERRED:
5187 switch (req->range) {
5188 case REQ_RANGE_CITY:
5189 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
5190 case REQ_RANGE_TRADE_ROUTE:
5191 {
5192 enum fc_tristate ret;
5193
5194 if (context->city->acquire_t != CACQ_FOUNDED) {
5195 return TRI_YES;
5196 }
5197
5198 ret = TRI_NO;
5199 trade_partners_iterate(context->city, trade_partner) {
5200 if (trade_partner == NULL) {
5201 ret = TRI_MAYBE;
5202 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
5203 return TRI_YES;
5204 }
5205 } trade_partners_iterate_end;
5206
5207 return ret;
5208 }
5209 case REQ_RANGE_LOCAL:
5210 case REQ_RANGE_TILE:
5211 case REQ_RANGE_CADJACENT:
5212 case REQ_RANGE_ADJACENT:
5213 case REQ_RANGE_CONTINENT:
5214 case REQ_RANGE_PLAYER:
5215 case REQ_RANGE_TEAM:
5216 case REQ_RANGE_ALLIANCE:
5217 case REQ_RANGE_WORLD:
5218 case REQ_RANGE_COUNT:
5219 break;
5220 }
5221
5222 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
5223 req->range);
5224
5225 return TRI_MAYBE;
5226
5227 case CITYS_LAST:
5228 break;
5229 }
5230
5231 /* Not implemented */
5232 log_error("is_req_active(): citystatus %d not supported.",
5233 citystatus);
5234
5235 return TRI_MAYBE;
5236}
5237
5238/**********************************************************************/
5245static enum fc_tristate
5246is_minsize_req_active(const struct civ_map *nmap,
5247 const struct req_context *context,
5248 const struct player *other_player,
5249 const struct requirement *req)
5250{
5251 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINSIZE);
5252
5253 if (context->city == NULL) {
5254 return TRI_MAYBE;
5255 } else {
5256 if (req->range == REQ_RANGE_TRADE_ROUTE) {
5257 enum fc_tristate ret;
5258
5259 if (city_size_get(context->city) >= req->source.value.minsize) {
5260 return TRI_YES;
5261 }
5262
5263 ret = TRI_NO;
5264 trade_partners_iterate(context->city, trade_partner) {
5265 if (trade_partner == NULL) {
5266 ret = TRI_MAYBE;
5267 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
5268 return TRI_YES;
5269 }
5270 } trade_partners_iterate_end;
5271
5272 return ret;
5273 } else {
5274 return BOOL_TO_TRISTATE(city_size_get(context->city)
5275 >= req->source.value.minsize);
5276 }
5277 }
5278}
5279
5280/**********************************************************************/
5287static enum fc_tristate
5288is_counter_req_active(const struct civ_map *nmap,
5289 const struct req_context *context,
5290 const struct player *other_player,
5291 const struct requirement *req)
5292{
5293 const struct counter *count;
5294
5295 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_COUNTER);
5296
5297 count = req->source.value.counter;
5298
5299 if (NULL == context->city) {
5300 return TRI_MAYBE;
5301 }
5302 return BOOL_TO_TRISTATE(count->checkpoint <=
5303 context->city->counter_values[
5304 counter_index(count)]);
5305}
5306
5307/**********************************************************************/
5315static enum fc_tristate
5316is_achievement_req_active(const struct civ_map *nmap,
5317 const struct req_context *context,
5318 const struct player *other_player,
5319 const struct requirement *req)
5320{
5321 const struct achievement *achievement;
5322
5323 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ACHIEVEMENT);
5324
5325 achievement = req->source.value.achievement;
5326
5327 if (req->range == REQ_RANGE_WORLD) {
5328 return BOOL_TO_TRISTATE(achievement_claimed(achievement));
5329 } else if (context->player == NULL) {
5330 return TRI_MAYBE;
5331 } else if (req->range == REQ_RANGE_ALLIANCE
5332 || req->range == REQ_RANGE_TEAM) {
5333 players_iterate_alive(plr2) {
5334 if (players_in_same_range(context->player, plr2, req->range)
5335 && achievement_player_has(achievement, plr2)) {
5336 return TRI_YES;
5337 }
5338 } players_iterate_alive_end;
5339 return TRI_NO;
5340 } else if (req->range == REQ_RANGE_PLAYER) {
5341 if (achievement_player_has(achievement, context->player)) {
5342 return TRI_YES;
5343 } else {
5344 return TRI_NO;
5345 }
5346 }
5347
5348 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
5349
5350 return TRI_MAYBE;
5351}
5352
5353/**********************************************************************/
5361static enum fc_tristate
5362is_latitude_req_active(const struct civ_map *nmap,
5363 const struct req_context *context,
5364 const struct player *other_player,
5365 const struct requirement *req)
5366{
5367 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
5368
5369 fc_assert_ret_val(req != NULL, TRI_MAYBE);
5370 fc_assert(context != NULL);
5371
5372 switch (req->source.kind) {
5373 case VUT_MINLATITUDE:
5374 min = req->source.value.latitude;
5375 break;
5376 case VUT_MAXLATITUDE:
5377 max = req->source.value.latitude;
5378 break;
5379 default:
5380 fc_assert(req->source.kind == VUT_MINLATITUDE
5381 || req->source.kind == VUT_MAXLATITUDE);
5382 break;
5383 }
5384
5385 switch (req->range) {
5386 case REQ_RANGE_WORLD:
5387 return BOOL_TO_TRISTATE(min <= MAP_MAX_REAL_LATITUDE(wld.map)
5388 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
5389
5390 case REQ_RANGE_TILE:
5391 if (context->tile == NULL) {
5392 return TRI_MAYBE;
5393 } else {
5394 int tile_lat = map_signed_latitude(context->tile);
5395
5396 return BOOL_TO_TRISTATE(min <= tile_lat && max >= tile_lat);
5397 }
5398
5399 case REQ_RANGE_CADJACENT:
5400 if (context->tile == NULL) {
5401 return TRI_MAYBE;
5402 }
5403
5404 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
5405 int tile_lat = map_signed_latitude(adjc_tile);
5406
5407 if (min <= tile_lat && max >= tile_lat) {
5408 return TRI_YES;
5409 }
5410 } cardinal_adjc_iterate_end;
5411 return TRI_NO;
5412
5413 case REQ_RANGE_ADJACENT:
5414 if (!context->tile) {
5415 return TRI_MAYBE;
5416 }
5417
5418 adjc_iterate(nmap, context->tile, adjc_tile) {
5419 int tile_lat = map_signed_latitude(adjc_tile);
5420
5421 if (min <= tile_lat && max >= tile_lat) {
5422 return TRI_YES;
5423 }
5424 } adjc_iterate_end;
5425 return TRI_NO;
5426
5427 case REQ_RANGE_CITY:
5428 case REQ_RANGE_TRADE_ROUTE:
5429 case REQ_RANGE_CONTINENT:
5430 case REQ_RANGE_PLAYER:
5431 case REQ_RANGE_TEAM:
5432 case REQ_RANGE_ALLIANCE:
5433 case REQ_RANGE_LOCAL:
5434 case REQ_RANGE_COUNT:
5435 break;
5436 }
5437
5438 fc_assert_msg(FALSE,
5439 "Illegal range %d for latitude requirement.", req->range);
5440
5441 return TRI_MAYBE;
5442}
5443
5444/**********************************************************************/
5451static enum fc_tristate
5452is_minyear_req_active(const struct civ_map *nmap,
5453 const struct req_context *context,
5454 const struct player *other_player,
5455 const struct requirement *req)
5456{
5457 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINYEAR);
5458
5459 return BOOL_TO_TRISTATE(game.info.year >= req->source.value.minyear);
5460}
5461
5462/**********************************************************************/
5469static enum fc_tristate
5470is_mincalfrag_req_active(const struct civ_map *nmap,
5471 const struct req_context *context,
5472 const struct player *other_player,
5473 const struct requirement *req)
5474{
5475 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINCALFRAG);
5476
5477 return BOOL_TO_TRISTATE(game.info.fragment_count
5478 >= req->source.value.mincalfrag);
5479}
5480
5481/**********************************************************************/
5488static enum fc_tristate
5489is_topology_req_active(const struct civ_map *nmap,
5490 const struct req_context *context,
5491 const struct player *other_player,
5492 const struct requirement *req)
5493{
5494 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TOPO);
5495
5496 return BOOL_TO_TRISTATE(
5497 current_topo_has_flag(req->source.value.topo_property));
5498}
5499
5500/**********************************************************************/
5507static enum fc_tristate
5508is_wrap_req_active(const struct civ_map *nmap,
5509 const struct req_context *context,
5510 const struct player *other_player,
5511 const struct requirement *req)
5512{
5513 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_WRAP);
5514
5515 return BOOL_TO_TRISTATE(
5516 current_wrap_has_flag(req->source.value.wrap_property));
5517}
5518
5519/**********************************************************************/
5527static enum fc_tristate
5528is_serversetting_req_active(const struct civ_map *nmap,
5529 const struct req_context *context,
5530 const struct player *other_player,
5531 const struct requirement *req)
5532{
5533 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_SERVERSETTING);
5534
5535 return BOOL_TO_TRISTATE(ssetv_setting_has_value(
5536 req->source.value.ssetval));
5537}
5538
5539/* Not const for potential ruleset-related adjustment */
5540 static struct req_def req_definitions[VUT_COUNT] = {
5541 [VUT_NONE] = {is_none_req_active, REQUCH_YES},
5542
5543 /* Alphabetical order of enum constant */
5544 [VUT_ACHIEVEMENT] = {is_achievement_req_active, REQUCH_YES, REQUC_PRESENT},
5545 [VUT_ACTION] = {is_action_req_active, REQUCH_YES},
5546 [VUT_ACTIVITY] = {is_activity_req_active, REQUCH_NO},
5547 [VUT_ADVANCE] = {is_tech_req_active, REQUCH_NO},
5548 [VUT_AGE] = {is_age_req_active, REQUCH_YES, REQUC_PRESENT},
5549 [VUT_FORM_AGE] = {is_form_age_req_active, REQUCH_YES, REQUC_PRESENT},
5550 [VUT_AI_LEVEL] = {is_ai_req_active, REQUCH_HACK},
5551 [VUT_CITYSTATUS] = {is_citystatus_req_active, REQUCH_NO, REQUC_CITYSTATUS},
5552 [VUT_CITYTILE] = {is_citytile_req_active, REQUCH_NO, REQUC_CITYTILE},
5553 [VUT_COUNTER] = {is_counter_req_active, REQUCH_NO},
5554 [VUT_DIPLREL] = {is_diplrel_req_active, REQUCH_NO},
5555 [VUT_DIPLREL_TILE] = {is_diplrel_tile_req_active, REQUCH_NO},
5556 [VUT_DIPLREL_TILE_O] = {is_diplrel_tile_o_req_active, REQUCH_NO},
5557 [VUT_DIPLREL_UNITANY] = {is_diplrel_unitany_req_active, REQUCH_NO},
5558 [VUT_DIPLREL_UNITANY_O] = {is_diplrel_unitany_o_req_active, REQUCH_NO},
5559 [VUT_EXTRA] = {is_extra_req_active, REQUCH_NO, REQUC_LOCAL},
5560 [VUT_EXTRAFLAG] = {is_extraflag_req_active, REQUCH_NO, REQUC_LOCAL},
5561 [VUT_GOOD] = {is_good_req_active, REQUCH_NO},
5562 [VUT_GOVERNMENT] = {is_gov_req_active, REQUCH_NO},
5563 [VUT_IMPROVEMENT] = {is_building_req_active, REQUCH_NO, REQUC_IMPR},
5564 [VUT_IMPR_GENUS] = {is_buildinggenus_req_active, REQUCH_YES},
5565 [VUT_IMPR_FLAG] = {is_buildingflag_req_active, REQUCH_YES},
5566 [VUT_PLAYER_FLAG] = {is_plr_flag_req_active, REQUCH_NO},
5567 [VUT_PLAYER_STATE] = {is_plr_state_req_active, REQUCH_NO},
5568 [VUT_MAXLATITUDE] = {is_latitude_req_active, REQUCH_YES},
5569 [VUT_MAXTILEUNITS] = {is_maxunitsontile_req_active, REQUCH_NO},
5570 [VUT_MINCALFRAG] = {is_mincalfrag_req_active, REQUCH_NO},
5571 [VUT_MINCULTURE] = {is_minculture_req_active, REQUCH_NO},
5572 [VUT_MINFOREIGNPCT] = {is_minforeignpct_req_active, REQUCH_NO},
5573 [VUT_MINHP] = {is_minhitpoints_req_active, REQUCH_NO},
5574 [VUT_MINLATITUDE] = {is_latitude_req_active, REQUCH_NO},
5575 [VUT_MINMOVES] = {is_minmovefrags_req_active, REQUCH_NO},
5576 [VUT_MINSIZE] = {is_minsize_req_active, REQUCH_NO},
5577 [VUT_MINTECHS] = {is_mintechs_req_active, REQUCH_ACT, REQUC_WORLD},
5578 [VUT_MINCITIES] = {is_mincities_req_active, REQUCH_NO},
5579 [VUT_MINVETERAN] = {is_minveteran_req_active, REQUCH_SCRIPTS, REQUC_PRESENT},
5580 [VUT_MINYEAR] = {is_minyear_req_active, REQUCH_HACK, REQUC_PRESENT},
5581 [VUT_NATION] = {is_nation_req_active, REQUCH_HACK, REQUC_NALLY},
5582 [VUT_NATIONALITY] = {is_nationality_req_active, REQUCH_NO},
5583 [VUT_NATIONGROUP] = {is_nationgroup_req_active, REQUCH_HACK, REQUC_NALLY},
5584 [VUT_ORIGINAL_OWNER] = {is_originalowner_req_active, REQUCH_HACK},
5585 [VUT_OTYPE] = {is_outputtype_req_active, REQUCH_YES},
5586 [VUT_ROADFLAG] = {is_roadflag_req_active, REQUCH_NO, REQUC_LOCAL},
5587 [VUT_SERVERSETTING] = {is_serversetting_req_active, REQUCH_HACK},
5588 [VUT_SPECIALIST] = {is_specialist_req_active, REQUCH_YES},
5589 [VUT_STYLE] = {is_style_req_active, REQUCH_HACK},
5590 [VUT_TECHFLAG] = {is_techflag_req_active, REQUCH_NO},
5591 [VUT_TERRAIN] = {is_terrain_req_active, REQUCH_NO},
5592 [VUT_TERRAINALTER] = {is_terrainalter_req_active, REQUCH_NO},
5593 [VUT_TERRAINCLASS] = {is_terrainclass_req_active, REQUCH_NO},
5594 [VUT_TERRFLAG] = {is_terrainflag_req_active, REQUCH_NO},
5595 [VUT_TOPO] = {is_topology_req_active, REQUCH_YES},
5596 [VUT_WRAP] = {is_wrap_req_active, REQUCH_YES},
5597 [VUT_UCFLAG] = {is_unitclassflag_req_active, REQUCH_YES},
5598 [VUT_UCLASS] = {is_unitclass_req_active, REQUCH_YES},
5599 [VUT_UNITSTATE] = {is_unitstate_req_active, REQUCH_NO},
5600 [VUT_UTFLAG] = {is_unitflag_req_active, REQUCH_YES},
5601 [VUT_UTYPE] = {is_unittype_req_active, REQUCH_YES}
5602};
5603
5604/**********************************************************************/
5616 bool is_req_active(const struct req_context *context,
5617 const struct player *other_player,
5618 const struct requirement *req,
5619 const enum req_problem_type prob_type)
5620{
5621 const struct civ_map *nmap = &(wld.map);
5622 enum fc_tristate eval = tri_req_present(nmap, context, other_player, req);
5623
5624 if (eval == TRI_MAYBE) {
5625 if (prob_type == RPT_POSSIBLE) {
5626 return TRUE;
5627 } else {
5628 return FALSE;
5629 }
5630 }
5631 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
5632}
5633
5634/**********************************************************************/
5642static
5643 enum fc_tristate tri_req_present(const struct civ_map *nmap,
5644 const struct req_context *context,
5645 const struct player *other_player,
5646 const struct requirement *req)
5647{
5648 if (context == NULL) {
5649 context = req_context_empty();
5650 }
5651
5652 if (req->source.kind >= VUT_COUNT) {
5653 log_error("tri_req_present(): invalid source kind %d.",
5654 req->source.kind);
5655 return TRI_NO;
5656 }
5657
5658 fc_assert_ret_val(req_definitions[req->source.kind].cb != NULL, TRI_NO);
5659
5660 return req_definitions[req->source.kind].cb(nmap, context,
5661 other_player, req);
5662}
5663
5664/**********************************************************************/
5672 enum fc_tristate tri_req_active(const struct req_context *context,
5673 const struct player *other_player,
5674 const struct requirement *req)
5675{
5676 const struct civ_map *nmap = &(wld.map);
5677 enum fc_tristate eval = tri_req_present(nmap, context, other_player, req);
5678
5679 if (!req->present) {
5680 if (TRI_NO == eval) {
5681 return TRI_YES;
5682 }
5683 if (TRI_YES == eval) {
5684 return TRI_NO;
5685 }
5686 }
5687
5688 return eval;
5689}
5690
5691/**********************************************************************/
5705 bool are_reqs_active(const struct req_context *context,
5706 const struct player *other_player,
5707 const struct requirement_vector *reqs,
5708 const enum req_problem_type prob_type)
5709{
5710 requirement_vector_iterate(reqs, preq) {
5711 if (!is_req_active(context, other_player, preq, prob_type)) {
5712 return FALSE;
5713 }
5714 } requirement_vector_iterate_end;
5715
5716 return TRUE;
5717}
5718
5719/**********************************************************************/
5723 bool are_reqs_active_ranges(const enum req_range min_range,
5724 const enum req_range max_range,
5725 const struct req_context *context,
5726 const struct player *other_player,
5727 const struct requirement_vector *reqs,
5728 const enum req_problem_type prob_type)
5729{
5730 requirement_vector_iterate(reqs, preq) {
5731 if (preq->range >= min_range && preq->range <= max_range) {
5732 if (!is_req_active(context, other_player, preq, prob_type)) {
5733 return FALSE;
5734 }
5735 }
5736 } requirement_vector_iterate_end;
5737
5738 return TRUE;
5739}
5740
5741/**********************************************************************/
5747enum fc_tristate
5748tri_req_active_turns(int pass, int period,
5749 const struct req_context *context,
5750 const struct player *other_player,
5751 const struct requirement *req)
5752{
5753 /* FIXME: doubles code from calendar.c */
5754 int ypt = get_world_bonus(EFT_TURN_YEARS);
5755 int fpt = get_world_bonus(EFT_TURN_FRAGMENTS);
5756 int fragment = game.info.fragment_count;
5757 int fragment1 = fragment; /* if fragments don't advance */
5758 int year_inc, year_inc1;
5759 const int slowdown = (victory_enabled(VC_SPACERACE)
5760 ? get_world_bonus(EFT_SLOW_DOWN_TIMELINE) : 0);
5761 bool present, present1;
5762
5763 fc_assert(pass >= 0 && period >= 0);
5764 if (slowdown >= 3) {
5765 if (ypt > 1) {
5766 ypt = 1;
5767 }
5768 } else if (slowdown >= 2) {
5769 if (ypt > 2) {
5770 ypt = 2;
5771 }
5772 } else if (slowdown >= 1) {
5773 if (ypt > 5) {
5774 ypt = 5;
5775 }
5776 }
5777 year_inc = ypt * pass;
5778 year_inc1 = year_inc + ypt * period;
5779 if (game.calendar.calendar_fragments) {
5780 int fragment_years;
5781
5782 fragment += fpt * pass;
5783 fragment_years = fragment / game.calendar.calendar_fragments;
5784 year_inc += fragment_years;
5785 fragment -= fragment_years * game.calendar.calendar_fragments;
5786 fragment1 = fragment + fpt * period;
5787 fragment_years += fragment1 / game.calendar.calendar_fragments;
5788 year_inc1 += fragment_years;
5789 fragment1 -= fragment_years * game.calendar.calendar_fragments;
5790 }
5791 if (game.calendar.calendar_skip_0 && game.info.year < 0) {
5792 if (year_inc + game.info.year >= 0) {
5793 year_inc++;
5794 year_inc1++;
5795 } else if (year_inc1 + game.info.year >= 0) {
5796 year_inc1++;
5797 }
5798 }
5799
5800 switch (req->source.kind) {
5801 case VUT_AGE:
5802 switch (req->range) {
5803 case REQ_RANGE_LOCAL:
5804 if (context->unit == NULL || !is_server()) {
5805 return TRI_MAYBE;
5806 } else {
5807 int ua = game.info.turn + pass - context->unit->birth_turn;
5808
5809 present = req->source.value.age <= ua;
5810 present1 = req->source.value.age <= ua + period;
5811 }
5812 break;
5813 case REQ_RANGE_CITY:
5814 if (context->city == NULL) {
5815 return TRI_MAYBE;
5816 } else {
5817 int ca = game.info.turn + pass - context->city->turn_founded;
5818
5819 present = req->source.value.age <= ca;
5820 present1 = req->source.value.age <= ca + period;
5821 }
5822 break;
5823 case REQ_RANGE_PLAYER:
5824 if (context->player == NULL) {
5825 return TRI_MAYBE;
5826 } else {
5827 present = req->source.value.age
5828 <= player_age(context->player) + pass;
5829 present1 = req->source.value.age
5830 <= player_age(context->player) + pass + period;
5831 }
5832 break;
5833 default:
5834 return TRI_MAYBE;
5835 }
5836 break;
5837 case VUT_FORM_AGE:
5838 if (context->unit == NULL || !is_server()) {
5839 return TRI_MAYBE;
5840 } else {
5841 int ua = game.info.turn + pass - context->unit->current_form_turn;
5842
5843 present = req->source.value.form_age <= ua;
5844 present1 = req->source.value.form_age <= ua + period;
5845 }
5846 break;
5847 case VUT_MINYEAR:
5848 present = game.info.year + year_inc >= req->source.value.minyear;
5849 present1 = game.info.year + year_inc1 >= req->source.value.minyear;
5850 break;
5851 case VUT_MINCALFRAG:
5852 if (game.calendar.calendar_fragments <= period) {
5853 /* Hope that the requirement is valid and fragments advance fine */
5854 return TRI_YES;
5855 }
5856 present = fragment >= req->source.value.mincalfrag;
5857 present1 = fragment1 >= req->source.value.mincalfrag;
5858 break;
5859 default:
5860 /* No special handling invented */
5861 return tri_req_active(context, other_player, req);
5862 }
5863 return BOOL_TO_TRISTATE(req->present
5864 ? present || present1 : !(present && present1));
5865}
5866
5867/**********************************************************************/
5872 enum fc_tristate default_tester_cb
5873 (const struct req_context *context,
5874 const struct player *other_player,
5875 const struct requirement *req,
5876 void *data, int n_data)
5877{
5878 int i;
5879
5880 fc_assert_ret_val(data || n_data == 0, TRI_NO);
5881
5882 for (i = 0; i < n_data; i++) {
5883 if (are_requirements_contradictions(&((struct requirement *) data)[i],
5884 req)) {
5885 return TRI_NO;
5886 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
5887 return TRI_YES;
5888 }
5889 }
5890
5891 return tri_req_active(context, other_player, req);
5892}
5893
5894/**********************************************************************/
5900enum fc_tristate
5901 tri_reqs_cb_active(const struct req_context *context,
5902 const struct player *other_player,
5903 const struct requirement_vector *reqs,
5904 struct requirement_vector *maybe_reqs,
5905 req_tester_cb tester,
5906 void *data, int n_data)
5907{
5908 bool active = TRUE;
5909 bool certain = TRUE;
5910
5911 fc_assert_ret_val(NULL != tester, TRI_NO);
5912 requirement_vector_iterate(reqs, preq) {
5913 switch(tester(context, other_player, preq,
5914 data, n_data)) {
5915 case TRI_NO:
5916 active = FALSE;
5917 certain = TRUE;
5918 break;
5919 case TRI_YES:
5920 break;
5921 case TRI_MAYBE:
5922 certain = FALSE;
5923 if (maybe_reqs) {
5924 requirement_vector_append(maybe_reqs, *preq);
5925 }
5926 break;
5927 default:
5928 fc_assert(FALSE);
5929 active = FALSE;
5930 }
5931 if (!active) {
5932 break;
5933 }
5934 } requirement_vector_iterate_end;
5935
5936 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
5937}
5938
5939/**********************************************************************/
5947enum req_unchanging_status
5948 is_req_unchanging(const struct req_context *context,
5949 const struct requirement *req)
5950{
5951 enum req_unchanging_status s;
5952 const struct civ_map *nmap = &(wld.map);
5953
5954 fc_assert_ret_val(req, REQUCH_NO);
5955 fc_assert_ret_val_msg(universals_n_is_valid(req->source.kind), REQUCH_NO,
5956 "Invalid source kind %d.", req->source.kind);
5957 s = req_definitions[req->source.kind].unchanging;
5958
5959 if (req->survives) {
5960 /* Special case for surviving requirements */
5961 /* Buildings may obsolete even here */
5962 if (VUT_IMPROVEMENT == req->source.kind) {
5963 const struct impr_type *b = req->source.value.building;
5964
5965 if (can_improvement_go_obsolete(b)) {
5966 if (improvement_obsolete(context->player, b, context->city)) {
5967 /* FIXME: sometimes can unobsolete, but considering it
5968 * may sometimes put the function on endless recursion */
5969 return REQUCH_ACT; /* Mostly about techs */
5970 } else {
5971 /* NOTE: may obsoletion reqs be unchanging? Hardly but why not. */
5972 return REQUCH_NO;
5973 }
5974 }
5975 }
5976 s = unchanging_present(nmap, s, context, req);
5977 if (s != REQUCH_NO) {
5978 return unchanging_noally(nmap, s, context, req);
5979 }
5980 } else {
5981 req_unchanging_cond_cb cond
5982 = req_definitions[req->source.kind].unchanging_cond;
5983
5984 if (cond) {
5985 return cond(nmap, s, context, req);
5986 }
5987 }
5988
5989 return s;
5990}
5991
5992/**********************************************************************/
5995enum req_unchanging_status
5996 is_req_preventing(const struct req_context *context,
5997 const struct player *other_player,
5998 const struct requirement *req,
5999 enum req_problem_type prob_type)
6000{
6001 enum req_unchanging_status u = is_req_unchanging(context, req);
6002
6003 if (REQUCH_NO != u) {
6004 /* presence is precalculated */
6005 bool auto_present = (req->survives
6006 && !(VUT_IMPROVEMENT == req->source.kind
6007 && can_improvement_go_obsolete(req->source.value.building)))
6008 || REQUC_PRESENT == req_definitions[req->source.kind].unchanging_cond
6009 || REQUC_WORLD == req_definitions[req->source.kind].unchanging_cond;
6010
6011 if (auto_present ? req->present
6012 : is_req_active(context, other_player, req, RPT_POSSIBLE)) {
6013 /* Unchanging but does not block */
6014 return REQUCH_NO;
6015 }
6016 }
6017
6018 return u;
6019}
6020
6021/**********************************************************************/
6025 bool is_req_in_vec(const struct requirement *req,
6026 const struct requirement_vector *vec)
6027{
6028 requirement_vector_iterate(vec, preq) {
6029 if (are_requirements_equal(req, preq)) {
6030 return TRUE;
6031 }
6032 } requirement_vector_iterate_end;
6033
6034 return FALSE;
6035}
6036
6037/**********************************************************************/
6043 bool req_vec_wants_type(const struct requirement_vector *reqs,
6044 enum universals_n kind)
6045{
6046 requirement_vector_iterate(reqs, preq) {
6047 if (preq->present && preq->source.kind == kind) {
6048 return TRUE;
6049 }
6050 } requirement_vector_iterate_end;
6051 return FALSE;
6052}
6053
6054/**********************************************************************/
6062 bool universal_never_there(const struct universal *source)
6063{
6064 switch (source->kind) {
6065 case VUT_ACTION:
6066 return !action_is_in_use(source->value.action);
6067 case VUT_UTFLAG:
6068 return !utype_flag_is_in_use(source->value.unitflag);
6069 case VUT_UCFLAG:
6070 return !uclass_flag_is_in_use(source->value.unitclassflag);
6071 case VUT_EXTRAFLAG:
6072 return !extra_flag_is_in_use(source->value.extraflag);
6073 case VUT_MINLATITUDE:
6074 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
6075 case VUT_MAXLATITUDE:
6076 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
6077 case VUT_COUNTER:
6078 case VUT_OTYPE:
6079 case VUT_SPECIALIST:
6080 case VUT_AI_LEVEL:
6081 case VUT_CITYTILE:
6082 case VUT_CITYSTATUS:
6083 case VUT_STYLE:
6084 case VUT_TOPO:
6085 case VUT_WRAP:
6086 case VUT_SERVERSETTING:
6087 case VUT_NATION:
6088 case VUT_NATIONGROUP:
6089 case VUT_ADVANCE:
6090 case VUT_TECHFLAG:
6091 case VUT_GOVERNMENT:
6092 case VUT_ACHIEVEMENT:
6093 case VUT_IMPROVEMENT:
6094 case VUT_IMPR_GENUS:
6095 case VUT_IMPR_FLAG:
6096 case VUT_PLAYER_FLAG:
6097 case VUT_PLAYER_STATE:
6098 case VUT_MINSIZE:
6099 case VUT_MINCULTURE:
6100 case VUT_MINFOREIGNPCT:
6101 case VUT_MINTECHS:
6102 case VUT_MINCITIES:
6103 case VUT_NATIONALITY:
6104 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
6105 case VUT_DIPLREL:
6106 case VUT_DIPLREL_TILE:
6107 case VUT_DIPLREL_TILE_O:
6108 case VUT_DIPLREL_UNITANY:
6109 case VUT_DIPLREL_UNITANY_O:
6110 case VUT_MAXTILEUNITS:
6111 case VUT_UTYPE:
6112 case VUT_UCLASS:
6113 case VUT_MINVETERAN:
6114 case VUT_UNITSTATE:
6115 case VUT_ACTIVITY:
6116 case VUT_MINMOVES:
6117 case VUT_MINHP:
6118 case VUT_AGE:
6119 case VUT_FORM_AGE:
6120 case VUT_ROADFLAG:
6121 case VUT_MINCALFRAG:
6122 case VUT_TERRAIN:
6123 case VUT_EXTRA:
6124 case VUT_GOOD:
6125 case VUT_TERRAINCLASS:
6126 case VUT_TERRFLAG:
6127 case VUT_TERRAINALTER:
6128 case VUT_MINYEAR:
6129 case VUT_NONE:
6130 case VUT_COUNT:
6131 /* Not implemented. */
6132 break;
6133 }
6134
6135 return FALSE;
6136}
6137
6138/**********************************************************************/
6145 bool req_is_impossible_to_fulfill(const struct requirement *req)
6146{
6147 /* Not known to be impossible to fulfill */
6148 return req->present && universal_never_there(&req->source);
6149}
6150
6151/**********************************************************************/
6158 bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
6159{
6160 requirement_vector_iterate(reqs, preq) {
6161 if (req_is_impossible_to_fulfill(preq)) {
6162 return TRUE;
6163 }
6164 } requirement_vector_iterate_end;
6165
6166 /* Not known to be impossible to fulfill */
6167 return FALSE;
6168}
6169
6170/**********************************************************************/
6177 req_vec_num_in_item
6178req_vec_vector_number(const void *parent_item,
6179 const struct requirement_vector *vec)
6180{
6181 if (vec) {
6182 return 0;
6183 } else {
6184 return -1;
6185 }
6186}
6187
6188/********************************************************************/
6196struct requirement_vector *
6197req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
6198{
6199 fc_assert_ret_val(number == 0, NULL);
6200 return (struct requirement_vector *)parent_item;
6201}
6202
6203/**********************************************************************/
6213 const char *req_vec_change_translation(const struct req_vec_change *change,
6214 const requirement_vector_namer namer)
6215{
6216 const char *req_vec_description;
6217 static char buf[MAX_LEN_NAME * 3];
6218 struct astring astr;
6219
6220 fc_assert_ret_val(change, NULL);
6221 fc_assert_ret_val(req_vec_change_operation_is_valid(change->operation),
6222 NULL);
6223
6224 /* Get rid of the previous. */
6225 buf[0] = '\0';
6226
6227 if (namer == NULL) {
6228 /* TRANS: default description of a requirement vector
6229 * (used in ruledit) */
6230 req_vec_description = _("the requirement vector");
6231 } else {
6232 req_vec_description = namer(change->vector_number);
6233 }
6234
6235 switch (change->operation) {
6236 case RVCO_REMOVE:
6237 fc_snprintf(buf, sizeof(buf),
6238 /* TRANS: remove a requirement from a requirement vector
6239 * (in ruledit).
6240 * The first %s is the operation.
6241 * The second %s is the requirement.
6242 * The third %s is a description of the requirement vector,
6243 * like "actor_reqs" */
6244 _("%s %s from %s"),
6245 req_vec_change_operation_name(change->operation),
6246 req_to_fstring(&change->req, &astr),
6247 req_vec_description);
6248 astr_free(&astr);
6249 break;
6250 case RVCO_APPEND:
6251 fc_snprintf(buf, sizeof(buf),
6252 /* TRANS: append a requirement to a requirement vector
6253 * (in ruledit).
6254 * The first %s is the operation.
6255 * The second %s is the requirement.
6256 * The third %s is a description of the requirement vector,
6257 * like "actor_reqs" */
6258 _("%s %s to %s"),
6259 req_vec_change_operation_name(change->operation),
6260 req_to_fstring(&change->req, &astr),
6261 req_vec_description);
6262 astr_free(&astr);
6263 break;
6264 case RVCO_NOOP:
6265 fc_snprintf(buf, sizeof(buf),
6266 /* TRANS: do nothing to a requirement vector (in ruledit).
6267 * The first %s is a description of the requirement vector,
6268 * like "actor_reqs" */
6269 _("Do nothing to %s"), req_vec_description);
6270 break;
6271 }
6272
6273 return buf;
6274}
6275
6276/**********************************************************************/
6286 bool req_vec_change_apply(const struct req_vec_change *modification,
6287 requirement_vector_by_number getter,
6288 const void *parent_item)
6289{
6290 struct requirement_vector *target
6291 = getter(parent_item, modification->vector_number);
6292 int i = 0;
6293
6294 switch (modification->operation) {
6295 case RVCO_APPEND:
6296 requirement_vector_append(target, modification->req);
6297 return TRUE;
6298 case RVCO_REMOVE:
6299 requirement_vector_iterate(target, preq) {
6300 if (are_requirements_equal(&modification->req, preq)) {
6301 requirement_vector_remove(target, i);
6302 return TRUE;
6303 }
6304 i++;
6305 } requirement_vector_iterate_end;
6306 return FALSE;
6307 case RVCO_NOOP:
6308 return FALSE;
6309 }
6310
6311 return FALSE;
6312}
6313
6314/**********************************************************************/
6323struct req_vec_problem *
6324req_vec_problem_new_transl(int num_suggested_solutions,
6325 const char *description,
6326 const char *description_translated)
6327{
6328 struct req_vec_problem *out;
6329 int i;
6330
6331 out = fc_malloc(sizeof(*out));
6332
6333 fc_strlcpy(out->description, description, sizeof(out->description));
6334 fc_strlcpy(out->description_translated, _(description_translated),
6335 sizeof(out->description_translated));
6336
6337 out->num_suggested_solutions = num_suggested_solutions;
6338 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
6339 * sizeof(struct req_vec_change));
6340 for (i = 0; i < out->num_suggested_solutions; i++) {
6341 /* No suggestions are ready yet. */
6342 out->suggested_solutions[i].operation = RVCO_NOOP;
6343 out->suggested_solutions[i].vector_number = -1;
6344 out->suggested_solutions[i].req.source.kind = VUT_NONE;
6345 }
6346
6347 return out;
6348}
6349
6350/**********************************************************************/
6358 struct req_vec_problem *req_vec_problem_new(int num_suggested_solutions,
6359 const char *descr, ...)
6360{
6361 char description[500];
6362 char description_translated[500];
6363 va_list ap;
6364
6365 va_start(ap, descr);
6366 fc_vsnprintf(description, sizeof(description), descr, ap);
6367 va_end(ap);
6368
6369 va_start(ap, descr);
6370 fc_vsnprintf(description_translated, sizeof(description_translated),
6371 _(descr), ap);
6372 va_end(ap);
6373
6374 return req_vec_problem_new_transl(num_suggested_solutions,
6375 description, description_translated);
6376}
6377
6378/**********************************************************************/
6383 void req_vec_problem_free(struct req_vec_problem *issue)
6384{
6385 FC_FREE(issue->suggested_solutions);
6386 issue->num_suggested_solutions = 0;
6387
6388 FC_FREE(issue);
6389}
6390
6391/**********************************************************************/
6402struct req_vec_problem *
6403req_vec_get_first_contradiction(const struct requirement_vector *vec,
6404 requirement_vector_number get_num,
6405 const void *parent_item)
6406{
6407 int i, j;
6408 req_vec_num_in_item vec_num;
6409
6410 if (vec == NULL || requirement_vector_size(vec) == 0) {
6411 /* No vector. */
6412 return NULL;
6413 }
6414
6415 if (get_num == NULL || parent_item == NULL) {
6416 vec_num = 0;
6417 } else {
6418 vec_num = get_num(parent_item, vec);
6419 }
6420
6421 /* Look for contradictions */
6422 for (i = 0; i < requirement_vector_size(vec); i++) {
6423 struct requirement *preq = requirement_vector_get(vec, i);
6424 for (j = 0; j < requirement_vector_size(vec); j++) {
6425 struct requirement *nreq = requirement_vector_get(vec, j);
6426
6427 if (are_requirements_contradictions(preq, nreq)) {
6428 struct req_vec_problem *problem;
6429 struct astring astr;
6430 struct astring nastr;
6431
6432 problem = req_vec_problem_new(2,
6433 N_("Requirements {%s} and {%s} contradict each other."),
6434 req_to_fstring(preq, &astr), req_to_fstring(nreq, &nastr));
6435
6436 astr_free(&astr);
6437 astr_free(&nastr);
6438
6439 /* The solution is to remove one of the contradictions. */
6440 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6441 problem->suggested_solutions[0].vector_number = vec_num;
6442 problem->suggested_solutions[0].req = *preq;
6443
6444 problem->suggested_solutions[1].operation = RVCO_REMOVE;
6445 problem->suggested_solutions[1].vector_number = vec_num;
6446 problem->suggested_solutions[1].req = *nreq;
6447
6448 /* Only the first contradiction is reported. */
6449 return problem;
6450 }
6451 }
6452 }
6453
6454 return NULL;
6455}
6456
6457/**********************************************************************/
6467struct req_vec_problem *
6468req_vec_suggest_repair(const struct requirement_vector *vec,
6469 requirement_vector_number get_num,
6470 const void *parent_item)
6471{
6472 /* Check for self contradictins. */
6473 return req_vec_get_first_contradiction(vec, get_num, parent_item);
6474}
6475
6476/**********************************************************************/
6488struct req_vec_problem *
6489req_vec_get_first_missing_univ(const struct requirement_vector *vec,
6490 requirement_vector_number get_num,
6491 const void *parent_item)
6492{
6493 int i;
6494 req_vec_num_in_item vec_num;
6495 struct req_vec_problem *problem = NULL;
6496
6497 if (vec == NULL || requirement_vector_size(vec) == 0) {
6498 /* No vector. */
6499 return NULL;
6500 }
6501
6502 if (get_num == NULL || parent_item == NULL) {
6503 vec_num = 0;
6504 } else {
6505 vec_num = get_num(parent_item, vec);
6506 }
6507
6508 /* Look for contradictions */
6509 for (i = 0; i < requirement_vector_size(vec); i++) {
6510 struct requirement *preq = requirement_vector_get(vec, i);
6511
6512 if (universal_never_there(&preq->source)) {
6513 struct astring astr;
6514
6515 if (preq->present) {
6516 /* The requirement vector can never be fulfilled. Removing the
6517 * requirement makes it possible to fulfill it. This is a rule
6518 * change and shouldn't be "fixed" without thinking. Don't offer any
6519 * automatic solution to prevent mindless "fixes". */
6520 /* TRANS: ruledit warns a user about an unused requirement vector
6521 * that never can be fulfilled because it asks for something that
6522 * never will be there. */
6523 if (problem == NULL) {
6524 problem = req_vec_problem_new(0,
6525 N_("Requirement {%s} requires %s but it will never be"
6526 " there."),
6527 req_to_fstring(preq, &astr), universal_rule_name(&preq->source));
6528 astr_free(&astr);
6529 }
6530
6531 /* Continue to check if other problems have a solution proposal,
6532 * and prefer to return those. */
6533 continue;
6534 }
6535
6536 if (problem != NULL) {
6537 /* Free previous one (one with no solution proposals) */
6538 req_vec_problem_free(problem);
6539 }
6540
6541 problem = req_vec_problem_new(1,
6542 N_("Requirement {%s} mentions %s but it will never be there."),
6543 req_to_fstring(preq, &astr), universal_rule_name(&preq->source));
6544
6545 astr_free(&astr);
6546
6547 /* The solution is to remove the reference to the missing
6548 * universal. */
6549 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6550 problem->suggested_solutions[0].vector_number = vec_num;
6551 problem->suggested_solutions[0].req = *preq;
6552
6553 /* Only the first missing universal is reported. */
6554 return problem;
6555 }
6556 }
6557
6558 return problem;
6559}
6560
6561/**********************************************************************/
6573struct req_vec_problem *
6574req_vec_get_first_redundant_req(const struct requirement_vector *vec,
6575 requirement_vector_number get_num,
6576 const void *parent_item)
6577{
6578 int i, j;
6579 req_vec_num_in_item vec_num;
6580
6581 if (vec == NULL || requirement_vector_size(vec) == 0) {
6582 /* No vector. */
6583 return NULL;
6584 }
6585
6586 if (get_num == NULL || parent_item == NULL) {
6587 vec_num = 0;
6588 } else {
6589 vec_num = get_num(parent_item, vec);
6590 }
6591
6592 /* Look for repeated requirements */
6593 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
6594 struct requirement *preq = requirement_vector_get(vec, i);
6595 for (j = i + 1; j < requirement_vector_size(vec); j++) {
6596 struct requirement *nreq = requirement_vector_get(vec, j);
6597
6598 if (are_requirements_equal(preq, nreq)) {
6599 struct req_vec_problem *problem;
6600 struct astring astr;
6601 struct astring nastr;
6602
6603 problem = req_vec_problem_new(2,
6604 N_("Requirements {%s} and {%s} are the same."),
6605 req_to_fstring(preq, &astr), req_to_fstring(nreq, &nastr));
6606
6607 astr_free(&astr);
6608 astr_free(&nastr);
6609
6610 /* The solution is to remove one of the redundant requirements. */
6611 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6612 problem->suggested_solutions[0].vector_number = vec_num;
6613 problem->suggested_solutions[0].req = *preq;
6614
6615 problem->suggested_solutions[1].operation = RVCO_REMOVE;
6616 problem->suggested_solutions[1].vector_number = vec_num;
6617 problem->suggested_solutions[1].req = *nreq;
6618
6619 /* Only the first redundancy is reported. */
6620 return problem;
6621 }
6622 }
6623 }
6624
6625 return NULL;
6626}
6627
6628/**********************************************************************/
6639struct req_vec_problem *
6640req_vec_suggest_improvement(const struct requirement_vector *vec,
6641 requirement_vector_number get_num,
6642 const void *parent_item)
6643{
6644 struct req_vec_problem *out;
6645
6646 out = req_vec_suggest_repair(vec, get_num, parent_item);
6647 if (out != NULL) {
6648 /* A bug, not just a potential improvement */
6649 return out;
6650 }
6651
6652 /* Check if a universal that never will appear in the game is checked. */
6653 out = req_vec_get_first_missing_univ(vec, get_num, parent_item);
6654 if (out != NULL) {
6655 return out;
6656 }
6657
6658 /* Check if a requirement is redundant. */
6659 out = req_vec_get_first_redundant_req(vec, get_num, parent_item);
6660 return out;
6661}
6662
6663/**********************************************************************/
6667 bool are_universals_equal(const struct universal *psource1,
6668 const struct universal *psource2)
6669{
6670 if (psource1->kind != psource2->kind) {
6671 return FALSE;
6672 }
6673 switch (psource1->kind) {
6674 case VUT_NONE:
6675 return TRUE;
6676 case VUT_COUNTER:
6677 return psource1->value.counter == psource2->value.counter;
6678 case VUT_ADVANCE:
6679 return psource1->value.advance == psource2->value.advance;
6680 case VUT_TECHFLAG:
6681 return psource1->value.techflag == psource2->value.techflag;
6682 case VUT_GOVERNMENT:
6683 return psource1->value.govern == psource2->value.govern;
6684 case VUT_ACHIEVEMENT:
6685 return psource1->value.achievement == psource2->value.achievement;
6686 case VUT_STYLE:
6687 return psource1->value.style == psource2->value.style;
6688 case VUT_IMPROVEMENT:
6689 return psource1->value.building == psource2->value.building;
6690 case VUT_IMPR_GENUS:
6691 return psource1->value.impr_genus == psource2->value.impr_genus;
6692 case VUT_IMPR_FLAG:
6693 return psource1->value.impr_flag == psource2->value.impr_flag;
6694 case VUT_PLAYER_FLAG:
6695 return psource1->value.plr_flag == psource2->value.plr_flag;
6696 case VUT_PLAYER_STATE:
6697 return psource1->value.plrstate == psource2->value.plrstate;
6698 case VUT_EXTRA:
6699 return psource1->value.extra == psource2->value.extra;
6700 case VUT_GOOD:
6701 return psource1->value.good == psource2->value.good;
6702 case VUT_TERRAIN:
6703 return psource1->value.terrain == psource2->value.terrain;
6704 case VUT_TERRFLAG:
6705 return psource1->value.terrainflag == psource2->value.terrainflag;
6706 case VUT_NATION:
6707 return psource1->value.nation == psource2->value.nation;
6708 case VUT_NATIONGROUP:
6709 return psource1->value.nationgroup == psource2->value.nationgroup;
6710 case VUT_NATIONALITY:
6711 return psource1->value.nationality == psource2->value.nationality;
6712 case VUT_ORIGINAL_OWNER:
6713 return psource1->value.origowner == psource2->value.origowner;
6714 case VUT_DIPLREL:
6715 case VUT_DIPLREL_TILE:
6716 case VUT_DIPLREL_TILE_O:
6717 case VUT_DIPLREL_UNITANY:
6718 case VUT_DIPLREL_UNITANY_O:
6719 return psource1->value.diplrel == psource2->value.diplrel;
6720 case VUT_UTYPE:
6721 return psource1->value.utype == psource2->value.utype;
6722 case VUT_UTFLAG:
6723 return psource1->value.unitflag == psource2->value.unitflag;
6724 case VUT_UCLASS:
6725 return psource1->value.uclass == psource2->value.uclass;
6726 case VUT_UCFLAG:
6727 return psource1->value.unitclassflag == psource2->value.unitclassflag;
6728 case VUT_MINVETERAN:
6729 return psource1->value.minveteran == psource2->value.minveteran;
6730 case VUT_UNITSTATE:
6731 return psource1->value.unit_state == psource2->value.unit_state;
6732 case VUT_ACTIVITY:
6733 return psource1->value.activity == psource2->value.activity;
6734 case VUT_MINMOVES:
6735 return psource1->value.minmoves == psource2->value.minmoves;
6736 case VUT_MINHP:
6737 return psource1->value.min_hit_points == psource2->value.min_hit_points;
6738 case VUT_AGE:
6739 return psource1->value.age == psource2->value.age;
6740 case VUT_FORM_AGE:
6741 return psource1->value.form_age == psource2->value.form_age;
6742 case VUT_MINTECHS:
6743 return psource1->value.min_techs == psource2->value.min_techs;
6744 case VUT_MINCITIES:
6745 return psource1->value.min_cities == psource2->value.min_cities;
6746 case VUT_ACTION:
6747 return (action_number(psource1->value.action)
6748 == action_number(psource2->value.action));
6749 case VUT_OTYPE:
6750 return psource1->value.outputtype == psource2->value.outputtype;
6751 case VUT_SPECIALIST:
6752 return psource1->value.specialist == psource2->value.specialist;
6753 case VUT_MINSIZE:
6754 return psource1->value.minsize == psource2->value.minsize;
6755 case VUT_MINCULTURE:
6756 return psource1->value.minculture == psource2->value.minculture;
6757 case VUT_MINFOREIGNPCT:
6758 return psource1->value.minforeignpct == psource2->value.minforeignpct;
6759 case VUT_AI_LEVEL:
6760 return psource1->value.ai_level == psource2->value.ai_level;
6761 case VUT_MAXTILEUNITS:
6762 return psource1->value.max_tile_units == psource2->value.max_tile_units;
6763 case VUT_TERRAINCLASS:
6764 return psource1->value.terrainclass == psource2->value.terrainclass;
6765 case VUT_ROADFLAG:
6766 return psource1->value.roadflag == psource2->value.roadflag;
6767 case VUT_EXTRAFLAG:
6768 return psource1->value.extraflag == psource2->value.extraflag;
6769 case VUT_MINYEAR:
6770 return psource1->value.minyear == psource2->value.minyear;
6771 case VUT_MINCALFRAG:
6772 return psource1->value.mincalfrag == psource2->value.mincalfrag;
6773 case VUT_TOPO:
6774 return psource1->value.topo_property == psource2->value.topo_property;
6775 case VUT_WRAP:
6776 return psource1->value.wrap_property == psource2->value.wrap_property;
6777 case VUT_SERVERSETTING:
6778 return psource1->value.ssetval == psource2->value.ssetval;
6779 case VUT_TERRAINALTER:
6780 return psource1->value.terrainalter == psource2->value.terrainalter;
6781 case VUT_CITYTILE:
6782 return psource1->value.citytile == psource2->value.citytile;
6783 case VUT_CITYSTATUS:
6784 return psource1->value.citystatus == psource2->value.citystatus;
6785 case VUT_MINLATITUDE:
6786 case VUT_MAXLATITUDE:
6787 return psource1->value.latitude == psource2->value.latitude;
6788 case VUT_COUNT:
6789 break;
6790 }
6791
6792 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
6793 return FALSE;
6794}
6795
6796/**********************************************************************/
6800 const char *universal_rule_name(const struct universal *psource)
6801{
6802 static char buffer[10];
6803
6804 switch (psource->kind) {
6805 case VUT_NONE:
6806 return "(none)";
6807 case VUT_COUNTER:
6808 return counter_rule_name(psource->value.counter);
6809 case VUT_CITYTILE:
6810 return citytile_type_name(psource->value.citytile);
6811 case VUT_CITYSTATUS:
6812 return citystatus_type_name(psource->value.citystatus);
6813 case VUT_MINYEAR:
6814 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
6815
6816 return buffer;
6817 case VUT_MINCALFRAG:
6818 /* Rule name is 0-based number, not pretty name from ruleset */
6819 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
6820
6821 return buffer;
6822 case VUT_TOPO:
6823 return topo_flag_name(psource->value.topo_property);
6824 case VUT_WRAP:
6825 return wrap_flag_name(psource->value.wrap_property);
6826 case VUT_SERVERSETTING:
6827 return ssetv_rule_name(psource->value.ssetval);
6828 case VUT_ADVANCE:
6829 return advance_rule_name(psource->value.advance);
6830 case VUT_TECHFLAG:
6831 return tech_flag_id_name(psource->value.techflag);
6832 case VUT_GOVERNMENT:
6833 return government_rule_name(psource->value.govern);
6834 case VUT_ACHIEVEMENT:
6835 return achievement_rule_name(psource->value.achievement);
6836 case VUT_STYLE:
6837 return style_rule_name(psource->value.style);
6838 case VUT_IMPROVEMENT:
6839 return improvement_rule_name(psource->value.building);
6840 case VUT_IMPR_GENUS:
6841 return impr_genus_id_name(psource->value.impr_genus);
6842 case VUT_IMPR_FLAG:
6843 return impr_flag_id_name(psource->value.impr_flag);
6844 case VUT_PLAYER_FLAG:
6845 return plr_flag_id_name(psource->value.plr_flag);
6846 case VUT_PLAYER_STATE:
6847 return plrstate_type_name(psource->value.plrstate);
6848 case VUT_EXTRA:
6849 return extra_rule_name(psource->value.extra);
6850 case VUT_GOOD:
6851 return goods_rule_name(psource->value.good);
6852 case VUT_TERRAIN:
6853 return terrain_rule_name(psource->value.terrain);
6854 case VUT_TERRFLAG:
6855 return terrain_flag_id_name(psource->value.terrainflag);
6856 case VUT_NATION:
6857 return nation_rule_name(psource->value.nation);
6858 case VUT_NATIONGROUP:
6859 return nation_group_rule_name(psource->value.nationgroup);
6860 case VUT_DIPLREL:
6861 case VUT_DIPLREL_TILE:
6862 case VUT_DIPLREL_TILE_O:
6863 case VUT_DIPLREL_UNITANY:
6864 case VUT_DIPLREL_UNITANY_O:
6865 return diplrel_rule_name(psource->value.diplrel);
6866 case VUT_NATIONALITY:
6867 return nation_rule_name(psource->value.nationality);
6868 case VUT_ORIGINAL_OWNER:
6869 return nation_rule_name(psource->value.origowner);
6870 case VUT_UTYPE:
6871 return utype_rule_name(psource->value.utype);
6872 case VUT_UTFLAG:
6873 return unit_type_flag_id_name(psource->value.unitflag);
6874 case VUT_UCLASS:
6875 return uclass_rule_name(psource->value.uclass);
6876 case VUT_UCFLAG:
6877 return unit_class_flag_id_name(psource->value.unitclassflag);
6878 case VUT_MINVETERAN:
6879 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
6880
6881 return buffer;
6882 case VUT_UNITSTATE:
6883 return ustate_prop_name(psource->value.unit_state);
6884 case VUT_ACTIVITY:
6885 return unit_activity_name(psource->value.activity);
6886 case VUT_MINMOVES:
6887 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
6888
6889 return buffer;
6890 case VUT_MINHP:
6891 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
6892
6893 return buffer;
6894 case VUT_AGE:
6895 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
6896
6897 return buffer;
6898 case VUT_FORM_AGE:
6899 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
6900
6901 return buffer;
6902 case VUT_MINTECHS:
6903 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
6904
6905 return buffer;
6906 case VUT_MINCITIES:
6907 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_cities);
6908
6909 return buffer;
6910 case VUT_ACTION:
6911 return action_rule_name(psource->value.action);
6912 case VUT_OTYPE:
6913 return get_output_identifier(psource->value.outputtype);
6914 case VUT_SPECIALIST:
6915 return specialist_rule_name(psource->value.specialist);
6916 case VUT_MINSIZE:
6917 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
6918
6919 return buffer;
6920 case VUT_MINCULTURE:
6921 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
6922
6923 return buffer;
6924 case VUT_MINFOREIGNPCT:
6925 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
6926
6927 return buffer;
6928 case VUT_AI_LEVEL:
6929 return ai_level_name(psource->value.ai_level);
6930 case VUT_MAXTILEUNITS:
6931 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_units);
6932 return buffer;
6933 case VUT_TERRAINCLASS:
6934 return terrain_class_name(psource->value.terrainclass);
6935 case VUT_ROADFLAG:
6936 return road_flag_id_name(psource->value.roadflag);
6937 case VUT_EXTRAFLAG:
6938 return extra_flag_id_name(psource->value.extraflag);
6939 case VUT_TERRAINALTER:
6940 return terrain_alteration_name(psource->value.terrainalter);
6941 case VUT_MINLATITUDE:
6942 case VUT_MAXLATITUDE:
6943 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
6944
6945 return buffer;
6946 case VUT_COUNT:
6947 break;
6948 }
6949
6950 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
6951 return NULL;
6952}
6953
6954/**********************************************************************/
6962 const char *universal_name_translation(const struct universal *psource,
6963 char *buf, size_t bufsz)
6964{
6965 buf[0] = '\0'; /* to be safe. */
6966 switch (psource->kind) {
6967 case VUT_NONE:
6968 /* TRANS: missing value */
6969 fc_strlcat(buf, _("(none)"), bufsz);
6970 return buf;
6971 case VUT_ADVANCE:
6972 fc_strlcat(buf, advance_name_translation(psource->value.advance), bufsz);
6973 return buf;
6974 case VUT_COUNTER:
6975 fc_strlcat(buf, counter_name_translation(psource->value.counter), bufsz);
6976 return buf;
6977 case VUT_TECHFLAG:
6978 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
6979 tech_flag_id_translated_name(psource->value.techflag));
6980 return buf;
6981 case VUT_GOVERNMENT:
6982 fc_strlcat(buf, government_name_translation(psource->value.govern),
6983 bufsz);
6984 return buf;
6985 case VUT_ACHIEVEMENT:
6986 fc_strlcat(buf, achievement_name_translation(psource->value.achievement),
6987 bufsz);
6988 return buf;
6989 case VUT_STYLE:
6990 fc_strlcat(buf, style_name_translation(psource->value.style),
6991 bufsz);
6992 return buf;
6993 case VUT_IMPROVEMENT:
6994 fc_strlcat(buf, improvement_name_translation(psource->value.building),
6995 bufsz);
6996 return buf;
6997 case VUT_IMPR_GENUS:
6998 fc_strlcat(buf,
6999 impr_genus_id_translated_name(psource->value.impr_genus),
7000 bufsz);
7001 return buf;
7002 case VUT_IMPR_FLAG:
7003 fc_strlcat(buf,
7004 impr_flag_id_translated_name(psource->value.impr_flag),
7005 bufsz);
7006 return buf;
7007 case VUT_PLAYER_FLAG:
7008 fc_strlcat(buf,
7009 plr_flag_id_translated_name(psource->value.plr_flag),
7010 bufsz);
7011 return buf;
7012 case VUT_PLAYER_STATE:
7013 fc_strlcat(buf,
7014 plrstate_type_translated_name(psource->value.plrstate),
7015 bufsz);
7016 return buf;
7017 case VUT_EXTRA:
7018 fc_strlcat(buf, extra_name_translation(psource->value.extra), bufsz);
7019 return buf;
7020 case VUT_GOOD:
7021 fc_strlcat(buf, goods_name_translation(psource->value.good), bufsz);
7022 return buf;
7023 case VUT_TERRAIN:
7024 fc_strlcat(buf, terrain_name_translation(psource->value.terrain), bufsz);
7025 return buf;
7026 case VUT_NATION:
7027 fc_strlcat(buf, nation_adjective_translation(psource->value.nation),
7028 bufsz);
7029 return buf;
7030 case VUT_NATIONGROUP:
7031 fc_strlcat(buf, nation_group_name_translation(psource->value.nationgroup),
7032 bufsz);
7033 return buf;
7034 case VUT_NATIONALITY:
7035 cat_snprintf(buf, bufsz, _("%s citizens"),
7036 nation_adjective_translation(psource->value.nationality));
7037 return buf;
7038 case VUT_ORIGINAL_OWNER:
7039 /* TRANS: Keep short. City founding nation. */
7040 cat_snprintf(buf, bufsz, _("%s original owner"),
7041 nation_adjective_translation(psource->value.origowner));
7042 return buf;
7043 case VUT_DIPLREL:
7044 case VUT_DIPLREL_TILE:
7045 case VUT_DIPLREL_TILE_O:
7046 case VUT_DIPLREL_UNITANY:
7047 case VUT_DIPLREL_UNITANY_O:
7048 fc_strlcat(buf, diplrel_name_translation(psource->value.diplrel),
7049 bufsz);
7050 return buf;
7051 case VUT_UTYPE:
7052 fc_strlcat(buf, utype_name_translation(psource->value.utype), bufsz);
7053 return buf;
7054 case VUT_UTFLAG:
7055 cat_snprintf(buf, bufsz,
7056 /* TRANS: Unit type flag */
7057 Q_("?utflag:\"%s\" units"),
7058 unit_type_flag_id_translated_name(
7059 psource->value.unitflag));
7060 return buf;
7061 case VUT_UCLASS:
7062 cat_snprintf(buf, bufsz,
7063 /* TRANS: Unit class */
7064 _("%s units"),
7065 uclass_name_translation(psource->value.uclass));
7066 return buf;
7067 case VUT_UCFLAG:
7068 cat_snprintf(buf, bufsz,
7069 /* TRANS: Unit class flag */
7070 Q_("?ucflag:\"%s\" units"),
7071 unit_class_flag_id_translated_name(
7072 psource->value.unitclassflag));
7073 return buf;
7074 case VUT_MINVETERAN:
7075 /* FIXME */
7076 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
7077 psource->value.minveteran);
7078 return buf;
7079 case VUT_UNITSTATE:
7080 switch (psource->value.unit_state) {
7081 case USP_TRANSPORTED:
7082 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7083 cat_snprintf(buf, bufsz, _("Transported"));
7084 break;
7085 case USP_LIVABLE_TILE:
7086 cat_snprintf(buf, bufsz,
7087 /* TRANS: unit state. (appears in strings like
7088 * "Missile+On livable tile") */
7089 _("On livable tile"));
7090 break;
7091 case USP_TRANSPORTING:
7092 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7093 cat_snprintf(buf, bufsz, _("Transporting"));
7094 break;
7095 case USP_HAS_HOME_CITY:
7096 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
7097 cat_snprintf(buf, bufsz, _("Has a home city"));
7098 break;
7099 case USP_NATIVE_TILE:
7100 cat_snprintf(buf, bufsz,
7101 /* TRANS: unit state. (appears in strings like
7102 * "Missile+On native tile") */
7103 _("On native tile"));
7104 break;
7105 case USP_NATIVE_EXTRA:
7106 cat_snprintf(buf, bufsz,
7107 /* TRANS: unit state. (appears in strings like
7108 * "Missile+In native extra") */
7109 _("In native extra"));
7110 break;
7111 case USP_MOVED_THIS_TURN:
7112 /* TRANS: unit state. (appears in strings like
7113 * "Missile+Has moved this turn") */
7114 cat_snprintf(buf, bufsz, _("Has moved this turn"));
7115 break;
7116 case USP_COUNT:
7117 fc_assert_msg(psource->value.unit_state != USP_COUNT,
7118 "Invalid unit state property.");
7119 break;
7120 }
7121 return buf;
7122 case VUT_ACTIVITY:
7123 cat_snprintf(buf, bufsz, _("%s activity"),
7124 Q_(unit_activity_name(psource->value.activity)));
7125 return buf;
7126 case VUT_MINMOVES:
7127 /* TRANS: Minimum unit movement points left for requirement to be met
7128 * (%s is a string like "1" or "2 1/3") */
7129 cat_snprintf(buf, bufsz, _("%s MP"),
7130 move_points_text(psource->value.minmoves, TRUE));
7131 return buf;
7132 case VUT_MINHP:
7133 /* TRANS: HP = hit points */
7134 cat_snprintf(buf, bufsz, _("%d HP"),
7135 psource->value.min_hit_points);
7136 return buf;
7137 case VUT_AGE:
7138 cat_snprintf(buf, bufsz, _("Age %d"),
7139 psource->value.age);
7140 return buf;
7141 case VUT_FORM_AGE:
7142 cat_snprintf(buf, bufsz, _("Form age %d"),
7143 psource->value.form_age);
7144 return buf;
7145 case VUT_MINTECHS:
7146 cat_snprintf(buf, bufsz, _("%d Techs"),
7147 psource->value.min_techs);
7148 return buf;
7149 case VUT_MINCITIES:
7150 cat_snprintf(buf, bufsz, _("%d Cities"),
7151 psource->value.min_cities);
7152 return buf;
7153 case VUT_ACTION:
7154 fc_strlcat(buf, action_name_translation(psource->value.action),
7155 bufsz);
7156 return buf;
7157 case VUT_OTYPE:
7158 /* FIXME */
7159 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
7160 return buf;
7161 case VUT_SPECIALIST:
7162 fc_strlcat(buf, specialist_plural_translation(psource->value.specialist),
7163 bufsz);
7164 return buf;
7165 case VUT_MINSIZE:
7166 cat_snprintf(buf, bufsz, _("Size %d"),
7167 psource->value.minsize);
7168 return buf;
7169 case VUT_MINCULTURE:
7170 cat_snprintf(buf, bufsz, _("Culture %d"),
7171 psource->value.minculture);
7172 return buf;
7173 case VUT_MINFOREIGNPCT:
7174 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
7175 psource->value.minforeignpct);
7176 return buf;
7177 case VUT_AI_LEVEL:
7178 /* TRANS: "Hard AI" */
7179 cat_snprintf(buf, bufsz, _("%s AI"),
7180 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
7181 return buf;
7182 case VUT_MAXTILEUNITS:
7183 /* TRANS: here <= means 'less than or equal' */
7184 cat_snprintf(buf, bufsz, PL_("<=%d unit",
7185 "<=%d units", psource->value.max_tile_units),
7186 psource->value.max_tile_units);
7187 return buf;
7188 case VUT_TERRAINCLASS:
7189 /* TRANS: Terrain class: "Land terrain" */
7190 cat_snprintf(buf, bufsz, _("%s terrain"),
7191 terrain_class_name_translation(psource->value.terrainclass));
7192 return buf;
7193 case VUT_TERRFLAG:
7194 cat_snprintf(buf, bufsz,
7195 /* TRANS: Terrain flag */
7196 Q_("?terrflag:\"%s\" terrain"),
7197 terrain_flag_id_translated_name(
7198 psource->value.terrainflag));
7199 return buf;
7200 case VUT_ROADFLAG:
7201 cat_snprintf(buf, bufsz,
7202 /* TRANS: Road flag */
7203 Q_("?roadflag:\"%s\" road"),
7204 road_flag_id_translated_name(psource->value.roadflag));
7205 return buf;
7206 case VUT_EXTRAFLAG:
7207 cat_snprintf(buf, bufsz,
7208 /* TRANS: Extra flag */
7209 Q_("?extraflag:\"%s\" extra"),
7210 extra_flag_id_translated_name(psource->value.extraflag));
7211 return buf;
7212 case VUT_MINYEAR:
7213 cat_snprintf(buf, bufsz, _("After %s"),
7214 textyear(psource->value.minyear));
7215 return buf;
7216 case VUT_MINCALFRAG:
7217 /* TRANS: here >= means 'greater than or equal'.
7218 * %s identifies a calendar fragment (may be bare number). */
7219 cat_snprintf(buf, bufsz, _(">=%s"),
7220 textcalfrag(psource->value.mincalfrag));
7221 return buf;
7222 case VUT_TOPO:
7223 /* TRANS: topology flag name ("Hex", "ISO") */
7224 cat_snprintf(buf, bufsz, _("%s map"),
7225 _(topo_flag_name(psource->value.topo_property)));
7226 return buf;
7227 case VUT_WRAP:
7228 /* TRANS: wrap flag name ("WrapX", "WrapY") */
7229 cat_snprintf(buf, bufsz, _("%s map"),
7230 _(wrap_flag_name(psource->value.wrap_property)));
7231 return buf;
7232 case VUT_SERVERSETTING:
7233 fc_strlcat(buf, ssetv_human_readable(psource->value.ssetval, TRUE),
7234 bufsz);
7235 return buf;
7236 case VUT_TERRAINALTER:
7237 /* TRANS: "Irrigation possible" */
7238 cat_snprintf(buf, bufsz, _("%s possible"),
7239 Q_(terrain_alteration_name(psource->value.terrainalter)));
7240 return buf;
7241 case VUT_CITYTILE:
7242 switch (psource->value.citytile) {
7243 case CITYT_CENTER:
7244 fc_strlcat(buf, _("City center"), bufsz);
7245 break;
7246 case CITYT_CLAIMED:
7247 fc_strlcat(buf, _("Tile claimed"), bufsz);
7248 break;
7249 case CITYT_EXTRAS_OWNED:
7250 fc_strlcat(buf, _("Extras owned"), bufsz);
7251 break;
7252 case CITYT_WORKED:
7253 fc_strlcat(buf, _("Worked tile"), bufsz);
7254 break;
7255 case CITYT_SAME_CONTINENT:
7256 fc_strlcat(buf, _("Same continent tile"), bufsz);
7257 break;
7258 case CITYT_BORDERING_TCLASS_REGION:
7259 /* TRANS: Short for "a tile of other terrain class mass near city" */
7260 fc_strlcat(buf, _("Port reachable tile"), bufsz);
7261 break;
7262 case CITYT_LAST:
7263 fc_assert(psource->value.citytile != CITYT_LAST);
7264 fc_strlcat(buf, "error", bufsz);
7265 break;
7266 }
7267 return buf;
7268 case VUT_CITYSTATUS:
7269 switch (psource->value.citystatus) {
7270 case CITYS_OWNED_BY_ORIGINAL:
7271 fc_strlcat(buf, _("Owned by original"), bufsz);
7272 break;
7273 case CITYS_STARVED:
7274 fc_strlcat(buf, _("Starved"), bufsz);
7275 break;
7276 case CITYS_DISORDER:
7277 fc_strlcat(buf, _("Disorder"), bufsz);
7278 break;
7279 case CITYS_CELEBRATION:
7280 fc_strlcat(buf, _("Celebration"), bufsz);
7281 break;
7282 case CITYS_TRANSFERRED:
7283 /* TRANS: CityStatus value - city has changed hands */
7284 fc_strlcat(buf, _("Transferred"), bufsz);
7285 break;
7286 case CITYS_LAST:
7287 fc_assert(psource->value.citystatus != CITYS_LAST);
7288 fc_strlcat(buf, "error", bufsz);
7289 break;
7290 }
7291 return buf;
7292 case VUT_MINLATITUDE:
7293 /* TRANS: here >= means 'greater than or equal'. */
7294 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
7295 psource->value.latitude);
7296 return buf;
7297 case VUT_MAXLATITUDE:
7298 /* TRANS: here <= means 'less than or equal'. */
7299 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
7300 psource->value.latitude);
7301 return buf;
7302 case VUT_COUNT:
7303 break;
7304 }
7305
7306 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
7307 return buf;
7308}
7309
7310/**********************************************************************/
7313 const char *universal_type_rule_name(const struct universal *psource)
7314{
7315 return universals_n_name(psource->kind);
7316}
7317
7318/**********************************************************************/
7321 int universal_build_shield_cost(const struct city *pcity,
7322 const struct universal *target)
7323{
7324 switch (target->kind) {
7325 case VUT_IMPROVEMENT:
7326 return impr_build_shield_cost(pcity, target->value.building);
7327 case VUT_UTYPE:
7328 return utype_build_shield_cost(pcity, NULL, target->value.utype);
7329 default:
7330 break;
7331 }
7332 return FC_INFINITY;
7333}
7334
7335/**********************************************************************/
7340 bool universal_replace_in_req_vec(struct requirement_vector *reqs,
7341 const struct universal *to_replace,
7342 const struct universal *replacement)
7343{
7344 bool changed = FALSE;
7345
7346 requirement_vector_iterate(reqs, preq) {
7347 if (universal_is_mentioned_by_requirement(preq, to_replace)) {
7348 preq->source = *replacement;
7349 changed = TRUE;
7350 }
7351 } requirement_vector_iterate_end;
7352
7353 return changed;
7354}
7355
7356/**********************************************************************/
7360 bool universal_is_mentioned_by_requirements(
7361 const struct requirement_vector *reqs,
7362 const struct universal *psource)
7363{
7364 requirement_vector_iterate(reqs, preq) {
7365 if (universal_is_mentioned_by_requirement(preq, psource)) {
7366 return TRUE;
7367 }
7368 } requirement_vector_iterate_end;
7369
7370 return FALSE;
7371}
7372
7373/**********************************************************************/
7382 bool universals_mean_unfulfilled(struct requirement_vector *reqs,
7383 struct universal *unis,
7384 size_t n_unis)
7385{
7386 int i;
7387
7388 for (i = 0; i < n_unis; i++) {
7389 if (!universal_fulfills_requirements(FALSE, reqs, &unis[i])) {
7390 /* This universal makes it impossible to fulfill the specified
7391 * requirement vector */
7392 return TRUE;
7393 }
7394 }
7395
7396 /* No specified universal is known to guarantee that the requirement
7397 * vector never will be fulfilled. */
7398 return FALSE;
7399}
7400
7401/**********************************************************************/
7415 bool universals_say_everything(struct requirement_vector *reqs,
7416 struct universal *unis,
7417 size_t n_unis)
7418{
7419 requirement_vector_iterate(reqs, preq) {
7420 int i;
7421 bool req_mentioned_a_source = FALSE;
7422
7423 for (i = 0; i < n_unis; i++) {
7424 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
7425 case ITF_NO:
7426 case ITF_YES:
7427 /* this req matched this source */
7428 req_mentioned_a_source = TRUE;
7429 break;
7430 case ITF_NOT_APPLICABLE:
7431 /* Not a mention. */
7432 break;
7433 }
7434 }
7435
7436 if (!req_mentioned_a_source) {
7437 /* A requirement not relevant to any of the specified universals was
7438 * found in the requirement vector. */
7439 return FALSE;
7440 }
7441 } requirement_vector_iterate_end;
7442
7443 /* No requirement not relevant to any of the specified universals was
7444 * found in the requirement vector. */
7445 return TRUE;
7446}
7447
7448/**********************************************************************/
7451enum req_item_found
7452universal_fulfills_requirement(const struct requirement *preq,
7453 const struct universal *source)
7454{
7455 fc_assert_ret_val_msg(universal_found_function[source->kind],
7456 ITF_NOT_APPLICABLE,
7457 "No req item found function for %s",
7458 universal_type_rule_name(source));
7459
7460 return (*universal_found_function[source->kind])(preq, source);
7461}
7462
7463/**********************************************************************/
7473 bool universal_fulfills_requirements(bool check_necessary,
7474 const struct requirement_vector *reqs,
7475 const struct universal *source)
7476{
7477 bool necessary = FALSE;
7478
7479 fc_assert_ret_val_msg(universal_found_function[source->kind],
7480 !check_necessary,
7481 "No req item found function for %s",
7482 universal_type_rule_name(source));
7483
7484 requirement_vector_iterate(reqs, preq) {
7485 switch ((*universal_found_function[source->kind])(preq, source)) {
7486 case ITF_NOT_APPLICABLE:
7487 continue;
7488 case ITF_NO:
7489 if (preq->present) {
7490 return FALSE;
7491 }
7492 break;
7493 case ITF_YES:
7494 if (preq->present) {
7495 necessary = TRUE;
7496 } else {
7497 return FALSE;
7498 }
7499 break;
7500 }
7501 } requirement_vector_iterate_end;
7502
7503 return (!check_necessary || necessary);
7504}
7505
7506/**********************************************************************/
7510 bool universal_is_relevant_to_requirement(const struct requirement *req,
7511 const struct universal *source)
7512{
7513 switch (universal_fulfills_requirement(req, source)) {
7514 case ITF_NOT_APPLICABLE:
7515 return FALSE;
7516 case ITF_NO:
7517 case ITF_YES:
7518 return TRUE;
7519 }
7520
7521 log_error("Unhandled item_found value");
7522 return FALSE;
7523}
7524
7525/**********************************************************************/
7528 static enum req_item_found nation_found(const struct requirement *preq,
7529 const struct universal *source)
7530{
7531 fc_assert(source->value.nation);
7532
7533 switch (preq->source.kind) {
7534 case VUT_NATION:
7535 return preq->source.value.nation == source->value.nation ? ITF_YES
7536 : ITF_NO;
7537 case VUT_NATIONGROUP:
7538 return nation_is_in_group(source->value.nation,
7539 preq->source.value.nationgroup) ? ITF_YES
7540 : ITF_NO;
7541 default:
7542 break;
7543 }
7544
7545 return ITF_NOT_APPLICABLE;
7546}
7547
7548/**********************************************************************/
7551 static enum req_item_found government_found(const struct requirement *preq,
7552 const struct universal *source)
7553{
7554 fc_assert(source->value.govern);
7555
7556 if (preq->source.kind == VUT_GOVERNMENT) {
7557 return preq->source.value.govern == source->value.govern ? ITF_YES
7558 : ITF_NO;
7559 }
7560
7561 return ITF_NOT_APPLICABLE;
7562}
7563
7564/**********************************************************************/
7567 static enum req_item_found improvement_found(const struct requirement *preq,
7568 const struct universal *source)
7569{
7570 fc_assert(source->value.building);
7571
7572 /* We only ever return ITF_YES, because requiring a different
7573 * improvement does not mean that the improvement under consideration
7574 * cannot fulfill the requirements. This is necessary to allow
7575 * requirement vectors to specify multiple required improvements. */
7576
7577 switch (preq->source.kind) {
7578 case VUT_IMPROVEMENT:
7579 if (source->value.building == preq->source.value.building) {
7580 return ITF_YES;
7581 }
7582 break;
7583 case VUT_IMPR_GENUS:
7584 if (source->value.building->genus == preq->source.value.impr_genus) {
7585 return ITF_YES;
7586 }
7587 break;
7588 case VUT_IMPR_FLAG:
7589 if (improvement_has_flag(source->value.building,
7590 preq->source.value.impr_flag)) {
7591 return ITF_YES;
7592 }
7593 break;
7594 default:
7595 break;
7596 }
7597
7598 return ITF_NOT_APPLICABLE;
7599}
7600
7601/**********************************************************************/
7604 static enum req_item_found unit_class_found(const struct requirement *preq,
7605 const struct universal *source)
7606{
7607 fc_assert(source->value.uclass);
7608
7609 switch (preq->source.kind) {
7610 case VUT_UCLASS:
7611 return source->value.uclass == preq->source.value.uclass ? ITF_YES
7612 : ITF_NO;
7613 case VUT_UCFLAG:
7614 return uclass_has_flag(source->value.uclass,
7615 preq->source.value.unitclassflag) ? ITF_YES
7616 : ITF_NO;
7617
7618 default:
7619 /* Not found and not relevant. */
7620 return ITF_NOT_APPLICABLE;
7621 };
7622}
7623
7624/**********************************************************************/
7627 static enum req_item_found unit_type_found(const struct requirement *preq,
7628 const struct universal *source)
7629{
7630 fc_assert(source->value.utype);
7631
7632 switch (preq->source.kind) {
7633 case VUT_UTYPE:
7634 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
7635 case VUT_UCLASS:
7636 return utype_class(source->value.utype) == preq->source.value.uclass
7637 ? ITF_YES : ITF_NO;
7638 case VUT_UTFLAG:
7639 return utype_has_flag(source->value.utype,
7640 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
7641 case VUT_UCFLAG:
7642 return uclass_has_flag(utype_class(source->value.utype),
7643 preq->source.value.unitclassflag) ? ITF_YES
7644 : ITF_NO;
7645 default:
7646 /* Not found and not relevant. */
7647 return ITF_NOT_APPLICABLE;
7648 };
7649}
7650
7651/**********************************************************************/
7654static enum req_item_found
7655unit_activity_found(const struct requirement *preq,
7656 const struct universal *source)
7657{
7658 fc_assert_ret_val(unit_activity_is_valid(source->value.activity),
7659 ITF_NOT_APPLICABLE);
7660
7661 switch (preq->source.kind) {
7662 case VUT_ACTIVITY:
7663 return source->value.activity == preq->source.value.activity ? ITF_YES
7664 : ITF_NO;
7665 default:
7666 /* Not found and not relevant. */
7667 return ITF_NOT_APPLICABLE;
7668 };
7669}
7670
7671/**********************************************************************/
7674 static enum req_item_found terrain_type_found(const struct requirement *preq,
7675 const struct universal *source)
7676{
7677 fc_assert(source->value.terrain);
7678
7679 switch (preq->source.kind) {
7680 case VUT_TERRAIN:
7681 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
7682 case VUT_TERRAINCLASS:
7683 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
7684 ? ITF_YES : ITF_NO;
7685 case VUT_TERRFLAG:
7686 return terrain_has_flag(source->value.terrain,
7687 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
7688 case VUT_TERRAINALTER:
7689 return (terrain_can_support_alteration(source->value.terrain,
7690 preq->source.value.terrainalter)
7691 ? ITF_YES : ITF_NO);
7692 default:
7693 /* Not found and not relevant. */
7694 return ITF_NOT_APPLICABLE;
7695 };
7696}
7697
7698/**********************************************************************/
7701 static enum req_item_found city_tile_found(const struct requirement *preq,
7702 const struct universal *source)
7703{
7704 fc_assert_ret_val(citytile_type_is_valid(source->value.citytile),
7705 ITF_NOT_APPLICABLE);
7706
7707 switch (preq->source.kind) {
7708 case VUT_CITYTILE:
7709 return (source->value.citytile == preq->source.value.citytile
7710 ? ITF_YES
7711 /* The presence of one tile state doesn't block another */
7712 : ITF_NOT_APPLICABLE);
7713 default:
7714 /* Not found and not relevant. */
7715 return ITF_NOT_APPLICABLE;
7716 };
7717}
7718
7719/**********************************************************************/
7722 static enum req_item_found extra_type_found(const struct requirement *preq,
7723 const struct universal *source)
7724{
7725 fc_assert(source->value.extra);
7726
7727 switch (preq->source.kind) {
7728 case VUT_EXTRA:
7729 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
7730 case VUT_EXTRAFLAG:
7731 return extra_has_flag(source->value.extra,
7732 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
7733 case VUT_ROADFLAG:
7734 {
7735 struct road_type *r = extra_road_get(source->value.extra);
7736 return r && road_has_flag(r, preq->source.value.roadflag)
7737 ? ITF_YES : ITF_NO;
7738 }
7739 default:
7740 /* Not found and not relevant. */
7741 return ITF_NOT_APPLICABLE;
7742 }
7743}
7744
7745/**********************************************************************/
7748 static enum req_item_found action_found(const struct requirement *preq,
7749 const struct universal *source)
7750{
7751 fc_assert(source->value.action);
7752
7753 if (preq->source.kind == VUT_ACTION) {
7754 return preq->source.value.action == source->value.action ? ITF_YES
7755 : ITF_NO;
7756 }
7757
7758 return ITF_NOT_APPLICABLE;
7759}
7760
7761/**********************************************************************/
7764 static enum req_item_found diplrel_found(const struct requirement *preq,
7765 const struct universal *source)
7766{
7767 fc_assert_ret_val((source->kind == VUT_DIPLREL
7768 || source->kind == VUT_DIPLREL_TILE
7769 || source->kind == VUT_DIPLREL_TILE_O
7770 || source->kind == VUT_DIPLREL_UNITANY
7771 || source->kind == VUT_DIPLREL_UNITANY_O),
7772 ITF_NOT_APPLICABLE);
7773
7774 if (preq->source.kind == source->kind) {
7775 if (preq->source.value.diplrel == source->value.diplrel) {
7776 /* The diplrel itself. */
7777 return ITF_YES;
7778 }
7779 if (preq->source.value.diplrel == DRO_FOREIGN
7780 && source->value.diplrel < DS_LAST) {
7781 /* All diplstate_type values are to foreigners. */
7782 return ITF_YES;
7783 }
7784 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
7785 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
7786 /* A real embassy is an embassy. */
7787 return ITF_YES;
7788 }
7789 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
7790 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
7791 /* A real embassy is an embassy. */
7792 return ITF_YES;
7793 }
7794 if (preq->source.value.diplrel < DS_LAST
7795 && source->value.diplrel < DS_LAST
7796 && preq->range == REQ_RANGE_LOCAL) {
7797 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
7798 ITF_YES);
7799 /* Can only have one diplstate_type to a specific player. */
7800 return ITF_NO;
7801 }
7802 /* Can't say this diplrel blocks the other diplrel. */
7803 return ITF_NOT_APPLICABLE;
7804 }
7805
7806 /* Not relevant. */
7807 return ITF_NOT_APPLICABLE;
7808}
7809
7810/**********************************************************************/
7813 static enum req_item_found output_type_found(const struct requirement *preq,
7814 const struct universal *source)
7815{
7816 switch (preq->source.kind) {
7817 case VUT_OTYPE:
7818 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
7819 : ITF_NO;
7820 default:
7821 /* Not found and not relevant. */
7822 return ITF_NOT_APPLICABLE;
7823 }
7824}
7825
7826/**********************************************************************/
7829 static enum req_item_found ustate_found(const struct requirement *preq,
7830 const struct universal *source)
7831{
7832 if (preq->range != REQ_RANGE_LOCAL) {
7833 return ITF_NOT_APPLICABLE;
7834 }
7835
7836 if (preq->source.kind == VUT_UNITSTATE) {
7837 switch (source->value.unit_state) {
7838 case USP_TRANSPORTED:
7839 case USP_TRANSPORTING:
7840 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
7841 case USP_LIVABLE_TILE:
7842 case USP_NATIVE_TILE:
7843 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
7844 * UTYF_COAST_STRICT. */
7845 case USP_HAS_HOME_CITY:
7846 case USP_NATIVE_EXTRA:
7847 case USP_MOVED_THIS_TURN:
7848 if (source->value.unit_state == preq->source.value.unit_state) {
7849 /* The other unit states doesn't contradict */
7850 return ITF_YES;
7851 }
7852 break;
7853 case USP_COUNT:
7854 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
7855 ITF_NOT_APPLICABLE);
7856 }
7857 }
7858
7859 /* Not found and not relevant. */
7860 return ITF_NOT_APPLICABLE;
7861}
7862
7863/**********************************************************************/
7866 void universal_found_functions_init(void)
7867{
7868 universal_found_function[VUT_GOVERNMENT] = &government_found;
7869 universal_found_function[VUT_NATION] = &nation_found;
7870 universal_found_function[VUT_IMPROVEMENT] = &improvement_found;
7871 universal_found_function[VUT_UCLASS] = &unit_class_found;
7872 universal_found_function[VUT_UTYPE] = &unit_type_found;
7873 universal_found_function[VUT_ACTIVITY] = &unit_activity_found;
7874 universal_found_function[VUT_TERRAIN] = &terrain_type_found;
7875 universal_found_function[VUT_CITYTILE] = &city_tile_found;
7876 universal_found_function[VUT_EXTRA] = &extra_type_found;
7877 universal_found_function[VUT_OTYPE] = &output_type_found;
7878 universal_found_function[VUT_ACTION] = &action_found;
7879 universal_found_function[VUT_DIPLREL] = &diplrel_found;
7880 universal_found_function[VUT_DIPLREL_TILE] = &diplrel_found;
7881 universal_found_function[VUT_DIPLREL_TILE_O] = &diplrel_found;
7882 universal_found_function[VUT_DIPLREL_UNITANY] = &diplrel_found;
7883 universal_found_function[VUT_DIPLREL_UNITANY_O] = &diplrel_found;
7884 universal_found_function[VUT_UNITSTATE] = &ustate_found;
7885}
7886
7887/**********************************************************************/
7895 int requirement_kind_ereq(const int value,
7896 const enum req_range range,
7897 const bool present,
7898 const int max_value)
7899{
7900 /* The enumerators in each range starts with present for every possible
7901 * value followed by !present for every possible value. */
7902 const int pres_start = (present ? 0 : max_value);
7903
7904 /* The enumerators for every range follows all the positions of the
7905 * previous range(s). */
7906 const int range_start = ((max_value - 1) * 2) * range;
7907
7908 return range_start + pres_start + value;
7909}
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 *paction)
Definition actions.c:1195
action_is_in_use
bool action_is_in_use(struct action *paction)
Definition actions.c:5612
action_by_rule_name
struct action * action_by_rule_name(const char *name)
Definition actions.c:1044
action_rule_name
const char * action_rule_name(const struct action *action)
Definition actions.c:1181
action_id_rule_name
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1204
action_number
int action_number(const struct action *action)
Definition actions.c:1173
action_by_number
static struct action * action_by_number(action_id act_id)
Definition actions.h:390
ACTION_NONE
#define ACTION_NONE
Definition actions.h:55
astr_free
void astr_free(struct astring *astr)
Definition astring.c:148
astr_set
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:251
astr_init
void astr_init(struct astring *astr)
Definition astring.c:139
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:49
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
punit
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
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:381
req_problem_type
req_problem_type
Definition fc_types.h:706
RPT_POSSIBLE
@ RPT_POSSIBLE
Definition fc_types.h:707
MAX_LEN_NAME
#define MAX_LEN_NAME
Definition fc_types.h:66
VC_SPACERACE
@ VC_SPACERACE
Definition fc_types.h:1281
O_LAST
@ O_LAST
Definition fc_types.h:101
Continent_id
signed short Continent_id
Definition fc_types.h:376
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_normal
#define log_normal(message,...)
Definition log.h:107
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:941
map_signed_latitude
int map_signed_latitude(const struct tile *ptile)
Definition map.c:1566
same_pos
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:950
map_distance
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:660
map.h
current_topo_has_flag
#define current_topo_has_flag(flag)
Definition map.h:43
MAP_MAX_LATITUDE
#define MAP_MAX_LATITUDE
Definition map.h:560
adjc_iterate_end
#define adjc_iterate_end
Definition map.h:419
MAP_MAX_REAL_LATITUDE
#define MAP_MAX_REAL_LATITUDE(_nmap)
Definition map.h:572
square_iterate
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:377
cardinal_adjc_iterate_end
#define cardinal_adjc_iterate_end
Definition map.h:445
adjc_iterate
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:414
square_iterate_end
#define square_iterate_end
Definition map.h:380
cardinal_adjc_iterate
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:441
circle_iterate
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:387
current_wrap_has_flag
#define current_wrap_has_flag(flag)
Definition map.h:46
MAP_MIN_REAL_LATITUDE
#define MAP_MIN_REAL_LATITUDE(_nmap)
Definition map.h:574
circle_iterate_end
#define circle_iterate_end
Definition map.h:390
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:1016
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:318
is_native_tile
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:330
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:2002
diplrel_req_contradicts
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Definition player.c:1827
diplrel_by_rule_name
int diplrel_by_rule_name(const char *value)
Definition player.c:1585
players_on_same_team
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1480
is_diplrel_to_other
bool is_diplrel_to_other(const struct player *pplayer, int diplrel)
Definition player.c:1566
player_has_flag
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1994
diplrel_name_translation
const char * diplrel_name_translation(int value)
Definition player.c:1631
is_diplrel_between
bool is_diplrel_between(const struct player *player1, const struct player *player2, int diplrel)
Definition player.c:1516
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:1409
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:1619
player.h
players_iterate_end
#define players_iterate_end
Definition player.h:539
players_iterate
#define players_iterate(_pplayer)
Definition player.h:534
player_nation
#define player_nation(_plr_)
Definition player.h:408
is_ai
#define is_ai(plr)
Definition player.h:232
players_iterate_alive_end
#define players_iterate_alive_end
Definition player.h:549
players_iterate_alive
#define players_iterate_alive(_pplayer)
Definition player.h:544
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:5362
terrain_type_found
static enum req_item_found terrain_type_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7674
universal_never_there
bool universal_never_there(const struct universal *source)
Definition requirements.c:6062
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:5489
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:4026
universal_is_relevant_to_requirement
bool universal_is_relevant_to_requirement(const struct requirement *req, const struct universal *source)
Definition requirements.c:7510
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:6025
universal_build_shield_cost
int universal_build_shield_cost(const struct city *pcity, const struct universal *target)
Definition requirements.c:7321
city_tile_found
static enum req_item_found city_tile_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7701
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:6403
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:1011
unit_type_found
static enum req_item_found unit_type_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7627
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:5470
universal_extraction
void universal_extraction(const struct universal *source, int *kind, int *value)
Definition requirements.c:871
num_player_buildings
static int num_player_buildings(const struct player *pplayer, const struct impr_type *building)
Definition requirements.c:2022
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:3364
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:2599
num_continent_buildings
static int num_continent_buildings(const struct player *pplayer, int continent, const struct impr_type *building)
Definition requirements.c:2036
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:5643
req_to_fstring
const char * req_to_fstring(const struct requirement *req, struct astring *astr)
Definition requirements.c:1026
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:3530
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:6178
present_implies_not_present
static bool present_implies_not_present(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1627
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:3260
req_vec_by_number
struct requirement_vector * req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
Definition requirements.c:6197
universal_fulfills_requirements
bool universal_fulfills_requirements(bool check_necessary, const struct requirement_vector *reqs, const struct universal *source)
Definition requirements.c:7473
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:2934
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:4452
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:4335
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:6286
universal_copy
void universal_copy(struct universal *dst, const struct universal *src)
Definition requirements.c:861
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:1469
extra_type_found
static enum req_item_found extra_type_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7722
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:3995
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:5723
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:2268
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:3643
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:5616
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:2223
req_vec_change_translation
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
Definition requirements.c:6213
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:3933
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:1048
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:6468
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:2239
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:1441
req_from_values
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
Definition requirements.c:1422
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:5705
universal_rule_name
const char * universal_rule_name(const struct universal *psource)
Definition requirements.c:6800
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:3619
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:2315
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:4615
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:3762
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:4400
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:7340
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:5508
action_found
static enum req_item_found action_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7748
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:5873
are_requirements_contradictions
bool are_requirements_contradictions(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1685
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:5748
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:4048
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:6358
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:4571
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:3880
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:5288
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:1958
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:2670
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:7895
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:2954
req_vec_problem_free
void req_vec_problem_free(struct req_vec_problem *issue)
Definition requirements.c:6383
req_definitions
static struct req_def req_definitions[VUT_COUNT]
Definition requirements.c:5540
impr_contra_flag
static bool impr_contra_flag(const struct requirement *impr_req, const struct requirement *flag_req)
Definition requirements.c:1526
improvement_found
static enum req_item_found improvement_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7567
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:6489
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:3507
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:3461
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:2396
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:2837
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:1915
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:627
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:5316
universal_fulfills_requirement
enum req_item_found universal_fulfills_requirement(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7452
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:2061
city_center_contra
static bool city_center_contra(const struct requirement *cc_req, const struct requirement *ct_req)
Definition requirements.c:1584
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:4306
ustate_found
static enum req_item_found ustate_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7829
req_vec_wants_type
bool req_vec_wants_type(const struct requirement_vector *reqs, enum universals_n kind)
Definition requirements.c:6043
num_world_buildings_total
static int num_world_buildings_total(const struct impr_type *building)
Definition requirements.c:1972
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:5901
output_type_found
static enum req_item_found output_type_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7813
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:4500
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:6574
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:4523
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:3705
is_city_in_tile
static bool is_city_in_tile(const struct tile *ptile, const struct city *pcity)
Definition requirements.c:4597
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:3837
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:2356
does_req_contradicts_reqs
bool does_req_contradicts_reqs(const struct requirement *req, const struct requirement_vector *vec)
Definition requirements.c:1864
government_found
static enum req_item_found government_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7551
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:5528
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:2884
are_universals_equal
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
Definition requirements.c:6667
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:6324
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:7655
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:3553
is_mincities_req_active
static enum fc_tristate is_mincities_req_active(const struct civ_map *nmap, const struct req_context *context, const struct player *other_player, const struct requirement *req)
Definition requirements.c:3588
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:4226
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:5672
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:3153
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:7415
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:2739
nation_found
static enum req_item_found nation_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7528
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:7313
REQUC_PRESENT
#define REQUC_PRESENT
Definition requirements.c:100
universal_found_functions_init
void universal_found_functions_init(void)
Definition requirements.c:7866
unit_class_found
static enum req_item_found unit_class_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7604
IS_REQ_ACTIVE_VARIANT_ASSERT
#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind)
Definition requirements.c:1943
universal_number
int universal_number(const struct universal *source)
Definition requirements.c:881
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:2914
universal_is_mentioned_by_requirements
bool universal_is_mentioned_by_requirements(const struct requirement_vector *reqs, const struct universal *psource)
Definition requirements.c:7360
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:5246
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:3977
diplrel_found
static enum req_item_found diplrel_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7764
req_vec_is_impossible_to_fulfill
bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
Definition requirements.c:6158
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:4147
req_implies_req
bool req_implies_req(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1668
req_copy
void req_copy(struct requirement *dst, const struct requirement *src)
Definition requirements.c:1456
is_req_unchanging
enum req_unchanging_status is_req_unchanging(const struct req_context *context, const struct requirement *req)
Definition requirements.c:5948
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:2461
player_has_ever_built
static bool player_has_ever_built(const struct player *pplayer, const struct impr_type *building)
Definition requirements.c:2007
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:3051
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:5996
nation_contra_group
static bool nation_contra_group(const struct requirement *nation_req, const struct requirement *group_req)
Definition requirements.c:1558
req_is_impossible_to_fulfill
bool req_is_impossible_to_fulfill(const struct requirement *req)
Definition requirements.c:6145
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:1883
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:5452
are_requirements_opposites
static bool are_requirements_opposites(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1481
num_world_buildings
static int num_world_buildings(const struct impr_type *building)
Definition requirements.c:1986
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:4476
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:3953
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:2525
universal_name_translation
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
Definition requirements.c:6962
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:5003
universals_mean_unfulfilled
bool universals_mean_unfulfilled(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
Definition requirements.c:7382
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:6640
impr_contra_genus
static bool impr_contra_genus(const struct requirement *impr_req, const struct requirement *genus_req)
Definition requirements.c:1494
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:4068
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:627
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:187
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:265
packet_calendar_info::calendar_fragments
int calendar_fragments
Definition packets_gen.h:263
packet_game_info::global_advances
bool global_advances[A_LAST]
Definition packets_gen.h:168
packet_game_info::fragment_count
int fragment_count
Definition packets_gen.h:252
packet_game_info::turn
int turn
Definition packets_gen.h:247
packet_game_info::year
int year
Definition packets_gen.h:249
packet_game_info::global_advance_count
int global_advance_count
Definition packets_gen.h:167
player
Definition player.h:249
player::is_alive
bool is_alive
Definition player.h:268
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:75
tile
Definition tile.h:50
unit_class
Definition unittype.h:149
unit_type
Definition unittype.h:507
unit::tile
struct tile * tile
Definition unit.h:142
unit::utype
const struct unit_type * utype
Definition unit.h:141
universal
Definition fc_types.h:908
universal::kind
enum universals_n kind
Definition fc_types.h:910
universal::value
universals_u value
Definition fc_types.h:909
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:960
fc_strlcpy
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
fc_strcasecmp
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
fc_strlcat
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:822
cat_snprintf
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
fc_vsnprintf
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
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:300
advance_rule_name
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:309
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:62
terrain_has_flag
#define terrain_has_flag(terr, flag)
Definition terrain.h:176
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:111
tile_continent
#define tile_continent(_tile)
Definition tile.h:93
tile_has_extra
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
tile_owner
#define tile_owner(_tile)
Definition tile.h:97
goods_can_be_provided
bool goods_can_be_provided(const struct city *pcity, const struct goods_type *pgood, const struct unit *punit)
Definition traderoutes.c:687
goods_number
Goods_type_id goods_number(const struct goods_type *pgood)
Definition traderoutes.c:592
goods_has_flag
bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
Definition traderoutes.c:679
goods_by_rule_name
struct goods_type * goods_by_rule_name(const char *name)
Definition traderoutes.c:642
goods_rule_name
const char * goods_rule_name(struct goods_type *pgood)
Definition traderoutes.c:633
goods_name_translation
const char * goods_name_translation(struct goods_type *pgood)
Definition traderoutes.c:625
goods_by_number
struct goods_type * goods_by_number(Goods_type_id id)
Definition traderoutes.c:615
city_receives_goods
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
Definition traderoutes.c:705
trade_partners_iterate_end
#define trade_partners_iterate_end
Definition traderoutes.h:167
trade_partners_iterate
#define trade_partners_iterate(c, p)
Definition traderoutes.h:162
universals_u::utype
const struct unit_type * utype
Definition fc_types.h:728
universals_u::unitflag
int unitflag
Definition fc_types.h:749
universals_u::min_techs
int min_techs
Definition fc_types.h:767
universals_u::mincalfrag
int mincalfrag
Definition fc_types.h:744
universals_u::diplrel
int diplrel
Definition fc_types.h:754
universals_u::style
struct nation_style * style
Definition fc_types.h:732
universals_u::ai_level
enum ai_level ai_level
Definition fc_types.h:736
universals_u::specialist
struct specialist * specialist
Definition fc_types.h:725
universals_u::impr_genus
enum impr_genus_id impr_genus
Definition fc_types.h:758
universals_u::citytile
enum citytile_type citytile
Definition fc_types.h:737
universals_u::nationgroup
struct nation_group * nationgroup
Definition fc_types.h:731
universals_u::extra
struct extra_type * extra
Definition fc_types.h:729
universals_u::wrap_property
enum wrap_flag wrap_property
Definition fc_types.h:772
universals_u::plrstate
enum plrstate_type plrstate
Definition fc_types.h:739
universals_u::min_cities
int min_cities
Definition fc_types.h:768
universals_u::nation
struct nation_type * nation
Definition fc_types.h:722
universals_u::minmoves
int minmoves
Definition fc_types.h:761
universals_u::terrainclass
int terrainclass
Definition fc_types.h:746
universals_u::unitclassflag
int unitclassflag
Definition fc_types.h:748
universals_u::govern
struct government * govern
Definition fc_types.h:720
universals_u::origowner
struct nation_type * origowner
Definition fc_types.h:724
universals_u::age
int age
Definition fc_types.h:765
universals_u::minsize
int minsize
Definition fc_types.h:740
universals_u::impr_flag
enum impr_flag_id impr_flag
Definition fc_types.h:759
universals_u::max_tile_units
int max_tile_units
Definition fc_types.h:762
universals_u::terrainalter
int terrainalter
Definition fc_types.h:747
universals_u::minculture
int minculture
Definition fc_types.h:741
universals_u::citystatus
enum citystatus_type citystatus
Definition fc_types.h:738
universals_u::minforeignpct
int minforeignpct
Definition fc_types.h:742
universals_u::building
const struct impr_type * building
Definition fc_types.h:721
universals_u::achievement
struct achievement * achievement
Definition fc_types.h:730
universals_u::ssetval
ssetv ssetval
Definition fc_types.h:773
universals_u::techflag
int techflag
Definition fc_types.h:751
universals_u::advance
struct advance * advance
Definition fc_types.h:718
universals_u::activity
enum unit_activity activity
Definition fc_types.h:757
universals_u::good
struct goods_type * good
Definition fc_types.h:734
universals_u::terrain
struct terrain * terrain
Definition fc_types.h:726
universals_u::terrainflag
int terrainflag
Definition fc_types.h:750
universals_u::unit_state
enum ustate_prop unit_state
Definition fc_types.h:756
universals_u::minveteran
int minveteran
Definition fc_types.h:763
universals_u::extraflag
int extraflag
Definition fc_types.h:753
universals_u::outputtype
Output_type_id outputtype
Definition fc_types.h:745
universals_u::roadflag
int roadflag
Definition fc_types.h:752
universals_u::topo_property
enum topo_flag topo_property
Definition fc_types.h:771
universals_u::latitude
int latitude
Definition fc_types.h:769
universals_u::counter
struct counter * counter
Definition fc_types.h:719
universals_u::min_hit_points
int min_hit_points
Definition fc_types.h:764
universals_u::uclass
struct unit_class * uclass
Definition fc_types.h:727
universals_u::nationality
struct nation_type * nationality
Definition fc_types.h:723
universals_u::minyear
int minyear
Definition fc_types.h:743
universals_u::action
struct action * action
Definition fc_types.h:733
universals_u::form_age
int form_age
Definition fc_types.h:766
universals_u::plr_flag
enum plr_flag_id plr_flag
Definition fc_types.h:760
get_transporter_occupancy
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1816
unit_tile
#define unit_tile(_pu)
Definition unit.h:397
unit_owner
#define unit_owner(_pu)
Definition unit.h:396
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
unit_class_get
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2498
utype_by_number
struct unit_type * utype_by_number(const Unit_type_id id)
Definition unittype.c:112
unit_has_type_flag
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:190
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:773
utype_class
#define utype_class(_t_)
Definition unittype.h:756
utype_has_flag
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
victory_enabled
bool victory_enabled(enum victory_condition_type victory)
Definition victory.c:26
victory.h