Freeciv21
Develop your civilization from humble roots to a global empire
requirements.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 1996-2020 Freeciv21 and Freeciv contributors. This file is
3  __ __ part of Freeciv21. Freeciv21 is free software: you can
4 / \\..// \ redistribute it and/or modify it under the terms of the GNU
5  ( oo ) General Public License as published by the Free Software
6  \__/ Foundation, either version 3 of the License, or (at your
7  option) any later version. You should have received
8  a copy of the GNU General Public License along with Freeciv21. If not,
9  see https://www.gnu.org/licenses/.
10  */
11 // utility
12 #include "fcintl.h"
13 #include "log.h"
14 #include "support.h"
15 
16 // common
17 #include "achievements.h"
18 #include "calendar.h"
19 #include "citizens.h"
20 #include "culture.h"
21 #include "game.h"
22 #include "government.h"
23 #include "improvement.h"
24 #include "map.h"
25 #include "movement.h"
26 #include "nation.h"
27 #include "player.h"
28 #include "research.h"
29 #include "road.h"
30 #include "server_settings.h"
31 #include "specialist.h"
32 #include "style.h"
33 
34 #include "requirements.h"
35 
39 typedef enum req_item_found (*universal_found)(const struct requirement *,
40  const struct universal *);
41 static universal_found universal_found_function[VUT_COUNT] = {nullptr};
42 
51 struct universal universal_by_rule_name(const char *kind, const char *value)
52 {
53  struct universal source;
54 
55  source.kind = universals_n_by_name(kind, fc_strcasecmp);
56  if (!universals_n_is_valid(source.kind)) {
57  source.value.advance = nullptr; // Avoid uninitialized warning
58  return source;
59  }
60 
62 
63  return source;
64 }
65 
70 void universal_value_from_str(struct universal *source, const char *value)
71 {
72  // Finally scan the value string based on the type of the source.
73  switch (source->kind) {
74  case VUT_NONE:
75  return;
76  case VUT_ADVANCE:
78  if (source->value.advance != nullptr) {
79  return;
80  }
81  break;
82  case VUT_TECHFLAG:
83  source->value.techflag = tech_flag_id_by_name(value, fc_strcasecmp);
84  if (tech_flag_id_is_valid(tech_flag_id(source->value.techflag))) {
85  return;
86  }
87  break;
88  case VUT_GOVERNMENT:
90  if (source->value.govern != nullptr) {
91  return;
92  }
93  break;
94  case VUT_ACHIEVEMENT:
96  if (source->value.achievement != nullptr) {
97  return;
98  }
99  break;
100  case VUT_STYLE:
101  source->value.style = style_by_rule_name(value);
102  if (source->value.style != nullptr) {
103  return;
104  }
105  break;
106  case VUT_IMPROVEMENT:
108  if (source->value.building != nullptr) {
109  return;
110  }
111  break;
112  case VUT_IMPR_GENUS:
113  source->value.impr_genus = impr_genus_id_by_name(value, fc_strcasecmp);
114  if (impr_genus_id_is_valid(source->value.impr_genus)) {
115  return;
116  }
117  break;
118  case VUT_EXTRA:
120  if (source->value.extra != nullptr) {
121  return;
122  }
123  break;
124  case VUT_GOOD:
125  source->value.good = goods_by_rule_name(value);
126  if (source->value.good != nullptr) {
127  return;
128  }
129  break;
130  case VUT_TERRAIN:
132  if (source->value.terrain != T_UNKNOWN) {
133  return;
134  }
135  break;
136  case VUT_TERRFLAG:
137  source->value.terrainflag =
138  terrain_flag_id_by_name(value, fc_strcasecmp);
139  if (terrain_flag_id_is_valid(
140  terrain_flag_id(source->value.terrainflag))) {
141  return;
142  }
143  break;
144  case VUT_NATION:
146  if (source->value.nation != NO_NATION_SELECTED) {
147  return;
148  }
149  break;
150  case VUT_NATIONGROUP:
152  if (source->value.nationgroup != nullptr) {
153  return;
154  }
155  break;
156  case VUT_NATIONALITY:
158  if (source->value.nationality != NO_NATION_SELECTED) {
159  return;
160  }
161  break;
162  case VUT_DIPLREL:
164  if (source->value.diplrel != diplrel_other_invalid()) {
165  return;
166  }
167  break;
168  case VUT_UTYPE:
170  if (source->value.utype) {
171  return;
172  }
173  break;
174  case VUT_UTFLAG:
175  source->value.unitflag = unit_type_flag_id_by_name(value, fc_strcasecmp);
176  if (unit_type_flag_id_is_valid(
177  unit_type_flag_id(source->value.unitflag))) {
178  return;
179  }
180  break;
181  case VUT_UCLASS:
183  if (source->value.uclass) {
184  return;
185  }
186  break;
187  case VUT_UCFLAG:
188  source->value.unitclassflag =
189  unit_class_flag_id_by_name(value, fc_strcasecmp);
190  if (unit_class_flag_id_is_valid(
191  unit_class_flag_id(source->value.unitclassflag))) {
192  return;
193  }
194  break;
195  case VUT_MINVETERAN:
196  source->value.minveteran = atoi(value);
197  if (source->value.minveteran > 0) {
198  return;
199  }
200  break;
201  case VUT_UNITSTATE:
202  source->value.unit_state = ustate_prop_by_name(value, fc_strcasecmp);
203  if (ustate_prop_is_valid(source->value.unit_state)) {
204  return;
205  }
206  break;
207  case VUT_ACTIVITY:
208  source->value.activity = unit_activity_by_name(value, fc_strcasecmp);
209  if (unit_activity_is_valid(source->value.activity)) {
210  return;
211  }
212  break;
213  case VUT_MINMOVES:
214  source->value.minmoves = atoi(value);
215  if (source->value.minmoves > 0) {
216  return;
217  }
218  break;
219  case VUT_MINHP:
220  source->value.min_hit_points = atoi(value);
221  if (source->value.min_hit_points > 0) {
222  return;
223  }
224  break;
225  case VUT_AGE:
226  source->value.age = atoi(value);
227  if (source->value.age > 0) {
228  return;
229  }
230  break;
231  case VUT_MINTECHS:
232  source->value.min_techs = atoi(value);
233  if (source->value.min_techs > 0) {
234  return;
235  }
236  break;
237  case VUT_ACTION:
239  if (source->value.action != nullptr) {
240  return;
241  }
242  break;
243  case VUT_OTYPE:
245  if (source->value.outputtype != O_LAST) {
246  return;
247  }
248  break;
249  case VUT_SPECIALIST:
251  if (source->value.specialist) {
252  return;
253  }
254  break;
255  case VUT_MINSIZE:
256  source->value.minsize = atoi(value);
257  if (source->value.minsize > 0) {
258  return;
259  }
260  break;
261  case VUT_MINCULTURE:
262  source->value.minculture = atoi(value);
263  if (source->value.minculture > 0) {
264  return;
265  }
266  break;
267  case VUT_MINFOREIGNPCT:
268  source->value.minforeignpct = atoi(value);
269  if (source->value.minforeignpct > 0) {
270  return;
271  }
272  break;
273  case VUT_AI_LEVEL:
274  source->value.ai_level = ai_level_by_name(value, fc_strcasecmp);
275  if (ai_level_is_valid(source->value.ai_level)) {
276  return;
277  }
278  break;
279  case VUT_MAXTILEUNITS:
280  source->value.max_tile_units = atoi(value);
281  if (0 <= source->value.max_tile_units) {
282  return;
283  }
284  break;
285  case VUT_TERRAINCLASS:
286  source->value.terrainclass = terrain_class_by_name(value, fc_strcasecmp);
287  if (terrain_class_is_valid(terrain_class(source->value.terrainclass))) {
288  return;
289  }
290  break;
291  case VUT_BASEFLAG:
292  source->value.baseflag = base_flag_id_by_name(value, fc_strcasecmp);
293  if (base_flag_id_is_valid(base_flag_id(source->value.baseflag))) {
294  return;
295  }
296  break;
297  case VUT_ROADFLAG:
298  source->value.roadflag = road_flag_id_by_name(value, fc_strcasecmp);
299  if (road_flag_id_is_valid(road_flag_id(source->value.roadflag))) {
300  return;
301  }
302  break;
303  case VUT_EXTRAFLAG:
304  source->value.extraflag = extra_flag_id_by_name(value, fc_strcasecmp);
305  if (extra_flag_id_is_valid(extra_flag_id(source->value.extraflag))) {
306  return;
307  }
308  break;
309  case VUT_MINYEAR:
310  source->value.minyear = atoi(value);
311  return;
312  case VUT_MINCALFRAG:
313  // Rule names are 0-based numbers, not pretty names from ruleset
314  source->value.mincalfrag = atoi(value);
315  if (source->value.mincalfrag >= 0) {
316  // More range checking done later, in sanity_check_req_individual()
317  return;
318  }
319  break;
320  case VUT_TOPO:
321  source->value.topo_property = topo_flag_by_name(value, fc_strcasecmp);
322  if (topo_flag_is_valid(source->value.topo_property)) {
323  return;
324  }
325  break;
326  case VUT_SERVERSETTING:
328  if (source->value.ssetval != SSETV_NONE) {
329  return;
330  }
331  break;
332  case VUT_TERRAINALTER:
333  source->value.terrainalter =
334  terrain_alteration_by_name(value, fc_strcasecmp);
335  if (terrain_alteration_is_valid(
336  terrain_alteration(source->value.terrainalter))) {
337  return;
338  }
339  break;
340  case VUT_CITYTILE:
341  source->value.citytile = citytile_type_by_name(value, fc_strcasecmp);
342  if (citytile_type_is_valid(source->value.citytile)) {
343  return;
344  }
345  break;
346  case VUT_CITYSTATUS:
347  source->value.citystatus = citystatus_type_by_name(value, fc_strcasecmp);
348  if (citystatus_type_is_valid(source->value.citystatus)) {
349  return;
350  }
351  break;
352  case VUT_VISIONLAYER:
353  source->value.vlayer = vision_layer_by_name(value, fc_strcasecmp);
354  if (vision_layer_is_valid(source->value.vlayer)) {
355  return;
356  }
357  break;
358  case VUT_NINTEL:
359  source->value.nintel =
360  national_intelligence_by_name(value, fc_strcasecmp);
361  if (national_intelligence_is_valid(source->value.nintel)) {
362  return;
363  }
364  case VUT_COUNT:
365  break;
366  }
367 
368  // If we reach here there's been an error.
369  source->kind = universals_n_invalid();
370 }
371 
377 struct universal universal_by_number(const enum universals_n kind,
378  const int value)
379 {
380  struct universal source;
381 
382  source.kind = kind;
383 
384  switch (source.kind) {
385  case VUT_NONE:
386  // Avoid compiler warning about unitialized source.value
387  source.value.advance = nullptr;
388 
389  return source;
390  case VUT_ADVANCE:
391  source.value.advance = advance_by_number(value);
392  if (source.value.advance != nullptr) {
393  return source;
394  }
395  break;
396  case VUT_TECHFLAG:
397  source.value.techflag = value;
398  return source;
399  case VUT_GOVERNMENT:
400  source.value.govern = government_by_number(value);
401  if (source.value.govern != nullptr) {
402  return source;
403  }
404  break;
405  case VUT_ACHIEVEMENT:
406  source.value.achievement = achievement_by_number(value);
407  if (source.value.achievement != nullptr) {
408  return source;
409  }
410  break;
411  case VUT_STYLE:
412  source.value.style = style_by_number(value);
413  if (source.value.style != nullptr) {
414  return source;
415  }
416  break;
417  case VUT_IMPROVEMENT:
418  source.value.building = improvement_by_number(value);
419  if (source.value.building != nullptr) {
420  return source;
421  }
422  break;
423  case VUT_IMPR_GENUS:
424  source.value.impr_genus = impr_genus_id(value);
425  if (impr_genus_id_is_valid(source.value.impr_genus)) {
426  return source;
427  }
428  break;
429  case VUT_EXTRA:
430  source.value.extra = extra_by_number(value);
431  if (source.value.extra != nullptr) {
432  return source;
433  }
434  break;
435  case VUT_GOOD:
436  source.value.good = goods_by_number(value);
437  if (source.value.good != nullptr) {
438  return source;
439  }
440  break;
441  case VUT_TERRAIN:
442  source.value.terrain = terrain_by_number(value);
443  if (source.value.terrain != nullptr) {
444  return source;
445  }
446  break;
447  case VUT_TERRFLAG:
448  source.value.terrainflag = value;
449  if (terrain_flag_id_is_valid(
450  terrain_flag_id(source.value.terrainflag))) {
451  return source;
452  }
453  break;
454  case VUT_NATION:
455  source.value.nation = nation_by_number(value);
456  if (source.value.nation != nullptr) {
457  return source;
458  }
459  break;
460  case VUT_NATIONGROUP:
461  source.value.nationgroup = nation_group_by_number(value);
462  if (source.value.nationgroup != nullptr) {
463  return source;
464  }
465  break;
466  case VUT_DIPLREL:
467  source.value.diplrel = value;
468  if (source.value.diplrel != diplrel_other_invalid()) {
469  return source;
470  }
471  break;
472  case VUT_NATIONALITY:
473  source.value.nationality = nation_by_number(value);
474  if (source.value.nationality != nullptr) {
475  return source;
476  }
477  break;
478  case VUT_UTYPE:
479  source.value.utype = utype_by_number(value);
480  if (source.value.utype != nullptr) {
481  return source;
482  }
483  break;
484  case VUT_UTFLAG:
485  source.value.unitflag = value;
486  return source;
487  case VUT_UCLASS:
488  source.value.uclass = uclass_by_number(value);
489  if (source.value.uclass != nullptr) {
490  return source;
491  }
492  break;
493  case VUT_UCFLAG:
494  source.value.unitclassflag = value;
495  if (source.value.unitclassflag) {
496  return source;
497  }
498  break;
499  case VUT_MINVETERAN:
500  source.value.minveteran = value;
501  if (source.value.minveteran > 0) {
502  return source;
503  }
504  break;
505  case VUT_UNITSTATE:
506  source.value.unit_state = ustate_prop(value);
507  if (ustate_prop_is_valid(source.value.unit_state)) {
508  return source;
509  }
510  break;
511  case VUT_ACTIVITY:
512  source.value.activity = unit_activity(value);
513  if (unit_activity_is_valid(source.value.activity)) {
514  return source;
515  }
516  break;
517  case VUT_MINMOVES:
518  source.value.minmoves = value;
519  if (source.value.minmoves > 0) {
520  return source;
521  }
522  break;
523  case VUT_MINHP:
524  source.value.min_hit_points = value;
525  if (source.value.min_hit_points > 0) {
526  return source;
527  }
528  break;
529  case VUT_AGE:
530  source.value.age = value;
531  if (source.value.age > 0) {
532  return source;
533  }
534  break;
535  case VUT_MINTECHS:
536  source.value.min_techs = value;
537  if (source.value.min_techs > 0) {
538  return source;
539  }
540  break;
541  case VUT_ACTION:
542  source.value.action = action_by_number(value);
543  if (source.value.action != nullptr) {
544  return source;
545  }
546  break;
547  case VUT_OTYPE:
548  source.value.outputtype = output_type_id(value);
549  if (source.value.outputtype != O_LAST) {
550  return source;
551  }
552  break;
553  case VUT_SPECIALIST:
554  source.value.specialist = specialist_by_number(value);
555  if (source.value.specialist) {
556  return source;
557  }
558  break;
559  case VUT_MINSIZE:
560  source.value.minsize = value;
561  if (source.value.minsize > 0) {
562  return source;
563  }
564  break;
565  case VUT_MINCULTURE:
566  source.value.minculture = value;
567  if (source.value.minculture > 0) {
568  return source;
569  }
570  break;
571  case VUT_MINFOREIGNPCT:
572  source.value.minforeignpct = value;
573  if (source.value.minforeignpct > 0) {
574  return source;
575  }
576  break;
577  case VUT_AI_LEVEL:
578  source.value.ai_level = ai_level(value);
579  if (ai_level_is_valid(source.value.ai_level)) {
580  return source;
581  }
582  break;
583  case VUT_MAXTILEUNITS:
584  source.value.max_tile_units = value;
585  if (0 <= source.value.max_tile_units) {
586  return source;
587  }
588  break;
589  case VUT_TERRAINCLASS:
590  source.value.terrainclass = value;
591  if (terrain_class_is_valid(terrain_class(source.value.terrainclass))) {
592  return source;
593  }
594  break;
595  case VUT_BASEFLAG:
596  source.value.baseflag = value;
597  if (base_flag_id_is_valid(base_flag_id(source.value.baseflag))) {
598  return source;
599  }
600  break;
601  case VUT_ROADFLAG:
602  source.value.roadflag = value;
603  if (road_flag_id_is_valid(road_flag_id(source.value.roadflag))) {
604  return source;
605  }
606  break;
607  case VUT_EXTRAFLAG:
608  source.value.extraflag = value;
609  if (extra_flag_id_is_valid(extra_flag_id(source.value.extraflag))) {
610  return source;
611  }
612  break;
613  case VUT_MINYEAR:
614  source.value.minyear = value;
615  return source;
616  case VUT_MINCALFRAG:
617  source.value.mincalfrag = value;
618  if (source.value.mincalfrag >= 0) {
619  return source;
620  }
621  break;
622  case VUT_TOPO:
623  source.value.topo_property = topo_flag(value);
624  if (topo_flag_is_valid(source.value.topo_property)) {
625  return source;
626  }
627  break;
628  case VUT_SERVERSETTING:
629  source.value.ssetval = value;
630  if (source.value.ssetval != SSETV_NONE) {
631  return source;
632  }
633  break;
634  case VUT_TERRAINALTER:
635  source.value.terrainalter = value;
636  if (terrain_alteration_is_valid(
637  static_cast<terrain_alteration>(source.value.terrainalter))) {
638  return source;
639  }
640  break;
641  case VUT_CITYTILE:
642  source.value.citytile = citytile_type(value);
643  if (citytile_type_is_valid(source.value.citytile)) {
644  return source;
645  }
646  break;
647  case VUT_CITYSTATUS:
648  source.value.citystatus = citystatus_type(value);
649  if (citystatus_type_is_valid(source.value.citystatus)) {
650  return source;
651  }
652  break;
653  case VUT_VISIONLAYER:
654  source.value.vlayer = vision_layer(value);
655  if (vision_layer_is_valid(source.value.vlayer)) {
656  return source;
657  }
658  break;
659  case VUT_NINTEL:
660  source.value.nintel = static_cast<national_intelligence>(value);
661  if (national_intelligence_is_valid(source.value.nintel)) {
662  return source;
663  }
664  break;
665  case VUT_COUNT:
666  break;
667  }
668 
669  // If we reach here there's been an error.
670  source.kind = universals_n_invalid();
671  // Avoid compiler warning about unitialized source.value
672  source.value.advance = nullptr;
673 
674  return source;
675 }
676 
681 void universal_extraction(const struct universal *source, int *kind,
682  int *value)
683 {
684  *kind = source->kind;
685  *value = universal_number(source);
686 }
687 
691 int universal_number(const struct universal *source)
692 {
693  switch (source->kind) {
694  case VUT_NONE:
695  return 0;
696  case VUT_ADVANCE:
697  return advance_number(source->value.advance);
698  case VUT_TECHFLAG:
699  return source->value.techflag;
700  case VUT_GOVERNMENT:
701  return government_number(source->value.govern);
702  case VUT_ACHIEVEMENT:
703  return achievement_number(source->value.achievement);
704  case VUT_STYLE:
705  return style_number(source->value.style);
706  case VUT_IMPROVEMENT:
707  return improvement_number(source->value.building);
708  case VUT_IMPR_GENUS:
709  return source->value.impr_genus;
710  case VUT_EXTRA:
711  return extra_number(source->value.extra);
712  case VUT_GOOD:
713  return goods_number(source->value.good);
714  case VUT_TERRAIN:
715  return terrain_number(source->value.terrain);
716  case VUT_TERRFLAG:
717  return source->value.terrainflag;
718  case VUT_NATION:
719  return nation_index(source->value.nation);
720  case VUT_NATIONGROUP:
721  return nation_group_number(source->value.nationgroup);
722  case VUT_NATIONALITY:
723  return nation_index(source->value.nationality);
724  case VUT_DIPLREL:
725  return source->value.diplrel;
726  case VUT_UTYPE:
727  return utype_number(source->value.utype);
728  case VUT_UTFLAG:
729  return source->value.unitflag;
730  case VUT_UCLASS:
731  return uclass_number(source->value.uclass);
732  case VUT_UCFLAG:
733  return source->value.unitclassflag;
734  case VUT_MINVETERAN:
735  return source->value.minveteran;
736  case VUT_UNITSTATE:
737  return source->value.unit_state;
738  case VUT_ACTIVITY:
739  return source->value.activity;
740  case VUT_MINMOVES:
741  return source->value.minmoves;
742  case VUT_MINHP:
743  return source->value.min_hit_points;
744  case VUT_AGE:
745  return source->value.age;
746  case VUT_MINTECHS:
747  return source->value.min_techs;
748  case VUT_ACTION:
749  return action_number(source->value.action);
750  case VUT_OTYPE:
751  return source->value.outputtype;
752  case VUT_SPECIALIST:
753  return specialist_number(source->value.specialist);
754  case VUT_MINSIZE:
755  return source->value.minsize;
756  case VUT_MINCULTURE:
757  return source->value.minculture;
758  case VUT_MINFOREIGNPCT:
759  return source->value.minforeignpct;
760  case VUT_AI_LEVEL:
761  return source->value.ai_level;
762  case VUT_MAXTILEUNITS:
763  return source->value.max_tile_units;
764  case VUT_TERRAINCLASS:
765  return source->value.terrainclass;
766  case VUT_BASEFLAG:
767  return source->value.baseflag;
768  case VUT_ROADFLAG:
769  return source->value.roadflag;
770  case VUT_EXTRAFLAG:
771  return source->value.extraflag;
772  case VUT_MINYEAR:
773  return source->value.minyear;
774  case VUT_MINCALFRAG:
775  return source->value.mincalfrag;
776  case VUT_TOPO:
777  return source->value.topo_property;
778  case VUT_SERVERSETTING:
779  return source->value.ssetval;
780  case VUT_TERRAINALTER:
781  return source->value.terrainalter;
782  case VUT_CITYTILE:
783  return source->value.citytile;
784  case VUT_CITYSTATUS:
785  return source->value.citystatus;
786  case VUT_VISIONLAYER:
787  return source->value.vlayer;
788  case VUT_NINTEL:
789  return source->value.nintel;
790  case VUT_COUNT:
791  break;
792  }
793 
794  // If we reach here there's been an error.
795  fc_assert_msg(false, "universal_number(): invalid source kind %d.",
796  source->kind);
797  return 0;
798 }
799 
804 QString req_to_fstring(const struct requirement *req)
805 {
806  QString printable_req =
807  QStringLiteral("%1%2 %3 %4%5")
808  .arg(req->survives ? "surviving " : "", req_range_name(req->range),
810  req->present ? "" : "!", universal_rule_name(&req->source));
811 
812  return printable_req;
813 }
814 
822 struct requirement req_from_str(const char *type, const char *range,
823  bool survives, bool present, bool quiet,
824  const char *value)
825 {
826  struct requirement req;
827  bool invalid;
828  const char *error = nullptr;
829 
830  req.source = universal_by_rule_name(type, value);
831 
832  invalid = !universals_n_is_valid(req.source.kind);
833  if (invalid) {
834  error = "bad type or name";
835  } else {
836  /* Scan the range string to find the range. If no range is given a
837  * default fallback is used rather than giving an error. */
838  req.range = req_range_by_name(range, fc_strcasecmp);
839  if (!req_range_is_valid(req.range)) {
840  switch (req.source.kind) {
841  case VUT_NONE:
842  case VUT_COUNT:
843  break;
844  case VUT_IMPROVEMENT:
845  case VUT_IMPR_GENUS:
846  case VUT_EXTRA:
847  case VUT_GOOD:
848  case VUT_TERRAIN:
849  case VUT_TERRFLAG:
850  case VUT_UTYPE:
851  case VUT_UTFLAG:
852  case VUT_UCLASS:
853  case VUT_UCFLAG:
854  case VUT_MINVETERAN:
855  case VUT_UNITSTATE:
856  case VUT_ACTIVITY:
857  case VUT_MINMOVES:
858  case VUT_MINHP:
859  case VUT_AGE:
860  case VUT_ACTION:
861  case VUT_OTYPE:
862  case VUT_SPECIALIST:
863  case VUT_TERRAINCLASS:
864  case VUT_BASEFLAG:
865  case VUT_ROADFLAG:
866  case VUT_EXTRAFLAG:
867  case VUT_TERRAINALTER:
868  case VUT_CITYTILE:
869  case VUT_MAXTILEUNITS:
870  case VUT_VISIONLAYER:
871  req.range = REQ_RANGE_LOCAL;
872  break;
873  case VUT_MINSIZE:
874  case VUT_MINCULTURE:
875  case VUT_MINFOREIGNPCT:
876  case VUT_NATIONALITY:
877  case VUT_CITYSTATUS:
878  req.range = REQ_RANGE_CITY;
879  break;
880  case VUT_GOVERNMENT:
881  case VUT_ACHIEVEMENT:
882  case VUT_STYLE:
883  case VUT_ADVANCE:
884  case VUT_TECHFLAG:
885  case VUT_NATION:
886  case VUT_NATIONGROUP:
887  case VUT_DIPLREL:
888  case VUT_AI_LEVEL:
889  case VUT_NINTEL:
890  req.range = REQ_RANGE_PLAYER;
891  break;
892  case VUT_MINYEAR:
893  case VUT_MINCALFRAG:
894  case VUT_TOPO:
895  case VUT_MINTECHS:
896  case VUT_SERVERSETTING:
897  req.range = REQ_RANGE_WORLD;
898  break;
899  }
900  }
901 
902  req.survives = survives;
903  req.present = present;
904  req.quiet = quiet;
905 
906  /* These checks match what combinations are supported inside
907  * is_req_active(). However, it's only possible to do basic checks,
908  * not anything that might depend on the rest of the ruleset which
909  * might not have been loaded yet. */
910  switch (req.source.kind) {
911  case VUT_TERRAIN:
912  case VUT_EXTRA:
913  case VUT_TERRAINCLASS:
914  case VUT_TERRFLAG:
915  case VUT_BASEFLAG:
916  case VUT_ROADFLAG:
917  case VUT_EXTRAFLAG:
918  invalid =
919  (req.range != REQ_RANGE_LOCAL && req.range != REQ_RANGE_CADJACENT
920  && req.range != REQ_RANGE_ADJACENT && req.range != REQ_RANGE_CITY
921  && req.range != REQ_RANGE_TRADEROUTE);
922  break;
923  case VUT_ADVANCE:
924  case VUT_TECHFLAG:
925  case VUT_ACHIEVEMENT:
926  case VUT_MINTECHS:
927  invalid = (req.range < REQ_RANGE_PLAYER);
928  break;
929  case VUT_GOVERNMENT:
930  case VUT_AI_LEVEL:
931  case VUT_STYLE:
932  case VUT_NINTEL:
933  invalid = (req.range != REQ_RANGE_PLAYER);
934  break;
935  case VUT_MINSIZE:
936  case VUT_MINFOREIGNPCT:
937  case VUT_NATIONALITY:
938  case VUT_GOOD:
939  case VUT_CITYSTATUS:
940  invalid =
941  (req.range != REQ_RANGE_CITY && req.range != REQ_RANGE_TRADEROUTE);
942  break;
943  case VUT_MINCULTURE:
944  invalid =
945  (req.range != REQ_RANGE_CITY && req.range != REQ_RANGE_TRADEROUTE
946  && req.range != REQ_RANGE_PLAYER && req.range != REQ_RANGE_TEAM
947  && req.range != REQ_RANGE_ALLIANCE
948  && req.range != REQ_RANGE_WORLD);
949  break;
950  case VUT_DIPLREL:
951  invalid =
952  (req.range != REQ_RANGE_LOCAL && req.range != REQ_RANGE_PLAYER
953  && req.range != REQ_RANGE_TEAM && req.range != REQ_RANGE_ALLIANCE
954  && req.range != REQ_RANGE_WORLD)
955  // Non local foreign makes no sense.
956  || (req.source.value.diplrel == DRO_FOREIGN
957  && req.range != REQ_RANGE_LOCAL);
958  break;
959  case VUT_NATION:
960  case VUT_NATIONGROUP:
961  invalid = (req.range != REQ_RANGE_PLAYER && req.range != REQ_RANGE_TEAM
962  && req.range != REQ_RANGE_ALLIANCE
963  && req.range != REQ_RANGE_WORLD);
964  break;
965  case VUT_UTYPE:
966  case VUT_UTFLAG:
967  case VUT_UCLASS:
968  case VUT_UCFLAG:
969  case VUT_MINVETERAN:
970  case VUT_UNITSTATE:
971  case VUT_ACTIVITY:
972  case VUT_MINMOVES:
973  case VUT_MINHP:
974  case VUT_ACTION:
975  case VUT_OTYPE:
976  case VUT_SPECIALIST:
977  case VUT_TERRAINALTER: /* XXX could in principle support C/ADJACENT */
978  case VUT_VISIONLAYER:
979  invalid = (req.range != REQ_RANGE_LOCAL);
980  break;
981  case VUT_CITYTILE:
982  case VUT_MAXTILEUNITS:
983  invalid =
984  (req.range != REQ_RANGE_LOCAL && req.range != REQ_RANGE_CADJACENT
985  && req.range != REQ_RANGE_ADJACENT);
986  break;
987  case VUT_MINYEAR:
988  case VUT_MINCALFRAG:
989  case VUT_TOPO:
990  case VUT_SERVERSETTING:
991  invalid = (req.range != REQ_RANGE_WORLD);
992  break;
993  case VUT_AGE:
994  // FIXME: could support TRADEROUTE, TEAM, etc
995  invalid = (req.range != REQ_RANGE_LOCAL && req.range != REQ_RANGE_CITY
996  && req.range != REQ_RANGE_PLAYER);
997  break;
998  case VUT_IMPR_GENUS:
999  // TODO: Support other ranges too.
1000  invalid = req.range != REQ_RANGE_LOCAL;
1001  break;
1002  case VUT_IMPROVEMENT:
1003  /* Valid ranges depend on the building genus (wonder/improvement),
1004  * which might not have been loaded from the ruleset yet.
1005  * So we allow anything here, and do a proper check once ruleset
1006  * loading is complete, in sanity_check_req_individual(). */
1007  case VUT_NONE:
1008  invalid = false;
1009  break;
1010  case VUT_COUNT:
1011  break;
1012  }
1013  if (invalid) {
1014  error = "bad range";
1015  }
1016  }
1017 
1018  if (!invalid) {
1019  // Check 'survives'.
1020  switch (req.source.kind) {
1021  case VUT_IMPROVEMENT:
1022  // See buildings_in_range().
1023  invalid = survives && req.range <= REQ_RANGE_CONTINENT;
1024  break;
1025  case VUT_NATION:
1026  case VUT_ADVANCE:
1027  invalid = survives && req.range != REQ_RANGE_WORLD;
1028  break;
1029  case VUT_IMPR_GENUS:
1030  case VUT_GOVERNMENT:
1031  case VUT_TERRAIN:
1032  case VUT_UTYPE:
1033  case VUT_UTFLAG:
1034  case VUT_UCLASS:
1035  case VUT_UCFLAG:
1036  case VUT_MINVETERAN:
1037  case VUT_UNITSTATE:
1038  case VUT_ACTIVITY:
1039  case VUT_MINMOVES:
1040  case VUT_MINHP:
1041  case VUT_AGE:
1042  case VUT_ACTION:
1043  case VUT_OTYPE:
1044  case VUT_SPECIALIST:
1045  case VUT_MINSIZE:
1046  case VUT_MINCULTURE:
1047  case VUT_MINFOREIGNPCT:
1048  case VUT_AI_LEVEL:
1049  case VUT_TERRAINCLASS:
1050  case VUT_MINYEAR:
1051  case VUT_MINCALFRAG:
1052  case VUT_TOPO:
1053  case VUT_SERVERSETTING:
1054  case VUT_TERRAINALTER:
1055  case VUT_CITYTILE:
1056  case VUT_CITYSTATUS:
1057  case VUT_TERRFLAG:
1058  case VUT_NATIONALITY:
1059  case VUT_BASEFLAG:
1060  case VUT_ROADFLAG:
1061  case VUT_EXTRAFLAG:
1062  case VUT_EXTRA:
1063  case VUT_GOOD:
1064  case VUT_TECHFLAG:
1065  case VUT_ACHIEVEMENT:
1066  case VUT_NATIONGROUP:
1067  case VUT_STYLE:
1068  case VUT_DIPLREL:
1069  case VUT_MAXTILEUNITS:
1070  case VUT_MINTECHS:
1071  case VUT_VISIONLAYER:
1072  case VUT_NINTEL:
1073  // Most requirements don't support 'survives'.
1074  invalid = survives;
1075  break;
1076  case VUT_NONE:
1077  case VUT_COUNT:
1078  break;
1079  }
1080  if (invalid) {
1081  error = "bad 'survives'";
1082  }
1083  }
1084 
1085  if (invalid) {
1086  qCritical("Invalid requirement %s | %s | %s | %s | %s: %s", type, range,
1087  survives ? "survives" : "", present ? "present" : "", value,
1088  error);
1089  req.source.kind = universals_n_invalid();
1090  }
1091 
1092  return req;
1093 }
1094 
1099 struct requirement req_from_values(int type, int range, bool survives,
1100  bool present, bool quiet, int value)
1101 {
1102  struct requirement req;
1103 
1104  req.source = universal_by_number(universals_n(type), value);
1105  req.range = req_range(range);
1106  req.survives = survives;
1107  req.present = present;
1108  req.quiet = quiet;
1109 
1110  return req;
1111 }
1112 
1117 void req_get_values(const struct requirement *req, int *type, int *range,
1118  bool *survives, bool *present, bool *quiet, int *value)
1119 {
1120  universal_extraction(&req->source, type, value);
1121  *range = req->range;
1122  *survives = req->survives;
1123  *present = req->present;
1124  *quiet = req->quiet;
1125 }
1126 
1131 bool are_requirements_equal(const struct requirement *req1,
1132  const struct requirement *req2)
1133 {
1134  return (are_universals_equal(&req1->source, &req2->source)
1135  && req1->range == req2->range && req1->survives == req2->survives
1136  && req1->present == req2->present);
1137 }
1138 
1142 static bool are_requirements_opposites(const struct requirement *req1,
1143  const struct requirement *req2)
1144 {
1145  return (are_universals_equal(&req1->source, &req2->source)
1146  && req1->range == req2->range && req1->survives == req2->survives
1147  && req1->present != req2->present);
1148 }
1149 
1154 static bool impr_contra_genus(const struct requirement *impr_req,
1155  const struct requirement *genus_req)
1156 {
1157  // The input is sane.
1158  fc_assert_ret_val(impr_req->source.kind == VUT_IMPROVEMENT, false);
1159  fc_assert_ret_val(genus_req->source.kind == VUT_IMPR_GENUS, false);
1160 
1161  if (impr_req->range == REQ_RANGE_LOCAL
1162  && genus_req->range == REQ_RANGE_LOCAL) {
1163  // Applies to the same target building.
1164 
1165  if (impr_req->present && !genus_req->present) {
1166  // The target building can't not have the genus it has.
1167  return (impr_req->source.value.building->genus
1168  == genus_req->source.value.impr_genus);
1169  }
1170 
1171  if (impr_req->present && genus_req->present) {
1172  // The target building can't have another genus than it has.
1173  return (impr_req->source.value.building->genus
1174  != genus_req->source.value.impr_genus);
1175  }
1176  }
1177 
1178  // No special knowledge.
1179  return false;
1180 }
1181 
1186 static bool nation_contra_group(const struct requirement *nation_req,
1187  const struct requirement *group_req)
1188 {
1189  // The input is sane.
1190  fc_assert_ret_val(nation_req->source.kind == VUT_NATION, false);
1191  fc_assert_ret_val(group_req->source.kind == VUT_NATIONGROUP, false);
1192 
1193  if (nation_req->range == REQ_RANGE_PLAYER
1194  && group_req->range == REQ_RANGE_PLAYER) {
1195  // Applies to the same target building.
1196 
1197  if (nation_req->present && !group_req->present) {
1198  // The target nation can't be in the group.
1199  return nation_is_in_group(nation_req->source.value.nation,
1200  group_req->source.value.nationgroup);
1201  }
1202  }
1203 
1204  // No special knowledge.
1205  return false;
1206 }
1207 
1216  const struct requirement *req2)
1217 {
1218  if (are_requirements_opposites(req1, req2)) {
1219  // The exact opposite.
1220  return true;
1221  }
1222 
1223  switch (req1->source.kind) {
1224  case VUT_IMPROVEMENT:
1225  if (req2->source.kind == VUT_IMPR_GENUS) {
1226  return impr_contra_genus(req1, req2);
1227  }
1228 
1229  // No special knowledge.
1230  return false;
1231  break;
1232  case VUT_IMPR_GENUS:
1233  if (req2->source.kind == VUT_IMPROVEMENT) {
1234  return impr_contra_genus(req2, req1);
1235  }
1236 
1237  // No special knowledge.
1238  return false;
1239  break;
1240  case VUT_DIPLREL:
1241  if (req2->source.kind != VUT_DIPLREL) {
1242  /* Finding contradictions across requirement kinds aren't supported
1243  * for DiplRel requirements. */
1244  return false;
1245  } else {
1246  /* Use the special knowledge about DiplRel requirements to find
1247  * contradictions. */
1248 
1249  bv_diplrel_all_reqs req1_contra;
1250  int req2_pos;
1251 
1252  req1_contra = diplrel_req_contradicts(req1);
1253  req2_pos = requirement_diplrel_ereq(req2->source.value.diplrel,
1254  req2->range, req2->present);
1255 
1256  return BV_ISSET(req1_contra, req2_pos);
1257  }
1258  break;
1259  case VUT_MINMOVES:
1260  if (req2->source.kind != VUT_MINMOVES) {
1261  /* Finding contradictions across requirement kinds aren't supported
1262  * for MinMoveFrags requirements. */
1263  return false;
1264  } else if (req1->present == req2->present) {
1265  // No contradiction possible.
1266  return false;
1267  } else {
1268  /* Number of move fragments left can't be larger than the number
1269  * required to be present and smaller than the number required to not
1270  * be present when the number required to be present is smaller than
1271  * the number required to not be present. */
1272  if (req1->present) {
1273  return req1->source.value.minmoves >= req2->source.value.minmoves;
1274  } else {
1275  return req1->source.value.minmoves <= req2->source.value.minmoves;
1276  }
1277  }
1278  break;
1279  case VUT_NATION:
1280  if (req2->source.kind == VUT_NATIONGROUP) {
1281  return nation_contra_group(req1, req2);
1282  }
1283 
1284  // No special knowledge.
1285  return false;
1286  break;
1287  case VUT_NATIONGROUP:
1288  if (req2->source.kind == VUT_NATION) {
1289  return nation_contra_group(req2, req1);
1290  }
1291 
1292  // No special knowledge.
1293  return false;
1294  break;
1295  default:
1296  /* No special knowledge exists. The requirements aren't the exact
1297  * opposite of each other per the initial check. */
1298  return false;
1299  break;
1300  }
1301 }
1302 
1308  const struct requirement_vector *vec)
1309 {
1310  /* If the requirement is contradicted by any requirement in the vector it
1311  * contradicts the entire requirement vector. */
1312  requirement_vector_iterate(vec, preq)
1313  {
1314  if (are_requirements_contradictions(req, preq)) {
1315  return true;
1316  }
1317  }
1319 
1320  /* Not a singe requirement in the requirement vector is contradicted be
1321  * the specified requirement. */
1322  return false;
1323 }
1324 
1328 static inline bool players_in_same_range(const struct player *pplayer1,
1329  const struct player *pplayer2,
1330  enum req_range range)
1331 {
1332  switch (range) {
1333  case REQ_RANGE_WORLD:
1334  return true;
1335  case REQ_RANGE_ALLIANCE:
1336  return pplayers_allied(pplayer1, pplayer2);
1337  case REQ_RANGE_TEAM:
1338  return players_on_same_team(pplayer1, pplayer2);
1339  case REQ_RANGE_PLAYER:
1340  return pplayer1 == pplayer2;
1341  case REQ_RANGE_CONTINENT:
1342  case REQ_RANGE_TRADEROUTE:
1343  case REQ_RANGE_CITY:
1344  case REQ_RANGE_ADJACENT:
1345  case REQ_RANGE_CADJACENT:
1346  case REQ_RANGE_LOCAL:
1347  case REQ_RANGE_COUNT:
1348  break;
1349  }
1350 
1351  fc_assert_msg(false, "Invalid range %d.", range);
1352  return false;
1353 }
1354 
1359 static int num_world_buildings_total(const struct impr_type *building)
1360 {
1361  if (is_great_wonder(building)) {
1362  return (great_wonder_is_built(building)
1363  || great_wonder_is_destroyed(building)
1364  ? 1
1365  : 0);
1366  } else {
1367  qCritical("World-ranged requirements are only supported for wonders.");
1368  return 0;
1369  }
1370 }
1371 
1375 static int num_world_buildings(const struct impr_type *building)
1376 {
1377  if (is_great_wonder(building)) {
1378  return (great_wonder_is_built(building) ? 1 : 0);
1379  } else {
1380  qCritical("World-ranged requirements are only supported for wonders.");
1381  return 0;
1382  }
1383 }
1384 
1396 static bool player_has_ever_built(const struct player *pplayer,
1397  const struct impr_type *building)
1398 {
1399  if (is_wonder(building)) {
1400  return (wonder_is_built(pplayer, building)
1401  || wonder_is_lost(pplayer, building));
1402  } else {
1403  qCritical("Player-ranged requirements are only supported for wonders.");
1404  return false;
1405  }
1406 }
1407 
1411 static int num_player_buildings(const struct player *pplayer,
1412  const struct impr_type *building)
1413 {
1414  if (is_wonder(building)) {
1415  return (wonder_is_built(pplayer, building) ? 1 : 0);
1416  } else {
1417  qCritical("Player-ranged requirements are only supported for wonders.");
1418  return 0;
1419  }
1420 }
1421 
1425 static int num_continent_buildings(const struct player *pplayer,
1426  int continent,
1427  const struct impr_type *building)
1428 {
1429  if (is_wonder(building)) {
1430  const struct city *pcity;
1431 
1432  pcity = city_from_wonder(pplayer, building);
1433  if (pcity && pcity->tile && tile_continent(pcity->tile) == continent) {
1434  return 1;
1435  }
1436  } else {
1437  qCritical("Island-ranged requirements are only supported for wonders.");
1438  }
1439  return 0;
1440 }
1441 
1445 static int num_city_buildings(const struct city *pcity,
1446  const struct impr_type *building)
1447 {
1448  return (city_has_building(pcity, building) ? 1 : 0);
1449 }
1450 
1466 static enum fc_tristate is_building_in_range(
1467  const struct player *target_player, const struct city *target_city,
1468  const struct impr_type *target_building, enum req_range range,
1469  bool survives, const struct impr_type *source)
1470 {
1471  /* Check if it's certain that the building is obsolete given the
1472  * specification we have */
1473  if (improvement_obsolete(target_player, source, target_city)) {
1474  return TRI_NO;
1475  }
1476 
1477  if (survives) {
1478  // Check whether condition has ever held, using cached information.
1479  switch (range) {
1480  case REQ_RANGE_WORLD:
1481  return BOOL_TO_TRISTATE(num_world_buildings_total(source) > 0);
1482  case REQ_RANGE_ALLIANCE:
1483  case REQ_RANGE_TEAM:
1484  if (target_player == nullptr) {
1485  return TRI_MAYBE;
1486  }
1487  players_iterate_alive(plr2)
1488  {
1489  if (players_in_same_range(target_player, plr2, range)
1490  && player_has_ever_built(plr2, source)) {
1491  return TRI_YES;
1492  }
1493  }
1495  return TRI_NO;
1496  case REQ_RANGE_PLAYER:
1497  if (target_player == nullptr) {
1498  return TRI_MAYBE;
1499  }
1500  return BOOL_TO_TRISTATE(player_has_ever_built(target_player, source));
1501  case REQ_RANGE_CONTINENT:
1502  case REQ_RANGE_TRADEROUTE:
1503  case REQ_RANGE_CITY:
1504  case REQ_RANGE_LOCAL:
1505  case REQ_RANGE_CADJACENT:
1506  case REQ_RANGE_ADJACENT:
1507  // There is no sources cache for this.
1508  qCritical("Surviving requirements are only supported at "
1509  "World/Alliance/Team/Player ranges.");
1510  return TRI_NO;
1511  case REQ_RANGE_COUNT:
1512  break;
1513  }
1514 
1515  } else {
1516  // Non-surviving requirement.
1517  switch (range) {
1518  case REQ_RANGE_WORLD:
1519  return BOOL_TO_TRISTATE(num_world_buildings(source) > 0);
1520  case REQ_RANGE_ALLIANCE:
1521  case REQ_RANGE_TEAM:
1522  if (target_player == nullptr) {
1523  return TRI_MAYBE;
1524  }
1525  players_iterate_alive(plr2)
1526  {
1527  if (players_in_same_range(target_player, plr2, range)
1528  && num_player_buildings(plr2, source) > 0) {
1529  return TRI_YES;
1530  }
1531  }
1533  return TRI_NO;
1534  case REQ_RANGE_PLAYER:
1535  if (target_player == nullptr) {
1536  return TRI_MAYBE;
1537  }
1538  return BOOL_TO_TRISTATE(num_player_buildings(target_player, source)
1539  > 0);
1540  case REQ_RANGE_CONTINENT:
1541  /* At present, "Continent" effects can affect only
1542  * cities and units in cities. */
1543  if (target_player && target_city) {
1544  int continent = tile_continent(target_city->tile);
1545  return BOOL_TO_TRISTATE(
1546  num_continent_buildings(target_player, continent, source) > 0);
1547  } else {
1548  return TRI_MAYBE;
1549  }
1550  case REQ_RANGE_TRADEROUTE:
1551  if (target_city) {
1552  if (num_city_buildings(target_city, source) > 0) {
1553  return TRI_YES;
1554  } else {
1555  trade_partners_iterate(target_city, trade_partner)
1556  {
1557  if (num_city_buildings(trade_partner, source) > 0) {
1558  return TRI_YES;
1559  }
1560  }
1562  }
1563  return TRI_NO;
1564  } else {
1565  return TRI_MAYBE;
1566  }
1567  case REQ_RANGE_CITY:
1568  if (target_city) {
1569  return BOOL_TO_TRISTATE(num_city_buildings(target_city, source) > 0);
1570  } else {
1571  return TRI_MAYBE;
1572  }
1573  case REQ_RANGE_LOCAL:
1574  if (target_building) {
1575  if (target_building == source) {
1576  return TRI_YES;
1577  } else {
1578  return TRI_NO;
1579  }
1580  } else {
1581  // TODO: other local targets
1582  return TRI_MAYBE;
1583  }
1584  case REQ_RANGE_CADJACENT:
1585  case REQ_RANGE_ADJACENT:
1586  return TRI_NO;
1587  case REQ_RANGE_COUNT:
1588  break;
1589  }
1590  }
1591 
1592  fc_assert_msg(false, "Invalid range %d.", range);
1593  return TRI_NO;
1594 }
1595 
1599 static enum fc_tristate is_tech_in_range(const struct player *target_player,
1600  enum req_range range, bool survives,
1601  Tech_type_id tech)
1602 {
1603  if (survives) {
1604  fc_assert(range == REQ_RANGE_WORLD);
1605  return BOOL_TO_TRISTATE(game.info.global_advances[tech]);
1606  }
1607 
1608  // Not a 'surviving' requirement.
1609  switch (range) {
1610  case REQ_RANGE_PLAYER:
1611  if (nullptr != target_player) {
1612  return BOOL_TO_TRISTATE(
1613  TECH_KNOWN
1614  == research_invention_state(research_get(target_player), tech));
1615  } else {
1616  return TRI_MAYBE;
1617  }
1618  case REQ_RANGE_TEAM:
1619  case REQ_RANGE_ALLIANCE:
1620  case REQ_RANGE_WORLD:
1621  if (nullptr == target_player) {
1622  return TRI_MAYBE;
1623  }
1624  players_iterate_alive(plr2)
1625  {
1626  if (players_in_same_range(target_player, plr2, range)) {
1627  if (research_invention_state(research_get(plr2), tech)
1628  == TECH_KNOWN) {
1629  return TRI_YES;
1630  }
1631  }
1632  }
1634 
1635  return TRI_NO;
1636  case REQ_RANGE_LOCAL:
1637  case REQ_RANGE_CADJACENT:
1638  case REQ_RANGE_ADJACENT:
1639  case REQ_RANGE_CITY:
1640  case REQ_RANGE_TRADEROUTE:
1641  case REQ_RANGE_CONTINENT:
1642  case REQ_RANGE_COUNT:
1643  break;
1644  }
1645 
1646  fc_assert_msg(false, "Invalid range %d.", range);
1647 
1648  return TRI_MAYBE;
1649 }
1650 
1654 static enum fc_tristate
1655 is_techflag_in_range(const struct player *target_player,
1656  enum req_range range, enum tech_flag_id techflag)
1657 {
1658  switch (range) {
1659  case REQ_RANGE_PLAYER:
1660  if (nullptr != target_player) {
1661  return BOOL_TO_TRISTATE(
1662  player_knows_techs_with_flag(target_player, techflag));
1663  } else {
1664  return TRI_MAYBE;
1665  }
1666  break;
1667  case REQ_RANGE_TEAM:
1668  case REQ_RANGE_ALLIANCE:
1669  if (nullptr == target_player) {
1670  return TRI_MAYBE;
1671  }
1672  players_iterate_alive(plr2)
1673  {
1674  if (players_in_same_range(target_player, plr2, range)
1675  && player_knows_techs_with_flag(plr2, techflag)) {
1676  return TRI_YES;
1677  }
1678  }
1680  return TRI_NO;
1681  case REQ_RANGE_WORLD:
1682  players_iterate(pplayer)
1683  {
1684  if (player_knows_techs_with_flag(pplayer, techflag)) {
1685  return TRI_YES;
1686  }
1687  }
1689 
1690  return TRI_NO;
1691  case REQ_RANGE_LOCAL:
1692  case REQ_RANGE_CADJACENT:
1693  case REQ_RANGE_ADJACENT:
1694  case REQ_RANGE_CITY:
1695  case REQ_RANGE_TRADEROUTE:
1696  case REQ_RANGE_CONTINENT:
1697  case REQ_RANGE_COUNT:
1698  break;
1699  }
1700 
1701  fc_assert_msg(false, "Invalid range %d.", range);
1702 
1703  return TRI_MAYBE;
1704 }
1705 
1709 static enum fc_tristate
1710 is_minculture_in_range(const struct city *target_city,
1711  const struct player *target_player,
1712  enum req_range range, int minculture)
1713 {
1714  switch (range) {
1715  case REQ_RANGE_CITY:
1716  if (!target_city) {
1717  return TRI_MAYBE;
1718  }
1719  return BOOL_TO_TRISTATE(city_culture(target_city) >= minculture);
1720  case REQ_RANGE_TRADEROUTE:
1721  if (!target_city) {
1722  return TRI_MAYBE;
1723  }
1724  if (city_culture(target_city) >= minculture) {
1725  return TRI_YES;
1726  } else {
1727  trade_partners_iterate(target_city, trade_partner)
1728  {
1729  if (city_culture(trade_partner) >= minculture) {
1730  return TRI_YES;
1731  }
1732  }
1734  return TRI_MAYBE;
1735  }
1736  case REQ_RANGE_PLAYER:
1737  case REQ_RANGE_TEAM:
1738  case REQ_RANGE_ALLIANCE:
1739  case REQ_RANGE_WORLD:
1740  if (nullptr == target_player) {
1741  return TRI_MAYBE;
1742  }
1743  players_iterate_alive(plr2)
1744  {
1745  if (players_in_same_range(target_player, plr2, range)) {
1746  if (player_culture(plr2) >= minculture) {
1747  return TRI_YES;
1748  }
1749  }
1750  }
1752  return TRI_NO;
1753  case REQ_RANGE_LOCAL:
1754  case REQ_RANGE_CADJACENT:
1755  case REQ_RANGE_ADJACENT:
1756  case REQ_RANGE_CONTINENT:
1757  case REQ_RANGE_COUNT:
1758  break;
1759  }
1760 
1761  fc_assert_msg(false, "Invalid range %d.", range);
1762 
1763  return TRI_MAYBE;
1764 }
1765 
1769 static enum fc_tristate
1770 is_minforeignpct_in_range(const struct city *target_city,
1771  enum req_range range, int min_foreign_pct)
1772 {
1773  fc_assert_ret_val(target_city != nullptr, TRI_NO);
1774 
1775  int foreign_pct;
1776 
1777  switch (range) {
1778  case REQ_RANGE_CITY:
1779  foreign_pct = citizens_nation_foreign(target_city) * 100
1780  / city_size_get(target_city);
1781  return BOOL_TO_TRISTATE(foreign_pct >= min_foreign_pct);
1782  case REQ_RANGE_TRADEROUTE:
1783  foreign_pct = citizens_nation_foreign(target_city) * 100
1784  / city_size_get(target_city);
1785  if (foreign_pct >= min_foreign_pct) {
1786  return TRI_YES;
1787  } else {
1788  trade_partners_iterate(target_city, trade_partner)
1789  {
1790  int notzero = city_size_get(trade_partner);
1791  fc_assert_ret_val(notzero, TRI_YES);
1792  foreign_pct = citizens_nation_foreign(trade_partner) * 100 / notzero;
1793  if (foreign_pct >= min_foreign_pct) {
1794  return TRI_YES;
1795  }
1796  }
1798  return TRI_MAYBE;
1799  }
1800  case REQ_RANGE_PLAYER:
1801  case REQ_RANGE_TEAM:
1802  case REQ_RANGE_ALLIANCE:
1803  case REQ_RANGE_WORLD:
1804  case REQ_RANGE_LOCAL:
1805  case REQ_RANGE_CADJACENT:
1806  case REQ_RANGE_ADJACENT:
1807  case REQ_RANGE_CONTINENT:
1808  case REQ_RANGE_COUNT:
1809  break;
1810  }
1811 
1812  fc_assert_msg(false, "Invalid range %d.", range);
1813 
1814  return TRI_MAYBE;
1815 }
1816 
1820 static enum fc_tristate
1821 is_tile_units_in_range(const struct tile *target_tile, enum req_range range,
1822  int max_units)
1823 {
1824  // TODO: if can't see V_INVIS -> TRI_MAYBE
1825  switch (range) {
1826  case REQ_RANGE_LOCAL:
1827  if (!target_tile) {
1828  return TRI_MAYBE;
1829  }
1830  return BOOL_TO_TRISTATE(unit_list_size(target_tile->units) <= max_units);
1831  case REQ_RANGE_CADJACENT:
1832  if (!target_tile) {
1833  return TRI_MAYBE;
1834  }
1835  if (unit_list_size(target_tile->units) <= max_units) {
1836  return TRI_YES;
1837  }
1838  cardinal_adjc_iterate(&(wld.map), target_tile, adjc_tile)
1839  {
1840  if (unit_list_size(adjc_tile->units) <= max_units) {
1841  return TRI_YES;
1842  }
1843  }
1845  return TRI_NO;
1846  case REQ_RANGE_ADJACENT:
1847  if (!target_tile) {
1848  return TRI_MAYBE;
1849  }
1850  if (unit_list_size(target_tile->units) <= max_units) {
1851  return TRI_YES;
1852  }
1853  adjc_iterate(&(wld.map), target_tile, adjc_tile)
1854  {
1855  if (unit_list_size(adjc_tile->units) <= max_units) {
1856  return TRI_YES;
1857  }
1858  }
1860  return TRI_NO;
1861  case REQ_RANGE_CITY:
1862  case REQ_RANGE_TRADEROUTE:
1863  case REQ_RANGE_CONTINENT:
1864  case REQ_RANGE_PLAYER:
1865  case REQ_RANGE_TEAM:
1866  case REQ_RANGE_ALLIANCE:
1867  case REQ_RANGE_WORLD:
1868  case REQ_RANGE_COUNT:
1869  break;
1870  }
1871 
1872  fc_assert_msg(false, "Invalid range %d.", range);
1873 
1874  return TRI_MAYBE;
1875 }
1876 
1880 static enum fc_tristate
1881 is_extra_type_in_range(const struct tile *target_tile,
1882  const struct city *target_city, enum req_range range,
1883  bool survives, struct extra_type *pextra)
1884 {
1885  Q_UNUSED(survives)
1886  switch (range) {
1887  case REQ_RANGE_LOCAL:
1888  // The requirement is filled if the tile has extra of requested type.
1889  if (!target_tile) {
1890  return TRI_MAYBE;
1891  }
1892  return BOOL_TO_TRISTATE(tile_has_extra(target_tile, pextra));
1893  case REQ_RANGE_CADJACENT:
1894  if (!target_tile) {
1895  return TRI_MAYBE;
1896  }
1897  return BOOL_TO_TRISTATE(tile_has_extra(target_tile, pextra)
1898  || is_extra_card_near(target_tile, pextra));
1899  case REQ_RANGE_ADJACENT:
1900  if (!target_tile) {
1901  return TRI_MAYBE;
1902  }
1903  return BOOL_TO_TRISTATE(tile_has_extra(target_tile, pextra)
1904  || is_extra_near_tile(target_tile, pextra));
1905  case REQ_RANGE_CITY:
1906  if (!target_city) {
1907  return TRI_MAYBE;
1908  }
1910  city_tile(target_city), ptile)
1911  {
1912  if (tile_has_extra(ptile, pextra)) {
1913  return TRI_YES;
1914  }
1915  }
1917 
1918  return TRI_NO;
1919 
1920  case REQ_RANGE_TRADEROUTE:
1921  if (!target_city) {
1922  return TRI_MAYBE;
1923  }
1925  city_tile(target_city), ptile)
1926  {
1927  if (tile_has_extra(ptile, pextra)) {
1928  return TRI_YES;
1929  }
1930  }
1932  trade_partners_iterate(target_city, trade_partner)
1933  {
1935  city_tile(trade_partner), ptile)
1936  {
1937  if (tile_has_extra(ptile, pextra)) {
1938  return TRI_YES;
1939  }
1940  }
1942  }
1944 
1945  return TRI_NO;
1946 
1947  case REQ_RANGE_CONTINENT:
1948  case REQ_RANGE_PLAYER:
1949  case REQ_RANGE_TEAM:
1950  case REQ_RANGE_ALLIANCE:
1951  case REQ_RANGE_WORLD:
1952  case REQ_RANGE_COUNT:
1953  break;
1954  }
1955 
1956  fc_assert_msg(false, "Invalid range %d.", range);
1957 
1958  return TRI_MAYBE;
1959 }
1960 
1964 static enum fc_tristate
1965 is_goods_type_in_range(const struct tile *target_tile,
1966  const struct city *target_city, enum req_range range,
1967  bool survives, struct goods_type *pgood)
1968 {
1969  Q_UNUSED(target_tile)
1970  Q_UNUSED(survives)
1971  switch (range) {
1972  case REQ_RANGE_LOCAL:
1973  case REQ_RANGE_CITY:
1974  // The requirement is filled if the tile has extra of requested type.
1975  if (!target_city) {
1976  return TRI_MAYBE;
1977  }
1978  return BOOL_TO_TRISTATE(city_receives_goods(target_city, pgood));
1979  case REQ_RANGE_CADJACENT:
1980  case REQ_RANGE_ADJACENT:
1981  case REQ_RANGE_TRADEROUTE:
1982  case REQ_RANGE_CONTINENT:
1983  case REQ_RANGE_PLAYER:
1984  case REQ_RANGE_TEAM:
1985  case REQ_RANGE_ALLIANCE:
1986  case REQ_RANGE_WORLD:
1987  case REQ_RANGE_COUNT:
1988  break;
1989  }
1990 
1991  fc_assert_msg(false, "Invalid range %d.", range);
1992 
1993  return TRI_MAYBE;
1994 }
1995 
1999 static enum fc_tristate is_terrain_in_range(const struct tile *target_tile,
2000  const struct city *target_city,
2001  enum req_range range,
2002  bool survives,
2003  const struct terrain *pterrain)
2004 {
2005  Q_UNUSED(survives)
2006  switch (range) {
2007  case REQ_RANGE_LOCAL:
2008  // The requirement is filled if the tile has the terrain.
2009  if (!target_tile) {
2010  return TRI_MAYBE;
2011  }
2012  return BOOL_TO_TRISTATE(pterrain
2013  && tile_terrain(target_tile) == pterrain);
2014  case REQ_RANGE_CADJACENT:
2015  if (!target_tile) {
2016  return TRI_MAYBE;
2017  }
2018  return BOOL_TO_TRISTATE(
2019  pterrain && is_terrain_card_near(target_tile, pterrain, true));
2020  case REQ_RANGE_ADJACENT:
2021  if (!target_tile) {
2022  return TRI_MAYBE;
2023  }
2024  return BOOL_TO_TRISTATE(
2025  pterrain && is_terrain_near_tile(target_tile, pterrain, true));
2026  case REQ_RANGE_CITY:
2027  if (!target_city) {
2028  return TRI_MAYBE;
2029  }
2030  if (pterrain != nullptr) {
2032  city_tile(target_city), ptile)
2033  {
2034  if (tile_terrain(ptile) == pterrain) {
2035  return TRI_YES;
2036  }
2037  }
2039  }
2040  return TRI_NO;
2041  case REQ_RANGE_TRADEROUTE:
2042  if (!target_city) {
2043  return TRI_MAYBE;
2044  }
2045  if (pterrain != nullptr) {
2047  city_tile(target_city), ptile)
2048  {
2049  if (tile_terrain(ptile) == pterrain) {
2050  return TRI_YES;
2051  }
2052  }
2054  trade_partners_iterate(target_city, trade_partner)
2055  {
2057  city_tile(trade_partner), ptile)
2058  {
2059  if (tile_terrain(ptile) == pterrain) {
2060  return TRI_YES;
2061  }
2062  }
2064  }
2066  }
2067  return TRI_NO;
2068  case REQ_RANGE_CONTINENT:
2069  case REQ_RANGE_PLAYER:
2070  case REQ_RANGE_TEAM:
2071  case REQ_RANGE_ALLIANCE:
2072  case REQ_RANGE_WORLD:
2073  case REQ_RANGE_COUNT:
2074  break;
2075  }
2076 
2077  fc_assert_msg(false, "Invalid range %d.", range);
2078 
2079  return TRI_MAYBE;
2080 }
2081 
2086  const struct tile *target_tile, const struct city *target_city,
2087  enum req_range range, bool survives, enum terrain_class pclass)
2088 {
2089  Q_UNUSED(survives)
2090  switch (range) {
2091  case REQ_RANGE_LOCAL:
2092  /* The requirement is filled if the tile has the terrain of correct
2093  * class. */
2094  if (!target_tile) {
2095  return TRI_MAYBE;
2096  }
2097  return BOOL_TO_TRISTATE(
2098  terrain_type_terrain_class(tile_terrain(target_tile)) == pclass);
2099  case REQ_RANGE_CADJACENT:
2100  if (!target_tile) {
2101  return TRI_MAYBE;
2102  }
2103  return BOOL_TO_TRISTATE(
2104  terrain_type_terrain_class(tile_terrain(target_tile)) == pclass
2105  || is_terrain_class_card_near(target_tile, pclass));
2106  case REQ_RANGE_ADJACENT:
2107  if (!target_tile) {
2108  return TRI_MAYBE;
2109  }
2110  return BOOL_TO_TRISTATE(
2111  terrain_type_terrain_class(tile_terrain(target_tile)) == pclass
2112  || is_terrain_class_near_tile(target_tile, pclass));
2113  case REQ_RANGE_CITY:
2114  if (!target_city) {
2115  return TRI_MAYBE;
2116  }
2118  city_tile(target_city), ptile)
2119  {
2120  const struct terrain *pterrain = tile_terrain(ptile);
2121  if (pterrain != T_UNKNOWN
2122  && terrain_type_terrain_class(pterrain) == pclass) {
2123  return TRI_YES;
2124  }
2125  }
2127 
2128  return TRI_NO;
2129  case REQ_RANGE_TRADEROUTE:
2130  if (!target_city) {
2131  return TRI_MAYBE;
2132  }
2134  city_tile(target_city), ptile)
2135  {
2136  const struct terrain *pterrain = tile_terrain(ptile);
2137  if (pterrain != T_UNKNOWN
2138  && terrain_type_terrain_class(pterrain) == pclass) {
2139  return TRI_YES;
2140  }
2141  }
2143 
2144  trade_partners_iterate(target_city, trade_partner)
2145  {
2147  city_tile(trade_partner), ptile)
2148  {
2149  const struct terrain *pterrain = tile_terrain(ptile);
2150  if (pterrain != T_UNKNOWN
2151  && terrain_type_terrain_class(pterrain) == pclass) {
2152  return TRI_YES;
2153  }
2154  }
2156  }
2158 
2159  return TRI_NO;
2160  case REQ_RANGE_CONTINENT:
2161  case REQ_RANGE_PLAYER:
2162  case REQ_RANGE_TEAM:
2163  case REQ_RANGE_ALLIANCE:
2164  case REQ_RANGE_WORLD:
2165  case REQ_RANGE_COUNT:
2166  break;
2167  }
2168 
2169  fc_assert_msg(false, "Invalid range %d.", range);
2170 
2171  return TRI_MAYBE;
2172 }
2173 
2177 static enum fc_tristate
2178 is_terrainflag_in_range(const struct tile *target_tile,
2179  const struct city *target_city, enum req_range range,
2180  bool survives, enum terrain_flag_id terrflag)
2181 {
2182  Q_UNUSED(survives)
2183  switch (range) {
2184  case REQ_RANGE_LOCAL:
2185  /* The requirement is fulfilled if the tile has a terrain with
2186  * correct flag. */
2187  if (!target_tile) {
2188  return TRI_MAYBE;
2189  }
2190  return BOOL_TO_TRISTATE(
2191  terrain_has_flag(tile_terrain(target_tile), terrflag));
2192  case REQ_RANGE_CADJACENT:
2193  if (!target_tile) {
2194  return TRI_MAYBE;
2195  }
2196  return BOOL_TO_TRISTATE(
2197  terrain_has_flag(tile_terrain(target_tile), terrflag)
2198  || is_terrain_flag_card_near(target_tile, terrflag));
2199  case REQ_RANGE_ADJACENT:
2200  if (!target_tile) {
2201  return TRI_MAYBE;
2202  }
2203  return BOOL_TO_TRISTATE(
2204  terrain_has_flag(tile_terrain(target_tile), terrflag)
2205  || is_terrain_flag_near_tile(target_tile, terrflag));
2206  case REQ_RANGE_CITY:
2207  if (!target_city) {
2208  return TRI_MAYBE;
2209  }
2211  city_tile(target_city), ptile)
2212  {
2213  const struct terrain *pterrain = tile_terrain(ptile);
2214  if (pterrain != T_UNKNOWN && terrain_has_flag(pterrain, terrflag)) {
2215  return TRI_YES;
2216  }
2217  }
2219 
2220  return TRI_NO;
2221  case REQ_RANGE_TRADEROUTE:
2222  if (!target_city) {
2223  return TRI_MAYBE;
2224  }
2226  city_tile(target_city), ptile)
2227  {
2228  const struct terrain *pterrain = tile_terrain(ptile);
2229  if (pterrain != T_UNKNOWN && terrain_has_flag(pterrain, terrflag)) {
2230  return TRI_YES;
2231  }
2232  }
2234 
2235  trade_partners_iterate(target_city, trade_partner)
2236  {
2238  city_tile(trade_partner), ptile)
2239  {
2240  const struct terrain *pterrain = tile_terrain(ptile);
2241  if (pterrain != T_UNKNOWN && terrain_has_flag(pterrain, terrflag)) {
2242  return TRI_YES;
2243  }
2244  }
2246  }
2248 
2249  return TRI_NO;
2250  case REQ_RANGE_CONTINENT:
2251  case REQ_RANGE_PLAYER:
2252  case REQ_RANGE_TEAM:
2253  case REQ_RANGE_ALLIANCE:
2254  case REQ_RANGE_WORLD:
2255  case REQ_RANGE_COUNT:
2256  break;
2257  }
2258 
2259  fc_assert_msg(false, "Invalid range %d.", range);
2260 
2261  return TRI_MAYBE;
2262 }
2263 
2267 static enum fc_tristate is_baseflag_in_range(const struct tile *target_tile,
2268  const struct city *target_city,
2269  enum req_range range,
2270  bool survives,
2271  enum base_flag_id baseflag)
2272 {
2273  Q_UNUSED(survives)
2274  switch (range) {
2275  case REQ_RANGE_LOCAL:
2276  // The requirement is filled if the tile has a base with correct flag.
2277  if (!target_tile) {
2278  return TRI_MAYBE;
2279  }
2280  return BOOL_TO_TRISTATE(tile_has_base_flag(target_tile, baseflag));
2281  case REQ_RANGE_CADJACENT:
2282  if (!target_tile) {
2283  return TRI_MAYBE;
2284  }
2285  return BOOL_TO_TRISTATE(
2286  tile_has_base_flag(target_tile, baseflag)
2287  || is_base_flag_card_near(target_tile, baseflag));
2288  case REQ_RANGE_ADJACENT:
2289  if (!target_tile) {
2290  return TRI_MAYBE;
2291  }
2292  return BOOL_TO_TRISTATE(
2293  tile_has_base_flag(target_tile, baseflag)
2294  || is_base_flag_near_tile(target_tile, baseflag));
2295  case REQ_RANGE_CITY:
2296  if (!target_city) {
2297  return TRI_MAYBE;
2298  }
2300  city_tile(target_city), ptile)
2301  {
2302  if (tile_has_base_flag(ptile, baseflag)) {
2303  return TRI_YES;
2304  }
2305  }
2307 
2308  return TRI_NO;
2309  case REQ_RANGE_TRADEROUTE:
2310  if (!target_city) {
2311  return TRI_MAYBE;
2312  }
2314  city_tile(target_city), ptile)
2315  {
2316  if (tile_has_base_flag(ptile, baseflag)) {
2317  return TRI_YES;
2318  }
2319  }
2321 
2322  trade_partners_iterate(target_city, trade_partner)
2323  {
2325  city_tile(trade_partner), ptile)
2326  {
2327  if (tile_has_base_flag(ptile, baseflag)) {
2328  return TRI_YES;
2329  }
2330  }
2332  }
2334 
2335  return TRI_NO;
2336  case REQ_RANGE_CONTINENT:
2337  case REQ_RANGE_PLAYER:
2338  case REQ_RANGE_TEAM:
2339  case REQ_RANGE_ALLIANCE:
2340  case REQ_RANGE_WORLD:
2341  case REQ_RANGE_COUNT:
2342  break;
2343  }
2344 
2345  fc_assert_msg(false, "Invalid range %d.", range);
2346 
2347  return TRI_MAYBE;
2348 }
2349 
2353 static enum fc_tristate is_roadflag_in_range(const struct tile *target_tile,
2354  const struct city *target_city,
2355  enum req_range range,
2356  bool survives,
2357  enum road_flag_id roadflag)
2358 {
2359  Q_UNUSED(survives)
2360  switch (range) {
2361  case REQ_RANGE_LOCAL:
2362  // The requirement is filled if the tile has a road with correct flag.
2363  if (!target_tile) {
2364  return TRI_MAYBE;
2365  }
2366  return BOOL_TO_TRISTATE(tile_has_road_flag(target_tile, roadflag));
2367  case REQ_RANGE_CADJACENT:
2368  if (!target_tile) {
2369  return TRI_MAYBE;
2370  }
2371  return BOOL_TO_TRISTATE(
2372  tile_has_road_flag(target_tile, roadflag)
2373  || is_road_flag_card_near(target_tile, roadflag));
2374  case REQ_RANGE_ADJACENT:
2375  if (!target_tile) {
2376  return TRI_MAYBE;
2377  }
2378  return BOOL_TO_TRISTATE(
2379  tile_has_road_flag(target_tile, roadflag)
2380  || is_road_flag_near_tile(target_tile, roadflag));
2381  case REQ_RANGE_CITY:
2382  if (!target_city) {
2383  return TRI_MAYBE;
2384  }
2386  city_tile(target_city), ptile)
2387  {
2388  if (tile_has_road_flag(ptile, roadflag)) {
2389  return TRI_YES;
2390  }
2391  }
2393 
2394  return TRI_NO;
2395  case REQ_RANGE_TRADEROUTE:
2396  if (!target_city) {
2397  return TRI_MAYBE;
2398  }
2400  city_tile(target_city), ptile)
2401  {
2402  if (tile_has_road_flag(ptile, roadflag)) {
2403  return TRI_YES;
2404  }
2405  }
2407 
2408  trade_partners_iterate(target_city, trade_partner)
2409  {
2411  city_tile(trade_partner), ptile)
2412  {
2413  if (tile_has_road_flag(ptile, roadflag)) {
2414  return TRI_YES;
2415  }
2416  }
2418  }
2420 
2421  return TRI_NO;
2422  case REQ_RANGE_CONTINENT:
2423  case REQ_RANGE_PLAYER:
2424  case REQ_RANGE_TEAM:
2425  case REQ_RANGE_ALLIANCE:
2426  case REQ_RANGE_WORLD:
2427  case REQ_RANGE_COUNT:
2428  break;
2429  }
2430 
2431  fc_assert_msg(false, "Invalid range %d.", range);
2432 
2433  return TRI_MAYBE;
2434 }
2435 
2439 static enum fc_tristate is_extraflag_in_range(const struct tile *target_tile,
2440  const struct city *target_city,
2441  enum req_range range,
2442  bool survives,
2443  enum extra_flag_id extraflag)
2444 {
2445  Q_UNUSED(survives)
2446  switch (range) {
2447  case REQ_RANGE_LOCAL:
2448  /* The requirement is filled if the tile has an extra with correct flag.
2449  */
2450  if (!target_tile) {
2451  return TRI_MAYBE;
2452  }
2453  return BOOL_TO_TRISTATE(tile_has_extra_flag(target_tile, extraflag));
2454  case REQ_RANGE_CADJACENT:
2455  if (!target_tile) {
2456  return TRI_MAYBE;
2457  }
2458  return BOOL_TO_TRISTATE(
2459  tile_has_extra_flag(target_tile, extraflag)
2460  || is_extra_flag_card_near(target_tile, extraflag));
2461  case REQ_RANGE_ADJACENT:
2462  if (!target_tile) {
2463  return TRI_MAYBE;
2464  }
2465  return BOOL_TO_TRISTATE(
2466  tile_has_extra_flag(target_tile, extraflag)
2467  || is_extra_flag_near_tile(target_tile, extraflag));
2468  case REQ_RANGE_CITY:
2469  if (!target_city) {
2470  return TRI_MAYBE;
2471  }
2473  city_tile(target_city), ptile)
2474  {
2475  if (tile_has_extra_flag(ptile, extraflag)) {
2476  return TRI_YES;
2477  }
2478  }
2480 
2481  return TRI_NO;
2482  case REQ_RANGE_TRADEROUTE:
2483  if (!target_city) {
2484  return TRI_MAYBE;
2485  }
2487  city_tile(target_city), ptile)
2488  {
2489  if (tile_has_extra_flag(ptile, extraflag)) {
2490  return TRI_YES;
2491  }
2492  }
2494 
2495  trade_partners_iterate(target_city, trade_partner)
2496  {
2498  city_tile(trade_partner), ptile)
2499  {
2500  if (tile_has_extra_flag(ptile, extraflag)) {
2501  return TRI_YES;
2502  }
2503  }
2505  }
2507 
2508  return TRI_NO;
2509  case REQ_RANGE_CONTINENT:
2510  case REQ_RANGE_PLAYER:
2511  case REQ_RANGE_TEAM:
2512  case REQ_RANGE_ALLIANCE:
2513  case REQ_RANGE_WORLD:
2514  case REQ_RANGE_COUNT:
2515  break;
2516  }
2517 
2518  fc_assert_msg(false, "Invalid range %d.", range);
2519 
2520  return TRI_MAYBE;
2521 }
2522 
2527 static enum fc_tristate
2528 is_terrain_alter_possible_in_range(const struct tile *target_tile,
2529  enum req_range range, bool survives,
2530  enum terrain_alteration alteration)
2531 {
2532  Q_UNUSED(survives)
2533  if (!target_tile) {
2534  return TRI_MAYBE;
2535  }
2536 
2537  switch (range) {
2538  case REQ_RANGE_LOCAL:
2540  tile_terrain(target_tile), alteration));
2541  case REQ_RANGE_CADJACENT:
2542  case REQ_RANGE_ADJACENT: // XXX Could in principle support ADJACENT.
2543  case REQ_RANGE_CITY:
2544  case REQ_RANGE_TRADEROUTE:
2545  case REQ_RANGE_CONTINENT:
2546  case REQ_RANGE_PLAYER:
2547  case REQ_RANGE_TEAM:
2548  case REQ_RANGE_ALLIANCE:
2549  case REQ_RANGE_WORLD:
2550  case REQ_RANGE_COUNT:
2551  break;
2552  }
2553 
2554  fc_assert_msg(false, "Invalid range %d.", range);
2555 
2556  return TRI_MAYBE;
2557 }
2558 
2562 static enum fc_tristate
2563 is_nation_in_range(const struct player *target_player, enum req_range range,
2564  bool survives, const struct nation_type *nation)
2565 {
2566  switch (range) {
2567  case REQ_RANGE_PLAYER:
2568  if (target_player == nullptr) {
2569  return TRI_MAYBE;
2570  }
2571  return BOOL_TO_TRISTATE(nation_of_player(target_player) == nation);
2572  case REQ_RANGE_TEAM:
2573  case REQ_RANGE_ALLIANCE:
2574  if (target_player == nullptr) {
2575  return TRI_MAYBE;
2576  }
2577  players_iterate_alive(plr2)
2578  {
2579  if (players_in_same_range(target_player, plr2, range)) {
2580  if (nation_of_player(plr2) == nation) {
2581  return TRI_YES;
2582  }
2583  }
2584  }
2586  return TRI_NO;
2587  case REQ_RANGE_WORLD:
2588  /* NB: if a player is ever removed outright from the game
2589  * (e.g. via /remove), rather than just dying, this 'survives'
2590  * requirement will stop being true for their nation.
2591  * create_command_newcomer() can also cause this to happen. */
2592  return BOOL_TO_TRISTATE(nullptr != nation->player
2593  && (survives || nation->player->is_alive));
2594  case REQ_RANGE_LOCAL:
2595  case REQ_RANGE_CADJACENT:
2596  case REQ_RANGE_ADJACENT:
2597  case REQ_RANGE_CITY:
2598  case REQ_RANGE_TRADEROUTE:
2599  case REQ_RANGE_CONTINENT:
2600  case REQ_RANGE_COUNT:
2601  break;
2602  }
2603 
2604  fc_assert_msg(false, "Invalid range %d.", range);
2605 
2606  return TRI_MAYBE;
2607 }
2608 
2612 static enum fc_tristate
2613 is_nation_group_in_range(const struct player *target_player,
2614  enum req_range range, bool survives,
2615  const struct nation_group *ngroup)
2616 {
2617  Q_UNUSED(survives)
2618  switch (range) {
2619  case REQ_RANGE_PLAYER:
2620  if (target_player == nullptr) {
2621  return TRI_MAYBE;
2622  }
2623  return BOOL_TO_TRISTATE(
2624  nation_is_in_group(nation_of_player(target_player), ngroup));
2625  case REQ_RANGE_TEAM:
2626  case REQ_RANGE_ALLIANCE:
2627  case REQ_RANGE_WORLD:
2628  if (target_player == nullptr) {
2629  return TRI_MAYBE;
2630  }
2631  players_iterate_alive(plr2)
2632  {
2633  if (players_in_same_range(target_player, plr2, range)) {
2634  if (nation_is_in_group(nation_of_player(plr2), ngroup)) {
2635  return TRI_YES;
2636  }
2637  }
2638  }
2640  return TRI_NO;
2641  case REQ_RANGE_LOCAL:
2642  case REQ_RANGE_CADJACENT:
2643  case REQ_RANGE_ADJACENT:
2644  case REQ_RANGE_CITY:
2645  case REQ_RANGE_TRADEROUTE:
2646  case REQ_RANGE_CONTINENT:
2647  case REQ_RANGE_COUNT:
2648  break;
2649  }
2650 
2651  fc_assert_msg(false, "Invalid range %d.", range);
2652 
2653  return TRI_MAYBE;
2654 }
2655 
2659 static enum fc_tristate
2660 is_nationality_in_range(const struct city *target_city, enum req_range range,
2661  const struct nation_type *nationality)
2662 {
2663  switch (range) {
2664  case REQ_RANGE_CITY:
2665  if (target_city == nullptr) {
2666  return TRI_MAYBE;
2667  }
2668  citizens_iterate(target_city, slot, count)
2669  {
2670  if (player_slot_get_player(slot)->nation == nationality) {
2671  return TRI_YES;
2672  }
2673  }
2675 
2676  return TRI_NO;
2677  case REQ_RANGE_TRADEROUTE:
2678  if (target_city == nullptr) {
2679  return TRI_MAYBE;
2680  }
2681  citizens_iterate(target_city, slot, count)
2682  {
2683  if (player_slot_get_player(slot)->nation == nationality) {
2684  return TRI_YES;
2685  }
2686  }
2688 
2689  trade_partners_iterate(target_city, trade_partner)
2690  {
2691  citizens_iterate(trade_partner, slot, count)
2692  {
2693  if (player_slot_get_player(slot)->nation == nationality) {
2694  return TRI_YES;
2695  }
2696  }
2698  }
2700 
2701  return TRI_NO;
2702  case REQ_RANGE_PLAYER:
2703  case REQ_RANGE_TEAM:
2704  case REQ_RANGE_ALLIANCE:
2705  case REQ_RANGE_WORLD:
2706  case REQ_RANGE_LOCAL:
2707  case REQ_RANGE_CADJACENT:
2708  case REQ_RANGE_ADJACENT:
2709  case REQ_RANGE_CONTINENT:
2710  case REQ_RANGE_COUNT:
2711  break;
2712  }
2713 
2714  fc_assert_msg(false, "Invalid range %d.", range);
2715 
2716  return TRI_MAYBE;
2717 }
2718 
2722 static enum fc_tristate
2723 is_diplrel_in_range(const struct player *target_player,
2724  const struct player *other_player, enum req_range range,
2725  int diplrel)
2726 {
2727  switch (range) {
2728  case REQ_RANGE_PLAYER:
2729  if (target_player == nullptr) {
2730  return TRI_MAYBE;
2731  }
2732  return BOOL_TO_TRISTATE(is_diplrel_to_other(target_player, diplrel));
2733  case REQ_RANGE_TEAM:
2734  case REQ_RANGE_ALLIANCE:
2735  case REQ_RANGE_WORLD:
2736  if (target_player == nullptr) {
2737  return TRI_MAYBE;
2738  }
2739  players_iterate_alive(plr2)
2740  {
2741  if (players_in_same_range(target_player, plr2, range)) {
2742  if (is_diplrel_to_other(plr2, diplrel)) {
2743  return TRI_YES;
2744  }
2745  }
2746  }
2748  return TRI_NO;
2749  case REQ_RANGE_LOCAL:
2750  if (target_player == nullptr || other_player == nullptr) {
2751  return TRI_MAYBE;
2752  }
2753  return BOOL_TO_TRISTATE(
2754  is_diplrel_between(target_player, other_player, diplrel));
2755  case REQ_RANGE_CADJACENT:
2756  case REQ_RANGE_ADJACENT:
2757  case REQ_RANGE_CITY:
2758  case REQ_RANGE_TRADEROUTE:
2759  case REQ_RANGE_CONTINENT:
2760  case REQ_RANGE_COUNT:
2761  break;
2762  }
2763 
2764  fc_assert_msg(false, "Invalid range %d.", range);
2765 
2766  return TRI_MAYBE;
2767 }
2768 
2772 static enum fc_tristate
2773 is_unittype_in_range(const struct unit_type *target_unittype,
2774  enum req_range range, bool survives,
2775  const struct unit_type *punittype)
2776 {
2777  Q_UNUSED(survives)
2778  /* If no target_unittype is given, we allow the req to be met. This is
2779  * to allow querying of certain effect types (like the presence of city
2780  * walls) without actually knowing the target unit. */
2781  return BOOL_TO_TRISTATE(
2782  range == REQ_RANGE_LOCAL
2783  && (!target_unittype || target_unittype == punittype));
2784 }
2785 
2789 static enum fc_tristate
2790 is_unitflag_in_range(const struct unit_type *target_unittype,
2791  enum req_range range, bool survives,
2792  enum unit_type_flag_id unitflag)
2793 {
2794  Q_UNUSED(survives)
2795  /* If no target_unittype is given, we allow the req to be met. This is
2796  * to allow querying of certain effect types (like the presence of city
2797  * walls) without actually knowing the target unit. */
2798  if (range != REQ_RANGE_LOCAL) {
2799  return TRI_NO;
2800  }
2801  if (!target_unittype) {
2802  return TRI_MAYBE;
2803  }
2804 
2805  return BOOL_TO_TRISTATE(utype_has_flag(target_unittype, unitflag));
2806 }
2807 
2811 static enum fc_tristate
2812 is_unitclass_in_range(const struct unit_type *target_unittype,
2813  enum req_range range, bool survives,
2814  struct unit_class *pclass)
2815 {
2816  Q_UNUSED(survives)
2817  /* If no target_unittype is given, we allow the req to be met. This is
2818  * to allow querying of certain effect types (like the presence of city
2819  * walls) without actually knowing the target unit. */
2820  return BOOL_TO_TRISTATE(
2821  range == REQ_RANGE_LOCAL
2822  && (!target_unittype || utype_class(target_unittype) == pclass));
2823 }
2824 
2828 static enum fc_tristate
2829 is_unitclassflag_in_range(const struct unit_type *target_unittype,
2830  enum req_range range, bool survives,
2831  enum unit_class_flag_id ucflag)
2832 {
2833  Q_UNUSED(survives)
2834  /* If no target_unittype is given, we allow the req to be met. This is
2835  * to allow querying of certain effect types (like the presence of city
2836  * walls) without actually knowing the target unit. */
2837  return BOOL_TO_TRISTATE(
2838  range == REQ_RANGE_LOCAL
2839  && (!target_unittype
2840  || uclass_has_flag(utype_class(target_unittype), ucflag)));
2841 }
2842 
2846 static enum fc_tristate is_unit_state(const struct unit *target_unit,
2847  enum req_range range, bool survives,
2848  enum ustate_prop uprop)
2849 {
2850  Q_UNUSED(survives)
2851  fc_assert_ret_val_msg(range == REQ_RANGE_LOCAL, TRI_NO,
2852  "Unsupported range \"%s\"", req_range_name(range));
2853 
2854  /* Could be asked with incomplete data.
2855  * is_req_active() will handle it based on prob_type. */
2856  if (target_unit == nullptr) {
2857  return TRI_MAYBE;
2858  }
2859 
2860  switch (uprop) {
2861  case USP_TRANSPORTED:
2862  return BOOL_TO_TRISTATE(target_unit->transporter != nullptr);
2863  case USP_LIVABLE_TILE:
2864  return BOOL_TO_TRISTATE(can_unit_exist_at_tile(&(wld.map), target_unit,
2865  unit_tile(target_unit)));
2866  break;
2867  case USP_DOMESTIC_TILE:
2868  return BOOL_TO_TRISTATE(tile_owner(unit_tile(target_unit))
2869  == unit_owner(target_unit));
2870  break;
2871  case USP_TRANSPORTING:
2872  return BOOL_TO_TRISTATE(0 < get_transporter_occupancy(target_unit));
2873  case USP_HAS_HOME_CITY:
2874  return BOOL_TO_TRISTATE(target_unit->homecity > 0);
2875  case USP_NATIVE_TILE:
2876  return BOOL_TO_TRISTATE(
2877  is_native_tile(unit_type_get(target_unit), unit_tile(target_unit)));
2878  break;
2879  case USP_NATIVE_EXTRA:
2881  unit_tile(target_unit), unit_type_get(target_unit)));
2882  break;
2883  case USP_MOVED_THIS_TURN:
2884  return BOOL_TO_TRISTATE(target_unit->moved);
2885  case USP_COUNT:
2886  fc_assert_msg(uprop != USP_COUNT, "Invalid unit state property.");
2887  // Invalid property is unknowable.
2888  return TRI_NO;
2889  }
2890 
2891  // Should never be reached
2892  fc_assert_msg(false, "Unsupported unit property %d", uprop);
2893  return TRI_NO;
2894 }
2895 
2899 static bool is_city_in_tile(const struct tile *ptile,
2900  const struct city *pcity)
2901 {
2902  if (pcity == nullptr) {
2903  return tile_city(ptile) != nullptr;
2904  } else {
2905  return is_city_center(pcity, ptile);
2906  }
2907 }
2908 
2912 static enum fc_tristate is_citytile_in_range(const struct tile *target_tile,
2913  const struct city *target_city,
2914  enum req_range range,
2915  enum citytile_type citytile)
2916 {
2917  if (target_tile) {
2918  if (citytile == CITYT_CENTER) {
2919  switch (range) {
2920  case REQ_RANGE_LOCAL:
2921  return BOOL_TO_TRISTATE(is_city_in_tile(target_tile, target_city));
2922  case REQ_RANGE_CADJACENT:
2923  if (is_city_in_tile(target_tile, target_city)) {
2924  return TRI_YES;
2925  }
2926  cardinal_adjc_iterate(&(wld.map), target_tile, adjc_tile)
2927  {
2928  if (is_city_in_tile(adjc_tile, target_city)) {
2929  return TRI_YES;
2930  }
2931  }
2933 
2934  return TRI_NO;
2935  case REQ_RANGE_ADJACENT:
2936  if (is_city_in_tile(target_tile, target_city)) {
2937  return TRI_YES;
2938  }
2939  adjc_iterate(&(wld.map), target_tile, adjc_tile)
2940  {
2941  if (is_city_in_tile(adjc_tile, target_city)) {
2942  return TRI_YES;
2943  }
2944  }
2946 
2947  return TRI_NO;
2948  case REQ_RANGE_CITY:
2949  case REQ_RANGE_TRADEROUTE:
2950  case REQ_RANGE_CONTINENT:
2951  case REQ_RANGE_PLAYER:
2952  case REQ_RANGE_TEAM:
2953  case REQ_RANGE_ALLIANCE:
2954  case REQ_RANGE_WORLD:
2955  case REQ_RANGE_COUNT:
2956  break;
2957  }
2958 
2959  fc_assert_msg(false, "Invalid range %d for citytile.", range);
2960 
2961  return TRI_MAYBE;
2962  } else if (citytile == CITYT_CLAIMED) {
2963  switch (range) {
2964  case REQ_RANGE_LOCAL:
2965  return BOOL_TO_TRISTATE(target_tile->owner != nullptr);
2966  case REQ_RANGE_CADJACENT:
2967  if (target_tile->owner != nullptr) {
2968  return TRI_YES;
2969  }
2970  cardinal_adjc_iterate(&(wld.map), target_tile, adjc_tile)
2971  {
2972  if (adjc_tile->owner != nullptr) {
2973  return TRI_YES;
2974  }
2975  }
2977 
2978  return TRI_NO;
2979  case REQ_RANGE_ADJACENT:
2980  if (target_tile->owner != nullptr) {
2981  return TRI_YES;
2982  }
2983  adjc_iterate(&(wld.map), target_tile, adjc_tile)
2984  {
2985  if (adjc_tile->owner != nullptr) {
2986  return TRI_YES;
2987  }
2988  }
2990 
2991  return TRI_NO;
2992  case REQ_RANGE_CITY:
2993  case REQ_RANGE_TRADEROUTE:
2994  case REQ_RANGE_CONTINENT:
2995  case REQ_RANGE_PLAYER:
2996  case REQ_RANGE_TEAM:
2997  case REQ_RANGE_ALLIANCE:
2998  case REQ_RANGE_WORLD:
2999  case REQ_RANGE_COUNT:
3000  break;
3001  }
3002 
3003  fc_assert_msg(false, "Invalid range %d for citytile.", range);
3004 
3005  return TRI_MAYBE;
3006  } else {
3007  // Not implemented
3008  qCritical("is_req_active(): citytile %d not supported.", citytile);
3009  return TRI_MAYBE;
3010  }
3011  } else {
3012  return TRI_MAYBE;
3013  }
3014 }
3015 
3020 static enum fc_tristate
3021 is_citystatus_in_range(const struct city *target_city, enum req_range range,
3022  enum citystatus_type citystatus)
3023 {
3024  if (citystatus == CITYS_OWNED_BY_ORIGINAL) {
3025  switch (range) {
3026  case REQ_RANGE_CITY:
3027  return BOOL_TO_TRISTATE(city_owner(target_city)
3028  == target_city->original);
3029  case REQ_RANGE_TRADEROUTE: {
3030  bool found = false;
3031 
3032  trade_partners_iterate(target_city, trade_partner)
3033  {
3034  if (city_owner(trade_partner) == trade_partner->original) {
3035  found = true;
3036  break;
3037  }
3038  }
3040 
3041  return BOOL_TO_TRISTATE(found);
3042  }
3043  case REQ_RANGE_LOCAL:
3044  case REQ_RANGE_CADJACENT:
3045  case REQ_RANGE_ADJACENT:
3046  case REQ_RANGE_CONTINENT:
3047  case REQ_RANGE_PLAYER:
3048  case REQ_RANGE_TEAM:
3049  case REQ_RANGE_ALLIANCE:
3050  case REQ_RANGE_WORLD:
3051  case REQ_RANGE_COUNT:
3052  break;
3053  }
3054 
3055  fc_assert_msg(false, "Invalid range %d for citystatus.", range);
3056 
3057  return TRI_MAYBE;
3058  } else {
3059  // Not implemented
3060  qCritical("is_req_active(): citystatus %d not supported.", citystatus);
3061  return TRI_MAYBE;
3062  }
3063 }
3064 
3068 static enum fc_tristate
3069 is_achievement_in_range(const struct player *target_player,
3070  enum req_range range,
3071  const struct achievement *achievement)
3072 {
3073  if (range == REQ_RANGE_WORLD) {
3075  } else if (target_player == nullptr) {
3076  return TRI_MAYBE;
3077  } else if (range == REQ_RANGE_ALLIANCE || range == REQ_RANGE_TEAM) {
3078  players_iterate_alive(plr2)
3079  {
3080  if (players_in_same_range(target_player, plr2, range)
3081  && achievement_player_has(achievement, plr2)) {
3082  return TRI_YES;
3083  }
3084  }
3086  return TRI_NO;
3087  } else if (range == REQ_RANGE_PLAYER) {
3088  if (achievement_player_has(achievement, target_player)) {
3089  return TRI_YES;
3090  } else {
3091  return TRI_NO;
3092  }
3093  } else {
3094  fc_assert_msg(false, "Illegal range %d for achievement requirement.",
3095  range);
3096  return TRI_MAYBE;
3097  }
3098 }
3099 
3112  const struct player *target_player, const struct player *other_player,
3113  const struct city *target_city, const struct impr_type *target_building,
3114  const struct tile *target_tile, const struct unit *target_unit,
3115  const struct unit_type *target_unittype,
3116  const struct output_type *target_output,
3117  const struct specialist *target_specialist,
3118  const struct action *target_action, const struct requirement *req,
3119  const enum req_problem_type prob_type,
3120  const enum vision_layer vision_layer,
3121  const enum national_intelligence nintel)
3122 {
3123  enum fc_tristate eval = TRI_NO;
3124 
3125  // The supplied unit has a type. Use it if the unit type is missing.
3126  if (target_unittype == nullptr && target_unit != nullptr) {
3127  target_unittype = unit_type_get(target_unit);
3128  }
3129 
3130  /* Note the target may actually not exist. In particular, effects that
3131  * have a VUT_TERRAIN may often be passed
3132  * to this function with a city as their target. In this case the
3133  * requirement is simply not met. */
3134  switch (req->source.kind) {
3135  case VUT_NONE:
3136  eval = TRI_YES;
3137  break;
3138  case VUT_ADVANCE:
3139  // The requirement is filled if the player owns the tech.
3140  eval = is_tech_in_range(target_player, req->range, req->survives,
3142  break;
3143  case VUT_TECHFLAG:
3144  eval = is_techflag_in_range(target_player, req->range,
3145  tech_flag_id(req->source.value.techflag));
3146  break;
3147  case VUT_GOVERNMENT:
3148  // The requirement is filled if the player is using the government.
3149  if (target_player == nullptr) {
3150  eval = TRI_MAYBE;
3151  } else {
3152  eval = BOOL_TO_TRISTATE(government_of_player(target_player)
3153  == req->source.value.govern);
3154  }
3155  break;
3156  case VUT_ACHIEVEMENT:
3157  eval = is_achievement_in_range(target_player, req->range,
3158  req->source.value.achievement);
3159  break;
3160  case VUT_STYLE:
3161  if (target_player == nullptr) {
3162  eval = TRI_MAYBE;
3163  } else {
3164  eval =
3165  BOOL_TO_TRISTATE(target_player->style == req->source.value.style);
3166  }
3167  break;
3168  case VUT_IMPROVEMENT:
3169  eval = is_building_in_range(target_player, target_city, target_building,
3170  req->range, req->survives,
3171  req->source.value.building);
3172  break;
3173  case VUT_IMPR_GENUS:
3174  eval = (target_building ? BOOL_TO_TRISTATE(
3175  target_building->genus == req->source.value.impr_genus)
3176  : TRI_MAYBE);
3177  break;
3178  case VUT_EXTRA:
3179  eval = is_extra_type_in_range(target_tile, target_city, req->range,
3180  req->survives, req->source.value.extra);
3181  break;
3182  case VUT_GOOD:
3183  eval = is_goods_type_in_range(target_tile, target_city, req->range,
3184  req->survives, req->source.value.good);
3185  break;
3186  case VUT_TERRAIN:
3187  eval = is_terrain_in_range(target_tile, target_city, req->range,
3188  req->survives, req->source.value.terrain);
3189  break;
3190  case VUT_TERRFLAG:
3191  eval = is_terrainflag_in_range(
3192  target_tile, target_city, req->range, req->survives,
3193  terrain_flag_id(req->source.value.terrainflag));
3194  break;
3195  case VUT_NATION:
3196  eval = is_nation_in_range(target_player, req->range, req->survives,
3197  req->source.value.nation);
3198  break;
3199  case VUT_NATIONGROUP:
3200  eval = is_nation_group_in_range(target_player, req->range, req->survives,
3201  req->source.value.nationgroup);
3202  break;
3203  case VUT_NATIONALITY:
3204  eval = is_nationality_in_range(target_city, req->range,
3205  req->source.value.nationality);
3206  break;
3207  case VUT_DIPLREL:
3208  eval = is_diplrel_in_range(target_player, other_player, req->range,
3209  req->source.value.diplrel);
3210  break;
3211  case VUT_UTYPE:
3212  if (target_unittype == nullptr) {
3213  eval = TRI_MAYBE;
3214  } else {
3215  eval = is_unittype_in_range(target_unittype, req->range, req->survives,
3216  req->source.value.utype);
3217  }
3218  break;
3219  case VUT_UTFLAG:
3220  eval =
3221  is_unitflag_in_range(target_unittype, req->range, req->survives,
3222  unit_type_flag_id(req->source.value.unitflag));
3223  break;
3224  case VUT_UCLASS:
3225  if (target_unittype == nullptr) {
3226  eval = TRI_MAYBE;
3227  } else {
3228  eval = is_unitclass_in_range(target_unittype, req->range,
3229  req->survives, req->source.value.uclass);
3230  }
3231  break;
3232  case VUT_UCFLAG:
3233  if (target_unittype == nullptr) {
3234  eval = TRI_MAYBE;
3235  } else {
3237  target_unittype, req->range, req->survives,
3238  unit_class_flag_id(req->source.value.unitclassflag));
3239  }
3240  break;
3241  case VUT_MINVETERAN:
3242  if (target_unit == nullptr) {
3243  eval = TRI_MAYBE;
3244  } else {
3245  eval = BOOL_TO_TRISTATE(target_unit->veteran
3246  >= req->source.value.minveteran);
3247  }
3248  break;
3249  case VUT_UNITSTATE:
3250  if (target_unit == nullptr) {
3251  eval = TRI_MAYBE;
3252  } else {
3253  eval = is_unit_state(target_unit, req->range, req->survives,
3254  req->source.value.unit_state);
3255  }
3256  break;
3257  case VUT_ACTIVITY:
3258  if (target_unit == nullptr) {
3259  eval = TRI_MAYBE;
3260  } else {
3261  eval = BOOL_TO_TRISTATE(target_unit->activity
3262  == req->source.value.activity);
3263  }
3264  break;
3265  case VUT_MINMOVES:
3266  if (target_unit == nullptr) {
3267  eval = TRI_MAYBE;
3268  } else {
3270  <= target_unit->moves_left);
3271  }
3272  break;
3273  case VUT_MINHP:
3274  if (target_unit == nullptr) {
3275  eval = TRI_MAYBE;
3276  } else {
3278  <= target_unit->hp);
3279  }
3280  break;
3281  case VUT_AGE:
3282  switch (req->range) {
3283  case REQ_RANGE_LOCAL:
3284  if (target_unit == nullptr || !is_server()) {
3285  eval = TRI_MAYBE;
3286  } else {
3287  eval = BOOL_TO_TRISTATE(req->source.value.age
3288  <= game.info.turn
3289  - target_unit->server.birth_turn);
3290  }
3291  break;
3292  case REQ_RANGE_CITY:
3293  if (target_city == nullptr) {
3294  eval = TRI_MAYBE;
3295  } else {
3296  eval =
3298  <= game.info.turn - target_city->turn_founded);
3299  }
3300  break;
3301  case REQ_RANGE_PLAYER:
3302  if (target_player == nullptr) {
3303  eval = TRI_MAYBE;
3304  } else {
3305  eval = BOOL_TO_TRISTATE(req->source.value.age
3306  <= player_age(target_player));
3307  }
3308  break;
3309  default:
3310  eval = TRI_MAYBE;
3311  break;
3312  }
3313  break;
3314  case VUT_MINTECHS:
3315  switch (req->range) {
3316  case REQ_RANGE_WORLD:
3317  // "None" does not count
3318  eval = BOOL_TO_TRISTATE((game.info.global_advance_count - 1)
3319  >= req->source.value.min_techs);
3320  break;
3321  case REQ_RANGE_PLAYER:
3322  if (target_player == nullptr) {
3323  eval = TRI_MAYBE;
3324  } else {
3325  // "None" does not count
3326  eval = BOOL_TO_TRISTATE(
3327  (research_get(target_player)->techs_researched - 1)
3328  >= req->source.value.min_techs);
3329  }
3330  break;
3331  default:
3332  eval = TRI_MAYBE;
3333  }
3334  break;
3335  case VUT_ACTION:
3336  eval =
3337  BOOL_TO_TRISTATE(target_action
3338  && action_number(target_action)
3339  == action_number(req->source.value.action));
3340  break;
3341  case VUT_OTYPE:
3342  eval = BOOL_TO_TRISTATE(target_output
3343  && target_output->index
3344  == req->source.value.outputtype);
3345  break;
3346  case VUT_SPECIALIST:
3347  eval = BOOL_TO_TRISTATE(target_specialist
3348  && target_specialist
3349  == req->source.value.specialist);
3350  break;
3351  case VUT_MINSIZE:
3352  if (target_city == nullptr) {
3353  eval = TRI_MAYBE;
3354  } else {
3355  if (req->range == REQ_RANGE_TRADEROUTE) {
3356  bool found = false;
3357 
3358  if (city_size_get(target_city) >= req->source.value.minsize) {
3359  eval = TRI_YES;
3360  break;
3361  }
3362  trade_partners_iterate(target_city, trade_partner)
3363  {
3364  if (city_size_get(trade_partner) >= req->source.value.minsize) {
3365  found = true;
3366  break;
3367  }
3368  }
3370  eval = BOOL_TO_TRISTATE(found);
3371  } else {
3372  eval = BOOL_TO_TRISTATE(city_size_get(target_city)
3373  >= req->source.value.minsize);
3374  }
3375  }
3376  break;
3377  case VUT_MINCULTURE:
3378  eval = is_minculture_in_range(target_city, target_player, req->range,
3379  req->source.value.minculture);
3380  break;
3381  case VUT_MINFOREIGNPCT:
3382  eval = is_minforeignpct_in_range(target_city, req->range,
3383  req->source.value.minforeignpct);
3384  break;
3385  case VUT_AI_LEVEL:
3386  if (target_player == nullptr) {
3387  eval = TRI_MAYBE;
3388  } else {
3389  eval = BOOL_TO_TRISTATE(is_ai(target_player)
3390  && target_player->ai_common.skill_level
3391  == req->source.value.ai_level);
3392  }
3393  break;
3394  case VUT_MAXTILEUNITS:
3395  eval = is_tile_units_in_range(target_tile, req->range,
3396  req->source.value.max_tile_units);
3397  break;
3398  case VUT_TERRAINCLASS:
3400  target_tile, target_city, req->range, req->survives,
3401  terrain_class(req->source.value.terrainclass));
3402  break;
3403  case VUT_BASEFLAG:
3404  eval = is_baseflag_in_range(target_tile, target_city, req->range,
3405  req->survives,
3406  base_flag_id(req->source.value.baseflag));
3407  break;
3408  case VUT_ROADFLAG:
3409  eval = is_roadflag_in_range(target_tile, target_city, req->range,
3410  req->survives,
3411  road_flag_id(req->source.value.roadflag));
3412  break;
3413  case VUT_EXTRAFLAG:
3414  eval = is_extraflag_in_range(target_tile, target_city, req->range,
3415  req->survives,
3416  extra_flag_id(req->source.value.extraflag));
3417  break;
3418  case VUT_MINYEAR:
3419  eval = BOOL_TO_TRISTATE(game.info.year >= req->source.value.minyear);
3420  break;
3421  case VUT_MINCALFRAG:
3422  eval = BOOL_TO_TRISTATE(game.info.fragment_count
3423  >= req->source.value.mincalfrag);
3424  break;
3425  case VUT_TOPO:
3426  eval = BOOL_TO_TRISTATE(
3428  break;
3429  case VUT_SERVERSETTING:
3430  eval =
3432  break;
3433  case VUT_TERRAINALTER:
3434  if (target_tile == nullptr) {
3435  eval = TRI_MAYBE;
3436  } else {
3438  target_tile, req->range, req->survives,
3439  terrain_alteration(req->source.value.terrainalter));
3440  }
3441  break;
3442  case VUT_CITYTILE:
3443  if (target_tile == nullptr) {
3444  eval = TRI_MAYBE;
3445  } else {
3446  eval = is_citytile_in_range(target_tile, target_city, req->range,
3447  req->source.value.citytile);
3448  }
3449  break;
3450  case VUT_CITYSTATUS:
3451  if (target_city == nullptr) {
3452  eval = TRI_MAYBE;
3453  } else {
3454  eval = is_citystatus_in_range(target_city, req->range,
3455  req->source.value.citystatus);
3456  }
3457  break;
3458  case VUT_VISIONLAYER:
3459  if (!vision_layer_is_valid(vision_layer)) {
3460  eval = TRI_MAYBE;
3461  } else {
3462  eval = BOOL_TO_TRISTATE(vision_layer == req->source.value.vlayer);
3463  }
3464  break;
3465  case VUT_NINTEL:
3466  if (!national_intelligence_is_valid(nintel)) {
3467  eval = TRI_MAYBE;
3468  } else {
3469  eval = BOOL_TO_TRISTATE(nintel == req->source.value.nintel);
3470  }
3471  break;
3472  case VUT_COUNT:
3473  qCritical("is_req_active(): invalid source kind %d.", req->source.kind);
3474  return false;
3475  }
3476 
3477  if (eval == TRI_MAYBE) {
3478  return prob_type == RPT_POSSIBLE;
3479  }
3480  if (req->present) {
3481  return (eval == TRI_YES);
3482  } else {
3483  return (eval == TRI_NO);
3484  }
3485 }
3486 
3500 bool are_reqs_active(const struct player *target_player,
3501  const struct player *other_player,
3502  const struct city *target_city,
3503  const struct impr_type *target_building,
3504  const struct tile *target_tile,
3505  const struct unit *target_unit,
3506  const struct unit_type *target_unittype,
3507  const struct output_type *target_output,
3508  const struct specialist *target_specialist,
3509  const struct action *target_action,
3510  const struct requirement_vector *reqs,
3511  const enum req_problem_type prob_type,
3512  const enum vision_layer vision_layer,
3513  const enum national_intelligence nintel)
3514 {
3516  {
3517  if (!is_req_active(target_player, other_player, target_city,
3518  target_building, target_tile, target_unit,
3519  target_unittype, target_output, target_specialist,
3520  target_action, preq, prob_type, vision_layer,
3521  nintel)) {
3522  return false;
3523  }
3524  }
3526  return true;
3527 }
3528 
3539 bool is_req_unchanging(const struct requirement *req)
3540 {
3541  switch (req->source.kind) {
3542  case VUT_NONE:
3543  case VUT_ACTION:
3544  case VUT_OTYPE:
3545  case VUT_SPECIALIST: // Only so long as it's at local range only
3546  case VUT_AI_LEVEL:
3547  case VUT_CITYTILE:
3548  case VUT_CITYSTATUS: // We don't *want* owner of our city to change
3549  case VUT_STYLE:
3550  case VUT_TOPO:
3551  case VUT_SERVERSETTING:
3552  case VUT_VISIONLAYER:
3553  case VUT_NINTEL:
3554  return true;
3555  case VUT_NATION:
3556  case VUT_NATIONGROUP:
3557  return (req->range != REQ_RANGE_ALLIANCE);
3558  case VUT_ADVANCE:
3559  case VUT_TECHFLAG:
3560  case VUT_GOVERNMENT:
3561  case VUT_ACHIEVEMENT:
3562  case VUT_IMPROVEMENT:
3563  case VUT_IMPR_GENUS:
3564  case VUT_MINSIZE:
3565  case VUT_MINCULTURE:
3566  case VUT_MINFOREIGNPCT:
3567  case VUT_MINTECHS:
3568  case VUT_NATIONALITY:
3569  case VUT_DIPLREL:
3570  case VUT_MAXTILEUNITS:
3571  case VUT_UTYPE: // Not sure about this one
3572  case VUT_UTFLAG: // Not sure about this one
3573  case VUT_UCLASS: // Not sure about this one
3574  case VUT_UCFLAG: // Not sure about this one
3575  case VUT_MINVETERAN:
3576  case VUT_UNITSTATE:
3577  case VUT_ACTIVITY:
3578  case VUT_MINMOVES:
3579  case VUT_MINHP:
3580  case VUT_AGE:
3581  case VUT_ROADFLAG:
3582  case VUT_EXTRAFLAG:
3583  case VUT_MINCALFRAG: // cyclically available
3584  return false;
3585  case VUT_TERRAIN:
3586  case VUT_EXTRA:
3587  case VUT_GOOD:
3588  case VUT_TERRAINCLASS:
3589  case VUT_TERRFLAG:
3590  case VUT_TERRAINALTER:
3591  case VUT_BASEFLAG:
3592  /* Terrains, specials and bases aren't really unchanging; in fact they're
3593  * practically guaranteed to change. We return TRUE here for historical
3594  * reasons and so that the AI doesn't get confused (since the AI
3595  * doesn't know how to meet special and terrain requirements). */
3596  return true;
3597  case VUT_MINYEAR:
3598  // Once year is reached, it does not change again
3599  return req->source.value.minyear > game.info.year;
3600  case VUT_COUNT:
3601  break;
3602  }
3603  fc_assert_msg(false, "Invalid source kind %d.", req->source.kind);
3604  return true;
3605 }
3606 
3611 bool is_req_in_vec(const struct requirement *req,
3612  const struct requirement_vector *vec)
3613 {
3614  requirement_vector_iterate(vec, preq)
3615  {
3616  if (are_requirements_equal(req, preq)) {
3617  return true;
3618  }
3619  }
3621 
3622  return false;
3623 }
3624 
3631 bool req_vec_wants_type(const struct requirement_vector *reqs,
3632  enum universals_n kind)
3633 {
3635  {
3636  if (preq->present && preq->source.kind == kind) {
3637  return true;
3638  }
3639  }
3641  return false;
3642 }
3643 
3652 req_vec_vector_number(const void *parent_item,
3653  const struct requirement_vector *vec)
3654 {
3655  Q_UNUSED(parent_item)
3656  if (vec) {
3657  return 0;
3658  } else {
3659  return -1;
3660  }
3661 }
3662 
3673 const char *req_vec_change_translation(const struct req_vec_change *change,
3674  const requirement_vector_namer namer)
3675 {
3676  const char *req_vec_description;
3677  static char buf[MAX_LEN_NAME * 3];
3678 
3679  fc_assert_ret_val(change, nullptr);
3680  fc_assert_ret_val(req_vec_change_operation_is_valid(change->operation),
3681  nullptr);
3682 
3683  // Get rid of the previous.
3684  buf[0] = '\0';
3685 
3686  if (namer == nullptr) {
3687  /* TRANS: default description of a requirement vector
3688  * (used in ruledit) */
3689  req_vec_description = _("the requirement vector");
3690  } else {
3691  req_vec_description = namer(change->vector_number);
3692  }
3693 
3694  switch (change->operation) {
3695  case RVCO_REMOVE:
3696  fc_snprintf(
3697  buf, sizeof(buf),
3698  /* TRANS: remove a requirement from a requirement vector
3699  * (in ruledit).
3700  * The first %s is the operation.
3701  * The second %s is the requirement.
3702  * The third %s is a description of the requirement vector,
3703  * like "actor_reqs" */
3704  _("%s %s from %s"), req_vec_change_operation_name(change->operation),
3705  qUtf8Printable(req_to_fstring(&change->req)), req_vec_description);
3706  break;
3707  case RVCO_APPEND:
3708  fc_snprintf(
3709  buf, sizeof(buf),
3710  /* TRANS: append a requirement to a requirement vector
3711  * (in ruledit).
3712  * The first %s is the operation.
3713  * The second %s is the requirement.
3714  * The third %s is a description of the requirement vector,
3715  * like "actor_reqs" */
3716  _("%s %s to %s"), req_vec_change_operation_name(change->operation),
3717  qUtf8Printable(req_to_fstring(&change->req)), req_vec_description);
3718  break;
3719  case RVCO_NOOP:
3720  fc_snprintf(buf, sizeof(buf),
3721  /* TRANS: do nothing to a requirement vector (in ruledit).
3722  * The first %s is a description of the requirement vector,
3723  * like "actor_reqs" */
3724  _("Do nothing to %s"), req_vec_description);
3725  break;
3726  }
3727 
3728  return buf;
3729 }
3730 
3741 bool req_vec_change_apply(const struct req_vec_change *modification,
3743  const void *parent_item)
3744 {
3745  struct requirement_vector *target =
3746  getter(parent_item, modification->vector_number);
3747  int i = 0;
3748 
3749  switch (modification->operation) {
3750  case RVCO_APPEND:
3751  requirement_vector_append(target, modification->req);
3752  return true;
3753  case RVCO_REMOVE:
3754  requirement_vector_iterate(target, preq)
3755  {
3756  if (are_requirements_equal(&modification->req, preq)) {
3757  requirement_vector_remove(target, i);
3758  return true;
3759  }
3760  i++;
3761  }
3763  return false;
3764  case RVCO_NOOP:
3765  return false;
3766  }
3767 
3768  return false;
3769 }
3770 
3780  const char *descr, ...)
3781 {
3782  int i;
3783  va_list ap;
3784 
3785  auto *out = new req_vec_problem{};
3786 
3787  va_start(ap, descr);
3788  fc_vsnprintf(out->description, sizeof(out->description), descr, ap);
3789  va_end(ap);
3790  va_start(ap, descr);
3791  fc_vsnprintf(out->description_translated,
3792  sizeof(out->description_translated), descr, ap);
3793  va_end(ap);
3794 
3795  out->num_suggested_solutions = num_suggested_solutions;
3796  out->suggested_solutions =
3797  new req_vec_change[out->num_suggested_solutions];
3798  for (i = 0; i < out->num_suggested_solutions; i++) {
3799  // No suggestions are ready yet.
3800  out->suggested_solutions[i].operation = RVCO_NOOP;
3801  out->suggested_solutions[i].vector_number = -1;
3802  out->suggested_solutions[i].req.source.kind = VUT_NONE;
3803  }
3804 
3805  return out;
3806 }
3807 
3814 {
3815  delete[] issue->suggested_solutions;
3816  issue->num_suggested_solutions = 0;
3817 
3818  delete issue;
3819 }
3820 
3832 struct req_vec_problem *
3833 req_vec_get_first_contradiction(const struct requirement_vector *vec,
3834  requirement_vector_number get_num,
3835  const void *parent_item)
3836 {
3837  int i, j;
3838  req_vec_num_in_item vec_num;
3839 
3840  if (vec == nullptr || requirement_vector_size(vec) == 0) {
3841  // No vector.
3842  return nullptr;
3843  }
3844 
3845  if (get_num == nullptr || parent_item == nullptr) {
3846  vec_num = 0;
3847  } else {
3848  vec_num = get_num(parent_item, vec);
3849  }
3850 
3851  // Look for contradictions
3852  for (i = 0; i < requirement_vector_size(vec); i++) {
3853  struct requirement *preq = requirement_vector_get(vec, i);
3854  for (j = 0; j < requirement_vector_size(vec); j++) {
3855  struct requirement *nreq = requirement_vector_get(vec, j);
3856 
3857  if (are_requirements_contradictions(preq, nreq)) {
3858  struct req_vec_problem *problem;
3859 
3860  problem = req_vec_problem_new(
3861  2, N_("Requirements {%s} and {%s} contradict each other."),
3862  qUtf8Printable(req_to_fstring(preq)),
3863  qUtf8Printable(req_to_fstring(nreq)));
3864 
3865  // The solution is to remove one of the contradictions.
3866  problem->suggested_solutions[0].operation = RVCO_REMOVE;
3867  problem->suggested_solutions[0].vector_number = vec_num;
3868  problem->suggested_solutions[0].req = *preq;
3869 
3870  problem->suggested_solutions[1].operation = RVCO_REMOVE;
3871  problem->suggested_solutions[1].vector_number = vec_num;
3872  problem->suggested_solutions[1].req = *nreq;
3873 
3874  // Only the first contradiction is reported.
3875  return problem;
3876  }
3877  }
3878  }
3879 
3880  return nullptr;
3881 }
3882 
3887 bool are_universals_equal(const struct universal *psource1,
3888  const struct universal *psource2)
3889 {
3890  if (psource1->kind != psource2->kind) {
3891  return false;
3892  }
3893  switch (psource1->kind) {
3894  case VUT_NONE:
3895  return true;
3896  case VUT_ADVANCE:
3897  return psource1->value.advance == psource2->value.advance;
3898  case VUT_TECHFLAG:
3899  return psource1->value.techflag == psource2->value.techflag;
3900  case VUT_GOVERNMENT:
3901  return psource1->value.govern == psource2->value.govern;
3902  case VUT_ACHIEVEMENT:
3903  return psource1->value.achievement == psource2->value.achievement;
3904  case VUT_STYLE:
3905  return psource1->value.style == psource2->value.style;
3906  case VUT_IMPROVEMENT:
3907  return psource1->value.building == psource2->value.building;
3908  case VUT_IMPR_GENUS:
3909  return psource1->value.impr_genus == psource2->value.impr_genus;
3910  case VUT_EXTRA:
3911  return psource1->value.extra == psource2->value.extra;
3912  case VUT_GOOD:
3913  return psource1->value.good == psource2->value.good;
3914  case VUT_TERRAIN:
3915  return psource1->value.terrain == psource2->value.terrain;
3916  case VUT_TERRFLAG:
3917  return psource1->value.terrainflag == psource2->value.terrainflag;
3918  case VUT_NATION:
3919  return psource1->value.nation == psource2->value.nation;
3920  case VUT_NATIONGROUP:
3921  return psource1->value.nationgroup == psource2->value.nationgroup;
3922  case VUT_NATIONALITY:
3923  return psource1->value.nationality == psource2->value.nationality;
3924  case VUT_DIPLREL:
3925  return psource1->value.diplrel == psource2->value.diplrel;
3926  case VUT_UTYPE:
3927  return psource1->value.utype == psource2->value.utype;
3928  case VUT_UTFLAG:
3929  return psource1->value.unitflag == psource2->value.unitflag;
3930  case VUT_UCLASS:
3931  return psource1->value.uclass == psource2->value.uclass;
3932  case VUT_UCFLAG:
3933  return psource1->value.unitclassflag == psource2->value.unitclassflag;
3934  case VUT_MINVETERAN:
3935  return psource1->value.minveteran == psource2->value.minveteran;
3936  case VUT_UNITSTATE:
3937  return psource1->value.unit_state == psource2->value.unit_state;
3938  case VUT_ACTIVITY:
3939  return psource1->value.activity == psource2->value.activity;
3940  case VUT_MINMOVES:
3941  return psource1->value.minmoves == psource2->value.minmoves;
3942  case VUT_MINHP:
3943  return psource1->value.min_hit_points == psource2->value.min_hit_points;
3944  case VUT_AGE:
3945  return psource1->value.age == psource2->value.age;
3946  case VUT_MINTECHS:
3947  return psource1->value.min_techs == psource2->value.min_techs;
3948  case VUT_ACTION:
3949  return (action_number(psource1->value.action)
3950  == action_number(psource2->value.action));
3951  case VUT_OTYPE:
3952  return psource1->value.outputtype == psource2->value.outputtype;
3953  case VUT_SPECIALIST:
3954  return psource1->value.specialist == psource2->value.specialist;
3955  case VUT_MINSIZE:
3956  return psource1->value.minsize == psource2->value.minsize;
3957  case VUT_MINCULTURE:
3958  return psource1->value.minculture == psource2->value.minculture;
3959  case VUT_MINFOREIGNPCT:
3960  return psource1->value.minforeignpct == psource2->value.minforeignpct;
3961  case VUT_AI_LEVEL:
3962  return psource1->value.ai_level == psource2->value.ai_level;
3963  case VUT_MAXTILEUNITS:
3964  return psource1->value.max_tile_units == psource2->value.max_tile_units;
3965  case VUT_TERRAINCLASS:
3966  return psource1->value.terrainclass == psource2->value.terrainclass;
3967  case VUT_BASEFLAG:
3968  return psource1->value.baseflag == psource2->value.baseflag;
3969  case VUT_ROADFLAG:
3970  return psource1->value.roadflag == psource2->value.roadflag;
3971  case VUT_EXTRAFLAG:
3972  return psource1->value.extraflag == psource2->value.extraflag;
3973  case VUT_MINYEAR:
3974  return psource1->value.minyear == psource2->value.minyear;
3975  case VUT_MINCALFRAG:
3976  return psource1->value.mincalfrag == psource2->value.mincalfrag;
3977  case VUT_TOPO:
3978  return psource1->value.topo_property == psource2->value.topo_property;
3979  case VUT_SERVERSETTING:
3980  return psource1->value.ssetval == psource2->value.ssetval;
3981  case VUT_TERRAINALTER:
3982  return psource1->value.terrainalter == psource2->value.terrainalter;
3983  case VUT_CITYTILE:
3984  return psource1->value.citytile == psource2->value.citytile;
3985  case VUT_CITYSTATUS:
3986  return psource1->value.citystatus == psource2->value.citystatus;
3987  case VUT_VISIONLAYER:
3988  return psource1->value.vlayer == psource2->value.vlayer;
3989  case VUT_NINTEL:
3990  return psource1->value.nintel == psource2->value.nintel;
3991  case VUT_COUNT:
3992  break;
3993  }
3994 
3995  fc_assert_msg(false, "Invalid source kind %d.", psource1->kind);
3996  return false;
3997 }
3998 
4003 const char *universal_rule_name(const struct universal *psource)
4004 {
4005  static char buffer[10];
4006 
4007  switch (psource->kind) {
4008  case VUT_NONE:
4009  return "(none)";
4010  case VUT_CITYTILE:
4011  return citytile_type_name(psource->value.citytile);
4012  case VUT_CITYSTATUS:
4013  return citystatus_type_name(psource->value.citystatus);
4014  case VUT_MINYEAR:
4015  fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minyear);
4016 
4017  return buffer;
4018  case VUT_MINCALFRAG:
4019  // Rule name is 0-based number, not pretty name from ruleset
4020  fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.mincalfrag);
4021 
4022  return buffer;
4023  case VUT_TOPO:
4024  return topo_flag_name(psource->value.topo_property);
4025  case VUT_SERVERSETTING:
4026  return ssetv_rule_name(psource->value.ssetval);
4027  case VUT_ADVANCE:
4028  return advance_rule_name(psource->value.advance);
4029  case VUT_TECHFLAG:
4030  return tech_flag_id_name(tech_flag_id(psource->value.techflag));
4031  case VUT_GOVERNMENT:
4032  return government_rule_name(psource->value.govern);
4033  case VUT_ACHIEVEMENT:
4034  return achievement_rule_name(psource->value.achievement);
4035  case VUT_STYLE:
4036  return style_rule_name(psource->value.style);
4037  case VUT_IMPROVEMENT:
4038  return improvement_rule_name(psource->value.building);
4039  case VUT_IMPR_GENUS:
4040  return impr_genus_id_name(psource->value.impr_genus);
4041  case VUT_EXTRA:
4042  return extra_rule_name(psource->value.extra);
4043  case VUT_GOOD:
4044  return goods_rule_name(psource->value.good);
4045  case VUT_TERRAIN:
4046  return terrain_rule_name(psource->value.terrain);
4047  case VUT_TERRFLAG:
4048  return terrain_flag_id_name(terrain_flag_id(psource->value.terrainflag));
4049  case VUT_NATION:
4050  return nation_rule_name(psource->value.nation);
4051  case VUT_NATIONGROUP:
4052  return nation_group_rule_name(psource->value.nationgroup);
4053  case VUT_DIPLREL:
4054  return diplrel_rule_name(psource->value.diplrel);
4055  case VUT_NATIONALITY:
4056  return nation_rule_name(psource->value.nationality);
4057  case VUT_UTYPE:
4058  return utype_rule_name(psource->value.utype);
4059  case VUT_UTFLAG:
4060  return unit_type_flag_id_name(
4061  unit_type_flag_id(psource->value.unitflag));
4062  case VUT_UCLASS:
4063  return uclass_rule_name(psource->value.uclass);
4064  case VUT_UCFLAG:
4065  return unit_class_flag_id_name(
4066  unit_class_flag_id(psource->value.unitclassflag));
4067  case VUT_MINVETERAN:
4068  fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minveteran);
4069 
4070  return buffer;
4071  case VUT_UNITSTATE:
4072  return ustate_prop_name(psource->value.unit_state);
4073  case VUT_ACTIVITY:
4074  return unit_activity_name(psource->value.activity);
4075  case VUT_MINMOVES:
4076  fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minmoves);
4077 
4078  return buffer;
4079  case VUT_MINHP:
4080  fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_hit_points);
4081 
4082  return buffer;
4083  case VUT_AGE:
4084  fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.age);
4085 
4086  return buffer;
4087  case VUT_MINTECHS:
4088  fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.min_techs);
4089 
4090  return buffer;
4091  case VUT_ACTION:
4092  return action_rule_name(psource->value.action);
4093  case VUT_OTYPE:
4094  return get_output_identifier(psource->value.outputtype);
4095  case VUT_SPECIALIST:
4096  return specialist_rule_name(psource->value.specialist);
4097  case VUT_MINSIZE:
4098  fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minsize);
4099 
4100  return buffer;
4101  case VUT_MINCULTURE:
4102  fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minculture);
4103 
4104  return buffer;
4105  case VUT_MINFOREIGNPCT:
4106  fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.minforeignpct);
4107 
4108  return buffer;
4109  case VUT_AI_LEVEL:
4110  return ai_level_name(psource->value.ai_level);
4111  case VUT_MAXTILEUNITS:
4112  fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.max_tile_units);
4113  return buffer;
4114  case VUT_TERRAINCLASS:
4115  return terrain_class_name(terrain_class(psource->value.terrainclass));
4116  case VUT_BASEFLAG:
4117  return base_flag_id_name(base_flag_id(psource->value.baseflag));
4118  case VUT_ROADFLAG:
4119  return road_flag_id_name(road_flag_id(psource->value.roadflag));
4120  case VUT_EXTRAFLAG:
4121  return extra_flag_id_name(extra_flag_id(psource->value.extraflag));
4122  case VUT_TERRAINALTER:
4123  return terrain_alteration_name(
4124  terrain_alteration(psource->value.terrainalter));
4125  case VUT_VISIONLAYER:
4126  return vision_layer_name(psource->value.vlayer);
4127  case VUT_NINTEL:
4128  return national_intelligence_name(psource->value.nintel);
4129  case VUT_COUNT:
4130  break;
4131  }
4132 
4133  fc_assert_msg(false, "Invalid source kind %d.", psource->kind);
4134  return nullptr;
4135 }
4136 
4145 const char *universal_name_translation(const struct universal *psource,
4146  char *buf, size_t bufsz)
4147 {
4148  buf[0] = '\0'; // to be safe.
4149  switch (psource->kind) {
4150  case VUT_NONE:
4151  // TRANS: missing value
4152  fc_strlcat(buf, _("(none)"), bufsz);
4153  return buf;
4154  case VUT_ADVANCE:
4155  fc_strlcat(buf, advance_name_translation(psource->value.advance), bufsz);
4156  return buf;
4157  case VUT_TECHFLAG:
4158  cat_snprintf(
4159  buf, bufsz, _("\"%s\" tech"),
4160  tech_flag_id_translated_name(tech_flag_id(psource->value.techflag)));
4161  return buf;
4162  case VUT_GOVERNMENT:
4164  bufsz);
4165  return buf;
4166  case VUT_ACHIEVEMENT:
4168  bufsz);
4169  return buf;
4170  case VUT_STYLE:
4171  fc_strlcat(buf, style_name_translation(psource->value.style), bufsz);
4172  return buf;
4173  case VUT_IMPROVEMENT:
4175  bufsz);
4176  return buf;
4177  case VUT_IMPR_GENUS:
4178  fc_strlcat(buf, impr_genus_id_translated_name(psource->value.impr_genus),
4179  bufsz);
4180  return buf;
4181  case VUT_EXTRA:
4182  fc_strlcat(buf, extra_name_translation(psource->value.extra), bufsz);
4183  return buf;
4184  case VUT_GOOD:
4185  fc_strlcat(buf, goods_name_translation(psource->value.good), bufsz);
4186  return buf;
4187  case VUT_TERRAIN:
4188  fc_strlcat(buf, terrain_name_translation(psource->value.terrain), bufsz);
4189  return buf;
4190  case VUT_NATION:
4192  bufsz);
4193  return buf;
4194  case VUT_NATIONGROUP:
4195  fc_strlcat(buf,
4197  bufsz);
4198  return buf;
4199  case VUT_NATIONALITY:
4200  cat_snprintf(buf, bufsz, _("%s citizens"),
4202  return buf;
4203  case VUT_DIPLREL:
4204  fc_strlcat(buf, diplrel_name_translation(psource->value.diplrel), bufsz);
4205  return buf;
4206  case VUT_UTYPE:
4207  fc_strlcat(buf, utype_name_translation(psource->value.utype), bufsz);
4208  return buf;
4209  case VUT_UTFLAG:
4210  cat_snprintf(buf, bufsz,
4211  // TRANS: Unit type flag
4212  Q_("?utflag:\"%s\" units"),
4213  unit_type_flag_id_translated_name(
4214  unit_type_flag_id(psource->value.unitflag)));
4215  return buf;
4216  case VUT_UCLASS:
4217  cat_snprintf(buf, bufsz,
4218  // TRANS: Unit class
4219  _("%s units"),
4221  return buf;
4222  case VUT_UCFLAG:
4223  cat_snprintf(buf, bufsz,
4224  // TRANS: Unit class flag
4225  Q_("?ucflag:\"%s\" units"),
4226  unit_class_flag_id_translated_name(
4227  unit_class_flag_id(psource->value.unitclassflag)));
4228  return buf;
4229  case VUT_MINVETERAN:
4230  // FIXME
4231  cat_snprintf(buf, bufsz, _("Veteran level >=%d"),
4232  psource->value.minveteran);
4233  return buf;
4234  case VUT_UNITSTATE:
4235  switch (psource->value.unit_state) {
4236  case USP_TRANSPORTED:
4237  /* TRANS: unit state. (appears in strings like "Missile+Transported")
4238  */
4239  cat_snprintf(buf, bufsz, _("Transported"));
4240  break;
4241  case USP_LIVABLE_TILE:
4242  cat_snprintf(buf, bufsz,
4243  /* TRANS: unit state. (appears in strings like
4244  * "Missile+On livable tile") */
4245  _("On livable tile"));
4246  break;
4247  case USP_DOMESTIC_TILE:
4248  cat_snprintf(buf, bufsz,
4249  /* TRANS: unit state. (appears in strings like
4250  * "Missile+On domestic tile") */
4251  _("On domestic tile"));
4252  break;
4253  case USP_TRANSPORTING:
4254  /* TRANS: unit state. (appears in strings like "Missile+Transported")
4255  */
4256  cat_snprintf(buf, bufsz, _("Transporting"));
4257  break;
4258  case USP_HAS_HOME_CITY:
4259  /* TRANS: unit state. (appears in strings like "Missile+Has a home
4260  * city") */
4261  cat_snprintf(buf, bufsz, _("Has a home city"));
4262  break;
4263  case USP_NATIVE_TILE:
4264  cat_snprintf(buf, bufsz,
4265  /* TRANS: unit state. (appears in strings like
4266  * "Missile+On native tile") */
4267  _("On native tile"));
4268  break;
4269  case USP_NATIVE_EXTRA:
4270  cat_snprintf(buf, bufsz,
4271  /* TRANS: unit state. (appears in strings like
4272  * "Missile+In native extra") */
4273  _("In native extra"));
4274  break;
4275  case USP_MOVED_THIS_TURN:
4276  /* TRANS: unit state. (appears in strings like
4277  * "Missile+Has moved this turn") */
4278  cat_snprintf(buf, bufsz, _("Has moved this turn"));
4279  break;
4280  case USP_COUNT:
4281  fc_assert_msg(psource->value.unit_state != USP_COUNT,
4282  "Invalid unit state property.");
4283  break;
4284  }
4285  return buf;
4286  case VUT_ACTIVITY:
4287  cat_snprintf(buf, bufsz, _("%s activity"),
4288  _(unit_activity_name(psource->value.activity)));
4289  return buf;
4290  case VUT_MINMOVES:
4291  /* TRANS: Minimum unit movement points left for requirement to be met
4292  * (%s is a string like "1" or "2 1/3") */
4293  cat_snprintf(buf, bufsz, _("%s MP"),
4294  move_points_text(psource->value.minmoves, true));
4295  return buf;
4296  case VUT_MINHP:
4297  // TRANS: HP = hit points
4298  cat_snprintf(buf, bufsz, _("%d HP"), psource->value.min_hit_points);
4299  return buf;
4300  case VUT_AGE:
4301  cat_snprintf(buf, bufsz, _("Age %d"), psource->value.age);
4302  return buf;
4303  case VUT_MINTECHS:
4304  cat_snprintf(buf, bufsz, _("%d Techs"), psource->value.min_techs);
4305  return buf;
4306  case VUT_ACTION:
4307  fc_strlcat(
4308  buf, qUtf8Printable(action_name_translation(psource->value.action)),
4309  bufsz);
4310  return buf;
4311  case VUT_OTYPE:
4312  // FIXME
4313  fc_strlcat(buf, get_output_name(psource->value.outputtype), bufsz);
4314  return buf;
4315  case VUT_SPECIALIST:
4317  bufsz);
4318  return buf;
4319  case VUT_MINSIZE:
4320  cat_snprintf(buf, bufsz, _("Size %d"), psource->value.minsize);
4321  return buf;
4322  case VUT_MINCULTURE:
4323  cat_snprintf(buf, bufsz, _("Culture %d"), psource->value.minculture);
4324  return buf;
4325  case VUT_MINFOREIGNPCT:
4326  cat_snprintf(buf, bufsz, _("%d%% Foreigners"),
4327  psource->value.minforeignpct);
4328  return buf;
4329  case VUT_AI_LEVEL:
4330  // TRANS: "Hard AI"
4331  cat_snprintf(buf, bufsz, _("%s AI"),
4332  ai_level_translated_name(psource->value.ai_level)); // FIXME
4333  return buf;
4334  case VUT_MAXTILEUNITS:
4335  // TRANS: here <= means 'less than or equal'
4336  cat_snprintf(
4337  buf, bufsz,
4338  PL_("<=%d unit", "<=%d units", psource->value.max_tile_units),
4339  psource->value.max_tile_units);
4340  return buf;
4341  case VUT_TERRAINCLASS:
4342  // TRANS: Terrain class: "Land terrain"
4343  cat_snprintf(buf, bufsz, _("%s terrain"),
4345  terrain_class(psource->value.terrainclass)));
4346  return buf;
4347  case VUT_TERRFLAG:
4348  cat_snprintf(buf, bufsz,
4349  // TRANS: Terrain flag
4350  Q_("?terrflag:\"%s\" terrain"),
4351  terrain_flag_id_translated_name(
4352  terrain_flag_id(psource->value.terrainflag)));
4353  return buf;
4354  case VUT_BASEFLAG:
4355  cat_snprintf(
4356  buf, bufsz,
4357  // TRANS: Base flag
4358  Q_("?baseflag:\"%s\" base"),
4359  base_flag_id_translated_name(base_flag_id(psource->value.baseflag)));
4360  return buf;
4361  case VUT_ROADFLAG:
4362  cat_snprintf(
4363  buf, bufsz,
4364  // TRANS: Road flag
4365  Q_("?roadflag:\"%s\" road"),
4366  road_flag_id_translated_name(road_flag_id(psource->value.roadflag)));
4367  return buf;
4368  case VUT_EXTRAFLAG:
4369  cat_snprintf(buf, bufsz,
4370  // TRANS: Extra flag
4371  Q_("?extraflag:\"%s\" extra"),
4372  extra_flag_id_translated_name(
4373  extra_flag_id(psource->value.extraflag)));
4374  return buf;
4375  case VUT_MINYEAR:
4376  cat_snprintf(buf, bufsz, _("After %s"),
4377  textyear(psource->value.minyear));
4378  return buf;
4379  case VUT_MINCALFRAG:
4380  /* TRANS: here >= means 'greater than or equal'.
4381  * %s identifies a calendar fragment (may be bare number). */
4382  cat_snprintf(buf, bufsz, _(">=%s"),
4383  textcalfrag(psource->value.mincalfrag));
4384  return buf;
4385  case VUT_TOPO:
4386  // TRANS: topology flag name ("WrapX", "ISO", etc)
4387  cat_snprintf(buf, bufsz, _("%s map"),
4388  _(topo_flag_name(psource->value.topo_property)));
4389  return buf;
4390  case VUT_SERVERSETTING:
4391  fc_strlcat(
4392  buf,
4393  qUtf8Printable(ssetv_human_readable(psource->value.ssetval, true)),
4394  bufsz);
4395  return buf;
4396  case VUT_TERRAINALTER:
4397  // TRANS: "Irrigation possible"
4398  cat_snprintf(buf, bufsz, _("%s possible"),
4399  Q_(terrain_alteration_name(
4400  terrain_alteration(psource->value.terrainalter))));
4401  return buf;
4402  case VUT_CITYTILE:
4403  switch (psource->value.citytile) {
4404  case CITYT_CENTER:
4405  fc_strlcat(buf, _("City center"), bufsz);
4406  break;
4407  case CITYT_CLAIMED:
4408  fc_strlcat(buf, _("Tile claimed"), bufsz);
4409  break;
4410  case CITYT_LAST:
4411  fc_assert(psource->value.citytile != CITYT_LAST);
4412  fc_strlcat(buf, "error", bufsz);
4413  break;
4414  }
4415  return buf;
4416  case VUT_CITYSTATUS:
4417  switch (psource->value.citystatus) {
4418  case CITYS_OWNED_BY_ORIGINAL:
4419  fc_strlcat(buf, _("Owned by original"), bufsz);
4420  break;
4421  case CITYS_LAST:
4422  fc_assert(psource->value.citystatus != CITYS_LAST);
4423  fc_strlcat(buf, "error", bufsz);
4424  break;
4425  }
4426  return buf;
4427  case VUT_VISIONLAYER:
4428  fc_strlcat(buf, vision_layer_translated_name(psource->value.vlayer),
4429  bufsz);
4430  return buf;
4431  case VUT_NINTEL:
4432  fc_strlcat(buf,
4433  national_intelligence_translated_name(psource->value.nintel),
4434  bufsz);
4435  return buf;
4436  case VUT_COUNT:
4437  break;
4438  }
4439 
4440  fc_assert_msg(false, "Invalid source kind %d.", psource->kind);
4441  return buf;
4442 }
4443 
4447 const char *universal_type_rule_name(const struct universal *psource)
4448 {
4449  return universals_n_name(psource->kind);
4450 }
4451 
4455 int universal_build_shield_cost(const struct city *pcity,
4456  const struct universal *target)
4457 {
4458  switch (target->kind) {
4459  case VUT_IMPROVEMENT:
4460  return impr_build_shield_cost(pcity, target->value.building);
4461  case VUT_UTYPE:
4462  return utype_build_shield_cost(pcity, target->value.utype);
4463  default:
4464  break;
4465  }
4466  return FC_INFINITY;
4467 }
4468 
4474 bool universal_replace_in_req_vec(struct requirement_vector *reqs,
4475  const struct universal *to_replace,
4476  const struct universal *replacement)
4477 {
4478  bool changed = false;
4479 
4481  {
4482  if (universal_is_mentioned_by_requirement(preq, to_replace)) {
4483  preq->source = *replacement;
4484  changed = true;
4485  }
4486  }
4488 
4489  return changed;
4490 }
4491 
4497  const struct requirement_vector *reqs, const struct universal *psource)
4498 {
4500  {
4501  if (universal_is_mentioned_by_requirement(preq, psource)) {
4502  return true;
4503  }
4504  }
4506 
4507  return false;
4508 }
4509 
4513 enum req_item_found
4514 universal_fulfills_requirement(const struct requirement *preq,
4515  const struct universal *source)
4516 {
4519  "No req item found function for %s", universal_type_rule_name(source));
4520 
4521  return (*universal_found_function[source->kind])(preq, source);
4522 }
4523 
4534 bool universal_fulfills_requirements(bool check_necessary,
4535  const struct requirement_vector *reqs,
4536  const struct universal *source)
4537 {
4538  bool necessary = false;
4539 
4541  universal_found_function[source->kind], !check_necessary,
4542  "No req item found function for %s", universal_type_rule_name(source));
4543 
4545  {
4546  switch ((*universal_found_function[source->kind])(preq, source)) {
4547  case ITF_NOT_APPLICABLE:
4548  continue;
4549  case ITF_NO:
4550  if (preq->present) {
4551  return false;
4552  }
4553  break;
4554  case ITF_YES:
4555  if (preq->present) {
4556  necessary = true;
4557  } else {
4558  return false;
4559  }
4560  break;
4561  }
4562  }
4564 
4565  return (!check_necessary || necessary);
4566 }
4567 
4573  bool check_necessary, const struct requirement_vector *reqs,
4574  const struct universal source)
4575 {
4576  return universal_fulfills_requirements(check_necessary, reqs, &source);
4577 }
4578 
4584  const struct universal *source)
4585 {
4586  switch (universal_fulfills_requirement(req, source)) {
4587  case ITF_NOT_APPLICABLE:
4588  return false;
4589  case ITF_NO:
4590  case ITF_YES:
4591  return true;
4592  }
4593 
4594  qCritical("Unhandled item_found value");
4595  return false;
4596 }
4597 
4601 static enum req_item_found nation_found(const struct requirement *preq,
4602  const struct universal *source)
4603 {
4604  fc_assert(source->value.nation);
4605 
4606  switch (preq->source.kind) {
4607  case VUT_NATION:
4608  return preq->source.value.nation == source->value.nation ? ITF_YES
4609  : ITF_NO;
4610  case VUT_NATIONGROUP:
4611  return nation_is_in_group(source->value.nation,
4612  preq->source.value.nationgroup)
4613  ? ITF_YES
4614  : ITF_NO;
4615  default:
4616  break;
4617  }
4618 
4619  return ITF_NOT_APPLICABLE;
4620 }
4621 
4625 static enum req_item_found government_found(const struct requirement *preq,
4626  const struct universal *source)
4627 {
4628  fc_assert(source->value.govern);
4629 
4630  if (preq->source.kind == VUT_GOVERNMENT) {
4631  return preq->source.value.govern == source->value.govern ? ITF_YES
4632  : ITF_NO;
4633  }
4634 
4635  return ITF_NOT_APPLICABLE;
4636 }
4637 
4641 static enum req_item_found improvement_found(const struct requirement *preq,
4642  const struct universal *source)
4643 {
4644  fc_assert(source->value.building);
4645 
4646  /* We only ever return ITF_YES, because requiring a different
4647  * improvement does not mean that the improvement under consideration
4648  * cannot fulfill the requirements. This is necessary to allow
4649  * requirement vectors to specify multiple required improvements. */
4650 
4651  switch (preq->source.kind) {
4652  case VUT_IMPROVEMENT:
4653  if (source->value.building == preq->source.value.building) {
4654  return ITF_YES;
4655  }
4656  break;
4657  case VUT_IMPR_GENUS:
4658  if (source->value.building->genus == preq->source.value.impr_genus) {
4659  return ITF_YES;
4660  }
4661  break;
4662  default:
4663  break;
4664  }
4665 
4666  return ITF_NOT_APPLICABLE;
4667 }
4668 
4672 static enum req_item_found unit_class_found(const struct requirement *preq,
4673  const struct universal *source)
4674 {
4675  fc_assert(source->value.uclass);
4676 
4677  switch (preq->source.kind) {
4678  case VUT_UCLASS:
4679  return source->value.uclass == preq->source.value.uclass ? ITF_YES
4680  : ITF_NO;
4681  case VUT_UCFLAG:
4682  return uclass_has_flag(
4683  source->value.uclass,
4684  unit_class_flag_id(preq->source.value.unitclassflag))
4685  ? ITF_YES
4686  : ITF_NO;
4687 
4688  default:
4689  // Not found and not relevant.
4690  return ITF_NOT_APPLICABLE;
4691  };
4692 }
4693 
4697 static enum req_item_found unit_type_found(const struct requirement *preq,
4698  const struct universal *source)
4699 {
4700  fc_assert(source->value.utype);
4701 
4702  switch (preq->source.kind) {
4703  case VUT_UTYPE:
4704  return source->value.utype == preq->source.value.utype ? ITF_YES
4705  : ITF_NO;
4706  case VUT_UCLASS:
4707  return utype_class(source->value.utype) == preq->source.value.uclass
4708  ? ITF_YES
4709  : ITF_NO;
4710  case VUT_UTFLAG:
4711  return utype_has_flag(source->value.utype, preq->source.value.unitflag)
4712  ? ITF_YES
4713  : ITF_NO;
4714  case VUT_UCFLAG:
4715  return uclass_has_flag(
4716  utype_class(source->value.utype),
4717  unit_class_flag_id(preq->source.value.unitclassflag))
4718  ? ITF_YES
4719  : ITF_NO;
4720  default:
4721  // Not found and not relevant.
4722  return ITF_NOT_APPLICABLE;
4723  };
4724 }
4725 
4729 static enum req_item_found
4730 unit_activity_found(const struct requirement *preq,
4731  const struct universal *source)
4732 {
4733  fc_assert_ret_val(unit_activity_is_valid(source->value.activity),
4735 
4736  switch (preq->source.kind) {
4737  case VUT_ACTIVITY:
4738  return source->value.activity == preq->source.value.activity ? ITF_YES
4739  : ITF_NO;
4740  default:
4741  // Not found and not relevant.
4742  return ITF_NOT_APPLICABLE;
4743  };
4744 }
4745 
4749 static enum req_item_found terrain_type_found(const struct requirement *preq,
4750  const struct universal *source)
4751 {
4752  fc_assert(source->value.terrain);
4753 
4754  switch (preq->source.kind) {
4755  case VUT_TERRAIN:
4756  return source->value.terrain == preq->source.value.terrain ? ITF_YES
4757  : ITF_NO;
4758  case VUT_TERRAINCLASS:
4759  return terrain_type_terrain_class(source->value.terrain)
4760  == preq->source.value.terrainclass
4761  ? ITF_YES
4762  : ITF_NO;
4763  case VUT_TERRFLAG:
4764  return terrain_has_flag(source->value.terrain,
4765  preq->source.value.terrainflag)
4766  ? ITF_YES
4767  : ITF_NO;
4768  default:
4769  // Not found and not relevant.
4770  return ITF_NOT_APPLICABLE;
4771  };
4772 }
4773 
4777 static enum req_item_found city_tile_found(const struct requirement *preq,
4778  const struct universal *source)
4779 {
4780  fc_assert_ret_val(citytile_type_is_valid(source->value.citytile),
4782 
4783  switch (preq->source.kind) {
4784  case VUT_CITYTILE:
4785  return (source->value.citytile == preq->source.value.citytile
4786  ? ITF_YES
4787  // The presence of one tile state doesn't block another
4788  : ITF_NOT_APPLICABLE);
4789  default:
4790  // Not found and not relevant.
4791  return ITF_NOT_APPLICABLE;
4792  };
4793 }
4794 
4798 static enum req_item_found extra_type_found(const struct requirement *preq,
4799  const struct universal *source)
4800 {
4801  fc_assert(source->value.extra);
4802 
4803  switch (preq->source.kind) {
4804  case VUT_EXTRA:
4805  return source->value.extra == preq->source.value.extra ? ITF_YES
4806  : ITF_NO;
4807  case VUT_EXTRAFLAG:
4808  return extra_has_flag(source->value.extra,
4809  extra_flag_id(preq->source.value.extraflag))
4810  ? ITF_YES
4811  : ITF_NO;
4812  case VUT_BASEFLAG: {
4813  struct base_type *b = extra_base_get(source->value.extra);
4814  return b && base_has_flag(b, base_flag_id(preq->source.value.baseflag))
4815  ? ITF_YES
4816  : ITF_NO;
4817  }
4818  case VUT_ROADFLAG: {
4819  struct road_type *r = extra_road_get(source->value.extra);
4820  return r && road_has_flag(r, road_flag_id(preq->source.value.roadflag))
4821  ? ITF_YES
4822  : ITF_NO;
4823  }
4824  default:
4825  // Not found and not relevant.
4826  return ITF_NOT_APPLICABLE;
4827  }
4828 }
4829 
4833 static enum req_item_found action_found(const struct requirement *preq,
4834  const struct universal *source)
4835 {
4836  fc_assert(source->value.action);
4837 
4838  if (preq->source.kind == VUT_ACTION) {
4839  return preq->source.value.action == source->value.action ? ITF_YES
4840  : ITF_NO;
4841  }
4842 
4843  return ITF_NOT_APPLICABLE;
4844 }
4845 
4849 static enum req_item_found diplrel_found(const struct requirement *preq,
4850  const struct universal *source)
4851 {
4852  if (preq->source.kind == VUT_DIPLREL) {
4853  if (preq->source.value.diplrel == source->value.diplrel) {
4854  // The diplrel itself.
4855  return ITF_YES;
4856  }
4857  if (preq->source.value.diplrel == DRO_FOREIGN
4858  && source->value.diplrel < DS_LAST) {
4859  // All diplstate_type values are to foreigners.
4860  return ITF_YES;
4861  }
4862  if (preq->source.value.diplrel == DRO_HOSTS_EMBASSY
4863  && source->value.diplrel == DRO_HOSTS_REAL_EMBASSY) {
4864  // A real embassy is an embassy.
4865  return ITF_YES;
4866  }
4867  if (preq->source.value.diplrel == DRO_HAS_EMBASSY
4868  && source->value.diplrel == DRO_HAS_REAL_EMBASSY) {
4869  // A real embassy is an embassy.
4870  return ITF_YES;
4871  }
4872  if (preq->source.value.diplrel < DS_LAST
4873  && source->value.diplrel < DS_LAST
4874  && preq->range == REQ_RANGE_LOCAL) {
4876  ITF_YES);
4877  // Can only have one diplstate_type to a specific player.
4878  return ITF_NO;
4879  }
4880  // Can't say this diplrel blocks the other diplrel.
4881  return ITF_NOT_APPLICABLE;
4882  }
4883 
4884  // Not relevant.
4885  return ITF_NOT_APPLICABLE;
4886 }
4887 
4891 static enum req_item_found output_type_found(const struct requirement *preq,
4892  const struct universal *source)
4893 {
4894  switch (preq->source.kind) {
4895  case VUT_OTYPE:
4896  return source->value.outputtype == preq->source.value.outputtype
4897  ? ITF_YES
4898  : ITF_NO;
4899  default:
4900  // Not found and not relevant.
4901  return ITF_NOT_APPLICABLE;
4902  }
4903 }
4904 
4909 {
4910  universal_found_function[VUT_GOVERNMENT] = &government_found;
4911  universal_found_function[VUT_NATION] = &nation_found;
4912  universal_found_function[VUT_IMPROVEMENT] = &improvement_found;
4917  universal_found_function[VUT_CITYTILE] = &city_tile_found;
4920  universal_found_function[VUT_ACTION] = &action_found;
4921  universal_found_function[VUT_DIPLREL] = &diplrel_found;
4922 }
4923 
4932 int requirement_kind_ereq(const int value, const enum req_range range,
4933  const bool present, const int max_value)
4934 {
4935  /* The enumerators in each range starts with present for every possible
4936  * value followed by !present for every possible value. */
4937  const int pres_start = (present ? 0 : max_value);
4938 
4939  /* The enumerators for every range follows all the positions of the
4940  * previous range(s). */
4941  const int range_start = ((max_value - 1) * 2) * range;
4942 
4943  return range_start + pres_start + value;
4944 }
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
Has the given player got the achievement?
int achievement_number(const struct achievement *pach)
Return the achievement id.
const char * achievement_rule_name(struct achievement *pach)
Return untranslated name of this achievement type.
struct achievement * achievement_by_number(int id)
Return achievements of given id.
struct achievement * achievement_by_rule_name(const char *name)
Returns achievement matching rule name or nullptr if there is no achievement with such name.
bool achievement_claimed(const struct achievement *pach)
Has anybody got the achievement?
const char * achievement_name_translation(struct achievement *pach)
Return translated name of this achievement type.
const char * action_rule_name(const struct action *action)
Get the rule name of the action.
Definition: actions.cpp:1343
int action_number(const struct action *action)
Get the universal number of the action.
Definition: actions.cpp:1338
struct action * action_by_rule_name(const char *name)
Return the action with the given name.
Definition: actions.cpp:1169
const QString action_name_translation(const struct action *action)
Get the action name used when displaying the action in the UI.
Definition: actions.cpp:1353
struct action * action_by_number(action_id act_id)
Return the action with the given id.
Definition: actions.cpp:1149
bool base_has_flag(const struct base_type *pbase, enum base_flag_id flag)
Check if base provides effect.
Definition: base.cpp:24
bool is_base_flag_card_near(const struct tile *ptile, enum base_flag_id flag)
Returns TRUE iff any cardinally adjacent tile contains a base with the given flag (does not check pti...
Definition: base.cpp:33
bool is_base_flag_near_tile(const struct tile *ptile, enum base_flag_id flag)
Returns TRUE iff any adjacent tile contains a base with the given flag (does not check ptile itself)
Definition: base.cpp:56
bool BV_ISSET(const BV &bv, int bit)
Definition: bitvector.h:37
const char * textcalfrag(int frag)
Produce a statically allocated textual representation of the given calendar fragment.
Definition: calendar.cpp:97
const char * textyear(int year)
Produce a statically allocated textual representation of the given year.
Definition: calendar.cpp:116
citizens citizens_nation_foreign(const struct city *pcity)
Get the number of foreign citizens.
Definition: citizens.cpp:82
#define citizens_iterate_end
Definition: citizens.h:44
#define citizens_iterate(_pcity, _pslot, _nationality)
Definition: citizens.h:37
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Return TRUE iff the city has this building in it.
Definition: city.cpp:1189
struct player * city_owner(const struct city *pcity)
Return the owner of the city.
Definition: city.cpp:1083
Output_type_id output_type_by_identifier(const char *id)
Find the output type for this output identifier.
Definition: city.cpp:620
struct tile * city_tile(const struct city *pcity)
Return the tile location of the city.
Definition: city.cpp:1095
int city_map_radius_sq_get(const struct city *pcity)
Returns the current squared radius of the city.
Definition: city.cpp:130
const char * get_output_identifier(Output_type_id output)
Return an id string for the output type.
Definition: city.cpp:592
bool is_city_center(const struct city *pcity, const struct tile *ptile)
Return TRUE if the city is centered at the given tile.
Definition: city.cpp:3497
const char * get_output_name(Output_type_id output)
Return a translated name for the output type.
Definition: city.cpp:602
citizens city_size_get(const struct city *pcity)
Get the city size.
Definition: city.cpp:1101
#define city_tile_iterate(_radius_sq, _city_tile, _tile)
Definition: city.h:202
#define city_tile_iterate_end
Definition: city.h:209
int city_culture(const struct city *pcity)
Return current culture score of the city.
Definition: culture.cpp:23
int player_culture(const struct player *plr)
Return current culture score of the player.
Definition: culture.cpp:40
struct @19::@20 reqs
struct extra_type * extra_type_by_rule_name(const char *name)
Returns extra type matching rule name or nullptr if there is no extra type with such name.
Definition: extras.cpp:183
struct extra_type * extra_by_number(int id)
Return extras type of given id.
Definition: extras.cpp:154
int extra_number(const struct extra_type *pextra)
Return the extra id.
Definition: extras.cpp:132
bool is_extra_flag_card_near(const struct tile *ptile, enum extra_flag_id flag)
Returns TRUE iff any cardinally adjacent tile contains an extra with the given flag (does not check p...
Definition: extras.cpp:788
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Check if extra has given flag.
Definition: extras.cpp:779
const char * extra_name_translation(const struct extra_type *pextra)
Return the (translated) name of the extra type.
Definition: extras.cpp:165
bool is_extra_near_tile(const struct tile *ptile, const struct extra_type *pextra)
Is there extra of the given type near tile? (Does not check ptile itself.)
Definition: extras.cpp:335
bool is_extra_flag_near_tile(const struct tile *ptile, enum extra_flag_id flag)
Returns TRUE iff any adjacent tile contains an extra with the given flag (does not check ptile itself...
Definition: extras.cpp:812
bool is_extra_card_near(const struct tile *ptile, const struct extra_type *pextra)
Is there extra of the given type cardinally near tile? (Does not check ptile itself....
Definition: extras.cpp:317
const char * extra_rule_name(const struct extra_type *pextra)
Return the (untranslated) rule name of the extra type.
Definition: extras.cpp:174
#define extra_base_get(_e_)
Definition: extras.h:170
#define extra_road_get(_e_)
Definition: extras.h:171
int Tech_type_id
Definition: fc_types.h:294
req_problem_type
Definition: fc_types.h:566
@ RPT_POSSIBLE
Definition: fc_types.h:567
#define MAX_LEN_NAME
Definition: fc_types.h:61
output_type_id
Definition: fc_types.h:84
@ O_LAST
Definition: fc_types.h:91
#define Q_(String)
Definition: fcintl.h:53
#define PL_(String1, String2, n)
Definition: fcintl.h:54
#define _(String)
Definition: fcintl.h:50
#define N_(String)
Definition: fcintl.h:52
struct civ_game game
Definition: game.cpp:47
bool is_server()
Is program type server?
Definition: game.cpp:57
struct world wld
Definition: game.cpp:48
struct government * government_of_player(const struct player *pplayer)
Return the government of a player.
Definition: government.cpp:107
struct government * government_by_number(const Government_type_id gov)
Return the government with the given index.
Definition: government.cpp:96
const char * government_rule_name(const struct government *pgovern)
Return the (untranslated) rule name of the government.
Definition: government.cpp:126
struct government * government_by_rule_name(const char *name)
Returns the government that has the given (untranslated) rule name.
Definition: government.cpp:48
Government_type_id government_number(const struct government *pgovern)
Return the government index.
Definition: government.cpp:84
const char * government_name_translation(const struct government *pgovern)
Return the (translated) name of the given government.
Definition: government.cpp:136
bool great_wonder_is_built(const struct impr_type *pimprove)
Returns whether this wonder is currently built.
const char * improvement_rule_name(const struct impr_type *pimprove)
Return the (untranslated) rule name of the improvement.
struct impr_type * improvement_by_rule_name(const char *name)
Does a linear search of improvement_types[].name.vernacular Returns nullptr when none match.
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
Returns whether this wonder has been destroyed.
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
Returns whether the player has lost this wonder after having owned it (small or great).
struct impr_type * improvement_by_number(const Impr_type_id id)
Returns the improvement type for the given index/ID.
bool wonder_is_built(const struct player *pplayer, const struct impr_type *pimprove)
Returns whether the player is currently in possession of this wonder (small or great) and it hasn't b...
Impr_type_id improvement_number(const struct impr_type *pimprove)
Return the improvement index.
int impr_build_shield_cost(const struct city *pcity, const struct impr_type *pimprove)
Returns the number of shields it takes to build this improvement.
bool is_wonder(const struct impr_type *pimprove)
Returns whether improvement is some kind of wonder.
bool is_great_wonder(const struct impr_type *pimprove)
Is this building a great wonder?
bool improvement_obsolete(const struct player *pplayer, const struct impr_type *pimprove, const struct city *pcity)
Returns TRUE if the improvement or wonder is obsolete.
struct city * city_from_wonder(const struct player *pplayer, const struct impr_type *pimprove)
Get the world city with this wonder (small or great).
const char * improvement_name_translation(const struct impr_type *pimprove)
Return the (translated) name of the given improvement.
#define fc_assert_msg(condition, message,...)
Definition: log.h:96
#define fc_assert(condition)
Definition: log.h:89
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition: log.h:132
#define current_topo_has_flag(flag)
Definition: map.h:37
#define adjc_iterate_end
Definition: map.h:358
#define cardinal_adjc_iterate_end
Definition: map.h:384
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition: map.h:351
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition: map.h:380
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Return TRUE iff the unit can "exist" at this location.
Definition: movement.cpp:267
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
This tile is native to unit.
Definition: movement.cpp:279
const char * move_points_text(int mp, bool reduce)
Simple version of move_points_text_full() – render positive movement points as text without any prefi...
Definition: movement.cpp:856
struct nation_type * nation_by_number(const Nation_type_id nation)
Return the nation with the given index.
Definition: nation.cpp:450
const char * nation_group_name_translation(const struct nation_group *pgroup)
Return the translated name of a nation group.
Definition: nation.cpp:953
const char * nation_rule_name(const struct nation_type *pnation)
Return the (untranslated) rule name of the nation (adjective form).
Definition: nation.cpp:115
const char * nation_adjective_translation(const struct nation_type *pnation)
Return the (translated) adjective for the given nation.
Definition: nation.cpp:126
struct nation_group * nation_group_by_rule_name(const char *name)
Return the nation group that has the given (untranslated) rule name.
Definition: nation.cpp:882
bool nation_is_in_group(const struct nation_type *pnation, const struct nation_group *pgroup)
Check if the given nation is in a given group.
Definition: nation.cpp:962
struct nation_group * nation_group_by_number(int id)
Return the nation group with the given index.
Definition: nation.cpp:870
struct nation_type * nation_by_rule_name(const char *name)
Returns the nation that has the given (untranslated) rule name (adjective).
Definition: nation.cpp:98
Nation_type_id nation_index(const struct nation_type *pnation)
Return the nation index.
Definition: nation.cpp:464
struct nation_type * nation_of_player(const struct player *pplayer)
Return the nation of a player.
Definition: nation.cpp:419
const char * nation_group_rule_name(const struct nation_group *pgroup)
Return the (untranslated) rule name of a nation group.
Definition: nation.cpp:942
int nation_group_number(const struct nation_group *pgroup)
Return the nation group index.
Definition: nation.cpp:823
#define NO_NATION_SELECTED
Definition: nation.h:21
bool player_knows_techs_with_flag(const struct player *pplayer, enum tech_flag_id flag)
Returns TRUE iff the player knows at least one tech which has the given flag.
Definition: player.cpp:1238
bv_diplrel_all_reqs diplrel_req_contradicts(const struct requirement *req)
Get the DiplRel requirements that are known to contradict the specified DiplRel requirement.
Definition: player.cpp:1714
int diplrel_by_rule_name(const char *value)
Return the diplomatic relation that has the given (untranslated) rule name.
Definition: player.cpp:1492
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Return TRUE if players are in the same team.
Definition: player.cpp:1405
const char * diplrel_name_translation(int value)
Return the translated name of the given diplomatic relation.
Definition: player.cpp:1538
bool is_diplrel_to_other(const struct player *pplayer, int diplrel)
Return TRUE iff pplayer has the diplomatic relation to any living player.
Definition: player.cpp:1471
bool is_diplrel_between(const struct player *player1, const struct player *player2, int diplrel)
Return TRUE iff player1 has the diplomatic relation to player2.
Definition: player.cpp:1422
struct player * player_slot_get_player(const struct player_slot *pslot)
Returns the team corresponding to the slot.
Definition: player.cpp:384
int player_age(const struct player *pplayer)
"Age" of the player: number of turns spent alive since created.
Definition: player.cpp:876
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Returns true iff players are allied.
Definition: player.cpp:1334
const char * diplrel_rule_name(int value)
Return the (untranslated) rule name of the given diplomatic relation.
Definition: player.cpp:1526
#define players_iterate_end
Definition: player.h:520
#define players_iterate(_pplayer)
Definition: player.h:514
#define is_ai(plr)
Definition: player.h:227
#define players_iterate_alive_end
Definition: player.h:532
#define players_iterate_alive(_pplayer)
Definition: player.h:526
static enum req_item_found terrain_type_found(const struct requirement *preq, const struct universal *source)
Find if a terrain type fulfills a requirement.
static enum fc_tristate is_terrainflag_in_range(const struct tile *target_tile, const struct city *target_city, enum req_range range, bool survives, enum terrain_flag_id terrflag)
Is there a terrain with the given flag within range of the target?
bool universal_is_relevant_to_requirement(const struct requirement *req, const struct universal *source)
Returns TRUE iff the specified universal is relevant to fulfilling the specified requirement.
bool is_req_in_vec(const struct requirement *req, const struct requirement_vector *vec)
Returns TRUE iff the requirement vector vec contains the requirement req.
static int num_city_buildings(const struct city *pcity, const struct impr_type *building)
Returns the number of buildings of a certain type in a city.
int universal_build_shield_cost(const struct city *pcity, const struct universal *target)
Return the number of shields it takes to build this universal.
static enum req_item_found city_tile_found(const struct requirement *preq, const struct universal *source)
Find if a tile state fulfills a requirement.
static enum fc_tristate is_citystatus_in_range(const struct city *target_city, enum req_range range, enum citystatus_type citystatus)
Is city with specific status in range.
static universal_found universal_found_function[VUT_COUNT]
static enum req_item_found unit_type_found(const struct requirement *preq, const struct universal *source)
Find if a unit type fulfills a requirement.
void universal_extraction(const struct universal *source, int *kind, int *value)
Extract universal structure into its components for serialization; the opposite of universal_by_numbe...
static int num_player_buildings(const struct player *pplayer, const struct impr_type *building)
Returns the number of buildings of a certain type owned by plr.
static enum fc_tristate is_baseflag_in_range(const struct tile *target_tile, const struct city *target_city, enum req_range range, bool survives, enum base_flag_id baseflag)
Is there a base with the given flag within range of the target?
static enum fc_tristate is_achievement_in_range(const struct player *target_player, enum req_range range, const struct achievement *achievement)
Has achievement been claimed by someone in range.
static enum fc_tristate is_minforeignpct_in_range(const struct city *target_city, enum req_range range, int min_foreign_pct)
Is city with at least min_foreign_pct foreigners in range?
static int num_continent_buildings(const struct player *pplayer, int continent, const struct impr_type *building)
Returns the number of buildings of a certain type on a continent.
req_vec_num_in_item req_vec_vector_number(const void *parent_item, const struct requirement_vector *vec)
Returns the requirement vector number of the specified requirement vector in the specified requiremen...
static enum fc_tristate is_extra_type_in_range(const struct tile *target_tile, const struct city *target_city, enum req_range range, bool survives, struct extra_type *pextra)
Is there a source extra type within range of the target?
bool universal_fulfills_requirements(bool check_necessary, const struct requirement_vector *reqs, const struct universal *source)
Will the universal 'source' fulfill the requirements in the list? If 'check_necessary' is FALSE: are ...
bool sv_universal_fulfills_requirements(bool check_necessary, const struct requirement_vector *reqs, const struct universal source)
Version of universal_fulfills_requirements that takes the universal by value.
static enum fc_tristate is_building_in_range(const struct player *target_player, const struct city *target_city, const struct impr_type *target_building, enum req_range range, bool survives, const struct impr_type *source)
Are there any source buildings within range of the target that are not obsolete?
bool req_vec_change_apply(const struct req_vec_change *modification, requirement_vector_by_number getter, const void *parent_item)
Returns TRUE iff the specified requirement vector modification was successfully applied to the specif...
bool are_requirements_equal(const struct requirement *req1, const struct requirement *req2)
Returns TRUE if req1 and req2 are equal.
static enum fc_tristate is_nation_group_in_range(const struct player *target_player, enum req_range range, bool survives, const struct nation_group *ngroup)
Is there a nation group within range of the target?
struct req_vec_problem * req_vec_problem_new(int num_suggested_solutions, const char *descr,...)
Returns a new requirement vector problem with the specified number of suggested solutions and the spe...
static enum req_item_found extra_type_found(const struct requirement *preq, const struct universal *source)
Find if an extra type fulfills a requirement.
bool is_req_active(const struct player *target_player, const struct player *other_player, const struct city *target_city, const struct impr_type *target_building, const struct tile *target_tile, const struct unit *target_unit, const struct unit_type *target_unittype, const struct output_type *target_output, const struct specialist *target_specialist, const struct action *target_action, const struct requirement *req, const enum req_problem_type prob_type, const enum vision_layer vision_layer, const enum national_intelligence nintel)
Checks the requirement to see if it is active on the given target.
bool is_req_unchanging(const struct requirement *req)
Return TRUE if this is an "unchanging" requirement.
struct req_vec_problem * req_vec_get_first_contradiction(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
Returns the first self contradiction found in the specified requirement vector with suggested solutio...
struct requirement req_from_str(const char *type, const char *range, bool survives, bool present, bool quiet, const char *value)
Parse a requirement type and value string into a requirement structure.
void universal_value_from_str(struct universal *source, const char *value)
Parse requirement value strings into a universal structure.
void req_get_values(const struct requirement *req, int *type, int *range, bool *survives, bool *present, bool *quiet, int *value)
Return the value of a req as a serializable integer.
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
Set the values of a req from serializable integers.
const char * universal_type_rule_name(const struct universal *psource)
Return untranslated name of the universal source name.
bool are_reqs_active(const struct player *target_player, const struct player *other_player, const struct city *target_city, const struct impr_type *target_building, const struct tile *target_tile, const struct unit *target_unit, const struct unit_type *target_unittype, const struct output_type *target_output, const struct specialist *target_specialist, const struct action *target_action, const struct requirement_vector *reqs, const enum req_problem_type prob_type, const enum vision_layer vision_layer, const enum national_intelligence nintel)
Checks the requirement(s) to see if they are active on the given target.
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
Make user-friendly text for the source.
static enum fc_tristate is_goods_type_in_range(const struct tile *target_tile, const struct city *target_city, enum req_range range, bool survives, struct goods_type *pgood)
Is there a source goods type within range of the target?
bool universal_replace_in_req_vec(struct requirement_vector *reqs, const struct universal *to_replace, const struct universal *replacement)
Replaces all instances of the universal to_replace with replacement in the requirement vector reqs an...
static enum req_item_found action_found(const struct requirement *preq, const struct universal *source)
Find if an action fulfills a requirement.
QString req_to_fstring(const struct requirement *req)
Returns the given requirement as a formatted string ready for printing.
static enum fc_tristate is_roadflag_in_range(const struct tile *target_tile, const struct city *target_city, enum req_range range, bool survives, enum road_flag_id roadflag)
Is there a road with the given flag within range of the target?
bool are_requirements_contradictions(const struct requirement *req1, const struct requirement *req2)
Returns TRUE if req1 and req2 contradicts each other.
static enum fc_tristate is_diplrel_in_range(const struct player *target_player, const struct player *other_player, enum req_range range, int diplrel)
Is the diplomatic state within range of the target?
void universal_found_functions_init()
Initialise universal_found_function array.
static enum fc_tristate is_unitclassflag_in_range(const struct unit_type *target_unittype, enum req_range range, bool survives, enum unit_class_flag_id ucflag)
Is there a unit with the given flag within range of the target?
int requirement_kind_ereq(const int value, const enum req_range range, const bool present, const int max_value)
Returns (the position of) the given requirement's enumerator in the enumeration of all possible requi...
void req_vec_problem_free(struct req_vec_problem *issue)
De-allocates resources associated with the given requirement vector problem.
static enum req_item_found improvement_found(const struct requirement *preq, const struct universal *source)
Find if an improvement fulfills a requirement.
static enum fc_tristate is_tech_in_range(const struct player *target_player, enum req_range range, bool survives, Tech_type_id tech)
Is there a source tech within range of the target?
static bool players_in_same_range(const struct player *pplayer1, const struct player *pplayer2, enum req_range range)
Returns TRUE if players are in the same requirements range.
enum req_item_found(* universal_found)(const struct requirement *, const struct universal *)
Container for req_item_found functions.
struct universal universal_by_number(const enum universals_n kind, const int value)
Combine values into a universal structure.
enum req_item_found universal_fulfills_requirement(const struct requirement *preq, const struct universal *source)
Will the universal 'source' fulfill this requirement?
static enum fc_tristate is_unitclass_in_range(const struct unit_type *target_unittype, enum req_range range, bool survives, struct unit_class *pclass)
Is there a unit with the given flag within range of the target?
bool req_vec_wants_type(const struct requirement_vector *reqs, enum universals_n kind)
Returns TRUE iff the specified requirement vector has a positive requirement of the specified require...
static int num_world_buildings_total(const struct impr_type *building)
Returns the number of total world buildings (this includes buildings that have been destroyed).
static enum fc_tristate is_techflag_in_range(const struct player *target_player, enum req_range range, enum tech_flag_id techflag)
Is there a tech with the given flag within range of the target?
static enum fc_tristate is_terrain_class_in_range(const struct tile *target_tile, const struct city *target_city, enum req_range range, bool survives, enum terrain_class pclass)
Is there a source terrain class within range of the target?
static enum req_item_found output_type_found(const struct requirement *preq, const struct universal *source)
Find if an output type fulfills a requirement.
static enum fc_tristate is_nation_in_range(const struct player *target_player, enum req_range range, bool survives, const struct nation_type *nation)
Is there a nation within range of the target?
static bool is_city_in_tile(const struct tile *ptile, const struct city *pcity)
Is center of given city in tile.
bool does_req_contradicts_reqs(const struct requirement *req, const struct requirement_vector *vec)
Returns TRUE if the given requirement contradicts the given requirement vector.
static enum req_item_found government_found(const struct requirement *preq, const struct universal *source)
Find if a government fulfills a requirement.
static enum fc_tristate is_unitflag_in_range(const struct unit_type *target_unittype, enum req_range range, bool survives, enum unit_type_flag_id unitflag)
Is there a unit with the given flag within range of the target?
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
Return TRUE iff the two sources are equivalent.
static enum req_item_found unit_activity_found(const struct requirement *preq, const struct universal *source)
Find if a unit activity fulfills a requirement.
static enum fc_tristate is_citytile_in_range(const struct tile *target_tile, const struct city *target_city, enum req_range range, enum citytile_type citytile)
Is center of given city in range.
static enum fc_tristate is_unittype_in_range(const struct unit_type *target_unittype, enum req_range range, bool survives, const struct unit_type *punittype)
Is there a unit of the given type within range of the target?
static enum req_item_found nation_found(const struct requirement *preq, const struct universal *source)
Find if a nation fulfills a requirement.
const char * universal_rule_name(const struct universal *psource)
Return the (untranslated) rule name of the universal.
static enum fc_tristate is_unit_state(const struct unit *target_unit, enum req_range range, bool survives, enum ustate_prop uprop)
Is the given property of the unit state true?
static enum fc_tristate is_minculture_in_range(const struct city *target_city, const struct player *target_player, enum req_range range, int minculture)
Is city or player with at least minculture culture in range?
static enum req_item_found unit_class_found(const struct requirement *preq, const struct universal *source)
Find if a unit class fulfills a requirement.
int universal_number(const struct universal *source)
Return the universal number of the constituent.
static enum fc_tristate is_tile_units_in_range(const struct tile *target_tile, enum req_range range, int max_units)
Is there a tile with max X units within range of the target?
bool universal_is_mentioned_by_requirements(const struct requirement_vector *reqs, const struct universal *psource)
Returns TRUE iff the universal 'psource' is directly mentioned by any of the requirements in 'reqs'.
static enum req_item_found diplrel_found(const struct requirement *preq, const struct universal *source)
Find if a diplrel fulfills a requirement.
static bool player_has_ever_built(const struct player *pplayer, const struct impr_type *building)
Returns whether a building of a certain type has ever been built by pplayer, even if it has subsequen...
static bool nation_contra_group(const struct requirement *nation_req, const struct requirement *group_req)
Returns TRUE if the specified nation requirement contradicts the specified nation group requirement.
static enum fc_tristate is_terrain_alter_possible_in_range(const struct tile *target_tile, enum req_range range, bool survives, enum terrain_alteration alteration)
Is there a terrain which can support the specified infrastructure within range of the target?
static bool are_requirements_opposites(const struct requirement *req1, const struct requirement *req2)
Returns TRUE if req1 and req2 directly negate each other.
static int num_world_buildings(const struct impr_type *building)
Returns the number of buildings of a certain type in the world.
static enum fc_tristate is_extraflag_in_range(const struct tile *target_tile, const struct city *target_city, enum req_range range, bool survives, enum extra_flag_id extraflag)
Is there an extra with the given flag within range of the target?
struct universal universal_by_rule_name(const char *kind, const char *value)
Parse requirement type (kind) and value strings into a universal structure.
static enum fc_tristate is_terrain_in_range(const struct tile *target_tile, const struct city *target_city, enum req_range range, bool survives, const struct terrain *pterrain)
Is there a source tile within range of the target?
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
Returns the specified requirement vector change as a translated string ready for use in the user inte...
static bool impr_contra_genus(const struct requirement *impr_req, const struct requirement *genus_req)
Returns TRUE if the specified building requirement contradicts the specified building genus requireme...
static enum fc_tristate is_nationality_in_range(const struct city *target_city, enum req_range range, const struct nation_type *nationality)
Is there a nationality within range of the target?
#define requirement_diplrel_ereq(_id_, _range_, _present_)
Definition: requirements.h:320
signed char req_vec_num_in_item
req_vec_num_in_item a requirement vectors number in an item.
Definition: requirements.h:143
req_vec_num_in_item(* requirement_vector_number)(const void *parent_item, const struct requirement_vector *vec)
Returns the requirement vector number of the specified requirement vector in the specified parent ite...
Definition: requirements.h:153
#define universal_is_mentioned_by_requirement(preq, psource)
Definition: requirements.h:248
#define requirement_vector_iterate_end
Definition: requirements.h:80
struct requirement_vector *(* requirement_vector_by_number)(const void *parent_item, req_vec_num_in_item number)
Returns a writable pointer to the specified requirement vector in the specified parent item or nullpt...
Definition: requirements.h:164
#define requirement_vector_iterate(req_vec, preq)
Definition: requirements.h:78
req_item_found
Definition: requirements.h:254
@ ITF_NO
Definition: requirements.h:254
@ ITF_YES
Definition: requirements.h:254
@ ITF_NOT_APPLICABLE
Definition: requirements.h:254
const char *(* requirement_vector_namer)(req_vec_num_in_item number)
Returns the name of the specified requirement vector number in the parent item or nullptr if parent i...
Definition: requirements.h:174
struct research * research_get(const struct player *pplayer)
Returns the research structure associated with the player.
Definition: research.cpp:110
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Returns state of the tech for current research.
Definition: research.cpp:609
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Check if road provides effect.
Definition: road.cpp:367
bool is_road_flag_card_near(const struct tile *ptile, enum road_flag_id flag)
Returns TRUE iff any cardinally adjacent tile contains a road with the given flag (does not check pti...
Definition: road.cpp:376
bool is_road_flag_near_tile(const struct tile *ptile, enum road_flag_id flag)
Returns TRUE iff any adjacent tile contains a road with the given flag (does not check ptile itself).
Definition: road.cpp:399
QString ssetv_human_readable(ssetv val, bool present)
Returns the server setting - value pair formated in a user readable way.
const char * ssetv_rule_name(ssetv val)
Returns the server setting - value pair encoded as a string.
bool ssetv_setting_has_value(ssetv val)
Returns if the server setting currently has the value in the pair.
ssetv ssetv_by_rule_name(const char *name)
Returns the server setting - value pair encoded in the string.
#define SSETV_NONE
fc_tristate
Definition: shared.h:42
@ TRI_YES
Definition: shared.h:42
@ TRI_NO
Definition: shared.h:42
@ TRI_MAYBE
Definition: shared.h:42
#define BOOL_TO_TRISTATE(tri)
Definition: shared.h:43
#define FC_INFINITY
Definition: shared.h:32
struct specialist * specialist_by_rule_name(const char *name)
Return the specialist type with the given (untranslated!) rule name.
Definition: specialist.cpp:104
const char * specialist_rule_name(const struct specialist *sp)
Return the (untranslated) rule name of the specialist type.
Definition: specialist.cpp:142
Specialist_type_id specialist_number(const struct specialist *sp)
Return the specialist item_number.
Definition: specialist.cpp:83
struct specialist * specialist_by_number(const Specialist_type_id id)
Return the specialist pointer for the given number.
Definition: specialist.cpp:92
const char * specialist_plural_translation(const struct specialist *sp)
Return the (translated, plural) name of the specialist type.
Definition: specialist.cpp:151
Definition: base.h:43
Definition: city.h:291
struct player * original
Definition: city.h:295
int turn_founded
Definition: city.h:357
struct tile * tile
Definition: city.h:293
struct packet_game_info info
Definition: game.h:80
enum impr_genus_id genus
Definition: improvement.h:71
struct player * player
Definition: nation.h:97
int index
Definition: city.h:232
enum ai_level skill_level
Definition: player.h:109
Definition: player.h:231
struct player_ai ai_common
Definition: player.h:270
bool is_alive
Definition: player.h:250
struct nation_style * style
Definition: player.h:261
req_vec_num_in_item vector_number
Definition: requirements.h:194
enum req_vec_change_operation operation
Definition: requirements.h:191
struct requirement req
Definition: requirements.h:192
int num_suggested_solutions
Definition: requirements.h:203
struct req_vec_change * suggested_solutions
Definition: requirements.h:204
enum req_range range
Definition: requirements.h:69
struct universal source
Definition: requirements.h:68
Definition: road.h:54
Definition: tile.h:42
struct unit_list * units
Definition: tile.h:50
struct player * owner
Definition: tile.h:52
Definition: unit.h:134
enum unit_activity activity
Definition: unit.h:154
int moves_left
Definition: unit.h:147
bool moved
Definition: unit.h:170
int hp
Definition: unit.h:148
struct unit::@76::@79 server
int homecity
Definition: unit.h:142
struct unit * transporter
Definition: unit.h:180
int veteran
Definition: unit.h:149
enum universals_n kind
Definition: fc_types.h:740
universals_u value
Definition: fc_types.h:739
struct civ_map map
Definition: world_object.h:21
struct nation_style * style_by_rule_name(const char *name)
Returns style matching rule name or nullptr if there is no style with such name.
Definition: style.cpp:103
const char * style_rule_name(const struct nation_style *pstyle)
Return the (untranslated) rule name of the style.
Definition: style.cpp:94
struct nation_style * style_by_number(int id)
Return style of given id.
Definition: style.cpp:74
int style_number(const struct nation_style *pstyle)
Return the style id.
Definition: style.cpp:54
const char * style_name_translation(const struct nation_style *pstyle)
Return the (translated) name of the style.
Definition: style.cpp:85
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
Definition: support.cpp:537
int fc_strcasecmp(const char *str0, const char *str1)
Compare strings like strcmp(), but ignoring case.
Definition: support.cpp:89
size_t fc_strlcat(char *dest, const char *src, size_t n)
fc_strlcat() provides utf-8 version of (non-standard) function strlcat() It is intended as more user-...
Definition: support.cpp:448
int cat_snprintf(char *str, size_t n, const char *format,...)
cat_snprintf is like a combination of fc_snprintf and fc_strlcat; it does snprintf to the end of an e...
Definition: support.cpp:564
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition: support.cpp:512
struct advance * advance_by_rule_name(const char *name)
Does a linear search of advances[].name.vernacular Returns nullptr when none match.
Definition: tech.cpp:180
const char * advance_rule_name(const struct advance *padvance)
Return the (untranslated) rule name of the advance/technology.
Definition: tech.cpp:283
struct advance * advance_by_number(const Tech_type_id atype)
Return the advance for the given advance index.
Definition: tech.cpp:94
Tech_type_id advance_number(const struct advance *padvance)
Return the advance index.
Definition: tech.cpp:85
const char * advance_name_translation(const struct advance *padvance)
Return the (translated) name of the given advance/technology.
Definition: tech.cpp:274
bool is_terrain_class_card_near(const struct tile *ptile, enum terrain_class tclass)
Is there terrain of the given class cardinally near tile? (Does not check ptile itself....
Definition: terrain.cpp:473
bool is_terrain_flag_near_tile(const struct tile *ptile, enum terrain_flag_id flag)
Returns TRUE iff any adjacent tile contains terrain with the given flag (does not check ptile itself)...
Definition: terrain.cpp:345
bool is_terrain_flag_card_near(const struct tile *ptile, enum terrain_flag_id flag)
Returns TRUE iff any cardinally adjacent tile contains terrain with the given flag (does not check pt...
Definition: terrain.cpp:325
struct terrain * terrain_by_number(const Terrain_type_id type)
Return the terrain for the given terrain index.
Definition: terrain.cpp:128
const char * terrain_rule_name(const struct terrain *pterrain)
Return the (untranslated) rule name of the terrain.
Definition: terrain.cpp:184
struct terrain * terrain_by_rule_name(const char *name)
Return the terrain type matching the name, or T_UNKNOWN if none matches.
Definition: terrain.cpp:140
const char * terrain_class_name_translation(enum terrain_class tclass)
Return the (translated) name of the given terrain class.
Definition: terrain.cpp:546
bool is_terrain_near_tile(const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Returns TRUE iff any adjacent tile contains the given terrain.
Definition: terrain.cpp:277
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Can terrain support given infrastructure?
Definition: terrain.cpp:558
bool is_terrain_card_near(const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Returns TRUE iff any cardinally adjacent tile contains the given terrain.
Definition: terrain.cpp:256
bool is_terrain_class_near_tile(const struct tile *ptile, enum terrain_class tclass)
Is there terrain of the given class near tile? (Does not check ptile itself.)
Definition: terrain.cpp:495
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
What terrain class terrain type belongs to.
Definition: terrain.cpp:464
const char * terrain_name_translation(const struct terrain *pterrain)
Return the (translated) name of the terrain.
Definition: terrain.cpp:175
Terrain_type_id terrain_number(const struct terrain *pterrain)
Return the terrain index.
Definition: terrain.cpp:119
#define T_UNKNOWN
Definition: terrain.h:51
#define terrain_has_flag(terr, flag)
Definition: terrain.h:260
bool tile_has_extra_flag(const struct tile *ptile, enum extra_flag_id flag)
Check if tile contains extra providing effect.
Definition: tile.cpp:914
bool tile_has_base_flag(const struct tile *ptile, enum base_flag_id flag)
Check if tile contains base providing effect.
Definition: tile.cpp:164
bool tile_has_native_base(const struct tile *ptile, const struct unit_type *punittype)
Check if tile contains base native for unit.
Definition: tile.cpp:327
bool tile_has_road_flag(const struct tile *ptile, enum road_flag_id flag)
Check if tile contains road providing effect.
Definition: tile.cpp:894
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
Definition: tile.cpp:72
#define tile_terrain(_tile)
Definition: tile.h:93
#define tile_continent(_tile)
Definition: tile.h:74
#define tile_has_extra(ptile, pextra)
Definition: tile.h:130
#define tile_owner(_tile)
Definition: tile.h:78
struct goods_type * goods_by_number(Goods_type_id id)
Return goods type of given id.
const char * goods_rule_name(struct goods_type *pgood)
Return untranslated name of this goods type.
struct goods_type * goods_by_rule_name(const char *name)
Returns goods type matching rule name or nullptr if there is no goods type with such name.
Goods_type_id goods_number(const struct goods_type *pgood)
Return the goods id.
const char * goods_name_translation(struct goods_type *pgood)
Return translated name of this goods type.
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
Does city receive goods.
#define trade_partners_iterate_end
Definition: traderoutes.h:163
#define trade_partners_iterate(c, p)
Definition: traderoutes.h:153
const struct unit_type * utype
Definition: fc_types.h:585
int unitflag
Definition: fc_types.h:607
int min_techs
Definition: fc_types.h:623
int mincalfrag
Definition: fc_types.h:602
struct nation_style * style
Definition: fc_types.h:589
enum vision_layer vlayer
Definition: fc_types.h:596
enum ai_level ai_level
Definition: fc_types.h:593
struct specialist * specialist
Definition: fc_types.h:582
enum impr_genus_id impr_genus
Definition: fc_types.h:617
enum citytile_type citytile
Definition: fc_types.h:594
struct nation_group * nationgroup
Definition: fc_types.h:588
struct extra_type * extra
Definition: fc_types.h:586
struct nation_type * nation
Definition: fc_types.h:580
int minmoves
Definition: fc_types.h:618
int terrainclass
Definition: fc_types.h:604
int unitclassflag
Definition: fc_types.h:606
struct government * govern
Definition: fc_types.h:578
int max_tile_units
Definition: fc_types.h:619
int terrainalter
Definition: fc_types.h:605
int minculture
Definition: fc_types.h:599
enum citystatus_type citystatus
Definition: fc_types.h:595
int minforeignpct
Definition: fc_types.h:600
const struct impr_type * building
Definition: fc_types.h:579
struct achievement * achievement
Definition: fc_types.h:587
ssetv ssetval
Definition: fc_types.h:626
int techflag
Definition: fc_types.h:609
struct advance * advance
Definition: fc_types.h:577
enum unit_activity activity
Definition: fc_types.h:616
struct goods_type * good
Definition: fc_types.h:591
struct terrain * terrain
Definition: fc_types.h:583
int terrainflag
Definition: fc_types.h:608
enum national_intelligence nintel
Definition: fc_types.h:597
enum ustate_prop unit_state
Definition: fc_types.h:615
int minveteran
Definition: fc_types.h:620
int extraflag
Definition: fc_types.h:612
Output_type_id outputtype
Definition: fc_types.h:603
int roadflag
Definition: fc_types.h:611
enum topo_flag topo_property
Definition: fc_types.h:625
int min_hit_points
Definition: fc_types.h:621
struct unit_class * uclass
Definition: fc_types.h:584
struct nation_type * nationality
Definition: fc_types.h:581
struct action * action
Definition: fc_types.h:590
int baseflag
Definition: fc_types.h:610
int get_transporter_occupancy(const struct unit *ptrans)
Return how many units are in the transport.
Definition: unit.cpp:1647
#define unit_tile(_pu)
Definition: unit.h:371
#define unit_owner(_pu)
Definition: unit.h:370
const struct unit_type * unit_type_get(const struct unit *punit)
Return the unit type for this unit.
Definition: unittype.cpp:114
const char * uclass_name_translation(const struct unit_class *pclass)
Return the (translated) name of the unit class.
Definition: unittype.cpp:1324
struct unit_type * utype_by_number(const Unit_type_id id)
Return a pointer for the unit type struct for the given unit type id.
Definition: unittype.cpp:103
const char * utype_rule_name(const struct unit_type *punittype)
Return the (untranslated) rule name of the unit type.
Definition: unittype.cpp:1274
int utype_build_shield_cost(const struct city *pcity, const struct unit_type *punittype)
Returns the number of shields it takes to build this unit type.
Definition: unittype.cpp:1141
struct unit_class * unit_class_by_rule_name(const char *s)
Returns the unit class that has the given (untranslated) rule name.
Definition: unittype.cpp:1463
const char * utype_name_translation(const struct unit_type *punittype)
Return the (translated) name of the unit type.
Definition: unittype.cpp:1256
struct unit_class * uclass_by_number(const Unit_Class_id id)
Returns unit class pointer for an ID value.
Definition: unittype.cpp:2129
struct unit_type * unit_type_by_rule_name(const char *name)
Returns the unit type that has the given (untranslated) rule name.
Definition: unittype.cpp:1444
Unit_type_id utype_number(const struct unit_type *punittype)
Return the unit type index.
Definition: unittype.cpp:91
const char * uclass_rule_name(const struct unit_class *pclass)
Return the (untranslated) rule name of the unit class.
Definition: unittype.cpp:1333
Unit_Class_id uclass_number(const struct unit_class *pclass)
Return the unit_class index.
Definition: unittype.cpp:2120
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition: unittype.h:704
#define utype_class(_t_)
Definition: unittype.h:691
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition: unittype.h:584