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 req_context *other_context,
58 const struct requirement *req);
59
60/* Function pointer for requirement-type-specific is_req_active handlers */
61typedef enum fc_tristate
62(*is_req_active_cb)(const struct civ_map *nmap,
63 const struct req_context *context,
64 const struct req_context *other_context,
65 const struct requirement *req);
66
67static inline bool are_tiles_in_range(const struct tile *tile1,
68 const struct tile *tile2,
69 enum req_range range);
70
71/**********************************************************************/
76static enum req_unchanging_status
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_TECHFLAG:
1172 case VUT_ACHIEVEMENT:
1173 case VUT_MINTECHS:
1174 invalid = (req.range < REQ_RANGE_PLAYER);
1175 break;
1176 case VUT_ADVANCE:
1177 invalid = (req.range < REQ_RANGE_PLAYER
1178 && req.range != REQ_RANGE_LOCAL);
1179 break;
1180 case VUT_GOVERNMENT:
1181 case VUT_AI_LEVEL:
1182 case VUT_STYLE:
1183 case VUT_MINCITIES:
1184 invalid = (req.range != REQ_RANGE_PLAYER);
1185 break;
1186 case VUT_MINSIZE:
1187 case VUT_MINFOREIGNPCT:
1188 case VUT_NATIONALITY:
1189 case VUT_CITYSTATUS:
1190 invalid = (req.range != REQ_RANGE_CITY
1191 && req.range != REQ_RANGE_TRADE_ROUTE);
1192 break;
1193 case VUT_GOOD:
1194 case VUT_ORIGINAL_OWNER:
1195 invalid = (req.range != REQ_RANGE_CITY);
1196 break;
1197 case VUT_MINCULTURE:
1198 invalid = (req.range != REQ_RANGE_CITY
1199 && req.range != REQ_RANGE_TRADE_ROUTE
1200 && req.range != REQ_RANGE_PLAYER
1201 && req.range != REQ_RANGE_TEAM
1202 && req.range != REQ_RANGE_ALLIANCE
1203 && req.range != REQ_RANGE_WORLD);
1204 break;
1205 case VUT_DIPLREL:
1206 invalid = (req.range != REQ_RANGE_LOCAL
1207 && req.range != REQ_RANGE_PLAYER
1208 && req.range != REQ_RANGE_TEAM
1209 && req.range != REQ_RANGE_ALLIANCE
1210 && req.range != REQ_RANGE_WORLD)
1211 /* Non local foreign makes no sense. */
1212 || (req.source.value.diplrel == DRO_FOREIGN
1213 && req.range != REQ_RANGE_LOCAL);
1214 break;
1215 case VUT_DIPLREL_TILE:
1216 invalid = (req.range != REQ_RANGE_LOCAL
1217 && req.range != REQ_RANGE_PLAYER
1218 && req.range != REQ_RANGE_TEAM
1219 && req.range != REQ_RANGE_ALLIANCE)
1220 /* Non local foreign makes no sense. */
1221 || (req.source.value.diplrel == DRO_FOREIGN
1222 && req.range != REQ_RANGE_LOCAL);
1223 break;
1224 case VUT_DIPLREL_TILE_O:
1225 invalid = (req.range != REQ_RANGE_LOCAL);
1226 break;
1227 case VUT_DIPLREL_UNITANY:
1228 invalid = (req.range != REQ_RANGE_LOCAL
1229 && req.range != REQ_RANGE_PLAYER
1230 && req.range != REQ_RANGE_TEAM
1231 && req.range != REQ_RANGE_ALLIANCE)
1232 /* Non local foreign makes no sense. */
1233 || (req.source.value.diplrel == DRO_FOREIGN
1234 && req.range != REQ_RANGE_LOCAL);
1235 break;
1236 case VUT_DIPLREL_UNITANY_O:
1237 invalid = (req.range != REQ_RANGE_LOCAL);
1238 break;
1239 case VUT_NATION:
1240 case VUT_NATIONGROUP:
1241 invalid = (req.range != REQ_RANGE_PLAYER
1242 && req.range != REQ_RANGE_TEAM
1243 && req.range != REQ_RANGE_ALLIANCE
1244 && req.range != REQ_RANGE_WORLD);
1245 break;
1246 case VUT_MINVETERAN:
1247 case VUT_UNITSTATE:
1248 case VUT_ACTIVITY:
1249 case VUT_MINMOVES:
1250 case VUT_MINHP:
1251 case VUT_ACTION:
1252 case VUT_OTYPE:
1253 case VUT_SPECIALIST:
1254 invalid = (req.range != REQ_RANGE_LOCAL);
1255 break;
1256 case VUT_UTYPE:
1257 case VUT_UTFLAG:
1258 case VUT_UCLASS:
1259 case VUT_UCFLAG:
1260 invalid = (req.range != REQ_RANGE_LOCAL
1261 && req.range != REQ_RANGE_TILE
1262 && req.range != REQ_RANGE_CADJACENT
1263 && req.range != REQ_RANGE_ADJACENT);
1264 break;
1265 case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
1266 invalid = (req.range != REQ_RANGE_TILE);
1267 break;
1268 case VUT_CITYTILE:
1269 case VUT_MAXTILEUNITS:
1270 invalid = (req.range != REQ_RANGE_TILE
1271 && req.range != REQ_RANGE_CADJACENT
1272 && req.range != REQ_RANGE_ADJACENT);
1273 break;
1274 case VUT_MINLATITUDE:
1275 case VUT_MAXLATITUDE:
1276 invalid = (req.range != REQ_RANGE_TILE
1277 && req.range != REQ_RANGE_CADJACENT
1278 && req.range != REQ_RANGE_ADJACENT
1279 && req.range != REQ_RANGE_WORLD)
1280 /* Avoid redundancy at tile range: no negated requirements
1281 * that could be emulated by a present requirement of the
1282 * other type */
1283 || (req.range == REQ_RANGE_TILE && !req.present);
1284 break;
1285 case VUT_MINYEAR:
1286 case VUT_MINCALFRAG:
1287 case VUT_TOPO:
1288 case VUT_WRAP:
1289 case VUT_SERVERSETTING:
1290 invalid = (req.range != REQ_RANGE_WORLD);
1291 break;
1292 case VUT_AGE:
1293 /* FIXME: could support TRADE_ROUTE, TEAM, etc */
1294 invalid = (req.range != REQ_RANGE_LOCAL
1295 && req.range != REQ_RANGE_CITY
1296 && req.range != REQ_RANGE_PLAYER);
1297 break;
1298 case VUT_FORM_AGE:
1299 invalid = (req.range != REQ_RANGE_LOCAL);
1300 break;
1301 case VUT_IMPR_GENUS:
1302 /* TODO: Support other ranges too. */
1303 invalid = (req.range != REQ_RANGE_LOCAL);
1304 break;
1305 case VUT_IMPR_FLAG:
1306 invalid = (req.range != REQ_RANGE_LOCAL
1307 && req.range != REQ_RANGE_TILE
1308 && req.range != REQ_RANGE_CITY);
1309 break;
1310 case VUT_COUNTER:
1311 invalid = req.range != REQ_RANGE_CITY;
1312 break;
1313 case VUT_PLAYER_FLAG:
1314 case VUT_PLAYER_STATE:
1315 invalid = (req.range != REQ_RANGE_PLAYER);
1316 break;
1317 case VUT_IMPROVEMENT:
1318 /* Valid ranges depend on the building genus (wonder/improvement),
1319 * which might not have been loaded from the ruleset yet.
1320 * So we allow anything here, and do a proper check once ruleset
1321 * loading is complete, in sanity_check_req_individual(). */
1322 case VUT_NONE:
1323 invalid = FALSE;
1324 break;
1325 case VUT_COUNT:
1326 break;
1327 }
1328 if (invalid) {
1329 error = "bad range";
1330 }
1331 }
1332
1333 if (!invalid) {
1334 /* Check 'survives'. */
1335 switch (req.source.kind) {
1336 case VUT_IMPROVEMENT:
1337 /* See buildings_in_range(). */
1338 invalid = survives && req.range <= REQ_RANGE_CONTINENT;
1339 break;
1340 case VUT_NATION:
1341 case VUT_ADVANCE:
1342 invalid = survives && req.range != REQ_RANGE_WORLD;
1343 break;
1344 case VUT_COUNTER:
1345 case VUT_IMPR_GENUS:
1346 case VUT_IMPR_FLAG:
1347 case VUT_PLAYER_FLAG:
1348 case VUT_PLAYER_STATE:
1349 case VUT_GOVERNMENT:
1350 case VUT_TERRAIN:
1351 case VUT_UTYPE:
1352 case VUT_UTFLAG:
1353 case VUT_UCLASS:
1354 case VUT_UCFLAG:
1355 case VUT_MINVETERAN:
1356 case VUT_UNITSTATE:
1357 case VUT_ACTIVITY:
1358 case VUT_MINMOVES:
1359 case VUT_MINHP:
1360 case VUT_AGE:
1361 case VUT_FORM_AGE:
1362 case VUT_ACTION:
1363 case VUT_OTYPE:
1364 case VUT_SPECIALIST:
1365 case VUT_MINSIZE:
1366 case VUT_MINCULTURE:
1367 case VUT_MINFOREIGNPCT:
1368 case VUT_AI_LEVEL:
1369 case VUT_TERRAINCLASS:
1370 case VUT_MINYEAR:
1371 case VUT_MINCALFRAG:
1372 case VUT_TOPO:
1373 case VUT_WRAP:
1374 case VUT_SERVERSETTING:
1375 case VUT_TERRAINALTER:
1376 case VUT_CITYTILE:
1377 case VUT_CITYSTATUS:
1378 case VUT_TERRFLAG:
1379 case VUT_NATIONALITY:
1380 case VUT_ORIGINAL_OWNER:
1381 case VUT_ROADFLAG:
1382 case VUT_EXTRAFLAG:
1383 case VUT_EXTRA:
1384 case VUT_GOOD:
1385 case VUT_TECHFLAG:
1386 case VUT_ACHIEVEMENT:
1387 case VUT_NATIONGROUP:
1388 case VUT_STYLE:
1389 case VUT_DIPLREL:
1390 case VUT_DIPLREL_TILE:
1391 case VUT_DIPLREL_TILE_O:
1392 case VUT_DIPLREL_UNITANY:
1393 case VUT_DIPLREL_UNITANY_O:
1394 case VUT_MAXTILEUNITS:
1395 case VUT_MINTECHS:
1396 case VUT_MINCITIES:
1397 case VUT_MINLATITUDE:
1398 case VUT_MAXLATITUDE:
1399 /* Most requirements don't support 'survives'. */
1400 invalid = survives;
1401 break;
1402 case VUT_NONE:
1403 case VUT_COUNT:
1404 break;
1405 }
1406 if (invalid) {
1407 error = "bad 'survives'";
1408 }
1409 }
1410
1411 if (invalid) {
1412 log_error("Invalid requirement %s | %s | %s | %s | %s: %s",
1413 type, range, survives ? "survives" : "",
1414 present ? "present" : "", value, error);
1415 req.source.kind = universals_n_invalid();
1416 }
1417
1418 return req;
1419}
1420
1421/**********************************************************************/
1425 struct requirement req_from_values(int type, int range,
1426 bool survives, bool present, bool quiet,
1427 int value)
1428{
1429 struct requirement req;
1430
1431 req.source = universal_by_number(type, value);
1432 req.range = range;
1433 req.survives = survives;
1434 req.present = present;
1435 req.quiet = quiet;
1436
1437 return req;
1438}
1439
1440/**********************************************************************/
1444 void req_get_values(const struct requirement *req,
1445 int *type, int *range,
1446 bool *survives, bool *present, bool *quiet,
1447 int *value)
1448{
1449 universal_extraction(&req->source, type, value);
1450 *range = req->range;
1451 *survives = req->survives;
1452 *present = req->present;
1453 *quiet = req->quiet;
1454}
1455
1456/**********************************************************************/
1459 void req_copy(struct requirement *dst, const struct requirement *src)
1460{
1461 universal_copy(&(dst->source), &(src->source));
1462 dst->range = src->range;
1463 dst->survives = src->survives;
1464 dst->present = src->present;
1465 dst->quiet = src->quiet;
1466}
1467
1468/**********************************************************************/
1472 bool are_requirements_equal(const struct requirement *req1,
1473 const struct requirement *req2)
1474{
1475 return (are_universals_equal(&req1->source, &req2->source)
1476 && req1->range == req2->range
1477 && req1->survives == req2->survives
1478 && req1->present == req2->present);
1479}
1480
1481/**********************************************************************/
1484 static bool are_requirements_opposites(const struct requirement *req1,
1485 const struct requirement *req2)
1486{
1487 return (are_universals_equal(&req1->source, &req2->source)
1488 && req1->range == req2->range
1489 && req1->survives == req2->survives
1490 && req1->present != req2->present);
1491}
1492
1493/**********************************************************************/
1497 static bool impr_contra_genus(const struct requirement *impr_req,
1498 const struct requirement *genus_req)
1499{
1500 /* The input is sane. */
1501 fc_assert_ret_val(impr_req->source.kind == VUT_IMPROVEMENT, FALSE);
1502 fc_assert_ret_val(genus_req->source.kind == VUT_IMPR_GENUS, FALSE);
1503
1504 if (impr_req->range == REQ_RANGE_LOCAL
1505 && genus_req->range == REQ_RANGE_LOCAL) {
1506 /* Applies to the same target building. */
1507
1508 if (impr_req->present && !genus_req->present) {
1509 /* The target building can't not have the genus it has. */
1510 return (impr_req->source.value.building->genus
1511 == genus_req->source.value.impr_genus);
1512 }
1513
1514 if (impr_req->present && genus_req->present) {
1515 /* The target building can't have another genus than it has. */
1516 return (impr_req->source.value.building->genus
1517 != genus_req->source.value.impr_genus);
1518 }
1519 }
1520
1521 /* No special knowledge. */
1522 return FALSE;
1523}
1524
1525/**********************************************************************/
1529 static bool impr_contra_flag(const struct requirement *impr_req,
1530 const struct requirement *flag_req)
1531{
1532 /* The input is sane. */
1533 fc_assert_ret_val(impr_req->source.kind == VUT_IMPROVEMENT, FALSE);
1534 fc_assert_ret_val(flag_req->source.kind == VUT_IMPR_FLAG, FALSE);
1535
1536 if (impr_req->range == REQ_RANGE_LOCAL
1537 && flag_req->range == REQ_RANGE_LOCAL) {
1538 /* Applies to the same target building. */
1539
1540 if (impr_req->present && !flag_req->present) {
1541 /* The target building can't not have the flag it has. */
1542 return improvement_has_flag(impr_req->source.value.building,
1543 flag_req->source.value.impr_flag);
1544 }
1545
1546 if (impr_req->present && flag_req->present) {
1547 /* The target building can't have another flag than it has. */
1548 return !improvement_has_flag(impr_req->source.value.building,
1549 flag_req->source.value.impr_flag);
1550 }
1551 }
1552
1553 /* No special knowledge. */
1554 return FALSE;
1555}
1556
1557/**********************************************************************/
1561 static bool nation_contra_group(const struct requirement *nation_req,
1562 const struct requirement *group_req)
1563{
1564 /* The input is sane. */
1565 fc_assert_ret_val(nation_req->source.kind == VUT_NATION, FALSE);
1566 fc_assert_ret_val(group_req->source.kind == VUT_NATIONGROUP, FALSE);
1567
1568 if (nation_req->range == REQ_RANGE_PLAYER
1569 && group_req->range == REQ_RANGE_PLAYER) {
1570 /* Applies to the same target building. */
1571
1572 if (nation_req->present && !group_req->present) {
1573 /* The target nation can't be in the group. */
1574 return nation_is_in_group(nation_req->source.value.nation,
1575 group_req->source.value.nationgroup);
1576 }
1577 }
1578
1579 /* No special knowledge. */
1580 return FALSE;
1581}
1582
1583/**********************************************************************/
1587 static bool city_center_contra(const struct requirement *cc_req,
1588 const struct requirement *ct_req)
1589{
1590 /* The input is sane. */
1591 fc_assert_ret_val(cc_req->source.kind == VUT_CITYTILE
1592 && ct_req->source.kind == VUT_CITYTILE, FALSE);
1593
1594 if (cc_req->source.value.citytile == CITYT_CENTER
1595 && cc_req->present && cc_req->range <= ct_req->range) {
1596 switch (ct_req->source.value.citytile) {
1597 case CITYT_CENTER:
1598 case CITYT_CLAIMED:
1599 case CITYT_EXTRAS_OWNED:
1600 case CITYT_WORKED:
1601 case CITYT_SAME_CONTINENT:
1602 /* Should be always on city center */
1603 return !ct_req->present;
1604 case CITYT_BORDERING_TCLASS_REGION:
1605 /* Handled later */
1606 break;
1607 case CITYT_LAST:
1608 /* Error */
1609 fc_assert_ret_val(ct_req->source.value.citytile != CITYT_LAST, FALSE);
1610 }
1611 }
1612 if ((cc_req->source.value.citytile == CITYT_SAME_CONTINENT
1613 || cc_req->source.value.citytile == CITYT_CENTER)
1614 && ct_req->source.value.citytile
1615 == CITYT_BORDERING_TCLASS_REGION
1616 && REQ_RANGE_TILE == cc_req->range
1617 && REQ_RANGE_TILE == ct_req->range) {
1618 /* Can't coexist */
1619 return cc_req->present ? ct_req->present : !ct_req->present;
1620 }
1621
1622 return FALSE;
1623}
1624
1625/**********************************************************************/
1630 static bool present_implies_not_present(const struct requirement *req1,
1631 const struct requirement *req2)
1632{
1633 const struct requirement *absent, *present;
1634
1635 if (req1->present == req2->present) {
1636 /* Can't use the knowledge in universal_found_function when both are
1637 * required to be absent or when both are required to be present.
1638 * It is no contradiction to require !Spy unit and !Missile unit class.
1639 * It is no contradiction to require River and Irrigation at the same
1640 * tile. */
1641 return FALSE;
1642 }
1643
1644 if (req1->present) {
1645 absent = req2;
1646 present = req1;
1647 } else {
1648 absent = req1;
1649 present = req2;
1650 }
1651
1652 if (!universal_found_function[present->source.kind]) {
1653 /* No knowledge to exploit. */
1654 return FALSE;
1655 }
1656
1657 if (present->range != absent->range) {
1658 /* Larger ranges are not always strict supersets of smaller ranges.
1659 * Example: Trade Route > CAdjacent but something may be in CAdjacent
1660 * but not in Trade Route. */
1661 return FALSE;
1662 }
1663
1664 return ITF_YES == universal_fulfills_requirement(absent,
1665 &present->source);
1666}
1667
1668/**********************************************************************/
1671 bool req_implies_req(const struct requirement *req1,
1672 const struct requirement *req2)
1673{
1674 struct requirement nreq2;
1675
1676 req_copy(&nreq2, req2);
1677 nreq2.present = !nreq2.present;
1678 return are_requirements_contradictions(req1, &nreq2);
1679}
1680
1681/**********************************************************************/
1688 bool are_requirements_contradictions(const struct requirement *req1,
1689 const struct requirement *req2)
1690{
1691 if (are_requirements_opposites(req1, req2)) {
1692 /* The exact opposite. */
1693 return TRUE;
1694 }
1695
1696 if (present_implies_not_present(req1, req2)) {
1697 return TRUE;
1698 }
1699
1700 switch (req1->source.kind) {
1701 case VUT_IMPROVEMENT:
1702 if (req2->source.kind == VUT_IMPR_GENUS) {
1703 return impr_contra_genus(req1, req2);
1704 } else if (req2->source.kind == VUT_IMPR_FLAG) {
1705 return impr_contra_flag(req1, req2);
1706 } else if (req2->source.kind == VUT_CITYTILE
1707 && req2->source.value.citytile == CITYT_CENTER
1708 && REQ_RANGE_TILE == req2->range
1709 && REQ_RANGE_TILE == req1->range
1710 && req1->present) {
1711 /* A building must be in a city */
1712 return !req2->present;
1713 }
1714
1715 /* No special knowledge. */
1716 return FALSE;
1717 case VUT_IMPR_GENUS:
1718 if (req2->source.kind == VUT_IMPROVEMENT) {
1719 return impr_contra_genus(req2, req1);
1720 }
1721
1722 /* No special knowledge. */
1723 return FALSE;
1724 case VUT_IMPR_FLAG:
1725 if (req2->source.kind == VUT_IMPROVEMENT) {
1726 return impr_contra_flag(req2, req1);
1727 }
1728
1729 /* No special knowledge. */
1730 return FALSE;
1731 case VUT_DIPLREL:
1732 case VUT_DIPLREL_TILE:
1733 case VUT_DIPLREL_TILE_O:
1734 case VUT_DIPLREL_UNITANY:
1735 case VUT_DIPLREL_UNITANY_O:
1736 if (req2->source.kind != req1->source.kind) {
1737 /* Finding contradictions across requirement kinds aren't supported
1738 * for DiplRel requirements. */
1739 return FALSE;
1740 } else {
1741 /* Use the special knowledge about DiplRel requirements to find
1742 * contradictions. */
1743
1744 bv_diplrel_all_reqs req1_contra;
1745 int req2_pos;
1746
1747 req1_contra = diplrel_req_contradicts(req1);
1748 req2_pos = requirement_diplrel_ereq(req2->source.value.diplrel,
1749 req2->range,
1750 req2->present);
1751
1752 return BV_ISSET(req1_contra, req2_pos);
1753 }
1754 break;
1755 case VUT_MINMOVES:
1756 if (req2->source.kind != VUT_MINMOVES) {
1757 /* Finding contradictions across requirement kinds aren't supported
1758 * for MinMoveFrags requirements. */
1759 return FALSE;
1760 } else if (req1->present == req2->present) {
1761 /* No contradiction possible. */
1762 return FALSE;
1763 } else {
1764 /* Number of move fragments left can't be larger than the number
1765 * required to be present and smaller than the number required to not
1766 * be present when the number required to be present is smaller than
1767 * the number required to not be present. */
1768 if (req1->present) {
1769 return req1->source.value.minmoves >= req2->source.value.minmoves;
1770 } else {
1771 return req1->source.value.minmoves <= req2->source.value.minmoves;
1772 }
1773 }
1774 break;
1775 case VUT_MINLATITUDE:
1776 case VUT_MAXLATITUDE:
1777 if (req2->source.kind != VUT_MINLATITUDE
1778 && req2->source.kind != VUT_MAXLATITUDE) {
1779 /* Finding contradictions across requirement kinds other than each
1780 * other is not supported for MinLatitude and MaxLatitude. */
1781 return FALSE;
1782 } else {
1783 /* For a contradiction, we need
1784 * - a minimum (present MinLatitude or negated MaxLatitude)
1785 * - a maximum (negated MinLatitude or present MaxLatitude)
1786 * - the maximum to be less than the minimum
1787 * - a requirement at the larger range that applies to the entire
1788 * range (i.e. a negated requirement, unless the range is Tile)
1789 * Otherwise, the two requirements could still be fulfilled
1790 * simultaneously by different tiles in the range */
1791
1792 /* Initial values beyond the boundaries to avoid edge cases */
1793 int minimum = -MAP_MAX_LATITUDE - 1, maximum = MAP_MAX_LATITUDE + 1;
1794 enum req_range covered_range = REQ_RANGE_TILE;
1795
1796#define EXTRACT_INFO(req) \
1797 if (req->present) { \
1798 if (req->source.kind == VUT_MINLATITUDE) { \
1799 /* present MinLatitude */ \
1800 minimum = MAX(minimum, req->source.value.latitude); \
1801 } else { \
1802 /* present MaxLatitude */ \
1803 maximum = MIN(maximum, req->source.value.latitude); \
1804 } \
1805 } else { \
1806 covered_range = MAX(covered_range, req->range); \
1807 if (req->source.kind == VUT_MINLATITUDE) { \
1808 /* negated MinLatitude */ \
1809 maximum = MIN(maximum, req->source.value.latitude - 1); \
1810 } else { \
1811 /* negated MaxLatitude */ \
1812 minimum = MAX(minimum, req->source.value.latitude + 1); \
1813 } \
1814 }
1815
1816 EXTRACT_INFO(req1);
1817 EXTRACT_INFO(req2);
1818
1819#undef EXTRACT_INFO
1820
1821 return (maximum < minimum
1822 && covered_range >= req1->range
1823 && covered_range >= req2->range);
1824 }
1825 break;
1826 case VUT_NATION:
1827 if (req2->source.kind == VUT_NATIONGROUP) {
1828 return nation_contra_group(req1, req2);
1829 }
1830
1831 /* No special knowledge. */
1832 return FALSE;
1833 break;
1834 case VUT_NATIONGROUP:
1835 if (req2->source.kind == VUT_NATION) {
1836 return nation_contra_group(req2, req1);
1837 }
1838
1839 /* No special knowledge. */
1840 return FALSE;
1841 break;
1842 case VUT_CITYTILE:
1843 if (req2->source.kind == VUT_CITYTILE) {
1844 return city_center_contra(req1, req2)
1845 || city_center_contra(req2, req1);
1846 } else if (req1->source.value.citytile == CITYT_CENTER
1847 && req2->source.kind == VUT_IMPROVEMENT
1848 && REQ_RANGE_TILE == req2->range
1849 && REQ_RANGE_TILE == req1->range
1850 && req2->present) {
1851 /* A building must be in a city */
1852 return !req1->present;
1853 }
1854
1855 return FALSE;
1856 default:
1857 /* No special knowledge exists. The requirements aren't the exact
1858 * opposite of each other per the initial check. */
1859 return FALSE;
1860 }
1861}
1862
1863/**********************************************************************/
1867 bool does_req_contradicts_reqs(const struct requirement *req,
1868 const struct requirement_vector *vec)
1869{
1870 /* If the requirement is contradicted by any requirement in the vector it
1871 * contradicts the entire requirement vector. */
1872 requirement_vector_iterate(vec, preq) {
1873 if (are_requirements_contradictions(req, preq)) {
1874 return TRUE;
1875 }
1876 } requirement_vector_iterate_end;
1877
1878 /* Not a singe requirement in the requirement vector is contradicted be
1879 * the specified requirement. */
1880 return FALSE;
1881}
1882
1883/**********************************************************************/
1886 static inline bool are_tiles_in_range(const struct tile *tile1,
1887 const struct tile *tile2,
1888 enum req_range range)
1889{
1890 switch (range) {
1891 case REQ_RANGE_ADJACENT:
1892 if (is_tiles_adjacent(tile1, tile2)) {
1893 return TRUE;
1894 }
1895 fc__fallthrough;
1896 case REQ_RANGE_TILE:
1897 return same_pos(tile1, tile2);
1898 case REQ_RANGE_CADJACENT:
1899 return map_distance(tile1, tile2) <= 1;
1900 case REQ_RANGE_CITY:
1901 case REQ_RANGE_TRADE_ROUTE:
1902 case REQ_RANGE_LOCAL:
1903 case REQ_RANGE_CONTINENT:
1904 case REQ_RANGE_PLAYER:
1905 case REQ_RANGE_TEAM:
1906 case REQ_RANGE_ALLIANCE:
1907 case REQ_RANGE_WORLD:
1908 case REQ_RANGE_COUNT:
1909 /* Invalid */
1910 fc_assert(FALSE);
1911 }
1912 return FALSE;
1913}
1914
1915/**********************************************************************/
1918 static inline bool players_in_same_range(const struct player *pplayer1,
1919 const struct player *pplayer2,
1920 enum req_range range)
1921{
1922 switch (range) {
1923 case REQ_RANGE_WORLD:
1924 return TRUE;
1925 case REQ_RANGE_ALLIANCE:
1926 return pplayers_allied(pplayer1, pplayer2);
1927 case REQ_RANGE_TEAM:
1928 return players_on_same_team(pplayer1, pplayer2);
1929 case REQ_RANGE_PLAYER:
1930 return pplayer1 == pplayer2;
1931 case REQ_RANGE_CONTINENT:
1932 case REQ_RANGE_TRADE_ROUTE:
1933 case REQ_RANGE_CITY:
1934 case REQ_RANGE_ADJACENT:
1935 case REQ_RANGE_CADJACENT:
1936 case REQ_RANGE_TILE:
1937 case REQ_RANGE_LOCAL:
1938 case REQ_RANGE_COUNT:
1939 break;
1940 }
1941
1942 fc_assert_msg(FALSE, "Invalid range %d.", range);
1943 return FALSE;
1944}
1945
1946#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind) \
1947{ \
1948 fc_assert_ret_val(req != NULL, TRI_MAYBE); \
1949 fc_assert_ret_val(req->source.kind == _kind, TRI_MAYBE); \
1950 fc_assert(context != NULL); \
1951}
1952
1953/**********************************************************************/
1961static enum fc_tristate
1962is_none_req_active(const struct civ_map *nmap,
1963 const struct req_context *context,
1964 const struct req_context *other_context,
1965 const struct requirement *req)
1966{
1967 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NONE);
1968
1969 return TRI_YES;
1970}
1971
1972/**********************************************************************/
1976 static int num_world_buildings_total(const struct impr_type *building)
1977{
1978 if (is_great_wonder(building)) {
1979 return (great_wonder_is_built(building)
1980 || great_wonder_is_destroyed(building) ? 1 : 0);
1981 } else {
1982 log_error("World-ranged requirements are only supported for wonders.");
1983 return 0;
1984 }
1985}
1986
1987/**********************************************************************/
1990 static int num_world_buildings(const struct impr_type *building)
1991{
1992 if (is_great_wonder(building)) {
1993 return (great_wonder_is_built(building) ? 1 : 0);
1994 } else {
1995 log_error("World-ranged requirements are only supported for wonders.");
1996 return 0;
1997 }
1998}
1999
2000/**********************************************************************/
2011 static bool player_has_ever_built(const struct player *pplayer,
2012 const struct impr_type *building)
2013{
2014 if (is_wonder(building)) {
2015 return (wonder_is_built(pplayer, building)
2016 || wonder_is_lost(pplayer, building) ? TRUE : FALSE);
2017 } else {
2018 log_error("Player-ranged requirements are only supported for wonders.");
2019 return FALSE;
2020 }
2021}
2022
2023/**********************************************************************/
2026 static int num_player_buildings(const struct player *pplayer,
2027 const struct impr_type *building)
2028{
2029 if (is_wonder(building)) {
2030 return (wonder_is_built(pplayer, building) ? 1 : 0);
2031 } else {
2032 log_error("Player-ranged requirements are only supported for wonders.");
2033 return 0;
2034 }
2035}
2036
2037/**********************************************************************/
2040 static int num_continent_buildings(const struct player *pplayer,
2041 int continent,
2042 const struct impr_type *building)
2043{
2044 if (is_wonder(building)) {
2045 const struct city *pcity;
2046
2047 pcity = city_from_wonder(pplayer, building);
2048 if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
2049 return 1;
2050 }
2051 } else {
2052 log_error("Island-ranged requirements are only supported for wonders.");
2053 }
2054 return 0;
2055}
2056
2057/**********************************************************************/
2065static enum fc_tristate
2066is_building_req_active(const struct civ_map *nmap,
2067 const struct req_context *context,
2068 const struct req_context *other_context,
2069 const struct requirement *req)
2070{
2071 const struct impr_type *building;
2072
2073 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPROVEMENT);
2074
2075 building = req->source.value.building;
2076
2077 /* Check if it's certain that the building is obsolete given the
2078 * specification we have */
2079 if (improvement_obsolete(context->player, building, context->city)) {
2080 return TRI_NO;
2081 }
2082
2083 if (req->survives) {
2084
2085 /* Check whether condition has ever held, using cached information. */
2086 switch (req->range) {
2087 case REQ_RANGE_WORLD:
2088 return BOOL_TO_TRISTATE(num_world_buildings_total(building) > 0);
2089 case REQ_RANGE_ALLIANCE:
2090 case REQ_RANGE_TEAM:
2091 if (context->player == NULL) {
2092 return TRI_MAYBE;
2093 }
2094 players_iterate_alive(plr2) {
2095 if (players_in_same_range(context->player, plr2, req->range)
2096 && player_has_ever_built(plr2, building)) {
2097 return TRI_YES;
2098 }
2099 } players_iterate_alive_end;
2100 return TRI_NO;
2101 case REQ_RANGE_PLAYER:
2102 if (context->player == NULL) {
2103 return TRI_MAYBE;
2104 }
2105 return BOOL_TO_TRISTATE(player_has_ever_built(context->player,
2106 building));
2107 case REQ_RANGE_CONTINENT:
2108 case REQ_RANGE_TRADE_ROUTE:
2109 case REQ_RANGE_CITY:
2110 case REQ_RANGE_LOCAL:
2111 case REQ_RANGE_TILE:
2112 case REQ_RANGE_CADJACENT:
2113 case REQ_RANGE_ADJACENT:
2114 /* There is no sources cache for this. */
2115 log_error("Surviving requirements are only supported at "
2116 "World/Alliance/Team/Player ranges.");
2117 return TRI_NO;
2118 case REQ_RANGE_COUNT:
2119 break;
2120 }
2121
2122 } else {
2123
2124 /* Non-surviving requirement. */
2125 switch (req->range) {
2126 case REQ_RANGE_WORLD:
2127 return BOOL_TO_TRISTATE(num_world_buildings(building) > 0);
2128 case REQ_RANGE_ALLIANCE:
2129 case REQ_RANGE_TEAM:
2130 if (context->player == NULL) {
2131 return TRI_MAYBE;
2132 }
2133 players_iterate_alive(plr2) {
2134 if (players_in_same_range(context->player, plr2, req->range)
2135 && num_player_buildings(plr2, building) > 0) {
2136 return TRI_YES;
2137 }
2138 } players_iterate_alive_end;
2139 return TRI_NO;
2140 case REQ_RANGE_PLAYER:
2141 if (context->player == NULL) {
2142 return TRI_MAYBE;
2143 }
2144 return BOOL_TO_TRISTATE(num_player_buildings(context->player,
2145 building)
2146 > 0);
2147 case REQ_RANGE_CONTINENT:
2148 /* At present, "Continent" effects can affect only
2149 * cities and units in cities. */
2150 if (context->player && context->city) {
2151 int continent = tile_continent(context->city->tile);
2152 return BOOL_TO_TRISTATE(num_continent_buildings(context->player,
2153 continent, building)
2154 > 0);
2155 } else {
2156 return TRI_MAYBE;
2157 }
2158 case REQ_RANGE_TRADE_ROUTE:
2159 if (context->city) {
2160 if (city_has_building(context->city, building)) {
2161 return TRI_YES;
2162 } else {
2163 enum fc_tristate ret = TRI_NO;
2164
2165 trade_partners_iterate(context->city, trade_partner) {
2166 if (trade_partner == NULL) {
2167 ret = TRI_MAYBE;
2168 } else if (city_has_building(trade_partner, building)) {
2169 return TRI_YES;
2170 }
2171 } trade_partners_iterate_end;
2172
2173 return ret;
2174 }
2175 } else {
2176 return TRI_MAYBE;
2177 }
2178 case REQ_RANGE_CITY:
2179 if (context->city) {
2180 return BOOL_TO_TRISTATE(city_has_building(context->city, building));
2181 } else {
2182 return TRI_MAYBE;
2183 }
2184 case REQ_RANGE_LOCAL:
2185 if (context->building) {
2186 if (context->building == building) {
2187 return TRI_YES;
2188 } else {
2189 return TRI_NO;
2190 }
2191 } else {
2192 /* TODO: other local targets */
2193 return TRI_MAYBE;
2194 }
2195 case REQ_RANGE_TILE:
2196 if (context->tile) {
2197 const struct city *pcity = tile_city(context->tile);
2198
2199 if (pcity) {
2200 return BOOL_TO_TRISTATE(city_has_building(pcity, building));
2201 } else {
2202 return TRI_NO;
2203 }
2204 } else {
2205 return TRI_MAYBE;
2206 }
2207 case REQ_RANGE_CADJACENT:
2208 case REQ_RANGE_ADJACENT:
2209 case REQ_RANGE_COUNT:
2210 break;
2211 }
2212
2213 }
2214
2215 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2216 return TRI_NO;
2217}
2218
2219/**********************************************************************/
2227static enum fc_tristate
2228is_buildinggenus_req_active(const struct civ_map *nmap,
2229 const struct req_context *context,
2230 const struct req_context *other_context,
2231 const struct requirement *req)
2232{
2233 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPR_GENUS);
2234
2235 return (context->building ? BOOL_TO_TRISTATE(
2236 context->building->genus
2237 == req->source.value.impr_genus)
2238 : TRI_MAYBE);
2239}
2240
2241/**********************************************************************/
2244 static enum fc_tristate is_buildingflag_in_city(const struct city *pcity,
2245 enum impr_flag_id flag)
2246{
2247 struct player *owner;
2248
2249 if (pcity == NULL) {
2250 return TRI_MAYBE;
2251 }
2252
2253 owner = city_owner(pcity);
2254 city_built_iterate(pcity, impr) {
2255 if (improvement_has_flag(impr, flag)
2256 && !improvement_obsolete(owner, impr, pcity)) {
2257 return TRI_YES;
2258 }
2259 } city_built_iterate_end;
2260
2261 return TRI_NO;
2262}
2263
2264/**********************************************************************/
2272static enum fc_tristate
2273is_buildingflag_req_active(const struct civ_map *nmap,
2274 const struct req_context *context,
2275 const struct req_context *other_context,
2276 const struct requirement *req)
2277{
2278 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_IMPR_FLAG);
2279
2280 switch (req->range) {
2281 case REQ_RANGE_LOCAL:
2282 return (context->building
2283 ? BOOL_TO_TRISTATE(improvement_has_flag(context->building,
2284 req->source.value.impr_flag))
2285 : TRI_MAYBE);
2286 case REQ_RANGE_CITY:
2287 return is_buildingflag_in_city(context->city, req->source.value.impr_flag);
2288 case REQ_RANGE_TILE:
2289 if (context->tile == NULL) {
2290 return TRI_MAYBE;
2291 }
2292 return is_buildingflag_in_city(tile_city(context->tile),
2293 req->source.value.impr_flag);
2294 case REQ_RANGE_CADJACENT:
2295 case REQ_RANGE_ADJACENT:
2296 case REQ_RANGE_TRADE_ROUTE:
2297 case REQ_RANGE_CONTINENT:
2298 case REQ_RANGE_PLAYER:
2299 case REQ_RANGE_ALLIANCE:
2300 case REQ_RANGE_TEAM:
2301 case REQ_RANGE_WORLD:
2302 case REQ_RANGE_COUNT:
2303 break;
2304 }
2305
2306 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2307
2308 return TRI_MAYBE;
2309}
2310
2311/**********************************************************************/
2319static enum fc_tristate
2320is_plr_flag_req_active(const struct civ_map *nmap,
2321 const struct req_context *context,
2322 const struct req_context *other_context,
2323 const struct requirement *req)
2324{
2325 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_PLAYER_FLAG);
2326
2327 switch (req->range) {
2328 case REQ_RANGE_PLAYER:
2329 return (context->player != NULL
2330 ? BOOL_TO_TRISTATE(player_has_flag(context->player,
2331 req->source.value.plr_flag))
2332 : TRI_MAYBE);
2333 case REQ_RANGE_LOCAL:
2334 case REQ_RANGE_CITY:
2335 case REQ_RANGE_TILE:
2336 case REQ_RANGE_CADJACENT:
2337 case REQ_RANGE_ADJACENT:
2338 case REQ_RANGE_TRADE_ROUTE:
2339 case REQ_RANGE_CONTINENT:
2340 case REQ_RANGE_ALLIANCE:
2341 case REQ_RANGE_TEAM:
2342 case REQ_RANGE_WORLD:
2343 case REQ_RANGE_COUNT:
2344 break;
2345 }
2346
2347 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2348
2349 return TRI_MAYBE;
2350}
2351
2352/**********************************************************************/
2360static enum fc_tristate
2361is_plr_state_req_active(const struct civ_map *nmap,
2362 const struct req_context *context,
2363 const struct req_context *other_context,
2364 const struct requirement *req)
2365{
2366 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_PLAYER_STATE);
2367
2368 switch (req->range) {
2369 case REQ_RANGE_PLAYER:
2370 return (context->player != NULL
2371 ? BOOL_TO_TRISTATE(player_has_state(context->player,
2372 req->source.value.plrstate))
2373 : TRI_MAYBE);
2374 case REQ_RANGE_LOCAL:
2375 case REQ_RANGE_CITY:
2376 case REQ_RANGE_TILE:
2377 case REQ_RANGE_CADJACENT:
2378 case REQ_RANGE_ADJACENT:
2379 case REQ_RANGE_TRADE_ROUTE:
2380 case REQ_RANGE_CONTINENT:
2381 case REQ_RANGE_ALLIANCE:
2382 case REQ_RANGE_TEAM:
2383 case REQ_RANGE_WORLD:
2384 case REQ_RANGE_COUNT:
2385 break;
2386 }
2387
2388 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2389
2390 return TRI_MAYBE;
2391}
2392
2393/**********************************************************************/
2401static enum fc_tristate
2402is_tech_req_active(const struct civ_map *nmap,
2403 const struct req_context *context,
2404 const struct req_context *other_context,
2405 const struct requirement *req)
2406{
2407 Tech_type_id tech;
2408
2409 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ADVANCE);
2410
2411 tech = advance_number(req->source.value.advance);
2412
2413 if (req->survives) {
2414 fc_assert(req->range == REQ_RANGE_WORLD);
2415 return BOOL_TO_TRISTATE(game.info.global_advances[tech]);
2416 }
2417
2418 /* Not a 'surviving' requirement. */
2419 switch (req->range) {
2420 case REQ_RANGE_PLAYER:
2421 if (context->player != nullptr) {
2422 return BOOL_TO_TRISTATE(TECH_KNOWN == research_invention_state
2423 (research_get(context->player), tech));
2424 } else {
2425 return TRI_MAYBE;
2426 }
2427 case REQ_RANGE_TEAM:
2428 case REQ_RANGE_ALLIANCE:
2429 case REQ_RANGE_WORLD:
2430 if (context->player == nullptr) {
2431 return TRI_MAYBE;
2432 }
2433 players_iterate_alive(plr2) {
2434 if (players_in_same_range(context->player, plr2, req->range)) {
2435 if (research_invention_state(research_get(plr2), tech)
2436 == TECH_KNOWN) {
2437 return TRI_YES;
2438 }
2439 }
2440 } players_iterate_alive_end;
2441
2442 return TRI_NO;
2443 case REQ_RANGE_LOCAL:
2444 if (context->player == nullptr) {
2445 return TRI_MAYBE;
2446 }
2447 if (research_get(context->player)->researching == tech) {
2448 return TRI_YES;
2449 }
2450 return TRI_NO;
2451 case REQ_RANGE_TILE:
2452 case REQ_RANGE_CADJACENT:
2453 case REQ_RANGE_ADJACENT:
2454 case REQ_RANGE_CITY:
2455 case REQ_RANGE_TRADE_ROUTE:
2456 case REQ_RANGE_CONTINENT:
2457 case REQ_RANGE_COUNT:
2458 break;
2459 }
2460
2461 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2462
2463 return TRI_MAYBE;
2464}
2465
2466/**********************************************************************/
2474static enum fc_tristate
2475is_techflag_req_active(const struct civ_map *nmap,
2476 const struct req_context *context,
2477 const struct req_context *other_context,
2478 const struct requirement *req)
2479{
2480 enum tech_flag_id techflag;
2481
2482 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TECHFLAG);
2483
2484 techflag = req->source.value.techflag;
2485
2486 switch (req->range) {
2487 case REQ_RANGE_PLAYER:
2488 if (NULL != context->player) {
2489 return BOOL_TO_TRISTATE(player_knows_techs_with_flag(context->player,
2490 techflag));
2491 } else {
2492 return TRI_MAYBE;
2493 }
2494 break;
2495 case REQ_RANGE_TEAM:
2496 case REQ_RANGE_ALLIANCE:
2497 if (NULL == context->player) {
2498 return TRI_MAYBE;
2499 }
2500 players_iterate_alive(plr2) {
2501 if (players_in_same_range(context->player, plr2, req->range)
2502 && player_knows_techs_with_flag(plr2, techflag)) {
2503 return TRI_YES;
2504 }
2505 } players_iterate_alive_end;
2506 return TRI_NO;
2507 case REQ_RANGE_WORLD:
2508 players_iterate(pplayer) {
2509 if (player_knows_techs_with_flag(pplayer, techflag)) {
2510 return TRI_YES;
2511 }
2512 } players_iterate_end;
2513
2514 return TRI_NO;
2515 case REQ_RANGE_LOCAL:
2516 case REQ_RANGE_TILE:
2517 case REQ_RANGE_CADJACENT:
2518 case REQ_RANGE_ADJACENT:
2519 case REQ_RANGE_CITY:
2520 case REQ_RANGE_TRADE_ROUTE:
2521 case REQ_RANGE_CONTINENT:
2522 case REQ_RANGE_COUNT:
2523 break;
2524 }
2525
2526 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2527
2528 return TRI_MAYBE;
2529}
2530
2531/**********************************************************************/
2539static enum fc_tristate
2540is_minculture_req_active(const struct civ_map *nmap,
2541 const struct req_context *context,
2542 const struct req_context *other_context,
2543 const struct requirement *req)
2544{
2545 int minculture;
2546
2547 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINCULTURE);
2548
2549 minculture = req->source.value.minculture;
2550
2551 switch (req->range) {
2552 case REQ_RANGE_CITY:
2553 if (!context->city) {
2554 return TRI_MAYBE;
2555 }
2556 return BOOL_TO_TRISTATE(city_culture(context->city) >= minculture);
2557 case REQ_RANGE_TRADE_ROUTE:
2558 if (!context->city) {
2559 return TRI_MAYBE;
2560 }
2561 if (city_culture(context->city) >= minculture) {
2562 return TRI_YES;
2563 } else {
2564 enum fc_tristate ret = TRI_NO;
2565
2566 trade_partners_iterate(context->city, trade_partner) {
2567 if (trade_partner == NULL) {
2568 ret = TRI_MAYBE;
2569 } else if (city_culture(trade_partner) >= minculture) {
2570 return TRI_YES;
2571 }
2572 } trade_partners_iterate_end;
2573
2574 return ret;
2575 }
2576 case REQ_RANGE_PLAYER:
2577 case REQ_RANGE_TEAM:
2578 case REQ_RANGE_ALLIANCE:
2579 case REQ_RANGE_WORLD:
2580 if (NULL == context->player) {
2581 return TRI_MAYBE;
2582 }
2583 players_iterate_alive(plr2) {
2584 if (players_in_same_range(context->player, plr2, req->range)) {
2585 if (player_culture(plr2) >= minculture) {
2586 return TRI_YES;
2587 }
2588 }
2589 } players_iterate_alive_end;
2590 return TRI_NO;
2591 case REQ_RANGE_LOCAL:
2592 case REQ_RANGE_TILE:
2593 case REQ_RANGE_CADJACENT:
2594 case REQ_RANGE_ADJACENT:
2595 case REQ_RANGE_CONTINENT:
2596 case REQ_RANGE_COUNT:
2597 break;
2598 }
2599
2600 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2601
2602 return TRI_MAYBE;
2603}
2604
2605/**********************************************************************/
2613static enum fc_tristate
2614is_minforeignpct_req_active(const struct civ_map *nmap,
2615 const struct req_context *context,
2616 const struct req_context *other_context,
2617 const struct requirement *req)
2618{
2619 int min_foreign_pct, foreign_pct;
2620
2621 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINFOREIGNPCT);
2622
2623 min_foreign_pct = req->source.value.minforeignpct;
2624
2625 switch (req->range) {
2626 case REQ_RANGE_CITY:
2627 if (!context->city) {
2628 return TRI_MAYBE;
2629 }
2630 foreign_pct = citizens_nation_foreign(context->city) * 100
2631 / city_size_get(context->city);
2632 return BOOL_TO_TRISTATE(foreign_pct >= min_foreign_pct);
2633 case REQ_RANGE_TRADE_ROUTE:
2634 if (!context->city) {
2635 return TRI_MAYBE;
2636 }
2637 foreign_pct = citizens_nation_foreign(context->city) * 100
2638 / city_size_get(context->city);
2639 if (foreign_pct >= min_foreign_pct) {
2640 return TRI_YES;
2641 } else {
2642 enum fc_tristate ret = TRI_NO;
2643
2644 trade_partners_iterate(context->city, trade_partner) {
2645 if (trade_partner == NULL) {
2646 ret = TRI_MAYBE;
2647 } else {
2648 foreign_pct = citizens_nation_foreign(trade_partner) * 100
2649 / city_size_get(trade_partner);
2650 if (foreign_pct >= min_foreign_pct) {
2651 return TRI_YES;
2652 }
2653 }
2654 } trade_partners_iterate_end;
2655
2656 return ret;
2657 }
2658 case REQ_RANGE_PLAYER:
2659 case REQ_RANGE_TEAM:
2660 case REQ_RANGE_ALLIANCE:
2661 case REQ_RANGE_WORLD:
2662 case REQ_RANGE_LOCAL:
2663 case REQ_RANGE_TILE:
2664 case REQ_RANGE_CADJACENT:
2665 case REQ_RANGE_ADJACENT:
2666 case REQ_RANGE_CONTINENT:
2667 case REQ_RANGE_COUNT:
2668 break;
2669 }
2670
2671 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2672
2673 return TRI_MAYBE;
2674}
2675
2676/**********************************************************************/
2684static enum fc_tristate
2685is_maxunitsontile_req_active(const struct civ_map *nmap,
2686 const struct req_context *context,
2687 const struct req_context *other_context,
2688 const struct requirement *req)
2689{
2690 int max_units;
2691
2692 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MAXTILEUNITS);
2693
2694 max_units = req->source.value.max_tile_units;
2695
2696 /* TODO: if can't see V_INVIS -> TRI_MAYBE */
2697 switch (req->range) {
2698 case REQ_RANGE_TILE:
2699 if (!context->tile) {
2700 return TRI_MAYBE;
2701 }
2702 return BOOL_TO_TRISTATE(unit_list_size(context->tile->units) <= max_units);
2703 case REQ_RANGE_CADJACENT:
2704 if (!context->tile) {
2705 return TRI_MAYBE;
2706 }
2707 if (unit_list_size(context->tile->units) <= max_units) {
2708 return TRI_YES;
2709 }
2710 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
2711 if (unit_list_size(adjc_tile->units) <= max_units) {
2712 return TRI_YES;
2713 }
2714 } cardinal_adjc_iterate_end;
2715 return TRI_NO;
2716 case REQ_RANGE_ADJACENT:
2717 if (!context->tile) {
2718 return TRI_MAYBE;
2719 }
2720 if (unit_list_size(context->tile->units) <= max_units) {
2721 return TRI_YES;
2722 }
2723 adjc_iterate(nmap, context->tile, adjc_tile) {
2724 if (unit_list_size(adjc_tile->units) <= max_units) {
2725 return TRI_YES;
2726 }
2727 } adjc_iterate_end;
2728 return TRI_NO;
2729 case REQ_RANGE_CITY:
2730 case REQ_RANGE_TRADE_ROUTE:
2731 case REQ_RANGE_CONTINENT:
2732 case REQ_RANGE_PLAYER:
2733 case REQ_RANGE_TEAM:
2734 case REQ_RANGE_ALLIANCE:
2735 case REQ_RANGE_WORLD:
2736 case REQ_RANGE_LOCAL:
2737 case REQ_RANGE_COUNT:
2738 break;
2739 }
2740
2741 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2742
2743 return TRI_MAYBE;
2744}
2745
2746/**********************************************************************/
2754static enum fc_tristate
2755is_extra_req_active(const struct civ_map *nmap,
2756 const struct req_context *context,
2757 const struct req_context *other_context,
2758 const struct requirement *req)
2759{
2760 const struct extra_type *pextra;
2761 enum fc_tristate ret;
2762
2763 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_EXTRA);
2764
2765 pextra = req->source.value.extra;
2766
2767 switch (req->range) {
2768 case REQ_RANGE_LOCAL:
2769 if (!context->extra) {
2770 return TRI_MAYBE;
2771 }
2772 return BOOL_TO_TRISTATE(context->extra == pextra);
2773 case REQ_RANGE_TILE:
2774 /* The requirement is filled if the tile has extra of requested type. */
2775 if (!context->tile) {
2776 return TRI_MAYBE;
2777 }
2778 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra));
2779 case REQ_RANGE_CADJACENT:
2780 if (!context->tile) {
2781 return TRI_MAYBE;
2782 }
2783 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2784 || is_extra_card_near(nmap, context->tile, pextra));
2785 case REQ_RANGE_ADJACENT:
2786 if (!context->tile) {
2787 return TRI_MAYBE;
2788 }
2789 return BOOL_TO_TRISTATE(tile_has_extra(context->tile, pextra)
2790 || is_extra_near_tile(nmap, context->tile, pextra));
2791 case REQ_RANGE_CITY:
2792 if (!context->city) {
2793 return TRI_MAYBE;
2794 }
2795 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
2796 city_tile(context->city), ptile) {
2797 if (tile_has_extra(ptile, pextra)) {
2798 return TRI_YES;
2799 }
2800 } city_tile_iterate_end;
2801
2802 return TRI_NO;
2803
2804 case REQ_RANGE_TRADE_ROUTE:
2805 if (!context->city) {
2806 return TRI_MAYBE;
2807 }
2808 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
2809 city_tile(context->city), ptile) {
2810 if (tile_has_extra(ptile, pextra)) {
2811 return TRI_YES;
2812 }
2813 } city_tile_iterate_end;
2814
2815 ret = TRI_NO;
2816 trade_partners_iterate(context->city, trade_partner) {
2817 if (trade_partner == NULL) {
2818 ret = TRI_MAYBE;
2819 } else {
2820 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
2821 city_tile(trade_partner), ptile) {
2822 if (tile_has_extra(ptile, pextra)) {
2823 return TRI_YES;
2824 }
2825 } city_tile_iterate_end;
2826 }
2827 } trade_partners_iterate_end;
2828
2829 return ret;
2830
2831 case REQ_RANGE_CONTINENT:
2832 case REQ_RANGE_PLAYER:
2833 case REQ_RANGE_TEAM:
2834 case REQ_RANGE_ALLIANCE:
2835 case REQ_RANGE_WORLD:
2836 case REQ_RANGE_COUNT:
2837 break;
2838 }
2839
2840 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2841
2842 return TRI_MAYBE;
2843}
2844
2845/**********************************************************************/
2853static enum fc_tristate
2854is_good_req_active(const struct civ_map *nmap,
2855 const struct req_context *context,
2856 const struct req_context *other_context,
2857 const struct requirement *req)
2858{
2859 const struct goods_type *pgood;
2860
2861 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_GOOD);
2862
2863 pgood = req->source.value.good;
2864
2865 switch (req->range) {
2866 case REQ_RANGE_LOCAL:
2867 case REQ_RANGE_CITY:
2868 /* The requirement is filled if the city imports good of requested type. */
2869 if (!context->city) {
2870 return TRI_MAYBE;
2871 }
2872 return BOOL_TO_TRISTATE(city_receives_goods(context->city, pgood)
2873 || (goods_has_flag(pgood, GF_SELF_PROVIDED)
2874 && goods_can_be_provided(context->city, pgood, NULL)));
2875 case REQ_RANGE_TILE:
2876 case REQ_RANGE_CADJACENT:
2877 case REQ_RANGE_ADJACENT:
2878 case REQ_RANGE_TRADE_ROUTE:
2879 case REQ_RANGE_CONTINENT:
2880 case REQ_RANGE_PLAYER:
2881 case REQ_RANGE_TEAM:
2882 case REQ_RANGE_ALLIANCE:
2883 case REQ_RANGE_WORLD:
2884 case REQ_RANGE_COUNT:
2885 break;
2886 }
2887
2888 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
2889
2890 return TRI_MAYBE;
2891}
2892
2893/**********************************************************************/
2901static enum fc_tristate
2902is_action_req_active(const struct civ_map *nmap,
2903 const struct req_context *context,
2904 const struct req_context *other_context,
2905 const struct requirement *req)
2906{
2907 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ACTION);
2908
2909 if (context->action) {
2910 return BOOL_TO_TRISTATE(action_number(context->action)
2911 == action_number(req->source.value.action));
2912 }
2913
2914 if (context->unit != nullptr && context->unit->action != ACTION_NONE) {
2915 log_normal("Unit action %s", action_id_rule_name(context->unit->action));
2916 return BOOL_TO_TRISTATE(context->unit->action
2917 == action_number(req->source.value.action));
2918 }
2919
2920 return TRI_NO;
2921}
2922
2923/**********************************************************************/
2931static enum fc_tristate
2932is_outputtype_req_active(const struct civ_map *nmap,
2933 const struct req_context *context,
2934 const struct req_context *other_context,
2935 const struct requirement *req)
2936{
2937 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_OTYPE);
2938
2939 return BOOL_TO_TRISTATE(context->output
2940 && context->output->index
2941 == req->source.value.outputtype);
2942}
2943
2944/**********************************************************************/
2952static enum fc_tristate
2953is_specialist_req_active(const struct civ_map *nmap,
2954 const struct req_context *context,
2955 const struct req_context *other_context,
2956 const struct requirement *req)
2957{
2958 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_SPECIALIST);
2959
2960 return BOOL_TO_TRISTATE(context->specialist
2961 && context->specialist
2962 == req->source.value.specialist);
2963}
2964
2965/**********************************************************************/
2973static enum fc_tristate
2974is_terrain_req_active(const struct civ_map *nmap,
2975 const struct req_context *context,
2976 const struct req_context *other_context,
2977 const struct requirement *req)
2978{
2979 const struct terrain *pterrain;
2980
2981 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRAIN);
2982
2983 pterrain = req->source.value.terrain;
2984
2985 switch (req->range) {
2986 case REQ_RANGE_TILE:
2987 /* The requirement is filled if the tile has the terrain. */
2988 if (!context->tile) {
2989 return TRI_MAYBE;
2990 }
2991 return pterrain && tile_terrain(context->tile) == pterrain;
2992 case REQ_RANGE_CADJACENT:
2993 if (!context->tile) {
2994 return TRI_MAYBE;
2995 }
2996 return BOOL_TO_TRISTATE(pterrain && is_terrain_card_near(nmap, context->tile, pterrain, TRUE));
2997 case REQ_RANGE_ADJACENT:
2998 if (!context->tile) {
2999 return TRI_MAYBE;
3000 }
3001 return BOOL_TO_TRISTATE(pterrain && is_terrain_near_tile(nmap, context->tile, pterrain, TRUE));
3002 case REQ_RANGE_CITY:
3003 if (!context->city) {
3004 return TRI_MAYBE;
3005 }
3006 if (pterrain != NULL) {
3007 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3008 city_tile(context->city), ptile) {
3009 if (tile_terrain(ptile) == pterrain) {
3010 return TRI_YES;
3011 }
3012 } city_tile_iterate_end;
3013 }
3014 return TRI_NO;
3015 case REQ_RANGE_TRADE_ROUTE:
3016 if (!context->city) {
3017 return TRI_MAYBE;
3018 }
3019 if (pterrain != NULL) {
3020 enum fc_tristate ret;
3021
3022 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3023 city_tile(context->city), ptile) {
3024 if (tile_terrain(ptile) == pterrain) {
3025 return TRI_YES;
3026 }
3027 } city_tile_iterate_end;
3028
3029 ret = TRI_NO;
3030 trade_partners_iterate(context->city, trade_partner) {
3031 if (trade_partner == NULL) {
3032 ret = TRI_MAYBE;
3033 } else {
3034 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3035 city_tile(trade_partner), ptile) {
3036 if (tile_terrain(ptile) == pterrain) {
3037 return TRI_YES;
3038 }
3039 } city_tile_iterate_end;
3040 }
3041 } trade_partners_iterate_end;
3042
3043 return ret;
3044 }
3045
3046 return TRI_MAYBE;
3047 case REQ_RANGE_CONTINENT:
3048 case REQ_RANGE_PLAYER:
3049 case REQ_RANGE_TEAM:
3050 case REQ_RANGE_ALLIANCE:
3051 case REQ_RANGE_WORLD:
3052 case REQ_RANGE_LOCAL:
3053 case REQ_RANGE_COUNT:
3054 break;
3055 }
3056
3057 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3058
3059 return TRI_MAYBE;
3060}
3061
3062/**********************************************************************/
3070static enum fc_tristate
3071is_terrainclass_req_active(const struct civ_map *nmap,
3072 const struct req_context *context,
3073 const struct req_context *other_context,
3074 const struct requirement *req)
3075{
3076 enum terrain_class pclass;
3077 enum fc_tristate ret;
3078
3079 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRAINCLASS);
3080
3081 pclass = req->source.value.terrainclass;
3082
3083 switch (req->range) {
3084 case REQ_RANGE_TILE:
3085 /* The requirement is filled if the tile has the terrain of correct class. */
3086 if (!context->tile) {
3087 return TRI_MAYBE;
3088 }
3089 return BOOL_TO_TRISTATE(terrain_type_terrain_class(tile_terrain(context->tile)) == pclass);
3090 case REQ_RANGE_CADJACENT:
3091 if (!context->tile) {
3092 return TRI_MAYBE;
3093 }
3094 return BOOL_TO_TRISTATE(terrain_type_terrain_class(tile_terrain(context->tile)) == pclass
3095 || is_terrain_class_card_near(nmap, context->tile, pclass));
3096 case REQ_RANGE_ADJACENT:
3097 if (!context->tile) {
3098 return TRI_MAYBE;
3099 }
3100 return BOOL_TO_TRISTATE(terrain_type_terrain_class(tile_terrain(context->tile)) == pclass
3101 || is_terrain_class_near_tile(nmap, context->tile, pclass));
3102 case REQ_RANGE_CITY:
3103 if (!context->city) {
3104 return TRI_MAYBE;
3105 }
3106 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3107 city_tile(context->city), ptile) {
3108 const struct terrain *pterrain = tile_terrain(ptile);
3109
3110 if (pterrain != T_UNKNOWN
3111 && terrain_type_terrain_class(pterrain) == pclass) {
3112 return TRI_YES;
3113 }
3114 } city_tile_iterate_end;
3115
3116 return TRI_NO;
3117 case REQ_RANGE_TRADE_ROUTE:
3118 if (!context->city) {
3119 return TRI_MAYBE;
3120 }
3121 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3122 city_tile(context->city), ptile) {
3123 const struct terrain *pterrain = tile_terrain(ptile);
3124
3125 if (pterrain != T_UNKNOWN
3126 && terrain_type_terrain_class(pterrain) == pclass) {
3127 return TRI_YES;
3128 }
3129 } city_tile_iterate_end;
3130
3131 ret = TRI_NO;
3132 trade_partners_iterate(context->city, trade_partner) {
3133 if (trade_partner == NULL) {
3134 ret = TRI_MAYBE;
3135 } else {
3136 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3137 city_tile(trade_partner), ptile) {
3138 const struct terrain *pterrain = tile_terrain(ptile);
3139
3140 if (pterrain != T_UNKNOWN
3141 && terrain_type_terrain_class(pterrain) == pclass) {
3142 return TRI_YES;
3143 }
3144 } city_tile_iterate_end;
3145 }
3146 } trade_partners_iterate_end;
3147
3148 return ret;
3149 case REQ_RANGE_CONTINENT:
3150 case REQ_RANGE_PLAYER:
3151 case REQ_RANGE_TEAM:
3152 case REQ_RANGE_ALLIANCE:
3153 case REQ_RANGE_WORLD:
3154 case REQ_RANGE_LOCAL:
3155 case REQ_RANGE_COUNT:
3156 break;
3157 }
3158
3159 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3160
3161 return TRI_MAYBE;
3162}
3163
3164/**********************************************************************/
3172static enum fc_tristate
3173is_terrainflag_req_active(const struct civ_map *nmap,
3174 const struct req_context *context,
3175 const struct req_context *other_context,
3176 const struct requirement *req)
3177{
3178 enum terrain_flag_id terrflag;
3179 enum fc_tristate ret;
3180
3181 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRFLAG);
3182
3183 terrflag = req->source.value.terrainflag;
3184
3185 switch (req->range) {
3186 case REQ_RANGE_TILE:
3187 /* The requirement is fulfilled if the tile has a terrain with
3188 * correct flag. */
3189 if (!context->tile) {
3190 return TRI_MAYBE;
3191 }
3192 return BOOL_TO_TRISTATE(terrain_has_flag(tile_terrain(context->tile),
3193 terrflag));
3194 case REQ_RANGE_CADJACENT:
3195 if (!context->tile) {
3196 return TRI_MAYBE;
3197 }
3198 return BOOL_TO_TRISTATE(terrain_has_flag(tile_terrain(context->tile),
3199 terrflag)
3200 || is_terrain_flag_card_near(nmap, context->tile,
3201 terrflag));
3202 case REQ_RANGE_ADJACENT:
3203 if (!context->tile) {
3204 return TRI_MAYBE;
3205 }
3206 return BOOL_TO_TRISTATE(terrain_has_flag(tile_terrain(context->tile),
3207 terrflag)
3208 || is_terrain_flag_near_tile(nmap, context->tile,
3209 terrflag));
3210 case REQ_RANGE_CITY:
3211 if (!context->city) {
3212 return TRI_MAYBE;
3213 }
3214 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3215 city_tile(context->city), ptile) {
3216 const struct terrain *pterrain = tile_terrain(ptile);
3217
3218 if (pterrain != T_UNKNOWN
3219 && terrain_has_flag(pterrain, terrflag)) {
3220 return TRI_YES;
3221 }
3222 } city_tile_iterate_end;
3223
3224 return TRI_NO;
3225 case REQ_RANGE_TRADE_ROUTE:
3226 if (!context->city) {
3227 return TRI_MAYBE;
3228 }
3229 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3230 city_tile(context->city), ptile) {
3231 const struct terrain *pterrain = tile_terrain(ptile);
3232
3233 if (pterrain != T_UNKNOWN
3234 && terrain_has_flag(pterrain, terrflag)) {
3235 return TRI_YES;
3236 }
3237 } city_tile_iterate_end;
3238
3239 ret = TRI_NO;
3240 trade_partners_iterate(context->city, trade_partner) {
3241 if (trade_partner == NULL) {
3242 ret = TRI_MAYBE;
3243 } else {
3244 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3245 city_tile(trade_partner), ptile) {
3246 const struct terrain *pterrain = tile_terrain(ptile);
3247
3248 if (pterrain != T_UNKNOWN
3249 && terrain_has_flag(pterrain, terrflag)) {
3250 return TRI_YES;
3251 }
3252 } city_tile_iterate_end;
3253 }
3254 } trade_partners_iterate_end;
3255
3256 return ret;
3257 case REQ_RANGE_CONTINENT:
3258 case REQ_RANGE_PLAYER:
3259 case REQ_RANGE_TEAM:
3260 case REQ_RANGE_ALLIANCE:
3261 case REQ_RANGE_WORLD:
3262 case REQ_RANGE_LOCAL:
3263 case REQ_RANGE_COUNT:
3264 break;
3265 }
3266
3267 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3268
3269 return TRI_MAYBE;
3270}
3271
3272/**********************************************************************/
3280static enum fc_tristate
3281is_roadflag_req_active(const struct civ_map *nmap,
3282 const struct req_context *context,
3283 const struct req_context *other_context,
3284 const struct requirement *req)
3285{
3286 enum road_flag_id roadflag;
3287 enum fc_tristate ret;
3288
3289 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ROADFLAG);
3290
3291 roadflag = req->source.value.roadflag;
3292
3293 switch (req->range) {
3294 case REQ_RANGE_LOCAL:
3295 {
3296 if (!context->extra) {
3297 return TRI_MAYBE;
3298 }
3299 struct road_type *r = extra_road_get(context->extra);
3300
3301 return BOOL_TO_TRISTATE(
3302 r && road_has_flag(r, roadflag)
3303 );
3304 }
3305 case REQ_RANGE_TILE:
3306 /* The requirement is filled if the tile has a road with correct flag. */
3307 if (!context->tile) {
3308 return TRI_MAYBE;
3309 }
3310 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag));
3311 case REQ_RANGE_CADJACENT:
3312 if (!context->tile) {
3313 return TRI_MAYBE;
3314 }
3315 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3316 || is_road_flag_card_near(nmap, context->tile,
3317 roadflag));
3318 case REQ_RANGE_ADJACENT:
3319 if (!context->tile) {
3320 return TRI_MAYBE;
3321 }
3322 return BOOL_TO_TRISTATE(tile_has_road_flag(context->tile, roadflag)
3323 || is_road_flag_near_tile(nmap, context->tile,
3324 roadflag));
3325 case REQ_RANGE_CITY:
3326 if (!context->city) {
3327 return TRI_MAYBE;
3328 }
3329 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3330 city_tile(context->city), ptile) {
3331 if (tile_has_road_flag(ptile, roadflag)) {
3332 return TRI_YES;
3333 }
3334 } city_tile_iterate_end;
3335
3336 return TRI_NO;
3337 case REQ_RANGE_TRADE_ROUTE:
3338 if (!context->city) {
3339 return TRI_MAYBE;
3340 }
3341 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3342 city_tile(context->city), ptile) {
3343 if (tile_has_road_flag(ptile, roadflag)) {
3344 return TRI_YES;
3345 }
3346 } city_tile_iterate_end;
3347
3348 ret = TRI_NO;
3349 trade_partners_iterate(context->city, trade_partner) {
3350 if (trade_partner == NULL) {
3351 ret = TRI_MAYBE;
3352 } else {
3353 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3354 city_tile(trade_partner), ptile) {
3355 if (tile_has_road_flag(ptile, roadflag)) {
3356 return TRI_YES;
3357 }
3358 } city_tile_iterate_end;
3359 }
3360 } trade_partners_iterate_end;
3361
3362 return ret;
3363 case REQ_RANGE_CONTINENT:
3364 case REQ_RANGE_PLAYER:
3365 case REQ_RANGE_TEAM:
3366 case REQ_RANGE_ALLIANCE:
3367 case REQ_RANGE_WORLD:
3368 case REQ_RANGE_COUNT:
3369 break;
3370 }
3371
3372 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3373
3374 return TRI_MAYBE;
3375}
3376
3377/**********************************************************************/
3385static enum fc_tristate
3386is_extraflag_req_active(const struct civ_map *nmap,
3387 const struct req_context *context,
3388 const struct req_context *other_context,
3389 const struct requirement *req)
3390{
3391 enum extra_flag_id extraflag;
3392 enum fc_tristate ret;
3393
3394 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_EXTRAFLAG);
3395
3396 extraflag = req->source.value.extraflag;
3397
3398 switch (req->range) {
3399 case REQ_RANGE_LOCAL:
3400 if (!context->extra) {
3401 return TRI_MAYBE;
3402 }
3403 return BOOL_TO_TRISTATE(extra_has_flag(context->extra, extraflag));
3404 case REQ_RANGE_TILE:
3405 /* The requirement is filled if the tile has an extra with correct flag. */
3406 if (!context->tile) {
3407 return TRI_MAYBE;
3408 }
3409 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag));
3410 case REQ_RANGE_CADJACENT:
3411 if (!context->tile) {
3412 return TRI_MAYBE;
3413 }
3414 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3415 || is_extra_flag_card_near(nmap, context->tile, extraflag));
3416 case REQ_RANGE_ADJACENT:
3417 if (!context->tile) {
3418 return TRI_MAYBE;
3419 }
3420 return BOOL_TO_TRISTATE(tile_has_extra_flag(context->tile, extraflag)
3421 || is_extra_flag_near_tile(nmap, context->tile, extraflag));
3422 case REQ_RANGE_CITY:
3423 if (!context->city) {
3424 return TRI_MAYBE;
3425 }
3426 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3427 city_tile(context->city), ptile) {
3428 if (tile_has_extra_flag(ptile, extraflag)) {
3429 return TRI_YES;
3430 }
3431 } city_tile_iterate_end;
3432
3433 return TRI_NO;
3434 case REQ_RANGE_TRADE_ROUTE:
3435 if (!context->city) {
3436 return TRI_MAYBE;
3437 }
3438 city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
3439 city_tile(context->city), ptile) {
3440 if (tile_has_extra_flag(ptile, extraflag)) {
3441 return TRI_YES;
3442 }
3443 } city_tile_iterate_end;
3444
3445 ret = TRI_NO;
3446 trade_partners_iterate(context->city, trade_partner) {
3447 if (trade_partner == NULL) {
3448 ret = TRI_MAYBE;
3449 } else {
3450 city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
3451 city_tile(trade_partner), ptile) {
3452 if (tile_has_extra_flag(ptile, extraflag)) {
3453 return TRI_YES;
3454 }
3455 } city_tile_iterate_end;
3456 }
3457 } trade_partners_iterate_end;
3458
3459 return ret;
3460 case REQ_RANGE_CONTINENT:
3461 case REQ_RANGE_PLAYER:
3462 case REQ_RANGE_TEAM:
3463 case REQ_RANGE_ALLIANCE:
3464 case REQ_RANGE_WORLD:
3465 case REQ_RANGE_COUNT:
3466 break;
3467 }
3468
3469 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3470
3471 return TRI_MAYBE;
3472}
3473
3474/**********************************************************************/
3482static enum fc_tristate
3483is_terrainalter_req_active(const struct civ_map *nmap,
3484 const struct req_context *context,
3485 const struct req_context *other_context,
3486 const struct requirement *req)
3487{
3488 enum terrain_alteration alteration;
3489
3490 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TERRAINALTER);
3491
3492 alteration = req->source.value.terrainalter;
3493
3494 if (!context->tile) {
3495 return TRI_MAYBE;
3496 }
3497
3498 switch (req->range) {
3499 case REQ_RANGE_TILE:
3500 return BOOL_TO_TRISTATE(terrain_can_support_alteration(
3501 tile_terrain(context->tile), alteration));
3502 case REQ_RANGE_CADJACENT:
3503 case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
3504 case REQ_RANGE_CITY:
3505 case REQ_RANGE_TRADE_ROUTE:
3506 case REQ_RANGE_CONTINENT:
3507 case REQ_RANGE_PLAYER:
3508 case REQ_RANGE_TEAM:
3509 case REQ_RANGE_ALLIANCE:
3510 case REQ_RANGE_WORLD:
3511 case REQ_RANGE_LOCAL:
3512 case REQ_RANGE_COUNT:
3513 break;
3514 }
3515
3516 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3517
3518 return TRI_MAYBE;
3519}
3520
3521/**********************************************************************/
3529static enum fc_tristate
3530is_gov_req_active(const struct civ_map *nmap,
3531 const struct req_context *context,
3532 const struct req_context *other_context,
3533 const struct requirement *req)
3534{
3535 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_GOVERNMENT);
3536
3537 if (context->player == NULL) {
3538 return TRI_MAYBE;
3539 } else {
3540 return BOOL_TO_TRISTATE(government_of_player(context->player)
3541 == req->source.value.govern);
3542 }
3543}
3544
3545/**********************************************************************/
3553static enum fc_tristate
3554is_style_req_active(const struct civ_map *nmap,
3555 const struct req_context *context,
3556 const struct req_context *other_context,
3557 const struct requirement *req)
3558{
3559 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_STYLE);
3560
3561 if (context->player == NULL) {
3562 return TRI_MAYBE;
3563 } else {
3564 return BOOL_TO_TRISTATE(context->player->style
3565 == req->source.value.style);
3566 }
3567}
3568
3569/**********************************************************************/
3577static enum fc_tristate
3578is_mintechs_req_active(const struct civ_map *nmap,
3579 const struct req_context *context,
3580 const struct req_context *other_context,
3581 const struct requirement *req)
3582{
3583 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINTECHS);
3584
3585 switch (req->range) {
3586 case REQ_RANGE_WORLD:
3587 /* "None" does not count */
3588 return ((game.info.global_advance_count - 1)
3589 >= req->source.value.min_techs);
3590 case REQ_RANGE_PLAYER:
3591 if (context->player == NULL) {
3592 return TRI_MAYBE;
3593 } else {
3594 /* "None" does not count */
3595 return BOOL_TO_TRISTATE(
3596 (research_get(context->player)->techs_researched - 1)
3597 >= req->source.value.min_techs
3598 );
3599 }
3600 default:
3601 return TRI_MAYBE;
3602 }
3603}
3604
3605/**********************************************************************/
3613static enum fc_tristate
3614is_mincities_req_active(const struct civ_map *nmap,
3615 const struct req_context *context,
3616 const struct req_context *other_context,
3617 const struct requirement *req)
3618{
3619 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINCITIES);
3620
3621 switch (req->range) {
3622 case REQ_RANGE_PLAYER:
3623 if (context->player == NULL) {
3624 return TRI_MAYBE;
3625 } else {
3626 /* "None" does not count */
3627 return BOOL_TO_TRISTATE(
3628 city_list_size(context->player->cities)
3629 >= req->source.value.min_cities
3630 );
3631 }
3632 default:
3633 return TRI_MAYBE;
3634 }
3635}
3636
3637/**********************************************************************/
3645static enum fc_tristate
3646is_ai_req_active(const struct civ_map *nmap,
3647 const struct req_context *context,
3648 const struct req_context *other_context,
3649 const struct requirement *req)
3650{
3651 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_AI_LEVEL);
3652
3653 if (context->player == NULL) {
3654 return TRI_MAYBE;
3655 } else {
3656 return BOOL_TO_TRISTATE(is_ai(context->player)
3657 && context->player->ai_common.skill_level
3658 == req->source.value.ai_level);
3659 }
3660}
3661
3662/**********************************************************************/
3670static enum fc_tristate
3671is_nation_req_active(const struct civ_map *nmap,
3672 const struct req_context *context,
3673 const struct req_context *other_context,
3674 const struct requirement *req)
3675{
3676 const struct nation_type *nation;
3677
3678 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NATION);
3679
3680 nation = req->source.value.nation;
3681
3682 switch (req->range) {
3683 case REQ_RANGE_PLAYER:
3684 if (context->player == NULL) {
3685 return TRI_MAYBE;
3686 }
3687 return BOOL_TO_TRISTATE(nation_of_player(context->player) == nation);
3688 case REQ_RANGE_TEAM:
3689 case REQ_RANGE_ALLIANCE:
3690 if (context->player == NULL) {
3691 return TRI_MAYBE;
3692 }
3693 players_iterate_alive(plr2) {
3694 if (players_in_same_range(context->player, plr2, req->range)) {
3695 if (nation_of_player(plr2) == nation) {
3696 return TRI_YES;
3697 }
3698 }
3699 } players_iterate_alive_end;
3700 return TRI_NO;
3701 case REQ_RANGE_WORLD:
3702 /* NB: if a player is ever removed outright from the game
3703 * (e.g. via /remove), rather than just dying, this 'survives'
3704 * requirement will stop being true for their nation.
3705 * create_command_newcomer() can also cause this to happen. */
3706 return BOOL_TO_TRISTATE(NULL != nation->player
3707 && (req->survives || nation->player->is_alive));
3708 case REQ_RANGE_LOCAL:
3709 case REQ_RANGE_TILE:
3710 case REQ_RANGE_CADJACENT:
3711 case REQ_RANGE_ADJACENT:
3712 case REQ_RANGE_CITY:
3713 case REQ_RANGE_TRADE_ROUTE:
3714 case REQ_RANGE_CONTINENT:
3715 case REQ_RANGE_COUNT:
3716 break;
3717 }
3718
3719 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3720
3721 return TRI_MAYBE;
3722}
3723
3724/**********************************************************************/
3732static enum fc_tristate
3733is_nationgroup_req_active(const struct civ_map *nmap,
3734 const struct req_context *context,
3735 const struct req_context *other_context,
3736 const struct requirement *req)
3737{
3738 const struct nation_group *ngroup;
3739
3740 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NATIONGROUP);
3741
3742 ngroup = req->source.value.nationgroup;
3743
3744 switch (req->range) {
3745 case REQ_RANGE_PLAYER:
3746 if (context->player == NULL) {
3747 return TRI_MAYBE;
3748 }
3749 return BOOL_TO_TRISTATE(nation_is_in_group(
3750 nation_of_player(context->player), ngroup));
3751 case REQ_RANGE_TEAM:
3752 case REQ_RANGE_ALLIANCE:
3753 case REQ_RANGE_WORLD:
3754 if (context->player == NULL) {
3755 return TRI_MAYBE;
3756 }
3757 players_iterate_alive(plr2) {
3758 if (players_in_same_range(context->player, plr2, req->range)) {
3759 if (nation_is_in_group(nation_of_player(plr2), ngroup)) {
3760 return TRI_YES;
3761 }
3762 }
3763 } players_iterate_alive_end;
3764 return TRI_NO;
3765 case REQ_RANGE_LOCAL:
3766 case REQ_RANGE_TILE:
3767 case REQ_RANGE_CADJACENT:
3768 case REQ_RANGE_ADJACENT:
3769 case REQ_RANGE_CITY:
3770 case REQ_RANGE_TRADE_ROUTE:
3771 case REQ_RANGE_CONTINENT:
3772 case REQ_RANGE_COUNT:
3773 break;
3774 }
3775
3776 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3777
3778 return TRI_MAYBE;
3779}
3780
3781/**********************************************************************/
3789static enum fc_tristate
3790is_nationality_req_active(const struct civ_map *nmap,
3791 const struct req_context *context,
3792 const struct req_context *other_context,
3793 const struct requirement *req)
3794{
3795 const struct nation_type *nationality;
3796 enum fc_tristate ret;
3797
3798 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_NATIONALITY);
3799
3800 nationality = req->source.value.nationality;
3801
3802 switch (req->range) {
3803 case REQ_RANGE_CITY:
3804 if (context->city == NULL) {
3805 return TRI_MAYBE;
3806 }
3807 citizens_iterate(context->city, slot, count) {
3808 if (player_slot_get_player(slot)->nation == nationality) {
3809 return TRI_YES;
3810 }
3811 } citizens_iterate_end;
3812
3813 return TRI_NO;
3814 case REQ_RANGE_TRADE_ROUTE:
3815 if (context->city == NULL) {
3816 return TRI_MAYBE;
3817 }
3818 citizens_iterate(context->city, slot, count) {
3819 if (player_slot_get_player(slot)->nation == nationality) {
3820 return TRI_YES;
3821 }
3822 } citizens_iterate_end;
3823
3824 ret = TRI_NO;
3825 trade_partners_iterate(context->city, trade_partner) {
3826 if (trade_partner == NULL) {
3827 ret = TRI_MAYBE;
3828 } else {
3829 citizens_iterate(trade_partner, slot, count) {
3830 if (player_slot_get_player(slot)->nation == nationality) {
3831 return TRI_YES;
3832 }
3833 } citizens_iterate_end;
3834 }
3835 } trade_partners_iterate_end;
3836
3837 return ret;
3838 case REQ_RANGE_PLAYER:
3839 case REQ_RANGE_TEAM:
3840 case REQ_RANGE_ALLIANCE:
3841 case REQ_RANGE_WORLD:
3842 case REQ_RANGE_LOCAL:
3843 case REQ_RANGE_TILE:
3844 case REQ_RANGE_CADJACENT:
3845 case REQ_RANGE_ADJACENT:
3846 case REQ_RANGE_CONTINENT:
3847 case REQ_RANGE_COUNT:
3848 break;
3849 }
3850
3851 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3852
3853 return TRI_MAYBE;
3854}
3855
3856/**********************************************************************/
3864static enum fc_tristate
3865is_originalowner_req_active(const struct civ_map *nmap,
3866 const struct req_context *context,
3867 const struct req_context *other_context,
3868 const struct requirement *req)
3869{
3870 const struct nation_type *nation;
3871
3872 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ORIGINAL_OWNER);
3873
3874 nation = req->source.value.origowner;
3875
3876 switch (req->range) {
3877 case REQ_RANGE_CITY:
3878 if (context->city == NULL || context->city->original == NULL) {
3879 return TRI_MAYBE;
3880 }
3881 if (player_nation(context->city->original) == nation) {
3882 return TRI_YES;
3883 }
3884
3885 return TRI_NO;
3886 case REQ_RANGE_TRADE_ROUTE:
3887 case REQ_RANGE_PLAYER:
3888 case REQ_RANGE_TEAM:
3889 case REQ_RANGE_ALLIANCE:
3890 case REQ_RANGE_WORLD:
3891 case REQ_RANGE_LOCAL:
3892 case REQ_RANGE_TILE:
3893 case REQ_RANGE_CADJACENT:
3894 case REQ_RANGE_ADJACENT:
3895 case REQ_RANGE_CONTINENT:
3896 case REQ_RANGE_COUNT:
3897 break;
3898 }
3899
3900 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
3901
3902 return TRI_MAYBE;
3903}
3904
3905/**********************************************************************/
3908 static enum fc_tristate is_diplrel_in_range(const struct player *target_player,
3909 const struct player *other_player,
3910 enum req_range range,
3911 int diplrel)
3912{
3913 switch (range) {
3914 case REQ_RANGE_PLAYER:
3915 if (target_player == NULL) {
3916 return TRI_MAYBE;
3917 }
3918 return BOOL_TO_TRISTATE(is_diplrel_to_other(target_player, diplrel));
3919 case REQ_RANGE_TEAM:
3920 case REQ_RANGE_ALLIANCE:
3921 case REQ_RANGE_WORLD:
3922 if (target_player == NULL) {
3923 return TRI_MAYBE;
3924 }
3925 players_iterate_alive(plr2) {
3926 if (players_in_same_range(target_player, plr2, range)) {
3927 if (is_diplrel_to_other(plr2, diplrel)) {
3928 return TRI_YES;
3929 }
3930 }
3931 } players_iterate_alive_end;
3932 return TRI_NO;
3933 case REQ_RANGE_LOCAL:
3934 if (target_player == NULL || other_player == NULL) {
3935 return TRI_MAYBE;
3936 }
3937 return BOOL_TO_TRISTATE(is_diplrel_between(target_player, other_player, diplrel));
3938 case REQ_RANGE_TILE:
3939 case REQ_RANGE_CADJACENT:
3940 case REQ_RANGE_ADJACENT:
3941 case REQ_RANGE_CITY:
3942 case REQ_RANGE_TRADE_ROUTE:
3943 case REQ_RANGE_CONTINENT:
3944 case REQ_RANGE_COUNT:
3945 break;
3946 }
3947
3948 fc_assert_msg(FALSE, "Invalid range %d.", range);
3949
3950 return TRI_MAYBE;
3951}
3952
3953/**********************************************************************/
3961static enum fc_tristate
3962is_diplrel_req_active(const struct civ_map *nmap,
3963 const struct req_context *context,
3964 const struct req_context *other_context,
3965 const struct requirement *req)
3966{
3967 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL);
3968
3969 return is_diplrel_in_range(context->player, other_context->player,
3970 req->range, req->source.value.diplrel);
3971}
3972
3973/**********************************************************************/
3981static enum fc_tristate
3982is_diplrel_tile_req_active(const struct civ_map *nmap,
3983 const struct req_context *context,
3984 const struct req_context *other_context,
3985 const struct requirement *req)
3986{
3987 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_TILE);
3988
3989 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
3990 : NULL,
3991 context->player,
3992 req->range,
3993 req->source.value.diplrel);
3994}
3995
3996/**********************************************************************/
4005static enum fc_tristate
4006is_diplrel_tile_o_req_active(const struct civ_map *nmap,
4007 const struct req_context *context,
4008 const struct req_context *other_context,
4009 const struct requirement *req)
4010{
4011 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_TILE_O);
4012
4013 return is_diplrel_in_range(context->tile ? tile_owner(context->tile)
4014 : NULL,
4015 other_context->player,
4016 req->range,
4017 req->source.value.diplrel);
4018}
4019
4020/**********************************************************************/
4023static enum fc_tristate
4024is_diplrel_unitany_in_range(const struct tile *target_tile,
4025 const struct player *other_player,
4026 enum req_range range,
4027 int diplrel)
4028{
4029 enum fc_tristate out = TRI_NO;
4030
4031 if (target_tile == NULL) {
4032 return TRI_MAYBE;
4033 }
4034
4035 unit_list_iterate(target_tile->units, target_unit) {
4036 enum fc_tristate for_target_unit = is_diplrel_in_range(
4037 unit_owner(target_unit), other_player, range, diplrel);
4038
4039 out = fc_tristate_or(out, for_target_unit);
4040 } unit_list_iterate_end;
4041
4042 return out;
4043}
4044
4045/**********************************************************************/
4054static enum fc_tristate
4055is_diplrel_unitany_req_active(const struct civ_map *nmap,
4056 const struct req_context *context,
4057 const struct req_context *other_context,
4058 const struct requirement *req)
4059{
4060 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_UNITANY);
4061
4062 return is_diplrel_unitany_in_range(context->tile, context->player,
4063 req->range,
4064 req->source.value.diplrel);
4065}
4066
4067/**********************************************************************/
4076static enum fc_tristate
4077is_diplrel_unitany_o_req_active(const struct civ_map *nmap,
4078 const struct req_context *context,
4079 const struct req_context *other_context,
4080 const struct requirement *req)
4081{
4082 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_DIPLREL_UNITANY_O);
4083
4084 return is_diplrel_unitany_in_range(context->tile, other_context->player,
4085 req->range,
4086 req->source.value.diplrel);
4087}
4088
4089/**********************************************************************/
4097static enum fc_tristate
4098is_unittype_req_active(const struct civ_map *nmap,
4099 const struct req_context *context,
4100 const struct req_context *other_context,
4101 const struct requirement *req)
4102{
4103 const struct unit_type *punittype;
4104
4105 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UTYPE);
4106
4107 punittype = req->source.value.utype;
4108
4109 switch (req->range) {
4110 case REQ_RANGE_LOCAL:
4111 if (!context->unittype) {
4112 return TRI_MAYBE;
4113 }
4114 return BOOL_TO_TRISTATE(context->unittype == punittype);
4115 case REQ_RANGE_TILE:
4116 case REQ_RANGE_CADJACENT:
4117 case REQ_RANGE_ADJACENT:
4118 if (context->tile == nullptr) {
4119 return TRI_MAYBE;
4120 }
4121
4122 unit_list_iterate(context->tile->units, punit) {
4123 if (punit->utype == punittype) {
4124 return TRI_YES;
4125 }
4126 } unit_list_iterate_end;
4127
4128 if (req->range == REQ_RANGE_TILE) {
4129 return TRI_NO;
4130 }
4131
4132 if (req->range == REQ_RANGE_CADJACENT) {
4133 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4134 unit_list_iterate(adjc_tile->units, punit) {
4135 if (punit->utype == punittype) {
4136 return TRI_YES;
4137 }
4138 } unit_list_iterate_end;
4139 } cardinal_adjc_iterate_end;
4140 } else {
4141 fc_assert(req->range == REQ_RANGE_ADJACENT);
4142
4143 adjc_iterate(nmap, context->tile, adjc_tile) {
4144 unit_list_iterate(adjc_tile->units, punit) {
4145 if (punit->utype == punittype) {
4146 return TRI_YES;
4147 }
4148 } unit_list_iterate_end;
4149 } adjc_iterate_end;
4150 }
4151
4152 return TRI_NO;
4153
4154 case REQ_RANGE_CITY:
4155 case REQ_RANGE_TRADE_ROUTE:
4156 case REQ_RANGE_CONTINENT:
4157 case REQ_RANGE_PLAYER:
4158 case REQ_RANGE_TEAM:
4159 case REQ_RANGE_ALLIANCE:
4160 case REQ_RANGE_WORLD:
4161 case REQ_RANGE_COUNT:
4162 fc_assert(FALSE);
4163 break;
4164 }
4165
4166 return TRI_NO;
4167}
4168
4169/**********************************************************************/
4177static enum fc_tristate
4178is_unitflag_req_active(const struct civ_map *nmap,
4179 const struct req_context *context,
4180 const struct req_context *other_context,
4181 const struct requirement *req)
4182{
4183 enum unit_type_flag_id unitflag;
4184
4185 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UTFLAG);
4186
4187 unitflag = req->source.value.unitflag;
4188
4189 switch (req->range) {
4190 case REQ_RANGE_LOCAL:
4191 if (!context->unittype) {
4192 return TRI_MAYBE;
4193 }
4194 return BOOL_TO_TRISTATE(utype_has_flag(context->unittype, unitflag));
4195 case REQ_RANGE_TILE:
4196 case REQ_RANGE_CADJACENT:
4197 case REQ_RANGE_ADJACENT:
4198 if (context->tile == nullptr) {
4199 return TRI_MAYBE;
4200 }
4201
4202 unit_list_iterate(context->tile->units, punit) {
4203 if (unit_has_type_flag(punit, unitflag)) {
4204 return TRI_YES;
4205 }
4206 } unit_list_iterate_end;
4207
4208 if (req->range == REQ_RANGE_TILE) {
4209 return TRI_NO;
4210 }
4211
4212 if (req->range == REQ_RANGE_CADJACENT) {
4213 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4214 unit_list_iterate(adjc_tile->units, punit) {
4215 if (unit_has_type_flag(punit, unitflag)) {
4216 return TRI_YES;
4217 }
4218 } unit_list_iterate_end;
4219 } cardinal_adjc_iterate_end;
4220 } else {
4221 fc_assert(req->range == REQ_RANGE_ADJACENT);
4222
4223 adjc_iterate(nmap, context->tile, adjc_tile) {
4224 unit_list_iterate(adjc_tile->units, punit) {
4225 if (unit_has_type_flag(punit, unitflag)) {
4226 return TRI_YES;
4227 }
4228 } unit_list_iterate_end;
4229 } adjc_iterate_end;
4230 }
4231
4232 return TRI_NO;
4233
4234 case REQ_RANGE_CITY:
4235 case REQ_RANGE_TRADE_ROUTE:
4236 case REQ_RANGE_CONTINENT:
4237 case REQ_RANGE_PLAYER:
4238 case REQ_RANGE_TEAM:
4239 case REQ_RANGE_ALLIANCE:
4240 case REQ_RANGE_WORLD:
4241 case REQ_RANGE_COUNT:
4242 fc_assert(FALSE);
4243 break;
4244 }
4245
4246 return TRI_NO;
4247}
4248
4249/**********************************************************************/
4257static enum fc_tristate
4258is_unitclass_req_active(const struct civ_map *nmap,
4259 const struct req_context *context,
4260 const struct req_context *other_context,
4261 const struct requirement *req)
4262{
4263 const struct unit_class *pclass;
4264
4265 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UCLASS);
4266
4267 pclass = req->source.value.uclass;
4268
4269 switch (req->range) {
4270 case REQ_RANGE_LOCAL:
4271 if (!context->unittype) {
4272 return TRI_MAYBE;
4273 }
4274 return BOOL_TO_TRISTATE(utype_class(context->unittype) == pclass);
4275 case REQ_RANGE_TILE:
4276 case REQ_RANGE_CADJACENT:
4277 case REQ_RANGE_ADJACENT:
4278 if (context->tile == nullptr) {
4279 return TRI_MAYBE;
4280 }
4281
4282 unit_list_iterate(context->tile->units, punit) {
4283 if (unit_class_get(punit) == pclass) {
4284 return TRI_YES;
4285 }
4286 } unit_list_iterate_end;
4287
4288 if (req->range == REQ_RANGE_TILE) {
4289 return TRI_NO;
4290 }
4291
4292 if (req->range == REQ_RANGE_CADJACENT) {
4293 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4294 unit_list_iterate(adjc_tile->units, punit) {
4295 if (unit_class_get(punit) == pclass) {
4296 return TRI_YES;
4297 }
4298 } unit_list_iterate_end;
4299 } cardinal_adjc_iterate_end;
4300 } else {
4301 fc_assert(req->range == REQ_RANGE_ADJACENT);
4302
4303 adjc_iterate(nmap, context->tile, adjc_tile) {
4304 unit_list_iterate(adjc_tile->units, punit) {
4305 if (unit_class_get(punit) == pclass) {
4306 return TRI_YES;
4307 }
4308 } unit_list_iterate_end;
4309 } adjc_iterate_end;
4310 }
4311
4312 return TRI_NO;
4313
4314 case REQ_RANGE_CITY:
4315 case REQ_RANGE_TRADE_ROUTE:
4316 case REQ_RANGE_CONTINENT:
4317 case REQ_RANGE_PLAYER:
4318 case REQ_RANGE_TEAM:
4319 case REQ_RANGE_ALLIANCE:
4320 case REQ_RANGE_WORLD:
4321 case REQ_RANGE_COUNT:
4322 fc_assert(FALSE);
4323 break;
4324 }
4325
4326 return TRI_NO;
4327}
4328
4329/**********************************************************************/
4337static enum fc_tristate
4338is_unitclassflag_req_active(const struct civ_map *nmap,
4339 const struct req_context *context,
4340 const struct req_context *other_context,
4341 const struct requirement *req)
4342{
4343 enum unit_class_flag_id ucflag;
4344
4345 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UCFLAG);
4346
4347 ucflag = req->source.value.unitclassflag;
4348
4349 switch (req->range) {
4350 case REQ_RANGE_LOCAL:
4351 if (!context->unittype) {
4352 return TRI_MAYBE;
4353 }
4354 return BOOL_TO_TRISTATE(uclass_has_flag(utype_class(context->unittype), ucflag));
4355 case REQ_RANGE_TILE:
4356 case REQ_RANGE_CADJACENT:
4357 case REQ_RANGE_ADJACENT:
4358 if (context->tile == nullptr) {
4359 return TRI_MAYBE;
4360 }
4361
4362 unit_list_iterate(context->tile->units, punit) {
4363 if (unit_has_class_flag(punit, ucflag)) {
4364 return TRI_YES;
4365 }
4366 } unit_list_iterate_end;
4367
4368 if (req->range == REQ_RANGE_TILE) {
4369 return TRI_NO;
4370 }
4371
4372 if (req->range == REQ_RANGE_CADJACENT) {
4373 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4374 unit_list_iterate(adjc_tile->units, punit) {
4375 if (unit_has_class_flag(punit, ucflag)) {
4376 return TRI_YES;
4377 }
4378 } unit_list_iterate_end;
4379 } cardinal_adjc_iterate_end;
4380 } else {
4381 fc_assert(req->range == REQ_RANGE_ADJACENT);
4382
4383 adjc_iterate(nmap, context->tile, adjc_tile) {
4384 unit_list_iterate(adjc_tile->units, punit) {
4385 if (unit_has_class_flag(punit, ucflag)) {
4386 return TRI_YES;
4387 }
4388 } unit_list_iterate_end;
4389 } adjc_iterate_end;
4390 }
4391
4392 return TRI_NO;
4393
4394 case REQ_RANGE_CITY:
4395 case REQ_RANGE_TRADE_ROUTE:
4396 case REQ_RANGE_CONTINENT:
4397 case REQ_RANGE_PLAYER:
4398 case REQ_RANGE_TEAM:
4399 case REQ_RANGE_ALLIANCE:
4400 case REQ_RANGE_WORLD:
4401 case REQ_RANGE_COUNT:
4402 fc_assert(FALSE);
4403 break;
4404 }
4405
4406 return TRI_NO;
4407}
4408
4409/**********************************************************************/
4417static enum fc_tristate
4418is_unitstate_req_active(const struct civ_map *nmap,
4419 const struct req_context *context,
4420 const struct req_context *other_context,
4421 const struct requirement *req)
4422{
4423 enum ustate_prop uprop;
4424
4425 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_UNITSTATE);
4426
4427 uprop = req->source.value.unit_state;
4428
4429 fc_assert_ret_val_msg(req->range == REQ_RANGE_LOCAL, TRI_NO,
4430 "Unsupported range \"%s\"",
4431 req_range_name(req->range));
4432
4433 /* Could be asked with incomplete data.
4434 * is_req_active() will handle it based on prob_type. */
4435 if (context->unit == NULL) {
4436 return TRI_MAYBE;
4437 }
4438
4439 switch (uprop) {
4440 case USP_TRANSPORTED:
4441 return BOOL_TO_TRISTATE(context->unit->transporter != NULL);
4442 case USP_LIVABLE_TILE:
4443 return BOOL_TO_TRISTATE(
4444 can_unit_exist_at_tile(nmap, context->unit,
4445 unit_tile(context->unit)));
4446 break;
4447 case USP_TRANSPORTING:
4448 return BOOL_TO_TRISTATE(0 < get_transporter_occupancy(context->unit));
4449 case USP_HAS_HOME_CITY:
4450 return BOOL_TO_TRISTATE(context->unit->homecity > 0);
4451 case USP_NATIVE_TILE:
4452 return BOOL_TO_TRISTATE(
4453 is_native_tile(unit_type_get(context->unit),
4454 unit_tile(context->unit)));
4455 break;
4456 case USP_NATIVE_EXTRA:
4457 return BOOL_TO_TRISTATE(
4458 tile_has_native_base(unit_tile(context->unit),
4459 unit_type_get(context->unit)));
4460 break;
4461 case USP_MOVED_THIS_TURN:
4462 return BOOL_TO_TRISTATE(context->unit->moved);
4463 case USP_COUNT:
4464 fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
4465 /* Invalid property is unknowable. */
4466 return TRI_NO;
4467 }
4468
4469 /* Should never be reached */
4470 fc_assert_msg(FALSE, "Unsupported unit property %d", uprop);
4471
4472 return TRI_NO;
4473}
4474
4475/**********************************************************************/
4483static enum fc_tristate
4484is_activity_req_active(const struct civ_map *nmap,
4485 const struct req_context *context,
4486 const struct req_context *other_context,
4487 const struct requirement *req)
4488{
4489 enum unit_activity activity;
4490
4491 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ACTIVITY);
4492
4493 activity = req->source.value.activity;
4494
4495 fc_assert_ret_val_msg(req->range == REQ_RANGE_LOCAL, TRI_NO,
4496 "Unsupported range \"%s\"",
4497 req_range_name(req->range));
4498
4499 if (context->unit == NULL) {
4500 /* FIXME: Excluding ACTIVITY_IDLE here is a bit ugly, but done because
4501 * it's the zero value that context has by default - so many callers
4502 * who meant not to set specific activity actually have ACTIVITY_IDLE
4503 * instead of ACTIVITY_LAST */
4504 if (context->activity != ACTIVITY_LAST && context->activity != ACTIVITY_IDLE) {
4505 return BOOL_TO_TRISTATE(activity == context->activity);
4506 }
4507
4508 /* Could be asked with incomplete data.
4509 * is_req_active() will handle it based on prob_type. */
4510 return TRI_MAYBE;
4511 }
4512
4513 switch (context->unit->activity) {
4514 case ACTIVITY_IDLE:
4515 case ACTIVITY_SENTRY:
4516 case ACTIVITY_GOTO:
4517 case ACTIVITY_EXPLORE:
4518 /* Seen as idle. */
4519 return BOOL_TO_TRISTATE(activity == ACTIVITY_IDLE);
4520 default:
4521 /* Handled below. */
4522 break;
4523 }
4524
4525 return BOOL_TO_TRISTATE(context->unit->activity == activity);
4526}
4527
4528/**********************************************************************/
4536static enum fc_tristate
4537is_minveteran_req_active(const struct civ_map *nmap,
4538 const struct req_context *context,
4539 const struct req_context *other_context,
4540 const struct requirement *req)
4541{
4542 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINVETERAN);
4543
4544 if (context->unit == NULL) {
4545 return TRI_MAYBE;
4546 } else {
4547 return BOOL_TO_TRISTATE(context->unit->veteran
4548 >= req->source.value.minveteran);
4549 }
4550}
4551
4552/**********************************************************************/
4560static enum fc_tristate
4561is_minmovefrags_req_active(const struct civ_map *nmap,
4562 const struct req_context *context,
4563 const struct req_context *other_context,
4564 const struct requirement *req)
4565{
4566 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINMOVES);
4567
4568 if (context->unit == NULL) {
4569 return TRI_MAYBE;
4570 } else {
4571 return BOOL_TO_TRISTATE(req->source.value.minmoves
4572 <= context->unit->moves_left);
4573 }
4574}
4575
4576/**********************************************************************/
4584static enum fc_tristate
4585is_minhitpoints_req_active(const struct civ_map *nmap,
4586 const struct req_context *context,
4587 const struct req_context *other_context,
4588 const struct requirement *req)
4589{
4590 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINHP);
4591
4592 if (context->unit == NULL) {
4593 return TRI_MAYBE;
4594 } else {
4595 return BOOL_TO_TRISTATE(req->source.value.min_hit_points
4596 <= context->unit->hp);
4597 }
4598}
4599
4600/**********************************************************************/
4608static enum fc_tristate
4609is_age_req_active(const struct civ_map *nmap,
4610 const struct req_context *context,
4611 const struct req_context *other_context,
4612 const struct requirement *req)
4613{
4614 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_AGE);
4615
4616 switch (req->range) {
4617 case REQ_RANGE_LOCAL:
4618 if (context->unit == NULL || !is_server()) {
4619 return TRI_MAYBE;
4620 } else {
4621 return BOOL_TO_TRISTATE(
4622 req->source.value.age <=
4623 game.info.turn - context->unit->birth_turn);
4624 }
4625 break;
4626 case REQ_RANGE_CITY:
4627 if (context->city == NULL) {
4628 return TRI_MAYBE;
4629 } else {
4630 return BOOL_TO_TRISTATE(
4631 req->source.value.age <=
4632 game.info.turn - context->city->turn_founded);
4633 }
4634 break;
4635 case REQ_RANGE_PLAYER:
4636 if (context->player == NULL) {
4637 return TRI_MAYBE;
4638 } else {
4639 return BOOL_TO_TRISTATE(req->source.value.age
4640 <= player_age(context->player));
4641 }
4642 break;
4643 default:
4644 return TRI_MAYBE;
4645 break;
4646 }
4647}
4648
4649/**********************************************************************/
4657static enum fc_tristate
4658is_form_age_req_active(const struct civ_map *nmap,
4659 const struct req_context *context,
4660 const struct req_context *other_context,
4661 const struct requirement *req)
4662{
4663 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_FORM_AGE);
4664
4665 switch (req->range) {
4666 case REQ_RANGE_LOCAL:
4667 if (context->unit == NULL || !is_server()) {
4668 return TRI_MAYBE;
4669 } else {
4670 return BOOL_TO_TRISTATE(
4671 req->source.value.form_age <=
4672 game.info.turn - context->unit->current_form_turn);
4673 }
4674 break;
4675 default:
4676 return TRI_MAYBE;
4677 break;
4678 }
4679}
4680
4681/**********************************************************************/
4684 static bool is_city_in_tile(const struct tile *ptile,
4685 const struct city *pcity)
4686{
4687 if (pcity == NULL) {
4688 return tile_city(ptile) != NULL;
4689 } else {
4690 return is_city_center(pcity, ptile);
4691 }
4692}
4693
4694/**********************************************************************/
4702static enum fc_tristate
4703is_citytile_req_active(const struct civ_map *nmap,
4704 const struct req_context *context,
4705 const struct req_context *other_context,
4706 const struct requirement *req)
4707{
4708 enum citytile_type citytile;
4709
4710 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_CITYTILE);
4711
4712 citytile = req->source.value.citytile;
4713
4714 fc_assert_ret_val(req_range_is_valid(req->range), TRI_MAYBE);
4715 if (context->tile == NULL) {
4716 return TRI_MAYBE;
4717 }
4718
4719 switch (citytile) {
4720 case CITYT_CENTER:
4721 switch (req->range) {
4722 case REQ_RANGE_TILE:
4723 return BOOL_TO_TRISTATE(is_city_in_tile(context->tile,
4724 context->city));
4725 case REQ_RANGE_CADJACENT:
4726 if (is_city_in_tile(context->tile, context->city)) {
4727 return TRI_YES;
4728 }
4729 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4730 if (is_city_in_tile(adjc_tile, context->city)) {
4731 return TRI_YES;
4732 }
4733 } cardinal_adjc_iterate_end;
4734
4735 return TRI_NO;
4736 case REQ_RANGE_ADJACENT:
4737 if (is_city_in_tile(context->tile, context->city)) {
4738 return TRI_YES;
4739 }
4740 adjc_iterate(nmap, context->tile, adjc_tile) {
4741 if (is_city_in_tile(adjc_tile, context->city)) {
4742 return TRI_YES;
4743 }
4744 } adjc_iterate_end;
4745
4746 return TRI_NO;
4747 case REQ_RANGE_CITY:
4748 case REQ_RANGE_TRADE_ROUTE:
4749 case REQ_RANGE_CONTINENT:
4750 case REQ_RANGE_PLAYER:
4751 case REQ_RANGE_TEAM:
4752 case REQ_RANGE_ALLIANCE:
4753 case REQ_RANGE_WORLD:
4754 case REQ_RANGE_LOCAL:
4755 case REQ_RANGE_COUNT:
4756 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4757 break;
4758 }
4759
4760 return TRI_MAYBE;
4761 case CITYT_CLAIMED:
4762 switch (req->range) {
4763 case REQ_RANGE_TILE:
4764 return BOOL_TO_TRISTATE(context->tile->owner != NULL);
4765 case REQ_RANGE_CADJACENT:
4766 if (context->tile->owner != NULL) {
4767 return TRI_YES;
4768 }
4769 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4770 if (adjc_tile->owner != NULL) {
4771 return TRI_YES;
4772 }
4773 } cardinal_adjc_iterate_end;
4774
4775 return TRI_NO;
4776 case REQ_RANGE_ADJACENT:
4777 if (context->tile->owner != NULL) {
4778 return TRI_YES;
4779 }
4780 adjc_iterate(nmap, context->tile, adjc_tile) {
4781 if (adjc_tile->owner != NULL) {
4782 return TRI_YES;
4783 }
4784 } adjc_iterate_end;
4785
4786 return TRI_NO;
4787 case REQ_RANGE_CITY:
4788 case REQ_RANGE_TRADE_ROUTE:
4789 case REQ_RANGE_CONTINENT:
4790 case REQ_RANGE_PLAYER:
4791 case REQ_RANGE_TEAM:
4792 case REQ_RANGE_ALLIANCE:
4793 case REQ_RANGE_WORLD:
4794 case REQ_RANGE_LOCAL:
4795 case REQ_RANGE_COUNT:
4796 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4797 break;
4798 }
4799
4800 return TRI_MAYBE;
4801 case CITYT_EXTRAS_OWNED:
4802 switch (req->range) {
4803 case REQ_RANGE_TILE:
4804 return BOOL_TO_TRISTATE(context->tile->extras_owner != NULL);
4805 case REQ_RANGE_CADJACENT:
4806 if (context->tile->extras_owner != NULL) {
4807 return TRI_YES;
4808 }
4809 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4810 if (adjc_tile->extras_owner != NULL) {
4811 return TRI_YES;
4812 }
4813 } cardinal_adjc_iterate_end;
4814
4815 return TRI_NO;
4816 case REQ_RANGE_ADJACENT:
4817 if (context->tile->extras_owner != NULL) {
4818 return TRI_YES;
4819 }
4820 adjc_iterate(nmap, context->tile, adjc_tile) {
4821 if (adjc_tile->extras_owner != NULL) {
4822 return TRI_YES;
4823 }
4824 } adjc_iterate_end;
4825
4826 return TRI_NO;
4827 case REQ_RANGE_CITY:
4828 case REQ_RANGE_TRADE_ROUTE:
4829 case REQ_RANGE_CONTINENT:
4830 case REQ_RANGE_PLAYER:
4831 case REQ_RANGE_TEAM:
4832 case REQ_RANGE_ALLIANCE:
4833 case REQ_RANGE_WORLD:
4834 case REQ_RANGE_LOCAL:
4835 case REQ_RANGE_COUNT:
4836 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4837 break;
4838 }
4839
4840 return TRI_MAYBE;
4841 case CITYT_WORKED:
4842 switch (req->range) {
4843 case REQ_RANGE_TILE:
4844 return BOOL_TO_TRISTATE(context->tile->worked != NULL);
4845 case REQ_RANGE_CADJACENT:
4846 if (context->tile->worked != NULL) {
4847 return TRI_YES;
4848 }
4849 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
4850 if (adjc_tile->worked != NULL) {
4851 return TRI_YES;
4852 }
4853 } cardinal_adjc_iterate_end;
4854
4855 return TRI_NO;
4856 case REQ_RANGE_ADJACENT:
4857 if (context->tile->worked != NULL) {
4858 return TRI_YES;
4859 }
4860 adjc_iterate(nmap, context->tile, adjc_tile) {
4861 if (adjc_tile->worked != NULL) {
4862 return TRI_YES;
4863 }
4864 } adjc_iterate_end;
4865
4866 return TRI_NO;
4867 case REQ_RANGE_CITY:
4868 case REQ_RANGE_TRADE_ROUTE:
4869 case REQ_RANGE_CONTINENT:
4870 case REQ_RANGE_PLAYER:
4871 case REQ_RANGE_TEAM:
4872 case REQ_RANGE_ALLIANCE:
4873 case REQ_RANGE_WORLD:
4874 case REQ_RANGE_LOCAL:
4875 case REQ_RANGE_COUNT:
4876 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4877 break;
4878 }
4879
4880 return TRI_MAYBE;
4881 case CITYT_SAME_CONTINENT:
4882 {
4883 Continent_id cc;
4884 const struct tile *target_tile = context->tile, *cc_tile;
4885
4886 if (!context->city) {
4887 return TRI_MAYBE;
4888 }
4889 cc_tile = city_tile(context->city);
4890 if (!cc_tile) {
4891 /* Unplaced virtual city */
4892 return TRI_MAYBE;
4893 }
4894 cc = tile_continent(cc_tile);
4895 /* Note: No special treatment of 0 == cc here*/
4896 switch (req->range) {
4897 case REQ_RANGE_TILE:
4898 return BOOL_TO_TRISTATE(tile_continent(target_tile) == cc);
4899 case REQ_RANGE_CADJACENT:
4900 if (tile_continent(target_tile) == cc) {
4901 return TRI_YES;
4902 }
4903 cardinal_adjc_iterate(nmap, target_tile, adjc_tile) {
4904 if (tile_continent(adjc_tile) == cc) {
4905 return TRI_YES;
4906 }
4907 } cardinal_adjc_iterate_end;
4908
4909 return TRI_NO;
4910 case REQ_RANGE_ADJACENT:
4911 if (tile_continent(target_tile) == cc) {
4912 return TRI_YES;
4913 }
4914 adjc_iterate(nmap, target_tile, adjc_tile) {
4915 if (tile_continent(adjc_tile) == cc) {
4916 return TRI_YES;
4917 }
4918 } adjc_iterate_end;
4919
4920 return TRI_NO;
4921 case REQ_RANGE_CITY:
4922 case REQ_RANGE_TRADE_ROUTE:
4923 case REQ_RANGE_CONTINENT:
4924 case REQ_RANGE_PLAYER:
4925 case REQ_RANGE_TEAM:
4926 case REQ_RANGE_ALLIANCE:
4927 case REQ_RANGE_WORLD:
4928 case REQ_RANGE_LOCAL:
4929 case REQ_RANGE_COUNT:
4930 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
4931 break;
4932 }
4933 }
4934
4935 return TRI_MAYBE;
4936 case CITYT_BORDERING_TCLASS_REGION:
4937 {
4938 int n = 0;
4939 Continent_id adjc_cont[8], cc;
4940 bool ukt = FALSE;
4941 const struct tile *target_tile = context->tile, *cc_tile;
4942
4943 if (!context->city) {
4944 return TRI_MAYBE;
4945 }
4946 cc_tile = city_tile(context->city);
4947 if (!cc_tile) {
4948 /* Unplaced virtual city */
4949 return TRI_MAYBE;
4950 }
4951 cc = tile_continent(cc_tile);
4952 if (!cc) {
4953 /* Don't know the city center terrain class.
4954 * Maybe, the city floats? Even if the rules prohibit it... */
4955 return TRI_MAYBE;
4956 }
4957 adjc_iterate(nmap, cc_tile, adjc_tile) {
4958 Continent_id tc = tile_continent(adjc_tile);
4959
4960 if (0 != tc) {
4961 bool seen = FALSE;
4962 int i = n;
4963
4964 if (tc == cc) {
4965 continue;
4966 }
4967 while (--i >= 0) {
4968 if (adjc_cont[i] == tc) {
4969 seen = TRUE;
4970 break;
4971 }
4972 }
4973 if (seen) {
4974 continue;
4975 }
4976 adjc_cont[n++] = tile_continent(adjc_tile);
4977 } else {
4978 /* Likely, it's a black tile in client and we don't know
4979 * We possibly can calculate, but keep it simple. */
4980 ukt = TRUE;
4981 }
4982 } adjc_iterate_end;
4983 if (0 == n) {
4984 return ukt ? TRI_MAYBE : TRI_NO;
4985 }
4986
4987 switch (req->range) {
4988 case REQ_RANGE_TILE:
4989 {
4990 Continent_id tc = tile_continent(target_tile);
4991
4992 if (cc == tc) {
4993 return TRI_NO;
4994 }
4995 if (0 == tc || ukt) {
4996 return TRI_MAYBE;
4997 }
4998 for (int i = 0; i < n; i++) {
4999 if (tc == adjc_cont[i]) {
5000 return TRI_YES;
5001 }
5002 }
5003 }
5004
5005 return TRI_NO;
5006 case REQ_RANGE_ADJACENT:
5007 if (ukt) {
5008 /* If ALL the tiles in range are on cc, we can say it's false */
5009 square_iterate(nmap, target_tile, 1, adjc_tile) {
5010 if (tile_continent(adjc_tile) != cc) {
5011 return TRI_MAYBE;
5012 }
5013 } square_iterate_end;
5014
5015 return TRI_NO;
5016 } else {
5017 square_iterate(nmap, target_tile, 1, adjc_tile) {
5018 Continent_id tc = tile_continent(adjc_tile);
5019
5020 if (0 == tc) {
5021 return TRI_MAYBE;
5022 }
5023 for (int i = 0; i < n; i++) {
5024 if (tc == adjc_cont[i]) {
5025 return TRI_YES;
5026 }
5027 }
5028 } square_iterate_end;
5029 }
5030
5031 return TRI_NO;
5032 case REQ_RANGE_CADJACENT:
5033 if (ukt) {
5034 /* If ALL the tiles in range are on cc, we can say it's false */
5035 circle_iterate(nmap, target_tile, 1, cadjc_tile) {
5036 if (tile_continent(cadjc_tile) != cc) {
5037 return TRI_MAYBE;
5038 }
5039 } circle_iterate_end;
5040 } else {
5041 circle_iterate(nmap, target_tile, 1, cadjc_tile) {
5042 Continent_id tc = tile_continent(cadjc_tile);
5043
5044 if (0 == tc) {
5045 return TRI_MAYBE;
5046 }
5047 for (int i = 0; i < n; i++) {
5048 if (tc == adjc_cont[i]) {
5049 return TRI_YES;
5050 }
5051 }
5052 } circle_iterate_end;
5053 }
5054
5055 return TRI_NO;
5056 case REQ_RANGE_CITY:
5057 case REQ_RANGE_TRADE_ROUTE:
5058 case REQ_RANGE_CONTINENT:
5059 case REQ_RANGE_PLAYER:
5060 case REQ_RANGE_TEAM:
5061 case REQ_RANGE_ALLIANCE:
5062 case REQ_RANGE_WORLD:
5063 case REQ_RANGE_LOCAL:
5064 case REQ_RANGE_COUNT:
5065 fc_assert_msg(FALSE, "Invalid range %d for citytile.", req->range);
5066 break;
5067 }
5068 }
5069
5070 return TRI_MAYBE;
5071 case CITYT_LAST:
5072 /* Handled below */
5073 break;
5074 }
5075
5076 /* Not implemented */
5077 log_error("is_req_active(): citytile %d not supported.",
5078 citytile);
5079 return TRI_MAYBE;
5080}
5081
5082/**********************************************************************/
5090static enum fc_tristate
5091is_citystatus_req_active(const struct civ_map *nmap,
5092 const struct req_context *context,
5093 const struct req_context *other_context,
5094 const struct requirement *req)
5095{
5096 enum citystatus_type citystatus;
5097
5098 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_CITYSTATUS);
5099
5100 citystatus = req->source.value.citystatus;
5101
5102 if (context->city == NULL) {
5103 return TRI_MAYBE;
5104 }
5105
5106 switch (citystatus) {
5107 case CITYS_OWNED_BY_ORIGINAL:
5108 switch (req->range) {
5109 case REQ_RANGE_CITY:
5110 if (context->city->original == NULL) {
5111 return TRI_MAYBE;
5112 }
5113 return BOOL_TO_TRISTATE(city_owner(context->city) == context->city->original);
5114 case REQ_RANGE_TRADE_ROUTE:
5115 {
5116 enum fc_tristate ret;
5117
5118 if (city_owner(context->city) == context->city->original) {
5119 return TRI_YES;
5120 }
5121
5122 ret = TRI_NO;
5123 trade_partners_iterate(context->city, trade_partner) {
5124 if (trade_partner == NULL || trade_partner->original == NULL) {
5125 ret = TRI_MAYBE;
5126 } else if (city_owner(trade_partner) == trade_partner->original) {
5127 return TRI_YES;
5128 }
5129 } trade_partners_iterate_end;
5130
5131 return ret;
5132 }
5133 case REQ_RANGE_LOCAL:
5134 case REQ_RANGE_TILE:
5135 case REQ_RANGE_CADJACENT:
5136 case REQ_RANGE_ADJACENT:
5137 case REQ_RANGE_CONTINENT:
5138 case REQ_RANGE_PLAYER:
5139 case REQ_RANGE_TEAM:
5140 case REQ_RANGE_ALLIANCE:
5141 case REQ_RANGE_WORLD:
5142 case REQ_RANGE_COUNT:
5143 break;
5144 }
5145
5146 fc_assert_msg(FALSE, "Invalid range %d for citystatus OwnedByOriginal.",
5147 req->range);
5148
5149 return TRI_MAYBE;
5150
5151 case CITYS_STARVED:
5152 switch (req->range) {
5153 case REQ_RANGE_CITY:
5154 return BOOL_TO_TRISTATE(context->city->had_famine);
5155 case REQ_RANGE_TRADE_ROUTE:
5156 {
5157 enum fc_tristate ret;
5158
5159 if (context->city->had_famine) {
5160 return TRI_YES;
5161 }
5162
5163 ret = TRI_NO;
5164 trade_partners_iterate(context->city, trade_partner) {
5165 if (trade_partner == NULL) {
5166 ret = TRI_MAYBE;
5167 } else if (trade_partner->had_famine) {
5168 return TRI_YES;
5169 }
5170 } trade_partners_iterate_end;
5171
5172 return ret;
5173 }
5174 case REQ_RANGE_LOCAL:
5175 case REQ_RANGE_TILE:
5176 case REQ_RANGE_CADJACENT:
5177 case REQ_RANGE_ADJACENT:
5178 case REQ_RANGE_CONTINENT:
5179 case REQ_RANGE_PLAYER:
5180 case REQ_RANGE_TEAM:
5181 case REQ_RANGE_ALLIANCE:
5182 case REQ_RANGE_WORLD:
5183 case REQ_RANGE_COUNT:
5184 break;
5185 }
5186
5187 fc_assert_msg(FALSE, "Invalid range %d for citystatus Starved.",
5188 req->range);
5189
5190 return TRI_MAYBE;
5191
5192 case CITYS_DISORDER:
5193 switch (req->range) {
5194 case REQ_RANGE_CITY:
5195 return BOOL_TO_TRISTATE(context->city->anarchy > 0);
5196 case REQ_RANGE_TRADE_ROUTE:
5197 {
5198 enum fc_tristate ret;
5199
5200 if (context->city->anarchy > 0) {
5201 return TRI_YES;
5202 }
5203
5204 ret = TRI_NO;
5205 trade_partners_iterate(context->city, trade_partner) {
5206 if (trade_partner == NULL) {
5207 ret = TRI_MAYBE;
5208 } else if (trade_partner->anarchy > 0) {
5209 return TRI_YES;
5210 }
5211 } trade_partners_iterate_end;
5212
5213 return ret;
5214 }
5215 case REQ_RANGE_LOCAL:
5216 case REQ_RANGE_TILE:
5217 case REQ_RANGE_CADJACENT:
5218 case REQ_RANGE_ADJACENT:
5219 case REQ_RANGE_CONTINENT:
5220 case REQ_RANGE_PLAYER:
5221 case REQ_RANGE_TEAM:
5222 case REQ_RANGE_ALLIANCE:
5223 case REQ_RANGE_WORLD:
5224 case REQ_RANGE_COUNT:
5225 break;
5226 }
5227
5228 fc_assert_msg(FALSE, "Invalid range %d for citystatus Disorder.",
5229 req->range);
5230
5231 return TRI_MAYBE;
5232
5233 case CITYS_CELEBRATION:
5234 switch (req->range) {
5235 case REQ_RANGE_CITY:
5236 return BOOL_TO_TRISTATE(context->city->rapture > 0);
5237 case REQ_RANGE_TRADE_ROUTE:
5238 {
5239 enum fc_tristate ret;
5240
5241 if (context->city->rapture > 0) {
5242 return TRI_YES;
5243 }
5244
5245 ret = TRI_NO;
5246 trade_partners_iterate(context->city, trade_partner) {
5247 if (trade_partner == NULL) {
5248 ret = TRI_MAYBE;
5249 } else if (trade_partner->rapture > 0) {
5250 return TRI_YES;
5251 }
5252 } trade_partners_iterate_end;
5253
5254 return ret;
5255 }
5256 case REQ_RANGE_LOCAL:
5257 case REQ_RANGE_TILE:
5258 case REQ_RANGE_CADJACENT:
5259 case REQ_RANGE_ADJACENT:
5260 case REQ_RANGE_CONTINENT:
5261 case REQ_RANGE_PLAYER:
5262 case REQ_RANGE_TEAM:
5263 case REQ_RANGE_ALLIANCE:
5264 case REQ_RANGE_WORLD:
5265 case REQ_RANGE_COUNT:
5266 break;
5267 }
5268
5269 fc_assert_msg(FALSE, "Invalid range %d for citystatus Celebration.",
5270 req->range);
5271
5272 return TRI_MAYBE;
5273
5274 case CITYS_TRANSFERRED:
5275 switch (req->range) {
5276 case REQ_RANGE_CITY:
5277 return BOOL_TO_TRISTATE(context->city->acquire_t != CACQ_FOUNDED);
5278 case REQ_RANGE_TRADE_ROUTE:
5279 {
5280 enum fc_tristate ret;
5281
5282 if (context->city->acquire_t != CACQ_FOUNDED) {
5283 return TRI_YES;
5284 }
5285
5286 ret = TRI_NO;
5287 trade_partners_iterate(context->city, trade_partner) {
5288 if (trade_partner == NULL) {
5289 ret = TRI_MAYBE;
5290 } else if (trade_partner->acquire_t != CACQ_FOUNDED) {
5291 return TRI_YES;
5292 }
5293 } trade_partners_iterate_end;
5294
5295 return ret;
5296 }
5297 case REQ_RANGE_LOCAL:
5298 case REQ_RANGE_TILE:
5299 case REQ_RANGE_CADJACENT:
5300 case REQ_RANGE_ADJACENT:
5301 case REQ_RANGE_CONTINENT:
5302 case REQ_RANGE_PLAYER:
5303 case REQ_RANGE_TEAM:
5304 case REQ_RANGE_ALLIANCE:
5305 case REQ_RANGE_WORLD:
5306 case REQ_RANGE_COUNT:
5307 break;
5308 }
5309
5310 fc_assert_msg(FALSE, "Invalid range %d for citystatus Transferred.",
5311 req->range);
5312
5313 return TRI_MAYBE;
5314
5315 case CITYS_LAST:
5316 break;
5317 }
5318
5319 /* Not implemented */
5320 log_error("is_req_active(): citystatus %d not supported.",
5321 citystatus);
5322
5323 return TRI_MAYBE;
5324}
5325
5326/**********************************************************************/
5334static enum fc_tristate
5335is_minsize_req_active(const struct civ_map *nmap,
5336 const struct req_context *context,
5337 const struct req_context *other_context,
5338 const struct requirement *req)
5339{
5340 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINSIZE);
5341
5342 if (context->city == NULL) {
5343 return TRI_MAYBE;
5344 } else {
5345 if (req->range == REQ_RANGE_TRADE_ROUTE) {
5346 enum fc_tristate ret;
5347
5348 if (city_size_get(context->city) >= req->source.value.minsize) {
5349 return TRI_YES;
5350 }
5351
5352 ret = TRI_NO;
5353 trade_partners_iterate(context->city, trade_partner) {
5354 if (trade_partner == NULL) {
5355 ret = TRI_MAYBE;
5356 } else if (city_size_get(trade_partner) >= req->source.value.minsize) {
5357 return TRI_YES;
5358 }
5359 } trade_partners_iterate_end;
5360
5361 return ret;
5362 } else {
5363 return BOOL_TO_TRISTATE(city_size_get(context->city)
5364 >= req->source.value.minsize);
5365 }
5366 }
5367}
5368
5369/**********************************************************************/
5377static enum fc_tristate
5378is_counter_req_active(const struct civ_map *nmap,
5379 const struct req_context *context,
5380 const struct req_context *other_context,
5381 const struct requirement *req)
5382{
5383 const struct counter *count;
5384
5385 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_COUNTER);
5386
5387 count = req->source.value.counter;
5388
5389 if (NULL == context->city) {
5390 return TRI_MAYBE;
5391 }
5392 return BOOL_TO_TRISTATE(count->checkpoint <=
5393 context->city->counter_values[
5394 counter_index(count)]);
5395}
5396
5397/**********************************************************************/
5405static enum fc_tristate
5406is_achievement_req_active(const struct civ_map *nmap,
5407 const struct req_context *context,
5408 const struct req_context *other_context,
5409 const struct requirement *req)
5410{
5411 const struct achievement *achievement;
5412
5413 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_ACHIEVEMENT);
5414
5415 achievement = req->source.value.achievement;
5416
5417 if (req->range == REQ_RANGE_WORLD) {
5418 return BOOL_TO_TRISTATE(achievement_claimed(achievement));
5419 } else if (context->player == NULL) {
5420 return TRI_MAYBE;
5421 } else if (req->range == REQ_RANGE_ALLIANCE
5422 || req->range == REQ_RANGE_TEAM) {
5423 players_iterate_alive(plr2) {
5424 if (players_in_same_range(context->player, plr2, req->range)
5425 && achievement_player_has(achievement, plr2)) {
5426 return TRI_YES;
5427 }
5428 } players_iterate_alive_end;
5429 return TRI_NO;
5430 } else if (req->range == REQ_RANGE_PLAYER) {
5431 if (achievement_player_has(achievement, context->player)) {
5432 return TRI_YES;
5433 } else {
5434 return TRI_NO;
5435 }
5436 }
5437
5438 fc_assert_msg(FALSE, "Invalid range %d.", req->range);
5439
5440 return TRI_MAYBE;
5441}
5442
5443/**********************************************************************/
5451static enum fc_tristate
5452is_latitude_req_active(const struct civ_map *nmap,
5453 const struct req_context *context,
5454 const struct req_context *other_context,
5455 const struct requirement *req)
5456{
5457 int min = -MAP_MAX_LATITUDE, max = MAP_MAX_LATITUDE;
5458
5459 fc_assert_ret_val(req != NULL, TRI_MAYBE);
5460 fc_assert(context != NULL);
5461
5462 switch (req->source.kind) {
5463 case VUT_MINLATITUDE:
5464 min = req->source.value.latitude;
5465 break;
5466 case VUT_MAXLATITUDE:
5467 max = req->source.value.latitude;
5468 break;
5469 default:
5470 fc_assert(req->source.kind == VUT_MINLATITUDE
5471 || req->source.kind == VUT_MAXLATITUDE);
5472 break;
5473 }
5474
5475 switch (req->range) {
5476 case REQ_RANGE_WORLD:
5477 return BOOL_TO_TRISTATE(min <= MAP_MAX_REAL_LATITUDE(wld.map)
5478 && max >= MAP_MIN_REAL_LATITUDE(wld.map));
5479
5480 case REQ_RANGE_TILE:
5481 if (context->tile == NULL) {
5482 return TRI_MAYBE;
5483 } else {
5484 int tile_lat = map_signed_latitude(context->tile);
5485
5486 return BOOL_TO_TRISTATE(min <= tile_lat && max >= tile_lat);
5487 }
5488
5489 case REQ_RANGE_CADJACENT:
5490 if (context->tile == NULL) {
5491 return TRI_MAYBE;
5492 }
5493
5494 cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
5495 int tile_lat = map_signed_latitude(adjc_tile);
5496
5497 if (min <= tile_lat && max >= tile_lat) {
5498 return TRI_YES;
5499 }
5500 } cardinal_adjc_iterate_end;
5501 return TRI_NO;
5502
5503 case REQ_RANGE_ADJACENT:
5504 if (!context->tile) {
5505 return TRI_MAYBE;
5506 }
5507
5508 adjc_iterate(nmap, context->tile, adjc_tile) {
5509 int tile_lat = map_signed_latitude(adjc_tile);
5510
5511 if (min <= tile_lat && max >= tile_lat) {
5512 return TRI_YES;
5513 }
5514 } adjc_iterate_end;
5515 return TRI_NO;
5516
5517 case REQ_RANGE_CITY:
5518 case REQ_RANGE_TRADE_ROUTE:
5519 case REQ_RANGE_CONTINENT:
5520 case REQ_RANGE_PLAYER:
5521 case REQ_RANGE_TEAM:
5522 case REQ_RANGE_ALLIANCE:
5523 case REQ_RANGE_LOCAL:
5524 case REQ_RANGE_COUNT:
5525 break;
5526 }
5527
5528 fc_assert_msg(FALSE,
5529 "Illegal range %d for latitude requirement.", req->range);
5530
5531 return TRI_MAYBE;
5532}
5533
5534/**********************************************************************/
5542static enum fc_tristate
5543is_minyear_req_active(const struct civ_map *nmap,
5544 const struct req_context *context,
5545 const struct req_context *other_context,
5546 const struct requirement *req)
5547{
5548 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINYEAR);
5549
5550 return BOOL_TO_TRISTATE(game.info.year >= req->source.value.minyear);
5551}
5552
5553/**********************************************************************/
5561static enum fc_tristate
5562is_mincalfrag_req_active(const struct civ_map *nmap,
5563 const struct req_context *context,
5564 const struct req_context *other_context,
5565 const struct requirement *req)
5566{
5567 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MINCALFRAG);
5568
5569 return BOOL_TO_TRISTATE(game.info.fragment_count
5570 >= req->source.value.mincalfrag);
5571}
5572
5573/**********************************************************************/
5581static enum fc_tristate
5582is_topology_req_active(const struct civ_map *nmap,
5583 const struct req_context *context,
5584 const struct req_context *other_context,
5585 const struct requirement *req)
5586{
5587 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TOPO);
5588
5589 return BOOL_TO_TRISTATE(
5590 current_topo_has_flag(req->source.value.topo_property));
5591}
5592
5593/**********************************************************************/
5601static enum fc_tristate
5602is_wrap_req_active(const struct civ_map *nmap,
5603 const struct req_context *context,
5604 const struct req_context *other_context,
5605 const struct requirement *req)
5606{
5607 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_WRAP);
5608
5609 return BOOL_TO_TRISTATE(
5610 current_wrap_has_flag(req->source.value.wrap_property));
5611}
5612
5613/**********************************************************************/
5621static enum fc_tristate
5622is_serversetting_req_active(const struct civ_map *nmap,
5623 const struct req_context *context,
5624 const struct req_context *other_context,
5625 const struct requirement *req)
5626{
5627 IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_SERVERSETTING);
5628
5629 return BOOL_TO_TRISTATE(ssetv_setting_has_value(
5630 req->source.value.ssetval));
5631}
5632
5633/* Not const for potential ruleset-related adjustment */
5634 static struct req_def req_definitions[VUT_COUNT] = {
5635 [VUT_NONE] = {is_none_req_active, REQUCH_YES},
5636
5637 /* Alphabetical order of enum constant */
5638 [VUT_ACHIEVEMENT] = {is_achievement_req_active, REQUCH_YES, REQUC_PRESENT},
5639 [VUT_ACTION] = {is_action_req_active, REQUCH_YES},
5640 [VUT_ACTIVITY] = {is_activity_req_active, REQUCH_NO},
5641 [VUT_ADVANCE] = {is_tech_req_active, REQUCH_NO},
5642 [VUT_AGE] = {is_age_req_active, REQUCH_YES, REQUC_PRESENT},
5643 [VUT_FORM_AGE] = {is_form_age_req_active, REQUCH_YES, REQUC_PRESENT},
5644 [VUT_AI_LEVEL] = {is_ai_req_active, REQUCH_HACK},
5645 [VUT_CITYSTATUS] = {is_citystatus_req_active, REQUCH_NO, REQUC_CITYSTATUS},
5646 [VUT_CITYTILE] = {is_citytile_req_active, REQUCH_NO, REQUC_CITYTILE},
5647 [VUT_COUNTER] = {is_counter_req_active, REQUCH_NO},
5648 [VUT_DIPLREL] = {is_diplrel_req_active, REQUCH_NO},
5649 [VUT_DIPLREL_TILE] = {is_diplrel_tile_req_active, REQUCH_NO},
5650 [VUT_DIPLREL_TILE_O] = {is_diplrel_tile_o_req_active, REQUCH_NO},
5651 [VUT_DIPLREL_UNITANY] = {is_diplrel_unitany_req_active, REQUCH_NO},
5652 [VUT_DIPLREL_UNITANY_O] = {is_diplrel_unitany_o_req_active, REQUCH_NO},
5653 [VUT_EXTRA] = {is_extra_req_active, REQUCH_NO, REQUC_LOCAL},
5654 [VUT_EXTRAFLAG] = {is_extraflag_req_active, REQUCH_NO, REQUC_LOCAL},
5655 [VUT_GOOD] = {is_good_req_active, REQUCH_NO},
5656 [VUT_GOVERNMENT] = {is_gov_req_active, REQUCH_NO},
5657 [VUT_IMPROVEMENT] = {is_building_req_active, REQUCH_NO, REQUC_IMPR},
5658 [VUT_IMPR_GENUS] = {is_buildinggenus_req_active, REQUCH_YES},
5659 [VUT_IMPR_FLAG] = {is_buildingflag_req_active, REQUCH_YES},
5660 [VUT_PLAYER_FLAG] = {is_plr_flag_req_active, REQUCH_NO},
5661 [VUT_PLAYER_STATE] = {is_plr_state_req_active, REQUCH_NO},
5662 [VUT_MAXLATITUDE] = {is_latitude_req_active, REQUCH_YES},
5663 [VUT_MAXTILEUNITS] = {is_maxunitsontile_req_active, REQUCH_NO},
5664 [VUT_MINCALFRAG] = {is_mincalfrag_req_active, REQUCH_NO},
5665 [VUT_MINCULTURE] = {is_minculture_req_active, REQUCH_NO},
5666 [VUT_MINFOREIGNPCT] = {is_minforeignpct_req_active, REQUCH_NO},
5667 [VUT_MINHP] = {is_minhitpoints_req_active, REQUCH_NO},
5668 [VUT_MINLATITUDE] = {is_latitude_req_active, REQUCH_NO},
5669 [VUT_MINMOVES] = {is_minmovefrags_req_active, REQUCH_NO},
5670 [VUT_MINSIZE] = {is_minsize_req_active, REQUCH_NO},
5671 [VUT_MINTECHS] = {is_mintechs_req_active, REQUCH_ACT, REQUC_WORLD},
5672 [VUT_MINCITIES] = {is_mincities_req_active, REQUCH_NO},
5673 [VUT_MINVETERAN] = {is_minveteran_req_active, REQUCH_SCRIPTS, REQUC_PRESENT},
5674 [VUT_MINYEAR] = {is_minyear_req_active, REQUCH_HACK, REQUC_PRESENT},
5675 [VUT_NATION] = {is_nation_req_active, REQUCH_HACK, REQUC_NALLY},
5676 [VUT_NATIONALITY] = {is_nationality_req_active, REQUCH_NO},
5677 [VUT_NATIONGROUP] = {is_nationgroup_req_active, REQUCH_HACK, REQUC_NALLY},
5678 [VUT_ORIGINAL_OWNER] = {is_originalowner_req_active, REQUCH_HACK},
5679 [VUT_OTYPE] = {is_outputtype_req_active, REQUCH_YES},
5680 [VUT_ROADFLAG] = {is_roadflag_req_active, REQUCH_NO, REQUC_LOCAL},
5681 [VUT_SERVERSETTING] = {is_serversetting_req_active, REQUCH_HACK},
5682 [VUT_SPECIALIST] = {is_specialist_req_active, REQUCH_YES},
5683 [VUT_STYLE] = {is_style_req_active, REQUCH_HACK},
5684 [VUT_TECHFLAG] = {is_techflag_req_active, REQUCH_NO},
5685 [VUT_TERRAIN] = {is_terrain_req_active, REQUCH_NO},
5686 [VUT_TERRAINALTER] = {is_terrainalter_req_active, REQUCH_NO},
5687 [VUT_TERRAINCLASS] = {is_terrainclass_req_active, REQUCH_NO},
5688 [VUT_TERRFLAG] = {is_terrainflag_req_active, REQUCH_NO},
5689 [VUT_TOPO] = {is_topology_req_active, REQUCH_YES},
5690 [VUT_WRAP] = {is_wrap_req_active, REQUCH_YES},
5691 [VUT_UCFLAG] = {is_unitclassflag_req_active, REQUCH_YES},
5692 [VUT_UCLASS] = {is_unitclass_req_active, REQUCH_YES},
5693 [VUT_UNITSTATE] = {is_unitstate_req_active, REQUCH_NO},
5694 [VUT_UTFLAG] = {is_unitflag_req_active, REQUCH_YES},
5695 [VUT_UTYPE] = {is_unittype_req_active, REQUCH_YES}
5696};
5697
5698/**********************************************************************/
5711 bool is_req_active(const struct req_context *context,
5712 const struct req_context *other_context,
5713 const struct requirement *req,
5714 const enum req_problem_type prob_type)
5715{
5716 const struct civ_map *nmap = &(wld.map);
5717 enum fc_tristate eval = tri_req_present(nmap, context, other_context,
5718 req);
5719
5720 if (eval == TRI_MAYBE) {
5721 if (prob_type == RPT_POSSIBLE) {
5722 return TRUE;
5723 } else {
5724 return FALSE;
5725 }
5726 }
5727 return req->present ? (eval != TRI_NO) : (eval != TRI_YES);
5728}
5729
5730/**********************************************************************/
5739static
5740 enum fc_tristate tri_req_present(const struct civ_map *nmap,
5741 const struct req_context *context,
5742 const struct req_context *other_context,
5743 const struct requirement *req)
5744{
5745 if (!context) {
5746 context = req_context_empty();
5747 }
5748 if (!other_context) {
5749 other_context = req_context_empty();
5750 }
5751
5752 if (req->source.kind >= VUT_COUNT) {
5753 log_error("tri_req_present(): invalid source kind %d.",
5754 req->source.kind);
5755 return TRI_NO;
5756 }
5757
5758 fc_assert_ret_val(req_definitions[req->source.kind].cb != NULL, TRI_NO);
5759
5760 return req_definitions[req->source.kind].cb(nmap, context,
5761 other_context, req);
5762}
5763
5764/**********************************************************************/
5773 enum fc_tristate tri_req_active(const struct req_context *context,
5774 const struct req_context *other_context,
5775 const struct requirement *req)
5776{
5777 const struct civ_map *nmap = &(wld.map);
5778 enum fc_tristate eval = tri_req_present(nmap, context, other_context, req);
5779
5780 if (!req->present) {
5781 if (TRI_NO == eval) {
5782 return TRI_YES;
5783 }
5784 if (TRI_YES == eval) {
5785 return TRI_NO;
5786 }
5787 }
5788
5789 return eval;
5790}
5791
5792/**********************************************************************/
5807 bool are_reqs_active(const struct req_context *context,
5808 const struct req_context *other_context,
5809 const struct requirement_vector *reqs,
5810 const enum req_problem_type prob_type)
5811{
5812 requirement_vector_iterate(reqs, preq) {
5813 if (!is_req_active(context, other_context, preq, prob_type)) {
5814 return FALSE;
5815 }
5816 } requirement_vector_iterate_end;
5817
5818 return TRUE;
5819}
5820
5821/**********************************************************************/
5825 bool are_reqs_active_ranges(const enum req_range min_range,
5826 const enum req_range max_range,
5827 const struct req_context *context,
5828 const struct req_context *other_context,
5829 const struct requirement_vector *reqs,
5830 const enum req_problem_type prob_type)
5831{
5832 requirement_vector_iterate(reqs, preq) {
5833 if (preq->range >= min_range && preq->range <= max_range) {
5834 if (!is_req_active(context, other_context, preq, prob_type)) {
5835 return FALSE;
5836 }
5837 }
5838 } requirement_vector_iterate_end;
5839
5840 return TRUE;
5841}
5842
5843/**********************************************************************/
5849enum fc_tristate
5850tri_req_active_turns(int pass, int period,
5851 const struct req_context *context,
5852 const struct req_context *other_context,
5853 const struct requirement *req)
5854{
5855 /* FIXME: doubles code from calendar.c */
5856 int ypt = get_world_bonus(EFT_TURN_YEARS);
5857 int fpt = get_world_bonus(EFT_TURN_FRAGMENTS);
5858 int fragment = game.info.fragment_count;
5859 int fragment1 = fragment; /* if fragments don't advance */
5860 int year_inc, year_inc1;
5861 const int slowdown = (victory_enabled(VC_SPACERACE)
5862 ? get_world_bonus(EFT_SLOW_DOWN_TIMELINE) : 0);
5863 bool present, present1;
5864
5865 fc_assert(pass >= 0 && period >= 0);
5866 if (slowdown >= 3) {
5867 if (ypt > 1) {
5868 ypt = 1;
5869 }
5870 } else if (slowdown >= 2) {
5871 if (ypt > 2) {
5872 ypt = 2;
5873 }
5874 } else if (slowdown >= 1) {
5875 if (ypt > 5) {
5876 ypt = 5;
5877 }
5878 }
5879 year_inc = ypt * pass;
5880 year_inc1 = year_inc + ypt * period;
5881 if (game.calendar.calendar_fragments) {
5882 int fragment_years;
5883
5884 fragment += fpt * pass;
5885 fragment_years = fragment / game.calendar.calendar_fragments;
5886 year_inc += fragment_years;
5887 fragment -= fragment_years * game.calendar.calendar_fragments;
5888 fragment1 = fragment + fpt * period;
5889 fragment_years += fragment1 / game.calendar.calendar_fragments;
5890 year_inc1 += fragment_years;
5891 fragment1 -= fragment_years * game.calendar.calendar_fragments;
5892 }
5893 if (game.calendar.calendar_skip_0 && game.info.year < 0) {
5894 if (year_inc + game.info.year >= 0) {
5895 year_inc++;
5896 year_inc1++;
5897 } else if (year_inc1 + game.info.year >= 0) {
5898 year_inc1++;
5899 }
5900 }
5901
5902 switch (req->source.kind) {
5903 case VUT_AGE:
5904 switch (req->range) {
5905 case REQ_RANGE_LOCAL:
5906 if (context->unit == NULL || !is_server()) {
5907 return TRI_MAYBE;
5908 } else {
5909 int ua = game.info.turn + pass - context->unit->birth_turn;
5910
5911 present = req->source.value.age <= ua;
5912 present1 = req->source.value.age <= ua + period;
5913 }
5914 break;
5915 case REQ_RANGE_CITY:
5916 if (context->city == NULL) {
5917 return TRI_MAYBE;
5918 } else {
5919 int ca = game.info.turn + pass - context->city->turn_founded;
5920
5921 present = req->source.value.age <= ca;
5922 present1 = req->source.value.age <= ca + period;
5923 }
5924 break;
5925 case REQ_RANGE_PLAYER:
5926 if (context->player == NULL) {
5927 return TRI_MAYBE;
5928 } else {
5929 present = req->source.value.age
5930 <= player_age(context->player) + pass;
5931 present1 = req->source.value.age
5932 <= player_age(context->player) + pass + period;
5933 }
5934 break;
5935 default:
5936 return TRI_MAYBE;
5937 }
5938 break;
5939 case VUT_FORM_AGE:
5940 if (context->unit == NULL || !is_server()) {
5941 return TRI_MAYBE;
5942 } else {
5943 int ua = game.info.turn + pass - context->unit->current_form_turn;
5944
5945 present = req->source.value.form_age <= ua;
5946 present1 = req->source.value.form_age <= ua + period;
5947 }
5948 break;
5949 case VUT_MINYEAR:
5950 present = game.info.year + year_inc >= req->source.value.minyear;
5951 present1 = game.info.year + year_inc1 >= req->source.value.minyear;
5952 break;
5953 case VUT_MINCALFRAG:
5954 if (game.calendar.calendar_fragments <= period) {
5955 /* Hope that the requirement is valid and fragments advance fine */
5956 return TRI_YES;
5957 }
5958 present = fragment >= req->source.value.mincalfrag;
5959 present1 = fragment1 >= req->source.value.mincalfrag;
5960 break;
5961 default:
5962 /* No special handling invented */
5963 return tri_req_active(context, other_context, req);
5964 }
5965 return BOOL_TO_TRISTATE(req->present
5966 ? present || present1 : !(present && present1));
5967}
5968
5969/**********************************************************************/
5974 enum fc_tristate default_tester_cb
5975 (const struct req_context *context,
5976 const struct req_context *other_context,
5977 const struct requirement *req,
5978 void *data, int n_data)
5979{
5980 int i;
5981
5982 fc_assert_ret_val(data || n_data == 0, TRI_NO);
5983
5984 for (i = 0; i < n_data; i++) {
5985 if (are_requirements_contradictions(&((struct requirement *) data)[i],
5986 req)) {
5987 return TRI_NO;
5988 } else if (req_implies_req(&((struct requirement *) data)[i], req)) {
5989 return TRI_YES;
5990 }
5991 }
5992
5993 return tri_req_active(context, other_context, req);
5994}
5995
5996/**********************************************************************/
6002enum fc_tristate
6003 tri_reqs_cb_active(const struct req_context *context,
6004 const struct req_context *other_context,
6005 const struct requirement_vector *reqs,
6006 struct requirement_vector *maybe_reqs,
6007 req_tester_cb tester,
6008 void *data, int n_data)
6009{
6010 bool active = TRUE;
6011 bool certain = TRUE;
6012
6013 fc_assert_ret_val(NULL != tester, TRI_NO);
6014 requirement_vector_iterate(reqs, preq) {
6015 switch(tester(context, other_context, preq,
6016 data, n_data)) {
6017 case TRI_NO:
6018 active = FALSE;
6019 certain = TRUE;
6020 break;
6021 case TRI_YES:
6022 break;
6023 case TRI_MAYBE:
6024 certain = FALSE;
6025 if (maybe_reqs) {
6026 requirement_vector_append(maybe_reqs, *preq);
6027 }
6028 break;
6029 default:
6030 fc_assert(FALSE);
6031 active = FALSE;
6032 }
6033 if (!active) {
6034 break;
6035 }
6036 } requirement_vector_iterate_end;
6037
6038 return certain ? (active ? TRI_YES : TRI_NO) : TRI_MAYBE;
6039}
6040
6041/**********************************************************************/
6049enum req_unchanging_status
6050 is_req_unchanging(const struct req_context *context,
6051 const struct requirement *req)
6052{
6053 enum req_unchanging_status s;
6054 const struct civ_map *nmap = &(wld.map);
6055
6056 fc_assert_ret_val(req, REQUCH_NO);
6057 fc_assert_ret_val_msg(universals_n_is_valid(req->source.kind), REQUCH_NO,
6058 "Invalid source kind %d.", req->source.kind);
6059 s = req_definitions[req->source.kind].unchanging;
6060
6061 if (req->survives) {
6062 /* Special case for surviving requirements */
6063 /* Buildings may obsolete even here */
6064 if (VUT_IMPROVEMENT == req->source.kind) {
6065 const struct impr_type *b = req->source.value.building;
6066
6067 if (can_improvement_go_obsolete(b)) {
6068 if (improvement_obsolete(context->player, b, context->city)) {
6069 /* FIXME: sometimes can unobsolete, but considering it
6070 * may sometimes put the function on endless recursion */
6071 return REQUCH_ACT; /* Mostly about techs */
6072 } else {
6073 /* NOTE: may obsoletion reqs be unchanging? Hardly but why not. */
6074 return REQUCH_NO;
6075 }
6076 }
6077 }
6078 s = unchanging_present(nmap, s, context, req);
6079 if (s != REQUCH_NO) {
6080 return unchanging_noally(nmap, s, context, req);
6081 }
6082 } else {
6083 req_unchanging_cond_cb cond
6084 = req_definitions[req->source.kind].unchanging_cond;
6085
6086 if (cond) {
6087 return cond(nmap, s, context, req);
6088 }
6089 }
6090
6091 return s;
6092}
6093
6094/**********************************************************************/
6097enum req_unchanging_status
6098 is_req_preventing(const struct req_context *context,
6099 const struct req_context *other_context,
6100 const struct requirement *req,
6101 enum req_problem_type prob_type)
6102{
6103 enum req_unchanging_status u = is_req_unchanging(context, req);
6104
6105 if (REQUCH_NO != u) {
6106 /* presence is precalculated */
6107 bool auto_present = (req->survives
6108 && !(VUT_IMPROVEMENT == req->source.kind
6109 && can_improvement_go_obsolete(req->source.value.building)))
6110 || REQUC_PRESENT == req_definitions[req->source.kind].unchanging_cond
6111 || REQUC_WORLD == req_definitions[req->source.kind].unchanging_cond;
6112
6113 if (auto_present ? req->present
6114 : is_req_active(context, other_context, req, RPT_POSSIBLE)) {
6115 /* Unchanging but does not block */
6116 return REQUCH_NO;
6117 }
6118 }
6119
6120 return u;
6121}
6122
6123/**********************************************************************/
6127 bool is_req_in_vec(const struct requirement *req,
6128 const struct requirement_vector *vec)
6129{
6130 requirement_vector_iterate(vec, preq) {
6131 if (are_requirements_equal(req, preq)) {
6132 return TRUE;
6133 }
6134 } requirement_vector_iterate_end;
6135
6136 return FALSE;
6137}
6138
6139/**********************************************************************/
6145 bool req_vec_wants_type(const struct requirement_vector *reqs,
6146 enum universals_n kind)
6147{
6148 requirement_vector_iterate(reqs, preq) {
6149 if (preq->present && preq->source.kind == kind) {
6150 return TRUE;
6151 }
6152 } requirement_vector_iterate_end;
6153 return FALSE;
6154}
6155
6156/**********************************************************************/
6164 bool universal_never_there(const struct universal *source)
6165{
6166 switch (source->kind) {
6167 case VUT_ACTION:
6168 return !action_is_in_use(source->value.action);
6169 case VUT_UTFLAG:
6170 return !utype_flag_is_in_use(source->value.unitflag);
6171 case VUT_UCFLAG:
6172 return !uclass_flag_is_in_use(source->value.unitclassflag);
6173 case VUT_EXTRAFLAG:
6174 return !extra_flag_is_in_use(source->value.extraflag);
6175 case VUT_MINLATITUDE:
6176 return source->value.latitude > MAP_MAX_REAL_LATITUDE(wld.map);
6177 case VUT_MAXLATITUDE:
6178 return source->value.latitude < MAP_MIN_REAL_LATITUDE(wld.map);
6179 case VUT_COUNTER:
6180 case VUT_OTYPE:
6181 case VUT_SPECIALIST:
6182 case VUT_AI_LEVEL:
6183 case VUT_CITYTILE:
6184 case VUT_CITYSTATUS:
6185 case VUT_STYLE:
6186 case VUT_TOPO:
6187 case VUT_WRAP:
6188 case VUT_SERVERSETTING:
6189 case VUT_NATION:
6190 case VUT_NATIONGROUP:
6191 case VUT_ADVANCE:
6192 case VUT_TECHFLAG:
6193 case VUT_GOVERNMENT:
6194 case VUT_ACHIEVEMENT:
6195 case VUT_IMPROVEMENT:
6196 case VUT_IMPR_GENUS:
6197 case VUT_IMPR_FLAG:
6198 case VUT_PLAYER_FLAG:
6199 case VUT_PLAYER_STATE:
6200 case VUT_MINSIZE:
6201 case VUT_MINCULTURE:
6202 case VUT_MINFOREIGNPCT:
6203 case VUT_MINTECHS:
6204 case VUT_MINCITIES:
6205 case VUT_NATIONALITY:
6206 case VUT_ORIGINAL_OWNER: /* As long as midgame player creation or civil war possible */
6207 case VUT_DIPLREL:
6208 case VUT_DIPLREL_TILE:
6209 case VUT_DIPLREL_TILE_O:
6210 case VUT_DIPLREL_UNITANY:
6211 case VUT_DIPLREL_UNITANY_O:
6212 case VUT_MAXTILEUNITS:
6213 case VUT_UTYPE:
6214 case VUT_UCLASS:
6215 case VUT_MINVETERAN:
6216 case VUT_UNITSTATE:
6217 case VUT_ACTIVITY:
6218 case VUT_MINMOVES:
6219 case VUT_MINHP:
6220 case VUT_AGE:
6221 case VUT_FORM_AGE:
6222 case VUT_ROADFLAG:
6223 case VUT_MINCALFRAG:
6224 case VUT_TERRAIN:
6225 case VUT_EXTRA:
6226 case VUT_GOOD:
6227 case VUT_TERRAINCLASS:
6228 case VUT_TERRFLAG:
6229 case VUT_TERRAINALTER:
6230 case VUT_MINYEAR:
6231 case VUT_NONE:
6232 case VUT_COUNT:
6233 /* Not implemented. */
6234 break;
6235 }
6236
6237 return FALSE;
6238}
6239
6240/**********************************************************************/
6247 bool req_is_impossible_to_fulfill(const struct requirement *req)
6248{
6249 /* Not known to be impossible to fulfill */
6250 return req->present && universal_never_there(&req->source);
6251}
6252
6253/**********************************************************************/
6260 bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
6261{
6262 requirement_vector_iterate(reqs, preq) {
6263 if (req_is_impossible_to_fulfill(preq)) {
6264 return TRUE;
6265 }
6266 } requirement_vector_iterate_end;
6267
6268 /* Not known to be impossible to fulfill */
6269 return FALSE;
6270}
6271
6272/**********************************************************************/
6279 req_vec_num_in_item
6280req_vec_vector_number(const void *parent_item,
6281 const struct requirement_vector *vec)
6282{
6283 if (vec) {
6284 return 0;
6285 } else {
6286 return -1;
6287 }
6288}
6289
6290/********************************************************************/
6298struct requirement_vector *
6299req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
6300{
6301 fc_assert_ret_val(number == 0, NULL);
6302 return (struct requirement_vector *)parent_item;
6303}
6304
6305/**********************************************************************/
6315 const char *req_vec_change_translation(const struct req_vec_change *change,
6316 const requirement_vector_namer namer)
6317{
6318 const char *req_vec_description;
6319 static char buf[MAX_LEN_NAME * 3];
6320 struct astring astr;
6321
6322 fc_assert_ret_val(change, NULL);
6323 fc_assert_ret_val(req_vec_change_operation_is_valid(change->operation),
6324 NULL);
6325
6326 /* Get rid of the previous. */
6327 buf[0] = '\0';
6328
6329 if (namer == NULL) {
6330 /* TRANS: default description of a requirement vector
6331 * (used in ruledit) */
6332 req_vec_description = _("the requirement vector");
6333 } else {
6334 req_vec_description = namer(change->vector_number);
6335 }
6336
6337 switch (change->operation) {
6338 case RVCO_REMOVE:
6339 fc_snprintf(buf, sizeof(buf),
6340 /* TRANS: remove a requirement from a requirement vector
6341 * (in ruledit).
6342 * The first %s is the operation.
6343 * The second %s is the requirement.
6344 * The third %s is a description of the requirement vector,
6345 * like "actor_reqs" */
6346 _("%s %s from %s"),
6347 req_vec_change_operation_name(change->operation),
6348 req_to_fstring(&change->req, &astr),
6349 req_vec_description);
6350 astr_free(&astr);
6351 break;
6352 case RVCO_APPEND:
6353 fc_snprintf(buf, sizeof(buf),
6354 /* TRANS: append a requirement to a requirement vector
6355 * (in ruledit).
6356 * The first %s is the operation.
6357 * The second %s is the requirement.
6358 * The third %s is a description of the requirement vector,
6359 * like "actor_reqs" */
6360 _("%s %s to %s"),
6361 req_vec_change_operation_name(change->operation),
6362 req_to_fstring(&change->req, &astr),
6363 req_vec_description);
6364 astr_free(&astr);
6365 break;
6366 case RVCO_NOOP:
6367 fc_snprintf(buf, sizeof(buf),
6368 /* TRANS: do nothing to a requirement vector (in ruledit).
6369 * The first %s is a description of the requirement vector,
6370 * like "actor_reqs" */
6371 _("Do nothing to %s"), req_vec_description);
6372 break;
6373 }
6374
6375 return buf;
6376}
6377
6378/**********************************************************************/
6388 bool req_vec_change_apply(const struct req_vec_change *modification,
6389 requirement_vector_by_number getter,
6390 const void *parent_item)
6391{
6392 struct requirement_vector *target
6393 = getter(parent_item, modification->vector_number);
6394 int i = 0;
6395
6396 switch (modification->operation) {
6397 case RVCO_APPEND:
6398 requirement_vector_append(target, modification->req);
6399 return TRUE;
6400 case RVCO_REMOVE:
6401 requirement_vector_iterate(target, preq) {
6402 if (are_requirements_equal(&modification->req, preq)) {
6403 requirement_vector_remove(target, i);
6404 return TRUE;
6405 }
6406 i++;
6407 } requirement_vector_iterate_end;
6408 return FALSE;
6409 case RVCO_NOOP:
6410 return FALSE;
6411 }
6412
6413 return FALSE;
6414}
6415
6416/**********************************************************************/
6425struct req_vec_problem *
6426req_vec_problem_new_transl(int num_suggested_solutions,
6427 const char *description,
6428 const char *description_translated)
6429{
6430 struct req_vec_problem *out;
6431 int i;
6432
6433 out = fc_malloc(sizeof(*out));
6434
6435 fc_strlcpy(out->description, description, sizeof(out->description));
6436 fc_strlcpy(out->description_translated, _(description_translated),
6437 sizeof(out->description_translated));
6438
6439 out->num_suggested_solutions = num_suggested_solutions;
6440 out->suggested_solutions = fc_malloc(out->num_suggested_solutions
6441 * sizeof(struct req_vec_change));
6442 for (i = 0; i < out->num_suggested_solutions; i++) {
6443 /* No suggestions are ready yet. */
6444 out->suggested_solutions[i].operation = RVCO_NOOP;
6445 out->suggested_solutions[i].vector_number = -1;
6446 out->suggested_solutions[i].req.source.kind = VUT_NONE;
6447 }
6448
6449 return out;
6450}
6451
6452/**********************************************************************/
6460 struct req_vec_problem *req_vec_problem_new(int num_suggested_solutions,
6461 const char *descr, ...)
6462{
6463 char description[500];
6464 char description_translated[500];
6465 va_list ap;
6466
6467 va_start(ap, descr);
6468 fc_vsnprintf(description, sizeof(description), descr, ap);
6469 va_end(ap);
6470
6471 va_start(ap, descr);
6472 fc_vsnprintf(description_translated, sizeof(description_translated),
6473 _(descr), ap);
6474 va_end(ap);
6475
6476 return req_vec_problem_new_transl(num_suggested_solutions,
6477 description, description_translated);
6478}
6479
6480/**********************************************************************/
6485 void req_vec_problem_free(struct req_vec_problem *issue)
6486{
6487 FC_FREE(issue->suggested_solutions);
6488 issue->num_suggested_solutions = 0;
6489
6490 FC_FREE(issue);
6491}
6492
6493/**********************************************************************/
6504struct req_vec_problem *
6505req_vec_get_first_contradiction(const struct requirement_vector *vec,
6506 requirement_vector_number get_num,
6507 const void *parent_item)
6508{
6509 int i, j;
6510 req_vec_num_in_item vec_num;
6511
6512 if (vec == NULL || requirement_vector_size(vec) == 0) {
6513 /* No vector. */
6514 return NULL;
6515 }
6516
6517 if (get_num == NULL || parent_item == NULL) {
6518 vec_num = 0;
6519 } else {
6520 vec_num = get_num(parent_item, vec);
6521 }
6522
6523 /* Look for contradictions */
6524 for (i = 0; i < requirement_vector_size(vec); i++) {
6525 struct requirement *preq = requirement_vector_get(vec, i);
6526 for (j = 0; j < requirement_vector_size(vec); j++) {
6527 struct requirement *nreq = requirement_vector_get(vec, j);
6528
6529 if (are_requirements_contradictions(preq, nreq)) {
6530 struct req_vec_problem *problem;
6531 struct astring astr;
6532 struct astring nastr;
6533
6534 problem = req_vec_problem_new(2,
6535 N_("Requirements {%s} and {%s} contradict each other."),
6536 req_to_fstring(preq, &astr), req_to_fstring(nreq, &nastr));
6537
6538 astr_free(&astr);
6539 astr_free(&nastr);
6540
6541 /* The solution is to remove one of the contradictions. */
6542 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6543 problem->suggested_solutions[0].vector_number = vec_num;
6544 problem->suggested_solutions[0].req = *preq;
6545
6546 problem->suggested_solutions[1].operation = RVCO_REMOVE;
6547 problem->suggested_solutions[1].vector_number = vec_num;
6548 problem->suggested_solutions[1].req = *nreq;
6549
6550 /* Only the first contradiction is reported. */
6551 return problem;
6552 }
6553 }
6554 }
6555
6556 return NULL;
6557}
6558
6559/**********************************************************************/
6569struct req_vec_problem *
6570req_vec_suggest_repair(const struct requirement_vector *vec,
6571 requirement_vector_number get_num,
6572 const void *parent_item)
6573{
6574 /* Check for self contradictins. */
6575 return req_vec_get_first_contradiction(vec, get_num, parent_item);
6576}
6577
6578/**********************************************************************/
6590struct req_vec_problem *
6591req_vec_get_first_missing_univ(const struct requirement_vector *vec,
6592 requirement_vector_number get_num,
6593 const void *parent_item)
6594{
6595 int i;
6596 req_vec_num_in_item vec_num;
6597 struct req_vec_problem *problem = NULL;
6598
6599 if (vec == NULL || requirement_vector_size(vec) == 0) {
6600 /* No vector. */
6601 return NULL;
6602 }
6603
6604 if (get_num == NULL || parent_item == NULL) {
6605 vec_num = 0;
6606 } else {
6607 vec_num = get_num(parent_item, vec);
6608 }
6609
6610 /* Look for contradictions */
6611 for (i = 0; i < requirement_vector_size(vec); i++) {
6612 struct requirement *preq = requirement_vector_get(vec, i);
6613
6614 if (universal_never_there(&preq->source)) {
6615 struct astring astr;
6616
6617 if (preq->present) {
6618 /* The requirement vector can never be fulfilled. Removing the
6619 * requirement makes it possible to fulfill it. This is a rule
6620 * change and shouldn't be "fixed" without thinking. Don't offer any
6621 * automatic solution to prevent mindless "fixes". */
6622 /* TRANS: ruledit warns a user about an unused requirement vector
6623 * that never can be fulfilled because it asks for something that
6624 * never will be there. */
6625 if (problem == NULL) {
6626 problem = req_vec_problem_new(0,
6627 N_("Requirement {%s} requires %s but it will never be"
6628 " there."),
6629 req_to_fstring(preq, &astr), universal_rule_name(&preq->source));
6630 astr_free(&astr);
6631 }
6632
6633 /* Continue to check if other problems have a solution proposal,
6634 * and prefer to return those. */
6635 continue;
6636 }
6637
6638 if (problem != NULL) {
6639 /* Free previous one (one with no solution proposals) */
6640 req_vec_problem_free(problem);
6641 }
6642
6643 problem = req_vec_problem_new(1,
6644 N_("Requirement {%s} mentions %s but it will never be there."),
6645 req_to_fstring(preq, &astr), universal_rule_name(&preq->source));
6646
6647 astr_free(&astr);
6648
6649 /* The solution is to remove the reference to the missing
6650 * universal. */
6651 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6652 problem->suggested_solutions[0].vector_number = vec_num;
6653 problem->suggested_solutions[0].req = *preq;
6654
6655 /* Only the first missing universal is reported. */
6656 return problem;
6657 }
6658 }
6659
6660 return problem;
6661}
6662
6663/**********************************************************************/
6675struct req_vec_problem *
6676req_vec_get_first_redundant_req(const struct requirement_vector *vec,
6677 requirement_vector_number get_num,
6678 const void *parent_item)
6679{
6680 int i, j;
6681 req_vec_num_in_item vec_num;
6682
6683 if (vec == NULL || requirement_vector_size(vec) == 0) {
6684 /* No vector. */
6685 return NULL;
6686 }
6687
6688 if (get_num == NULL || parent_item == NULL) {
6689 vec_num = 0;
6690 } else {
6691 vec_num = get_num(parent_item, vec);
6692 }
6693
6694 /* Look for repeated requirements */
6695 for (i = 0; i < requirement_vector_size(vec) - 1; i++) {
6696 struct requirement *preq = requirement_vector_get(vec, i);
6697 for (j = i + 1; j < requirement_vector_size(vec); j++) {
6698 struct requirement *nreq = requirement_vector_get(vec, j);
6699
6700 if (are_requirements_equal(preq, nreq)) {
6701 struct req_vec_problem *problem;
6702 struct astring astr;
6703 struct astring nastr;
6704
6705 problem = req_vec_problem_new(2,
6706 N_("Requirements {%s} and {%s} are the same."),
6707 req_to_fstring(preq, &astr), req_to_fstring(nreq, &nastr));
6708
6709 astr_free(&astr);
6710 astr_free(&nastr);
6711
6712 /* The solution is to remove one of the redundant requirements. */
6713 problem->suggested_solutions[0].operation = RVCO_REMOVE;
6714 problem->suggested_solutions[0].vector_number = vec_num;
6715 problem->suggested_solutions[0].req = *preq;
6716
6717 problem->suggested_solutions[1].operation = RVCO_REMOVE;
6718 problem->suggested_solutions[1].vector_number = vec_num;
6719 problem->suggested_solutions[1].req = *nreq;
6720
6721 /* Only the first redundancy is reported. */
6722 return problem;
6723 }
6724 }
6725 }
6726
6727 return NULL;
6728}
6729
6730/**********************************************************************/
6741struct req_vec_problem *
6742req_vec_suggest_improvement(const struct requirement_vector *vec,
6743 requirement_vector_number get_num,
6744 const void *parent_item)
6745{
6746 struct req_vec_problem *out;
6747
6748 out = req_vec_suggest_repair(vec, get_num, parent_item);
6749 if (out != NULL) {
6750 /* A bug, not just a potential improvement */
6751 return out;
6752 }
6753
6754 /* Check if a universal that never will appear in the game is checked. */
6755 out = req_vec_get_first_missing_univ(vec, get_num, parent_item);
6756 if (out != NULL) {
6757 return out;
6758 }
6759
6760 /* Check if a requirement is redundant. */
6761 out = req_vec_get_first_redundant_req(vec, get_num, parent_item);
6762 return out;
6763}
6764
6765/**********************************************************************/
6769 bool are_universals_equal(const struct universal *psource1,
6770 const struct universal *psource2)
6771{
6772 if (psource1->kind != psource2->kind) {
6773 return FALSE;
6774 }
6775 switch (psource1->kind) {
6776 case VUT_NONE:
6777 return TRUE;
6778 case VUT_COUNTER:
6779 return psource1->value.counter == psource2->value.counter;
6780 case VUT_ADVANCE:
6781 return psource1->value.advance == psource2->value.advance;
6782 case VUT_TECHFLAG:
6783 return psource1->value.techflag == psource2->value.techflag;
6784 case VUT_GOVERNMENT:
6785 return psource1->value.govern == psource2->value.govern;
6786 case VUT_ACHIEVEMENT:
6787 return psource1->value.achievement == psource2->value.achievement;
6788 case VUT_STYLE:
6789 return psource1->value.style == psource2->value.style;
6790 case VUT_IMPROVEMENT:
6791 return psource1->value.building == psource2->value.building;
6792 case VUT_IMPR_GENUS:
6793 return psource1->value.impr_genus == psource2->value.impr_genus;
6794 case VUT_IMPR_FLAG:
6795 return psource1->value.impr_flag == psource2->value.impr_flag;
6796 case VUT_PLAYER_FLAG:
6797 return psource1->value.plr_flag == psource2->value.plr_flag;
6798 case VUT_PLAYER_STATE:
6799 return psource1->value.plrstate == psource2->value.plrstate;
6800 case VUT_EXTRA:
6801 return psource1->value.extra == psource2->value.extra;
6802 case VUT_GOOD:
6803 return psource1->value.good == psource2->value.good;
6804 case VUT_TERRAIN:
6805 return psource1->value.terrain == psource2->value.terrain;
6806 case VUT_TERRFLAG:
6807 return psource1->value.terrainflag == psource2->value.terrainflag;
6808 case VUT_NATION:
6809 return psource1->value.nation == psource2->value.nation;
6810 case VUT_NATIONGROUP:
6811 return psource1->value.nationgroup == psource2->value.nationgroup;
6812 case VUT_NATIONALITY:
6813 return psource1->value.nationality == psource2->value.nationality;
6814 case VUT_ORIGINAL_OWNER:
6815 return psource1->value.origowner == psource2->value.origowner;
6816 case VUT_DIPLREL:
6817 case VUT_DIPLREL_TILE:
6818 case VUT_DIPLREL_TILE_O:
6819 case VUT_DIPLREL_UNITANY:
6820 case VUT_DIPLREL_UNITANY_O:
6821 return psource1->value.diplrel == psource2->value.diplrel;
6822 case VUT_UTYPE:
6823 return psource1->value.utype == psource2->value.utype;
6824 case VUT_UTFLAG:
6825 return psource1->value.unitflag == psource2->value.unitflag;
6826 case VUT_UCLASS:
6827 return psource1->value.uclass == psource2->value.uclass;
6828 case VUT_UCFLAG:
6829 return psource1->value.unitclassflag == psource2->value.unitclassflag;
6830 case VUT_MINVETERAN:
6831 return psource1->value.minveteran == psource2->value.minveteran;
6832 case VUT_UNITSTATE:
6833 return psource1->value.unit_state == psource2->value.unit_state;
6834 case VUT_ACTIVITY:
6835 return psource1->value.activity == psource2->value.activity;
6836 case VUT_MINMOVES:
6837 return psource1->value.minmoves == psource2->value.minmoves;
6838 case VUT_MINHP:
6839 return psource1->value.min_hit_points == psource2->value.min_hit_points;
6840 case VUT_AGE:
6841 return psource1->value.age == psource2->value.age;
6842 case VUT_FORM_AGE:
6843 return psource1->value.form_age == psource2->value.form_age;
6844 case VUT_MINTECHS:
6845 return psource1->value.min_techs == psource2->value.min_techs;
6846 case VUT_MINCITIES:
6847 return psource1->value.min_cities == psource2->value.min_cities;
6848 case VUT_ACTION:
6849 return (action_number(psource1->value.action)
6850 == action_number(psource2->value.action));
6851 case VUT_OTYPE:
6852 return psource1->value.outputtype == psource2->value.outputtype;
6853 case VUT_SPECIALIST:
6854 return psource1->value.specialist == psource2->value.specialist;
6855 case VUT_MINSIZE:
6856 return psource1->value.minsize == psource2->value.minsize;
6857 case VUT_MINCULTURE:
6858 return psource1->value.minculture == psource2->value.minculture;
6859 case VUT_MINFOREIGNPCT:
6860 return psource1->value.minforeignpct == psource2->value.minforeignpct;
6861 case VUT_AI_LEVEL:
6862 return psource1->value.ai_level == psource2->value.ai_level;
6863 case VUT_MAXTILEUNITS:
6864 return psource1->value.max_tile_units == psource2->value.max_tile_units;
6865 case VUT_TERRAINCLASS:
6866 return psource1->value.terrainclass == psource2->value.terrainclass;
6867 case VUT_ROADFLAG:
6868 return psource1->value.roadflag == psource2->value.roadflag;
6869 case VUT_EXTRAFLAG:
6870 return psource1->value.extraflag == psource2->value.extraflag;
6871 case VUT_MINYEAR:
6872 return psource1->value.minyear == psource2->value.minyear;
6873 case VUT_MINCALFRAG:
6874 return psource1->value.mincalfrag == psource2->value.mincalfrag;
6875 case VUT_TOPO:
6876 return psource1->value.topo_property == psource2->value.topo_property;
6877 case VUT_WRAP:
6878 return psource1->value.wrap_property == psource2->value.wrap_property;
6879 case VUT_SERVERSETTING:
6880 return psource1->value.ssetval == psource2->value.ssetval;
6881 case VUT_TERRAINALTER:
6882 return psource1->value.terrainalter == psource2->value.terrainalter;
6883 case VUT_CITYTILE:
6884 return psource1->value.citytile == psource2->value.citytile;
6885 case VUT_CITYSTATUS:
6886 return psource1->value.citystatus == psource2->value.citystatus;
6887 case VUT_MINLATITUDE:
6888 case VUT_MAXLATITUDE:
6889 return psource1->value.latitude == psource2->value.latitude;
6890 case VUT_COUNT:
6891 break;
6892 }
6893
6894 fc_assert_msg(FALSE, "Invalid source kind %d.", psource1->kind);
6895 return FALSE;
6896}
6897
6898/**********************************************************************/
6902 const char *universal_rule_name(const struct universal *psource)
6903{
6904 static char buffer[10];
6905
6906 switch (psource->kind) {
6907 case VUT_NONE:
6908 return "(none)";
6909 case VUT_COUNTER:
6910 return counter_rule_name(psource->value.counter);
6911 case VUT_CITYTILE:
6912 return citytile_type_name(psource->value.citytile);
6913 case VUT_CITYSTATUS:
6914 return citystatus_type_name(psource->value.citystatus);
6915 case VUT_MINYEAR:
6916 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
6917
6918 return buffer;
6919 case VUT_MINCALFRAG:
6920 /* Rule name is 0-based number, not pretty name from ruleset */
6921 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
6922
6923 return buffer;
6924 case VUT_TOPO:
6925 return topo_flag_name(psource->value.topo_property);
6926 case VUT_WRAP:
6927 return wrap_flag_name(psource->value.wrap_property);
6928 case VUT_SERVERSETTING:
6929 return ssetv_rule_name(psource->value.ssetval);
6930 case VUT_ADVANCE:
6931 return advance_rule_name(psource->value.advance);
6932 case VUT_TECHFLAG:
6933 return tech_flag_id_name(psource->value.techflag);
6934 case VUT_GOVERNMENT:
6935 return government_rule_name(psource->value.govern);
6936 case VUT_ACHIEVEMENT:
6937 return achievement_rule_name(psource->value.achievement);
6938 case VUT_STYLE:
6939 return style_rule_name(psource->value.style);
6940 case VUT_IMPROVEMENT:
6941 return improvement_rule_name(psource->value.building);
6942 case VUT_IMPR_GENUS:
6943 return impr_genus_id_name(psource->value.impr_genus);
6944 case VUT_IMPR_FLAG:
6945 return impr_flag_id_name(psource->value.impr_flag);
6946 case VUT_PLAYER_FLAG:
6947 return plr_flag_id_name(psource->value.plr_flag);
6948 case VUT_PLAYER_STATE:
6949 return plrstate_type_name(psource->value.plrstate);
6950 case VUT_EXTRA:
6951 return extra_rule_name(psource->value.extra);
6952 case VUT_GOOD:
6953 return goods_rule_name(psource->value.good);
6954 case VUT_TERRAIN:
6955 return terrain_rule_name(psource->value.terrain);
6956 case VUT_TERRFLAG:
6957 return terrain_flag_id_name(psource->value.terrainflag);
6958 case VUT_NATION:
6959 return nation_rule_name(psource->value.nation);
6960 case VUT_NATIONGROUP:
6961 return nation_group_rule_name(psource->value.nationgroup);
6962 case VUT_DIPLREL:
6963 case VUT_DIPLREL_TILE:
6964 case VUT_DIPLREL_TILE_O:
6965 case VUT_DIPLREL_UNITANY:
6966 case VUT_DIPLREL_UNITANY_O:
6967 return diplrel_rule_name(psource->value.diplrel);
6968 case VUT_NATIONALITY:
6969 return nation_rule_name(psource->value.nationality);
6970 case VUT_ORIGINAL_OWNER:
6971 return nation_rule_name(psource->value.origowner);
6972 case VUT_UTYPE:
6973 return utype_rule_name(psource->value.utype);
6974 case VUT_UTFLAG:
6975 return unit_type_flag_id_name(psource->value.unitflag);
6976 case VUT_UCLASS:
6977 return uclass_rule_name(psource->value.uclass);
6978 case VUT_UCFLAG:
6979 return unit_class_flag_id_name(psource->value.unitclassflag);
6980 case VUT_MINVETERAN:
6981 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
6982
6983 return buffer;
6984 case VUT_UNITSTATE:
6985 return ustate_prop_name(psource->value.unit_state);
6986 case VUT_ACTIVITY:
6987 return unit_activity_name(psource->value.activity);
6988 case VUT_MINMOVES:
6989 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
6990
6991 return buffer;
6992 case VUT_MINHP:
6993 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
6994
6995 return buffer;
6996 case VUT_AGE:
6997 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
6998
6999 return buffer;
7000 case VUT_FORM_AGE:
7001 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.form_age);
7002
7003 return buffer;
7004 case VUT_MINTECHS:
7005 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
7006
7007 return buffer;
7008 case VUT_MINCITIES:
7009 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_cities);
7010
7011 return buffer;
7012 case VUT_ACTION:
7013 return action_rule_name(psource->value.action);
7014 case VUT_OTYPE:
7015 return get_output_identifier(psource->value.outputtype);
7016 case VUT_SPECIALIST:
7017 return specialist_rule_name(psource->value.specialist);
7018 case VUT_MINSIZE:
7019 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
7020
7021 return buffer;
7022 case VUT_MINCULTURE:
7023 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
7024
7025 return buffer;
7026 case VUT_MINFOREIGNPCT:
7027 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
7028
7029 return buffer;
7030 case VUT_AI_LEVEL:
7031 return ai_level_name(psource->value.ai_level);
7032 case VUT_MAXTILEUNITS:
7033 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_units);
7034 return buffer;
7035 case VUT_TERRAINCLASS:
7036 return terrain_class_name(psource->value.terrainclass);
7037 case VUT_ROADFLAG:
7038 return road_flag_id_name(psource->value.roadflag);
7039 case VUT_EXTRAFLAG:
7040 return extra_flag_id_name(psource->value.extraflag);
7041 case VUT_TERRAINALTER:
7042 return terrain_alteration_name(psource->value.terrainalter);
7043 case VUT_MINLATITUDE:
7044 case VUT_MAXLATITUDE:
7045 fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.latitude);
7046
7047 return buffer;
7048 case VUT_COUNT:
7049 break;
7050 }
7051
7052 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
7053 return NULL;
7054}
7055
7056/**********************************************************************/
7064 const char *universal_name_translation(const struct universal *psource,
7065 char *buf, size_t bufsz)
7066{
7067 buf[0] = '\0'; /* to be safe. */
7068 switch (psource->kind) {
7069 case VUT_NONE:
7070 /* TRANS: missing value */
7071 fc_strlcat(buf, _("(none)"), bufsz);
7072 return buf;
7073 case VUT_ADVANCE:
7074 fc_strlcat(buf, advance_name_translation(psource->value.advance), bufsz);
7075 return buf;
7076 case VUT_COUNTER:
7077 fc_strlcat(buf, counter_name_translation(psource->value.counter), bufsz);
7078 return buf;
7079 case VUT_TECHFLAG:
7080 cat_snprintf(buf, bufsz, _("\"%s\" tech"),
7081 tech_flag_id_translated_name(psource->value.techflag));
7082 return buf;
7083 case VUT_GOVERNMENT:
7084 fc_strlcat(buf, government_name_translation(psource->value.govern),
7085 bufsz);
7086 return buf;
7087 case VUT_ACHIEVEMENT:
7088 fc_strlcat(buf, achievement_name_translation(psource->value.achievement),
7089 bufsz);
7090 return buf;
7091 case VUT_STYLE:
7092 fc_strlcat(buf, style_name_translation(psource->value.style),
7093 bufsz);
7094 return buf;
7095 case VUT_IMPROVEMENT:
7096 fc_strlcat(buf, improvement_name_translation(psource->value.building),
7097 bufsz);
7098 return buf;
7099 case VUT_IMPR_GENUS:
7100 fc_strlcat(buf,
7101 impr_genus_id_translated_name(psource->value.impr_genus),
7102 bufsz);
7103 return buf;
7104 case VUT_IMPR_FLAG:
7105 fc_strlcat(buf,
7106 impr_flag_id_translated_name(psource->value.impr_flag),
7107 bufsz);
7108 return buf;
7109 case VUT_PLAYER_FLAG:
7110 fc_strlcat(buf,
7111 plr_flag_id_translated_name(psource->value.plr_flag),
7112 bufsz);
7113 return buf;
7114 case VUT_PLAYER_STATE:
7115 fc_strlcat(buf,
7116 plrstate_type_translated_name(psource->value.plrstate),
7117 bufsz);
7118 return buf;
7119 case VUT_EXTRA:
7120 fc_strlcat(buf, extra_name_translation(psource->value.extra), bufsz);
7121 return buf;
7122 case VUT_GOOD:
7123 fc_strlcat(buf, goods_name_translation(psource->value.good), bufsz);
7124 return buf;
7125 case VUT_TERRAIN:
7126 fc_strlcat(buf, terrain_name_translation(psource->value.terrain), bufsz);
7127 return buf;
7128 case VUT_NATION:
7129 fc_strlcat(buf, nation_adjective_translation(psource->value.nation),
7130 bufsz);
7131 return buf;
7132 case VUT_NATIONGROUP:
7133 fc_strlcat(buf, nation_group_name_translation(psource->value.nationgroup),
7134 bufsz);
7135 return buf;
7136 case VUT_NATIONALITY:
7137 cat_snprintf(buf, bufsz, _("%s citizens"),
7138 nation_adjective_translation(psource->value.nationality));
7139 return buf;
7140 case VUT_ORIGINAL_OWNER:
7141 /* TRANS: Keep short. City founding nation. */
7142 cat_snprintf(buf, bufsz, _("%s original owner"),
7143 nation_adjective_translation(psource->value.origowner));
7144 return buf;
7145 case VUT_DIPLREL:
7146 case VUT_DIPLREL_TILE:
7147 case VUT_DIPLREL_TILE_O:
7148 case VUT_DIPLREL_UNITANY:
7149 case VUT_DIPLREL_UNITANY_O:
7150 fc_strlcat(buf, diplrel_name_translation(psource->value.diplrel),
7151 bufsz);
7152 return buf;
7153 case VUT_UTYPE:
7154 fc_strlcat(buf, utype_name_translation(psource->value.utype), bufsz);
7155 return buf;
7156 case VUT_UTFLAG:
7157 cat_snprintf(buf, bufsz,
7158 /* TRANS: Unit type flag */
7159 Q_("?utflag:\"%s\" units"),
7160 unit_type_flag_id_translated_name(
7161 psource->value.unitflag));
7162 return buf;
7163 case VUT_UCLASS:
7164 cat_snprintf(buf, bufsz,
7165 /* TRANS: Unit class */
7166 _("%s units"),
7167 uclass_name_translation(psource->value.uclass));
7168 return buf;
7169 case VUT_UCFLAG:
7170 cat_snprintf(buf, bufsz,
7171 /* TRANS: Unit class flag */
7172 Q_("?ucflag:\"%s\" units"),
7173 unit_class_flag_id_translated_name(
7174 psource->value.unitclassflag));
7175 return buf;
7176 case VUT_MINVETERAN:
7177 /* FIXME */
7178 cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
7179 psource->value.minveteran);
7180 return buf;
7181 case VUT_UNITSTATE:
7182 switch (psource->value.unit_state) {
7183 case USP_TRANSPORTED:
7184 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7185 cat_snprintf(buf, bufsz, _("Transported"));
7186 break;
7187 case USP_LIVABLE_TILE:
7188 cat_snprintf(buf, bufsz,
7189 /* TRANS: unit state. (appears in strings like
7190 * "Missile+On livable tile") */
7191 _("On livable tile"));
7192 break;
7193 case USP_TRANSPORTING:
7194 /* TRANS: unit state. (appears in strings like "Missile+Transported") */
7195 cat_snprintf(buf, bufsz, _("Transporting"));
7196 break;
7197 case USP_HAS_HOME_CITY:
7198 /* TRANS: unit state. (appears in strings like "Missile+Has a home city") */
7199 cat_snprintf(buf, bufsz, _("Has a home city"));
7200 break;
7201 case USP_NATIVE_TILE:
7202 cat_snprintf(buf, bufsz,
7203 /* TRANS: unit state. (appears in strings like
7204 * "Missile+On native tile") */
7205 _("On native tile"));
7206 break;
7207 case USP_NATIVE_EXTRA:
7208 cat_snprintf(buf, bufsz,
7209 /* TRANS: unit state. (appears in strings like
7210 * "Missile+In native extra") */
7211 _("In native extra"));
7212 break;
7213 case USP_MOVED_THIS_TURN:
7214 /* TRANS: unit state. (appears in strings like
7215 * "Missile+Has moved this turn") */
7216 cat_snprintf(buf, bufsz, _("Has moved this turn"));
7217 break;
7218 case USP_COUNT:
7219 fc_assert_msg(psource->value.unit_state != USP_COUNT,
7220 "Invalid unit state property.");
7221 break;
7222 }
7223 return buf;
7224 case VUT_ACTIVITY:
7225 cat_snprintf(buf, bufsz, _("%s activity"),
7226 Q_(unit_activity_name(psource->value.activity)));
7227 return buf;
7228 case VUT_MINMOVES:
7229 /* TRANS: Minimum unit movement points left for requirement to be met
7230 * (%s is a string like "1" or "2 1/3") */
7231 cat_snprintf(buf, bufsz, _("%s MP"),
7232 move_points_text(psource->value.minmoves, TRUE));
7233 return buf;
7234 case VUT_MINHP:
7235 /* TRANS: HP = hit points */
7236 cat_snprintf(buf, bufsz, _("%d HP"),
7237 psource->value.min_hit_points);
7238 return buf;
7239 case VUT_AGE:
7240 cat_snprintf(buf, bufsz, _("Age %d"),
7241 psource->value.age);
7242 return buf;
7243 case VUT_FORM_AGE:
7244 cat_snprintf(buf, bufsz, _("Form age %d"),
7245 psource->value.form_age);
7246 return buf;
7247 case VUT_MINTECHS:
7248 cat_snprintf(buf, bufsz, _("%d Techs"),
7249 psource->value.min_techs);
7250 return buf;
7251 case VUT_MINCITIES:
7252 cat_snprintf(buf, bufsz, _("%d Cities"),
7253 psource->value.min_cities);
7254 return buf;
7255 case VUT_ACTION:
7256 fc_strlcat(buf, action_name_translation(psource->value.action),
7257 bufsz);
7258 return buf;
7259 case VUT_OTYPE:
7260 /* FIXME */
7261 fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
7262 return buf;
7263 case VUT_SPECIALIST:
7264 fc_strlcat(buf, specialist_plural_translation(psource->value.specialist),
7265 bufsz);
7266 return buf;
7267 case VUT_MINSIZE:
7268 cat_snprintf(buf, bufsz, _("Size %d"),
7269 psource->value.minsize);
7270 return buf;
7271 case VUT_MINCULTURE:
7272 cat_snprintf(buf, bufsz, _("Culture %d"),
7273 psource->value.minculture);
7274 return buf;
7275 case VUT_MINFOREIGNPCT:
7276 cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
7277 psource->value.minforeignpct);
7278 return buf;
7279 case VUT_AI_LEVEL:
7280 /* TRANS: "Hard AI" */
7281 cat_snprintf(buf, bufsz, _("%s AI"),
7282 ai_level_translated_name(psource->value.ai_level)); /* FIXME */
7283 return buf;
7284 case VUT_MAXTILEUNITS:
7285 /* TRANS: here <= means 'less than or equal' */
7286 cat_snprintf(buf, bufsz, PL_("<=%d unit",
7287 "<=%d units", psource->value.max_tile_units),
7288 psource->value.max_tile_units);
7289 return buf;
7290 case VUT_TERRAINCLASS:
7291 /* TRANS: Terrain class: "Land terrain" */
7292 cat_snprintf(buf, bufsz, _("%s terrain"),
7293 terrain_class_name_translation(psource->value.terrainclass));
7294 return buf;
7295 case VUT_TERRFLAG:
7296 cat_snprintf(buf, bufsz,
7297 /* TRANS: Terrain flag */
7298 Q_("?terrflag:\"%s\" terrain"),
7299 terrain_flag_id_translated_name(
7300 psource->value.terrainflag));
7301 return buf;
7302 case VUT_ROADFLAG:
7303 cat_snprintf(buf, bufsz,
7304 /* TRANS: Road flag */
7305 Q_("?roadflag:\"%s\" road"),
7306 road_flag_id_translated_name(psource->value.roadflag));
7307 return buf;
7308 case VUT_EXTRAFLAG:
7309 cat_snprintf(buf, bufsz,
7310 /* TRANS: Extra flag */
7311 Q_("?extraflag:\"%s\" extra"),
7312 extra_flag_id_translated_name(psource->value.extraflag));
7313 return buf;
7314 case VUT_MINYEAR:
7315 cat_snprintf(buf, bufsz, _("After %s"),
7316 textyear(psource->value.minyear));
7317 return buf;
7318 case VUT_MINCALFRAG:
7319 /* TRANS: here >= means 'greater than or equal'.
7320 * %s identifies a calendar fragment (may be bare number). */
7321 cat_snprintf(buf, bufsz, _(">=%s"),
7322 textcalfrag(psource->value.mincalfrag));
7323 return buf;
7324 case VUT_TOPO:
7325 /* TRANS: topology flag name ("Hex", "ISO") */
7326 cat_snprintf(buf, bufsz, _("%s map"),
7327 _(topo_flag_name(psource->value.topo_property)));
7328 return buf;
7329 case VUT_WRAP:
7330 /* TRANS: wrap flag name ("WrapX", "WrapY") */
7331 cat_snprintf(buf, bufsz, _("%s map"),
7332 _(wrap_flag_name(psource->value.wrap_property)));
7333 return buf;
7334 case VUT_SERVERSETTING:
7335 fc_strlcat(buf, ssetv_human_readable(psource->value.ssetval, TRUE),
7336 bufsz);
7337 return buf;
7338 case VUT_TERRAINALTER:
7339 /* TRANS: "Irrigation possible" */
7340 cat_snprintf(buf, bufsz, _("%s possible"),
7341 Q_(terrain_alteration_name(psource->value.terrainalter)));
7342 return buf;
7343 case VUT_CITYTILE:
7344 switch (psource->value.citytile) {
7345 case CITYT_CENTER:
7346 fc_strlcat(buf, _("City center"), bufsz);
7347 break;
7348 case CITYT_CLAIMED:
7349 fc_strlcat(buf, _("Tile claimed"), bufsz);
7350 break;
7351 case CITYT_EXTRAS_OWNED:
7352 fc_strlcat(buf, _("Extras owned"), bufsz);
7353 break;
7354 case CITYT_WORKED:
7355 fc_strlcat(buf, _("Worked tile"), bufsz);
7356 break;
7357 case CITYT_SAME_CONTINENT:
7358 fc_strlcat(buf, _("Same continent tile"), bufsz);
7359 break;
7360 case CITYT_BORDERING_TCLASS_REGION:
7361 /* TRANS: Short for "a tile of other terrain class mass near city" */
7362 fc_strlcat(buf, _("Port reachable tile"), bufsz);
7363 break;
7364 case CITYT_LAST:
7365 fc_assert(psource->value.citytile != CITYT_LAST);
7366 fc_strlcat(buf, "error", bufsz);
7367 break;
7368 }
7369 return buf;
7370 case VUT_CITYSTATUS:
7371 switch (psource->value.citystatus) {
7372 case CITYS_OWNED_BY_ORIGINAL:
7373 fc_strlcat(buf, _("Owned by original"), bufsz);
7374 break;
7375 case CITYS_STARVED:
7376 fc_strlcat(buf, _("Starved"), bufsz);
7377 break;
7378 case CITYS_DISORDER:
7379 fc_strlcat(buf, _("Disorder"), bufsz);
7380 break;
7381 case CITYS_CELEBRATION:
7382 fc_strlcat(buf, _("Celebration"), bufsz);
7383 break;
7384 case CITYS_TRANSFERRED:
7385 /* TRANS: CityStatus value - city has changed hands */
7386 fc_strlcat(buf, _("Transferred"), bufsz);
7387 break;
7388 case CITYS_LAST:
7389 fc_assert(psource->value.citystatus != CITYS_LAST);
7390 fc_strlcat(buf, "error", bufsz);
7391 break;
7392 }
7393 return buf;
7394 case VUT_MINLATITUDE:
7395 /* TRANS: here >= means 'greater than or equal'. */
7396 cat_snprintf(buf, bufsz, _("Latitude >= %d"),
7397 psource->value.latitude);
7398 return buf;
7399 case VUT_MAXLATITUDE:
7400 /* TRANS: here <= means 'less than or equal'. */
7401 cat_snprintf(buf, bufsz, _("Latitude <= %d"),
7402 psource->value.latitude);
7403 return buf;
7404 case VUT_COUNT:
7405 break;
7406 }
7407
7408 fc_assert_msg(FALSE, "Invalid source kind %d.", psource->kind);
7409 return buf;
7410}
7411
7412/**********************************************************************/
7415 const char *universal_type_rule_name(const struct universal *psource)
7416{
7417 return universals_n_name(psource->kind);
7418}
7419
7420/**********************************************************************/
7423 int universal_build_shield_cost(const struct city *pcity,
7424 const struct universal *target)
7425{
7426 switch (target->kind) {
7427 case VUT_IMPROVEMENT:
7428 return impr_build_shield_cost(pcity, target->value.building);
7429 case VUT_UTYPE:
7430 return utype_build_shield_cost(pcity, NULL, target->value.utype);
7431 default:
7432 break;
7433 }
7434 return FC_INFINITY;
7435}
7436
7437/**********************************************************************/
7442 bool universal_replace_in_req_vec(struct requirement_vector *reqs,
7443 const struct universal *to_replace,
7444 const struct universal *replacement)
7445{
7446 bool changed = FALSE;
7447
7448 requirement_vector_iterate(reqs, preq) {
7449 if (universal_is_mentioned_by_requirement(preq, to_replace)) {
7450 preq->source = *replacement;
7451 changed = TRUE;
7452 }
7453 } requirement_vector_iterate_end;
7454
7455 return changed;
7456}
7457
7458/**********************************************************************/
7462 bool universal_is_mentioned_by_requirements(
7463 const struct requirement_vector *reqs,
7464 const struct universal *psource)
7465{
7466 requirement_vector_iterate(reqs, preq) {
7467 if (universal_is_mentioned_by_requirement(preq, psource)) {
7468 return TRUE;
7469 }
7470 } requirement_vector_iterate_end;
7471
7472 return FALSE;
7473}
7474
7475/**********************************************************************/
7484 bool universals_mean_unfulfilled(struct requirement_vector *reqs,
7485 struct universal *unis,
7486 size_t n_unis)
7487{
7488 int i;
7489
7490 for (i = 0; i < n_unis; i++) {
7491 if (!universal_fulfills_requirements(FALSE, reqs, &unis[i])) {
7492 /* This universal makes it impossible to fulfill the specified
7493 * requirement vector */
7494 return TRUE;
7495 }
7496 }
7497
7498 /* No specified universal is known to guarantee that the requirement
7499 * vector never will be fulfilled. */
7500 return FALSE;
7501}
7502
7503/**********************************************************************/
7517 bool universals_say_everything(struct requirement_vector *reqs,
7518 struct universal *unis,
7519 size_t n_unis)
7520{
7521 requirement_vector_iterate(reqs, preq) {
7522 int i;
7523 bool req_mentioned_a_source = FALSE;
7524
7525 for (i = 0; i < n_unis; i++) {
7526 switch (universal_fulfills_requirement(preq, &(unis[i]))) {
7527 case ITF_NO:
7528 case ITF_YES:
7529 /* this req matched this source */
7530 req_mentioned_a_source = TRUE;
7531 break;
7532 case ITF_NOT_APPLICABLE:
7533 /* Not a mention. */
7534 break;
7535 }
7536 }
7537
7538 if (!req_mentioned_a_source) {
7539 /* A requirement not relevant to any of the specified universals was
7540 * found in the requirement vector. */
7541 return FALSE;
7542 }
7543 } requirement_vector_iterate_end;
7544
7545 /* No requirement not relevant to any of the specified universals was
7546 * found in the requirement vector. */
7547 return TRUE;
7548}
7549
7550/**********************************************************************/
7553enum req_item_found
7554universal_fulfills_requirement(const struct requirement *preq,
7555 const struct universal *source)
7556{
7557 fc_assert_ret_val_msg(universal_found_function[source->kind],
7558 ITF_NOT_APPLICABLE,
7559 "No req item found function for %s",
7560 universal_type_rule_name(source));
7561
7562 return (*universal_found_function[source->kind])(preq, source);
7563}
7564
7565/**********************************************************************/
7575 bool universal_fulfills_requirements(bool check_necessary,
7576 const struct requirement_vector *reqs,
7577 const struct universal *source)
7578{
7579 bool necessary = FALSE;
7580
7581 fc_assert_ret_val_msg(universal_found_function[source->kind],
7582 !check_necessary,
7583 "No req item found function for %s",
7584 universal_type_rule_name(source));
7585
7586 requirement_vector_iterate(reqs, preq) {
7587 switch ((*universal_found_function[source->kind])(preq, source)) {
7588 case ITF_NOT_APPLICABLE:
7589 continue;
7590 case ITF_NO:
7591 if (preq->present) {
7592 return FALSE;
7593 }
7594 break;
7595 case ITF_YES:
7596 if (preq->present) {
7597 necessary = TRUE;
7598 } else {
7599 return FALSE;
7600 }
7601 break;
7602 }
7603 } requirement_vector_iterate_end;
7604
7605 return (!check_necessary || necessary);
7606}
7607
7608/**********************************************************************/
7612 bool universal_is_relevant_to_requirement(const struct requirement *req,
7613 const struct universal *source)
7614{
7615 switch (universal_fulfills_requirement(req, source)) {
7616 case ITF_NOT_APPLICABLE:
7617 return FALSE;
7618 case ITF_NO:
7619 case ITF_YES:
7620 return TRUE;
7621 }
7622
7623 log_error("Unhandled item_found value");
7624 return FALSE;
7625}
7626
7627/**********************************************************************/
7630 static enum req_item_found nation_found(const struct requirement *preq,
7631 const struct universal *source)
7632{
7633 fc_assert(source->value.nation);
7634
7635 switch (preq->source.kind) {
7636 case VUT_NATION:
7637 return preq->source.value.nation == source->value.nation ? ITF_YES
7638 : ITF_NO;
7639 case VUT_NATIONGROUP:
7640 return nation_is_in_group(source->value.nation,
7641 preq->source.value.nationgroup) ? ITF_YES
7642 : ITF_NO;
7643 default:
7644 break;
7645 }
7646
7647 return ITF_NOT_APPLICABLE;
7648}
7649
7650/**********************************************************************/
7653 static enum req_item_found government_found(const struct requirement *preq,
7654 const struct universal *source)
7655{
7656 fc_assert(source->value.govern);
7657
7658 if (preq->source.kind == VUT_GOVERNMENT) {
7659 return preq->source.value.govern == source->value.govern ? ITF_YES
7660 : ITF_NO;
7661 }
7662
7663 return ITF_NOT_APPLICABLE;
7664}
7665
7666/**********************************************************************/
7669 static enum req_item_found improvement_found(const struct requirement *preq,
7670 const struct universal *source)
7671{
7672 fc_assert(source->value.building);
7673
7674 /* We only ever return ITF_YES, because requiring a different
7675 * improvement does not mean that the improvement under consideration
7676 * cannot fulfill the requirements. This is necessary to allow
7677 * requirement vectors to specify multiple required improvements. */
7678
7679 switch (preq->source.kind) {
7680 case VUT_IMPROVEMENT:
7681 if (source->value.building == preq->source.value.building) {
7682 return ITF_YES;
7683 }
7684 break;
7685 case VUT_IMPR_GENUS:
7686 if (source->value.building->genus == preq->source.value.impr_genus) {
7687 return ITF_YES;
7688 }
7689 break;
7690 case VUT_IMPR_FLAG:
7691 if (improvement_has_flag(source->value.building,
7692 preq->source.value.impr_flag)) {
7693 return ITF_YES;
7694 }
7695 break;
7696 default:
7697 break;
7698 }
7699
7700 return ITF_NOT_APPLICABLE;
7701}
7702
7703/**********************************************************************/
7706 static enum req_item_found unit_class_found(const struct requirement *preq,
7707 const struct universal *source)
7708{
7709 fc_assert(source->value.uclass);
7710
7711 switch (preq->source.kind) {
7712 case VUT_UCLASS:
7713 return source->value.uclass == preq->source.value.uclass ? ITF_YES
7714 : ITF_NO;
7715 case VUT_UCFLAG:
7716 return uclass_has_flag(source->value.uclass,
7717 preq->source.value.unitclassflag) ? ITF_YES
7718 : ITF_NO;
7719
7720 default:
7721 /* Not found and not relevant. */
7722 return ITF_NOT_APPLICABLE;
7723 };
7724}
7725
7726/**********************************************************************/
7729 static enum req_item_found unit_type_found(const struct requirement *preq,
7730 const struct universal *source)
7731{
7732 fc_assert(source->value.utype);
7733
7734 switch (preq->source.kind) {
7735 case VUT_UTYPE:
7736 return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO;
7737 case VUT_UCLASS:
7738 return utype_class(source->value.utype) == preq->source.value.uclass
7739 ? ITF_YES : ITF_NO;
7740 case VUT_UTFLAG:
7741 return utype_has_flag(source->value.utype,
7742 preq->source.value.unitflag) ? ITF_YES : ITF_NO;
7743 case VUT_UCFLAG:
7744 return uclass_has_flag(utype_class(source->value.utype),
7745 preq->source.value.unitclassflag) ? ITF_YES
7746 : ITF_NO;
7747 default:
7748 /* Not found and not relevant. */
7749 return ITF_NOT_APPLICABLE;
7750 };
7751}
7752
7753/**********************************************************************/
7756static enum req_item_found
7757unit_activity_found(const struct requirement *preq,
7758 const struct universal *source)
7759{
7760 fc_assert_ret_val(unit_activity_is_valid(source->value.activity),
7761 ITF_NOT_APPLICABLE);
7762
7763 switch (preq->source.kind) {
7764 case VUT_ACTIVITY:
7765 return source->value.activity == preq->source.value.activity ? ITF_YES
7766 : ITF_NO;
7767 default:
7768 /* Not found and not relevant. */
7769 return ITF_NOT_APPLICABLE;
7770 };
7771}
7772
7773/**********************************************************************/
7776 static enum req_item_found terrain_type_found(const struct requirement *preq,
7777 const struct universal *source)
7778{
7779 fc_assert(source->value.terrain);
7780
7781 switch (preq->source.kind) {
7782 case VUT_TERRAIN:
7783 return source->value.terrain == preq->source.value.terrain ? ITF_YES : ITF_NO;
7784 case VUT_TERRAINCLASS:
7785 return terrain_type_terrain_class(source->value.terrain) == preq->source.value.terrainclass
7786 ? ITF_YES : ITF_NO;
7787 case VUT_TERRFLAG:
7788 return terrain_has_flag(source->value.terrain,
7789 preq->source.value.terrainflag) ? ITF_YES : ITF_NO;
7790 case VUT_TERRAINALTER:
7791 return (terrain_can_support_alteration(source->value.terrain,
7792 preq->source.value.terrainalter)
7793 ? ITF_YES : ITF_NO);
7794 default:
7795 /* Not found and not relevant. */
7796 return ITF_NOT_APPLICABLE;
7797 };
7798}
7799
7800/**********************************************************************/
7803 static enum req_item_found city_tile_found(const struct requirement *preq,
7804 const struct universal *source)
7805{
7806 fc_assert_ret_val(citytile_type_is_valid(source->value.citytile),
7807 ITF_NOT_APPLICABLE);
7808
7809 switch (preq->source.kind) {
7810 case VUT_CITYTILE:
7811 return (source->value.citytile == preq->source.value.citytile
7812 ? ITF_YES
7813 /* The presence of one tile state doesn't block another */
7814 : ITF_NOT_APPLICABLE);
7815 default:
7816 /* Not found and not relevant. */
7817 return ITF_NOT_APPLICABLE;
7818 };
7819}
7820
7821/**********************************************************************/
7824 static enum req_item_found extra_type_found(const struct requirement *preq,
7825 const struct universal *source)
7826{
7827 fc_assert(source->value.extra);
7828
7829 switch (preq->source.kind) {
7830 case VUT_EXTRA:
7831 return source->value.extra == preq->source.value.extra ? ITF_YES : ITF_NO;
7832 case VUT_EXTRAFLAG:
7833 return extra_has_flag(source->value.extra,
7834 preq->source.value.extraflag) ? ITF_YES : ITF_NO;
7835 case VUT_ROADFLAG:
7836 {
7837 struct road_type *r = extra_road_get(source->value.extra);
7838 return r && road_has_flag(r, preq->source.value.roadflag)
7839 ? ITF_YES : ITF_NO;
7840 }
7841 default:
7842 /* Not found and not relevant. */
7843 return ITF_NOT_APPLICABLE;
7844 }
7845}
7846
7847/**********************************************************************/
7850 static enum req_item_found action_found(const struct requirement *preq,
7851 const struct universal *source)
7852{
7853 fc_assert(source->value.action);
7854
7855 if (preq->source.kind == VUT_ACTION) {
7856 return preq->source.value.action == source->value.action ? ITF_YES
7857 : ITF_NO;
7858 }
7859
7860 return ITF_NOT_APPLICABLE;
7861}
7862
7863/**********************************************************************/
7866 static enum req_item_found diplrel_found(const struct requirement *preq,
7867 const struct universal *source)
7868{
7869 fc_assert_ret_val((source->kind == VUT_DIPLREL
7870 || source->kind == VUT_DIPLREL_TILE
7871 || source->kind == VUT_DIPLREL_TILE_O
7872 || source->kind == VUT_DIPLREL_UNITANY
7873 || source->kind == VUT_DIPLREL_UNITANY_O),
7874 ITF_NOT_APPLICABLE);
7875
7876 if (preq->source.kind == source->kind) {
7877 if (preq->source.value.diplrel == source->value.diplrel) {
7878 /* The diplrel itself. */
7879 return ITF_YES;
7880 }
7881 if (preq->source.value.diplrel == DRO_FOREIGN
7882 && source->value.diplrel < DS_LAST) {
7883 /* All diplstate_type values are to foreigners. */
7884 return ITF_YES;
7885 }
7886 if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
7887 && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
7888 /* A real embassy is an embassy. */
7889 return ITF_YES;
7890 }
7891 if (preq->source.value.diplrel == DRO_HAS_EMBASSY
7892 && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
7893 /* A real embassy is an embassy. */
7894 return ITF_YES;
7895 }
7896 if (preq->source.value.diplrel < DS_LAST
7897 && source->value.diplrel < DS_LAST
7898 && preq->range == REQ_RANGE_LOCAL) {
7899 fc_assert_ret_val(preq->source.value.diplrel != source->value.diplrel,
7900 ITF_YES);
7901 /* Can only have one diplstate_type to a specific player. */
7902 return ITF_NO;
7903 }
7904 /* Can't say this diplrel blocks the other diplrel. */
7905 return ITF_NOT_APPLICABLE;
7906 }
7907
7908 /* Not relevant. */
7909 return ITF_NOT_APPLICABLE;
7910}
7911
7912/**********************************************************************/
7915 static enum req_item_found output_type_found(const struct requirement *preq,
7916 const struct universal *source)
7917{
7918 switch (preq->source.kind) {
7919 case VUT_OTYPE:
7920 return source->value.outputtype == preq->source.value.outputtype ? ITF_YES
7921 : ITF_NO;
7922 default:
7923 /* Not found and not relevant. */
7924 return ITF_NOT_APPLICABLE;
7925 }
7926}
7927
7928/**********************************************************************/
7931 static enum req_item_found ustate_found(const struct requirement *preq,
7932 const struct universal *source)
7933{
7934 if (preq->range != REQ_RANGE_LOCAL) {
7935 return ITF_NOT_APPLICABLE;
7936 }
7937
7938 if (preq->source.kind == VUT_UNITSTATE) {
7939 switch (source->value.unit_state) {
7940 case USP_TRANSPORTED:
7941 case USP_TRANSPORTING:
7942 /* USP_TRANSPORTED and USP_TRANSPORTING don't exclude each other. */
7943 case USP_LIVABLE_TILE:
7944 case USP_NATIVE_TILE:
7945 /* USP_NATIVE_TILE isn't a strict subset of USP_LIVABLE_TILE. See
7946 * UTYF_COAST_STRICT. */
7947 case USP_HAS_HOME_CITY:
7948 case USP_NATIVE_EXTRA:
7949 case USP_MOVED_THIS_TURN:
7950 if (source->value.unit_state == preq->source.value.unit_state) {
7951 /* The other unit states doesn't contradict */
7952 return ITF_YES;
7953 }
7954 break;
7955 case USP_COUNT:
7956 fc_assert_ret_val(source->value.unit_state != USP_COUNT,
7957 ITF_NOT_APPLICABLE);
7958 }
7959 }
7960
7961 /* Not found and not relevant. */
7962 return ITF_NOT_APPLICABLE;
7963}
7964
7965/**********************************************************************/
7968 void universal_found_functions_init(void)
7969{
7970 universal_found_function[VUT_GOVERNMENT] = &government_found;
7971 universal_found_function[VUT_NATION] = &nation_found;
7972 universal_found_function[VUT_IMPROVEMENT] = &improvement_found;
7973 universal_found_function[VUT_UCLASS] = &unit_class_found;
7974 universal_found_function[VUT_UTYPE] = &unit_type_found;
7975 universal_found_function[VUT_ACTIVITY] = &unit_activity_found;
7976 universal_found_function[VUT_TERRAIN] = &terrain_type_found;
7977 universal_found_function[VUT_CITYTILE] = &city_tile_found;
7978 universal_found_function[VUT_EXTRA] = &extra_type_found;
7979 universal_found_function[VUT_OTYPE] = &output_type_found;
7980 universal_found_function[VUT_ACTION] = &action_found;
7981 universal_found_function[VUT_DIPLREL] = &diplrel_found;
7982 universal_found_function[VUT_DIPLREL_TILE] = &diplrel_found;
7983 universal_found_function[VUT_DIPLREL_TILE_O] = &diplrel_found;
7984 universal_found_function[VUT_DIPLREL_UNITANY] = &diplrel_found;
7985 universal_found_function[VUT_DIPLREL_UNITANY_O] = &diplrel_found;
7986 universal_found_function[VUT_UNITSTATE] = &ustate_found;
7987}
7988
7989/**********************************************************************/
7997 int requirement_kind_ereq(const int value,
7998 const enum req_range range,
7999 const bool present,
8000 const int max_value)
8001{
8002 /* The enumerators in each range starts with present for every possible
8003 * value followed by !present for every possible value. */
8004 const int pres_start = (present ? 0 : max_value);
8005
8006 /* The enumerators for every range follows all the positions of the
8007 * previous range(s). */
8008 const int range_start = ((max_value - 1) * 2) * range;
8009
8010 return range_start + pres_start + value;
8011}
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:1205
action_is_in_use
bool action_is_in_use(struct action *paction)
Definition actions.c:5629
action_by_rule_name
struct action * action_by_rule_name(const char *name)
Definition actions.c:1054
action_rule_name
const char * action_rule_name(const struct action *action)
Definition actions.c:1191
action_id_rule_name
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1214
action_number
int action_number(const struct action *action)
Definition actions.c:1183
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:1236
output_type_by_identifier
Output_type_id output_type_by_identifier(const char *id)
Definition city.c:647
get_output_identifier
const char * get_output_identifier(Output_type_id output)
Definition city.c:619
get_output_name
const char * get_output_name(Output_type_id output)
Definition city.c:629
city_map_radius_sq_get
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
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:859
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:825
city_built_iterate_end
#define city_built_iterate_end
Definition city.h:831
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:812
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:1001
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:904
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:884
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:875
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:676
RPT_POSSIBLE
@ RPT_POSSIBLE
Definition fc_types.h:677
MAX_LEN_NAME
#define MAX_LEN_NAME
Definition fc_types.h:66
VC_SPACERACE
@ VC_SPACERACE
Definition fc_types.h:1251
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:61
wld
struct world wld
Definition game.c:62
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:226
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:2004
diplrel_req_contradicts
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Definition player.c:1829
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:1996
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
terrain_type_found
static enum req_item_found terrain_type_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7776
universal_never_there
bool universal_never_there(const struct universal *source)
Definition requirements.c:6164
is_unitclass_req_active
static enum fc_tristate is_unitclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:4258
is_unitflag_req_active
static enum fc_tristate is_unitflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:4178
universal_is_relevant_to_requirement
bool universal_is_relevant_to_requirement(const struct requirement *req, const struct universal *source)
Definition requirements.c:7612
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:6127
universal_build_shield_cost
int universal_build_shield_cost(const struct city *pcity, const struct universal *target)
Definition requirements.c:7423
is_terrainflag_req_active
static enum fc_tristate is_terrainflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3173
city_tile_found
static enum req_item_found city_tile_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7803
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:6505
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
is_action_req_active
static enum fc_tristate is_action_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2902
unit_type_found
static enum req_item_found unit_type_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7729
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:2026
is_tech_req_active
static enum fc_tristate is_tech_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2402
is_none_req_active
static enum fc_tristate is_none_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:1962
num_continent_buildings
static int num_continent_buildings(const struct player *pplayer, int continent, const struct impr_type *building)
Definition requirements.c:2040
is_minveteran_req_active
static enum fc_tristate is_minveteran_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:4537
req_to_fstring
const char * req_to_fstring(const struct requirement *req, struct astring *astr)
Definition requirements.c:1026
is_counter_req_active
static enum fc_tristate is_counter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:5378
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:6280
present_implies_not_present
static bool present_implies_not_present(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1630
tri_req_active
enum fc_tristate tri_req_active(const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:5773
req_vec_by_number
struct requirement_vector * req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
Definition requirements.c:6299
universal_fulfills_requirements
bool universal_fulfills_requirements(bool check_necessary, const struct requirement_vector *reqs, const struct universal *source)
Definition requirements.c:7575
activity_is_valid_in_requirement
static bool activity_is_valid_in_requirement(enum unit_activity act)
Definition requirements.c:255
tri_reqs_cb_active
enum fc_tristate tri_reqs_cb_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, struct requirement_vector *maybe_reqs, req_tester_cb tester, void *data, int n_data)
Definition requirements.c:6003
is_minsize_req_active
static enum fc_tristate is_minsize_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:5335
is_ai_req_active
static enum fc_tristate is_ai_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3646
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
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:6388
universal_copy
void universal_copy(struct universal *dst, const struct universal *src)
Definition requirements.c:861
is_minculture_req_active
static enum fc_tristate is_minculture_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2540
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
is_terrain_req_active
static enum fc_tristate is_terrain_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2974
are_requirements_equal
bool are_requirements_equal(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1472
is_minforeignpct_req_active
static enum fc_tristate is_minforeignpct_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2614
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 req_context *other_context, const struct requirement *req)
Definition requirements.c:4055
is_minyear_req_active
static enum fc_tristate is_minyear_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:5543
extra_type_found
static enum req_item_found extra_type_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7824
is_buildingflag_req_active
static enum fc_tristate is_buildingflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2273
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:4024
req_vec_change_translation
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
Definition requirements.c:6315
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:6570
is_wrap_req_active
static enum fc_tristate is_wrap_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:5602
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:2244
is_latitude_req_active
static enum fc_tristate is_latitude_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:5452
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:1444
req_from_values
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
Definition requirements.c:1425
is_nationality_req_active
static enum fc_tristate is_nationality_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3790
universal_rule_name
const char * universal_rule_name(const struct universal *psource)
Definition requirements.c:6902
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
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:7442
action_found
static enum req_item_found action_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7850
is_minmovefrags_req_active
static enum fc_tristate is_minmovefrags_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:4561
is_diplrel_req_active
static enum fc_tristate is_diplrel_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3962
are_requirements_contradictions
bool are_requirements_contradictions(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1688
REQUC_IMPR
#define REQUC_IMPR
Definition requirements.c:221
is_maxunitsontile_req_active
static enum fc_tristate is_maxunitsontile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2685
req_vec_problem_new
struct req_vec_problem * req_vec_problem_new(int num_suggested_solutions, const char *descr,...)
Definition requirements.c:6460
is_buildinggenus_req_active
static enum fc_tristate is_buildinggenus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2228
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:3908
is_mintechs_req_active
static enum fc_tristate is_mintechs_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3578
is_req_active
bool is_req_active(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, const enum req_problem_type prob_type)
Definition requirements.c:5711
is_originalowner_req_active
static enum fc_tristate is_originalowner_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3865
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 req_context *other_context, const struct requirement *req)
Definition requirements.c:3982
universal_is_legal_in_requirement
bool universal_is_legal_in_requirement(const struct universal *univ)
Definition requirements.c:267
default_tester_cb
enum fc_tristate default_tester_cb(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, void *data, int n_data)
Definition requirements.c:5975
tri_req_present
static enum fc_tristate tri_req_present(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:5740
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:7997
is_achievement_req_active
static enum fc_tristate is_achievement_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:5406
req_vec_problem_free
void req_vec_problem_free(struct req_vec_problem *issue)
Definition requirements.c:6485
req_definitions
static struct req_def req_definitions[VUT_COUNT]
Definition requirements.c:5634
impr_contra_flag
static bool impr_contra_flag(const struct requirement *impr_req, const struct requirement *flag_req)
Definition requirements.c:1529
are_reqs_active
bool are_reqs_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
Definition requirements.c:5807
improvement_found
static enum req_item_found improvement_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7669
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:6591
is_extraflag_req_active
static enum fc_tristate is_extraflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3386
is_req_preventing
enum req_unchanging_status is_req_preventing(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, enum req_problem_type prob_type)
Definition requirements.c:6098
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 req_context *other_context, const struct requirement *req)
Definition requirements.c:2361
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:1918
universal_found
enum req_item_found(* universal_found)(const struct requirement *, const struct universal *)
Definition requirements.c:50
is_terrainclass_req_active
static enum fc_tristate is_terrainclass_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3071
universal_by_number
struct universal universal_by_number(const enum universals_n kind, const int value)
Definition requirements.c:627
is_roadflag_req_active
static enum fc_tristate is_roadflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3281
universal_fulfills_requirement
enum req_item_found universal_fulfills_requirement(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7554
is_building_req_active
static enum fc_tristate is_building_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2066
is_age_req_active
static enum fc_tristate is_age_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:4609
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 req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
Definition requirements.c:5825
is_gov_req_active
static enum fc_tristate is_gov_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3530
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 req_context *other_context, const struct requirement *req)
Definition requirements.c:4006
is_good_req_active
static enum fc_tristate is_good_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2854
is_unitstate_req_active
static enum fc_tristate is_unitstate_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:4418
city_center_contra
static bool city_center_contra(const struct requirement *cc_req, const struct requirement *ct_req)
Definition requirements.c:1587
ustate_found
static enum req_item_found ustate_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7931
is_terrainalter_req_active
static enum fc_tristate is_terrainalter_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3483
is_unittype_req_active
static enum fc_tristate is_unittype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:4098
req_vec_wants_type
bool req_vec_wants_type(const struct requirement_vector *reqs, enum universals_n kind)
Definition requirements.c:6145
num_world_buildings_total
static int num_world_buildings_total(const struct impr_type *building)
Definition requirements.c:1976
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
output_type_found
static enum req_item_found output_type_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7915
is_citystatus_req_active
static enum fc_tristate is_citystatus_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:5091
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:6676
is_mincities_req_active
static enum fc_tristate is_mincities_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3614
is_city_in_tile
static bool is_city_in_tile(const struct tile *ptile, const struct city *pcity)
Definition requirements.c:4684
does_req_contradicts_reqs
bool does_req_contradicts_reqs(const struct requirement *req, const struct requirement_vector *vec)
Definition requirements.c:1867
government_found
static enum req_item_found government_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7653
is_extra_req_active
static enum fc_tristate is_extra_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2755
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_mincalfrag_req_active
static enum fc_tristate is_mincalfrag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:5562
is_activity_req_active
static enum fc_tristate is_activity_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:4484
are_universals_equal
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
Definition requirements.c:6769
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:6426
is_nationgroup_req_active
static enum fc_tristate is_nationgroup_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3733
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:7757
is_minhitpoints_req_active
static enum fc_tristate is_minhitpoints_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:4585
tri_req_active_turns
enum fc_tristate tri_req_active_turns(int pass, int period, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:5850
is_outputtype_req_active
static enum fc_tristate is_outputtype_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2932
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:7517
is_unitclassflag_req_active
static enum fc_tristate is_unitclassflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:4338
nation_found
static enum req_item_found nation_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7630
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:7415
REQUC_PRESENT
#define REQUC_PRESENT
Definition requirements.c:100
universal_found_functions_init
void universal_found_functions_init(void)
Definition requirements.c:7968
is_style_req_active
static enum fc_tristate is_style_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3554
unit_class_found
static enum req_item_found unit_class_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7706
IS_REQ_ACTIVE_VARIANT_ASSERT
#define IS_REQ_ACTIVE_VARIANT_ASSERT(_kind)
Definition requirements.c:1946
universal_number
int universal_number(const struct universal *source)
Definition requirements.c:881
is_techflag_req_active
static enum fc_tristate is_techflag_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2475
universal_is_mentioned_by_requirements
bool universal_is_mentioned_by_requirements(const struct requirement_vector *reqs, const struct universal *psource)
Definition requirements.c:7462
REQUC_CITYTILE
#define REQUC_CITYTILE
Definition requirements.c:162
is_citytile_req_active
static enum fc_tristate is_citytile_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:4703
diplrel_found
static enum req_item_found diplrel_found(const struct requirement *preq, const struct universal *source)
Definition requirements.c:7866
req_vec_is_impossible_to_fulfill
bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
Definition requirements.c:6260
req_implies_req
bool req_implies_req(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1671
is_specialist_req_active
static enum fc_tristate is_specialist_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:2953
req_copy
void req_copy(struct requirement *dst, const struct requirement *src)
Definition requirements.c:1459
is_req_unchanging
enum req_unchanging_status is_req_unchanging(const struct req_context *context, const struct requirement *req)
Definition requirements.c:6050
player_has_ever_built
static bool player_has_ever_built(const struct player *pplayer, const struct impr_type *building)
Definition requirements.c:2011
is_req_active_cb
enum fc_tristate(* is_req_active_cb)(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:62
nation_contra_group
static bool nation_contra_group(const struct requirement *nation_req, const struct requirement *group_req)
Definition requirements.c:1561
is_serversetting_req_active
static enum fc_tristate is_serversetting_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:5622
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 req_context *other_context, const struct requirement *req)
Definition requirements.c:2320
is_nation_req_active
static enum fc_tristate is_nation_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:3671
req_is_impossible_to_fulfill
bool req_is_impossible_to_fulfill(const struct requirement *req)
Definition requirements.c:6247
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:1886
are_requirements_opposites
static bool are_requirements_opposites(const struct requirement *req1, const struct requirement *req2)
Definition requirements.c:1484
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 req_context *other_context, const struct requirement *req)
Definition requirements.c:4658
num_world_buildings
static int num_world_buildings(const struct impr_type *building)
Definition requirements.c:1990
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_topology_req_active
static enum fc_tristate is_topology_req_active(const struct civ_map *nmap, const struct req_context *context, const struct req_context *other_context, const struct requirement *req)
Definition requirements.c:5582
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 req_context *other_context, const struct requirement *req)
Definition requirements.c:4077
universal_name_translation
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
Definition requirements.c:7064
universal_by_rule_name
struct universal universal_by_rule_name(const char *kind, const char *value)
Definition requirements.c:236
universals_mean_unfulfilled
bool universals_mean_unfulfilled(struct requirement_vector *reqs, struct universal *unis, size_t n_unis)
Definition requirements.c:7484
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:6742
impr_contra_genus
static bool impr_contra_genus(const struct requirement *impr_req, const struct requirement *genus_req)
Definition requirements.c:1497
requirements.h
req_tester_cb
enum fc_tristate(* req_tester_cb)(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, void *data, int n_data)
Definition requirements.h:193
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
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:416
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:446
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:425
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:143
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:263
packet_calendar_info::calendar_fragments
int calendar_fragments
Definition packets_gen.h:261
packet_game_info::global_advances
bool global_advances[A_LAST]
Definition packets_gen.h:166
packet_game_info::fragment_count
int fragment_count
Definition packets_gen.h:250
packet_game_info::turn
int turn
Definition packets_gen.h:245
packet_game_info::year
int year
Definition packets_gen.h:247
packet_game_info::global_advance_count
int global_advance_count
Definition packets_gen.h:165
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::researching
Tech_type_id researching
Definition research.h:52
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:878
universal::kind
enum universals_n kind
Definition fc_types.h:880
universal::value
universals_u value
Definition fc_types.h:879
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:692
goods_number
Goods_type_id goods_number(const struct goods_type *pgood)
Definition traderoutes.c:597
goods_has_flag
bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
Definition traderoutes.c:684
goods_by_rule_name
struct goods_type * goods_by_rule_name(const char *name)
Definition traderoutes.c:647
goods_rule_name
const char * goods_rule_name(struct goods_type *pgood)
Definition traderoutes.c:638
goods_name_translation
const char * goods_name_translation(struct goods_type *pgood)
Definition traderoutes.c:630
goods_by_number
struct goods_type * goods_by_number(Goods_type_id id)
Definition traderoutes.c:620
city_receives_goods
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
Definition traderoutes.c:710
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:698
universals_u::unitflag
int unitflag
Definition fc_types.h:719
universals_u::min_techs
int min_techs
Definition fc_types.h:737
universals_u::mincalfrag
int mincalfrag
Definition fc_types.h:714
universals_u::diplrel
int diplrel
Definition fc_types.h:724
universals_u::style
struct nation_style * style
Definition fc_types.h:702
universals_u::ai_level
enum ai_level ai_level
Definition fc_types.h:706
universals_u::specialist
struct specialist * specialist
Definition fc_types.h:695
universals_u::impr_genus
enum impr_genus_id impr_genus
Definition fc_types.h:728
universals_u::citytile
enum citytile_type citytile
Definition fc_types.h:707
universals_u::nationgroup
struct nation_group * nationgroup
Definition fc_types.h:701
universals_u::extra
struct extra_type * extra
Definition fc_types.h:699
universals_u::wrap_property
enum wrap_flag wrap_property
Definition fc_types.h:742
universals_u::plrstate
enum plrstate_type plrstate
Definition fc_types.h:709
universals_u::min_cities
int min_cities
Definition fc_types.h:738
universals_u::nation
struct nation_type * nation
Definition fc_types.h:692
universals_u::minmoves
int minmoves
Definition fc_types.h:731
universals_u::terrainclass
int terrainclass
Definition fc_types.h:716
universals_u::unitclassflag
int unitclassflag
Definition fc_types.h:718
universals_u::govern
struct government * govern
Definition fc_types.h:690
universals_u::origowner
struct nation_type * origowner
Definition fc_types.h:694
universals_u::age
int age
Definition fc_types.h:735
universals_u::minsize
int minsize
Definition fc_types.h:710
universals_u::impr_flag
enum impr_flag_id impr_flag
Definition fc_types.h:729
universals_u::max_tile_units
int max_tile_units
Definition fc_types.h:732
universals_u::terrainalter
int terrainalter
Definition fc_types.h:717
universals_u::minculture
int minculture
Definition fc_types.h:711
universals_u::citystatus
enum citystatus_type citystatus
Definition fc_types.h:708
universals_u::minforeignpct
int minforeignpct
Definition fc_types.h:712
universals_u::building
const struct impr_type * building
Definition fc_types.h:691
universals_u::achievement
struct achievement * achievement
Definition fc_types.h:700
universals_u::ssetval
ssetv ssetval
Definition fc_types.h:743
universals_u::techflag
int techflag
Definition fc_types.h:721
universals_u::advance
struct advance * advance
Definition fc_types.h:688
universals_u::activity
enum unit_activity activity
Definition fc_types.h:727
universals_u::good
struct goods_type * good
Definition fc_types.h:704
universals_u::terrain
struct terrain * terrain
Definition fc_types.h:696
universals_u::terrainflag
int terrainflag
Definition fc_types.h:720
universals_u::unit_state
enum ustate_prop unit_state
Definition fc_types.h:726
universals_u::minveteran
int minveteran
Definition fc_types.h:733
universals_u::extraflag
int extraflag
Definition fc_types.h:723
universals_u::outputtype
Output_type_id outputtype
Definition fc_types.h:715
universals_u::roadflag
int roadflag
Definition fc_types.h:722
universals_u::topo_property
enum topo_flag topo_property
Definition fc_types.h:741
universals_u::latitude
int latitude
Definition fc_types.h:739
universals_u::counter
struct counter * counter
Definition fc_types.h:689
universals_u::min_hit_points
int min_hit_points
Definition fc_types.h:734
universals_u::uclass
struct unit_class * uclass
Definition fc_types.h:697
universals_u::nationality
struct nation_type * nationality
Definition fc_types.h:693
universals_u::minyear
int minyear
Definition fc_types.h:713
universals_u::action
struct action * action
Definition fc_types.h:703
universals_u::form_age
int form_age
Definition fc_types.h:736
universals_u::plr_flag
enum plr_flag_id plr_flag
Definition fc_types.h:730
get_transporter_occupancy
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1821
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_has_class_flag
bool unit_has_class_flag(const struct unit *punit, enum unit_class_flag_id flag)
Definition unittype.c:1649
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