Freeciv21
Develop your civilization from humble roots to a global empire
rscompat.cpp
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 1996-2020 Freeciv21 and Freeciv
3 \_ \ / __/ contributors. This file is part of Freeciv21.
4  _\ \ / /__ Freeciv21 is free software: you can redistribute it
5  \___ \____/ __/ and/or modify it under the terms of the GNU General
6  \_ _/ Public License as published by the Free Software
7  | @ @ \_ Foundation, either version 3 of the License,
8  | or (at your option) any later version.
9  _/ /\ You should have received a copy of the GNU
10  /o) (o/\ \_ General Public License along with Freeciv21.
11  \_____/ / If not, see https://www.gnu.org/licenses/.
12  \____/ ********************************************************/
13 
14 #include <string.h>
15 
16 // utility
17 #include "capability.h"
18 #include "fcintl.h"
19 #include "registry.h"
20 #include "section_file.h"
21 
22 // common
23 #include "actions.h"
24 #include "effects.h"
25 #include "movement.h"
26 #include "requirements.h"
27 #include "unittype.h"
28 
29 // server
30 #include "rssanity.h"
31 #include "ruleset.h"
32 
33 #include "rscompat.h"
34 
35 struct new_flags {
36  const char *name;
37  const char *helptxt;
38 };
39 
40 #define UTYF_LAST_USER_FLAG_3_0 UTYF_USER_FLAG_40
41 #define UCF_LAST_USER_FLAG_3_0 UCF_USER_FLAG_8
42 #define TER_LAST_USER_FLAG_3_0 TER_USER_8
43 
45 
51  const char *filename,
52  struct rscompat_info *info)
53 {
54  const char *datafile_options =
55  secfile_lookup_str(file, "datafile.options");
56  bool ok = false;
57  int format;
58 
59  if (!datafile_options) {
60  qCCritical(ruleset_category,
61  "\"%s\": ruleset capability problem:", filename);
62  qCCritical(ruleset_category, "%s", secfile_error());
63 
64  return 0;
65  }
66 
67  if (info->compat_mode) {
68  /* Check alternative capstr first, so that when we do the main capstr
69  * check, we already know that failures there are fatal (error message
70  * correct, can return immediately) */
71 
72  if (has_capabilities(RULESET_COMPAT_CAP, datafile_options)
73  && has_capabilities(datafile_options, RULESET_COMPAT_CAP)) {
74  ok = true;
75  }
76  }
77 
78  if (!ok) {
79  if (!has_capabilities(RULESET_CAPABILITIES, datafile_options)) {
80  qCCritical(ruleset_category,
81  "\"%s\": ruleset datafile appears incompatible:", filename);
82  qCCritical(ruleset_category, " datafile options: %s",
83  datafile_options);
84  qCCritical(ruleset_category, " supported options: %s",
86  qCCritical(ruleset_category, "Capability problem");
87 
88  return 0;
89  }
90  if (!has_capabilities(datafile_options, RULESET_CAPABILITIES)) {
91  qCCritical(ruleset_category,
92  "\"%s\": ruleset datafile claims required option(s)"
93  " that we don't support:",
94  filename);
95  qCCritical(ruleset_category, " datafile options: %s",
96  datafile_options);
97  qCCritical(ruleset_category, " supported options: %s",
99  qCCritical(ruleset_category, "Capability problem");
100 
101  return 0;
102  }
103  }
104 
105  if (!secfile_lookup_int(file, &format, "datafile.format_version")) {
106  qCritical("\"%s\": lacking legal format_version field", filename);
107  qCCritical(ruleset_category, "%s", secfile_error());
108 
109  return 0;
110  } else if (format == 0) {
111  qCritical("\"%s\": Illegal format_version value", filename);
112  qCCritical(ruleset_category, "Format version error");
113  }
114 
115  return format;
116 }
117 
124 static bool
126 {
127  struct req_vec_problem *problem;
128 
129  struct action *paction = action_by_number(ae->action);
130  /* Some changes requires starting to process an action's enablers from
131  * the beginning. */
132  bool needs_restart = false;
133 
134  while ((problem = action_enabler_suggest_repair(ae)) != nullptr) {
135  // A hard obligatory requirement is missing.
136 
137  int i;
138 
139  if (problem->num_suggested_solutions == 0) {
140  // Didn't get any suggestions about how to solve this.
141 
142  qCritical("Dropping an action enabler for %s."
143  " Don't know how to fix: %s.",
144  action_rule_name(paction), problem->description);
145  ae->disabled = true;
146 
147  req_vec_problem_free(problem);
148  return true;
149  }
150 
151  // Sanity check.
152  fc_assert_ret_val(problem->num_suggested_solutions > 0, needs_restart);
153 
154  // Only append is supported for upgrade
155  for (i = 0; i < problem->num_suggested_solutions; i++) {
156  if (problem->suggested_solutions[i].operation != RVCO_APPEND) {
157  /* A problem that isn't caused by missing obligatory hard
158  * requirements has been detected. Probably an old requirement that
159  * contradicted a hard requirement that wasn't documented by making
160  * it obligatory. In that case the enabler was never in use. The
161  * action it self would have blocked it. */
162 
163  qCritical("While adding hard obligatory reqs to action enabler"
164  " for %s: %s Dropping it.",
165  action_rule_name(paction), problem->description);
166  ae->disabled = true;
167  req_vec_problem_free(problem);
168  return true;
169  }
170  }
171 
172  for (i = 0; i < problem->num_suggested_solutions; i++) {
173  struct action_enabler *new_enabler;
174 
175  /* There can be more than one suggestion to apply. In that case both
176  * are applied to their own copy. The original should therefore be
177  * kept for now. */
178  new_enabler = action_enabler_copy(ae);
179 
180  // Apply the solution.
181  if (!req_vec_change_apply(&problem->suggested_solutions[i],
183  new_enabler)) {
184  qCritical(
185  "Failed to apply solution %s for %s to action enabler"
186  " for %s. Dropping it.",
189  problem->description, action_rule_name(paction));
190  new_enabler->disabled = true;
191  req_vec_problem_free(problem);
192  return true;
193  }
194 
195  if (problem->num_suggested_solutions - 1 == i) {
196  // The last modification is to the original enabler.
197  ae->action = new_enabler->action;
198  ae->disabled = new_enabler->disabled;
199  requirement_vector_copy(&ae->actor_reqs, &new_enabler->actor_reqs);
200  requirement_vector_copy(&ae->target_reqs, &new_enabler->target_reqs);
201  delete new_enabler;
202  new_enabler = nullptr;
203  } else {
204  // Register the new enabler
205  action_enabler_add(new_enabler);
206 
207  // This changes the number of action enablers.
208  needs_restart = true;
209  }
210  }
211 
212  req_vec_problem_free(problem);
213 
214  if (needs_restart) {
215  // May need to apply future upgrades to the copies too.
216  return true;
217  }
218  }
219 
220  return needs_restart;
221 }
222 
228 {
229  action_iterate(act_id)
230  {
231  bool restart_enablers_for_action;
232  do {
233  restart_enablers_for_action = false;
235  {
236  if (ae->disabled) {
237  // Ignore disabled enablers
238  continue;
239  }
241  /* Something important, probably the number of action enablers
242  * for this action, changed. Start over again on this action's
243  * enablers. */
244  restart_enablers_for_action = true;
245  break;
246  }
247  }
249  } while (restart_enablers_for_action);
250  }
252 }
253 
259 {
260  int flag;
261 
262  // Find the first unused user defined unit type flag.
263  for (flag = 0; flag < MAX_NUM_USER_UNIT_FLAGS; flag++) {
264  if (unit_type_flag_id_name_cb(unit_type_flag_id(flag + UTYF_USER_FLAG_1))
265  == nullptr) {
266  return flag;
267  }
268  }
269 
270  // All unit type user flags are taken.
272 }
273 
279 {
280  int flag;
281 
282  // Find the first unused user defined unit class flag.
283  for (flag = 0; flag < MAX_NUM_USER_UCLASS_FLAGS; flag++) {
285  unit_class_flag_id(flag + UCF_USER_FLAG_1))
286  == nullptr) {
287  return flag;
288  }
289  }
290 
291  // All unit class user flags are taken.
293 }
294 
300 {
301  int flag;
302 
303  // Find the first unused user defined terrain flag.
304  for (flag = 0; flag < MAX_NUM_USER_TER_FLAGS; flag++) {
305  if (terrain_flag_id_name_cb(terrain_flag_id(flag + TER_USER_1))
306  == nullptr) {
307  return flag;
308  }
309  }
310 
311  // All terrain user flags are taken.
312  return MAX_NUM_USER_TER_FLAGS;
313 }
314 
325 bool rscompat_names(struct rscompat_info *info)
326 {
327  if (info->ver_units < 20) {
328  /* Some unit type flags moved to the ruleset between 3.0 and 3.1.
329  * Add them back as user flags.
330  * XXX: ruleset might not need all of these, and may have enough
331  * flags of its own that these additional ones prevent conversion. */
332  const std::vector<new_flags> new_flags_31 = {
333  new_flags{N_("BeachLander"),
334  N_("Won't lose all movement when moving from"
335  " non-native terrain to native terrain.")},
336  new_flags{N_("Cant_Fortify"), nullptr},
337  };
338  fc_assert_ret_val(new_flags_31.size()
340  false);
341 
342  /* Some unit class flags moved to the ruleset between 3.0 and 3.1.
343  * Add them back as user flags.
344  * XXX: ruleset might not need all of these, and may have enough
345  * flags of its own that these additional ones prevent conversion. */
346  const std::vector<new_flags> new_class_flags_31 = {
347  new_flags{N_("Missile"), N_("Unit is destroyed when it attacks")},
348  new_flags{N_("CanPillage"), N_("Can pillage tile improvements.")},
349  new_flags{N_("CanFortify"), N_("Gets a 50% defensive bonus while"
350  " in cities.")},
351  };
352  fc_assert_ret_val(new_class_flags_31.size()
354  false);
355 
356  int first_free;
357  int i;
358 
359  // Unit type flags.
360  first_free = first_free_unit_type_user_flag() + UTYF_USER_FLAG_1;
361 
362  for (i = 0; i < new_flags_31.size(); i++) {
363  if (UTYF_USER_FLAG_1 + MAX_NUM_USER_UNIT_FLAGS <= first_free + i) {
364  // Can't add the user unit type flags.
365  qCCritical(ruleset_category,
366  "Can't upgrade the ruleset. Not enough free unit type "
367  "user flags to add user flags for the unit type flags "
368  "that used to be hardcoded.");
369  return false;
370  }
371  /* Shouldn't be possible for valid old ruleset to have flag names that
372  * clash with these ones */
373  if (unit_type_flag_id_by_name(new_flags_31[i].name, fc_strcasecmp)
374  != unit_type_flag_id_invalid()) {
375  qCCritical(ruleset_category,
376  "Ruleset had illegal user unit type flag '%s'",
377  new_flags_31[i].name);
378  return false;
379  }
380  set_user_unit_type_flag_name(unit_type_flag_id(first_free + i),
381  new_flags_31[i].name,
382  new_flags_31[i].helptxt);
383  }
384 
385  // Unit type class flags.
386  first_free = first_free_unit_class_user_flag() + UCF_USER_FLAG_1;
387 
388  for (i = 0; i < new_class_flags_31.size(); i++) {
389  if (UCF_USER_FLAG_1 + MAX_NUM_USER_UCLASS_FLAGS <= first_free + i) {
390  // Can't add the user unit type class flags.
391  qCCritical(ruleset_category,
392  "Can't upgrade the ruleset. Not enough free unit "
393  "type class user flags to add user flags for the "
394  "unit type class flags that used to be hardcoded.");
395  return false;
396  }
397  /* Shouldn't be possible for valid old ruleset to have flag names that
398  * clash with these ones */
399  if (unit_class_flag_id_by_name(new_class_flags_31[i].name,
401  != unit_class_flag_id_invalid()) {
402  qCCritical(ruleset_category,
403  "Ruleset had illegal user unit class flag '%s'",
404  new_class_flags_31[i].name);
405  return false;
406  }
407  set_user_unit_class_flag_name(unit_class_flag_id(first_free + i),
408  new_class_flags_31[i].name,
409  new_class_flags_31[i].helptxt);
410  }
411  }
412 
413  if (info->ver_terrain < 20) {
414  /* Some terrain flags moved to the ruleset between 3.0 and 3.1.
415  * Add them back as user flags.
416  * XXX: ruleset might not need all of these, and may have enough
417  * flags of its own that these additional ones prevent conversion. */
418  const std::vector<new_flags> new_flags_31 = {
419  new_flags{N_("NoFortify"),
420  N_("No units can fortify on this terrain.")},
421  };
422  fc_assert_ret_val(new_flags_31.size()
423  <= TER_USER_LAST - TER_LAST_USER_FLAG_3_0,
424  false);
425 
426  int first_free;
427  int i;
428 
429  // Terrain flags.
430  first_free = first_free_terrain_user_flag() + TER_USER_1;
431 
432  for (i = 0; i < new_flags_31.size(); i++) {
433  if (TER_USER_1 + MAX_NUM_USER_TER_FLAGS <= first_free + i) {
434  // Can't add the user terrain flags.
435  qCCritical(ruleset_category,
436  "Can't upgrade the ruleset. Not enough free terrain "
437  "user flags to add user flags for the terrain flags "
438  "that used to be hardcoded.");
439  return false;
440  }
441  /* Shouldn't be possible for valid old ruleset to have flag names that
442  * clash with these ones */
443  if (terrain_flag_id_by_name(new_flags_31[i].name, fc_strcasecmp)
444  != terrain_flag_id_invalid()) {
445  qCCritical(ruleset_category,
446  "Ruleset had illegal user terrain flag '%s'",
447  new_flags_31[i].name);
448  return false;
449  }
450  set_user_terrain_flag_name(terrain_flag_id(first_free + i),
451  new_flags_31[i].name,
452  new_flags_31[i].helptxt);
453  }
454  }
455 
456  // No errors encountered.
457  return true;
458 }
459 
472 static bool effect_handle_split_universal(struct effect *peffect,
473  struct universal original,
474  struct universal separated)
475 {
476  if (universal_is_mentioned_by_requirements(&peffect->reqs, &original)) {
477  // Copy the old effect.
478  struct effect *peffect_copy = effect_copy(peffect);
479 
480  // Replace the original requirement with the separated requirement.
481  return universal_replace_in_req_vec(&peffect_copy->reqs, &original,
482  &separated);
483  }
484 
485  return false;
486 }
487 
491 static bool effect_list_compat_cb(struct effect *peffect, void *data)
492 {
493  struct rscompat_info *info = static_cast<struct rscompat_info *>(data);
494 
495  if (info->ver_effects < 20) {
496  // Attack has been split in regular "Attack" and "Suicide Attack".
498  peffect, universal_by_number(VUT_ACTION, ACTION_ATTACK),
499  universal_by_number(VUT_ACTION, ACTION_SUICIDE_ATTACK));
500 
501  /* "Nuke City" and "Nuke Units" has been split from "Explode Nuclear".
502  * "Explode Nuclear" is now only about exploding at the current tile. */
504  peffect, universal_by_number(VUT_ACTION, ACTION_NUKE),
505  universal_by_number(VUT_ACTION, ACTION_NUKE_CITY));
507  peffect, universal_by_number(VUT_ACTION, ACTION_NUKE),
508  universal_by_number(VUT_ACTION, ACTION_NUKE_UNITS));
509 
510  /* Production or building targeted actions have been split in one action
511  * for each target. */
513  peffect,
514  universal_by_number(VUT_ACTION, ACTION_SPY_TARGETED_SABOTAGE_CITY),
515  universal_by_number(VUT_ACTION,
516  ACTION_SPY_SABOTAGE_CITY_PRODUCTION));
518  peffect,
519  universal_by_number(VUT_ACTION,
520  ACTION_SPY_TARGETED_SABOTAGE_CITY_ESC),
521  universal_by_number(VUT_ACTION,
522  ACTION_SPY_SABOTAGE_CITY_PRODUCTION_ESC));
523 
524  if (peffect->type == EFT_ILLEGAL_ACTION_MOVE_COST) {
525  /* Boarding a transporter became action enabler controlled in
526  * Freeciv 3.1. Old hard coded rules had no punishment for trying to
527  * do this when it is illegal according to the rules. */
528  effect_req_append(peffect,
529  req_from_str("Action", "Local", false, false, false,
530  "Transport Board"));
531  effect_req_append(peffect,
532  req_from_str("Action", "Local", false, false, false,
533  "Transport Embark"));
534  /* Disembarking became action enabler controlled in Freeciv 3.1. Old
535  * hard coded rules had no punishment for trying to do those when it
536  * is illegal according to the rules. */
537  effect_req_append(peffect,
538  req_from_str("Action", "Local", false, false, false,
539  "Transport Disembark"));
540  effect_req_append(peffect,
541  req_from_str("Action", "Local", false, false, false,
542  "Transport Disembark 2"));
543  }
544  }
545 
546  // Go to the next effect.
547  return true;
548 }
549 
553 static void effect_to_enabler(action_id action, struct section_file *file,
554  const char *sec_name,
555  struct rscompat_info *compat, const char *type)
556 {
557  int value = secfile_lookup_int_default(file, 1, "%s.value", sec_name);
558  char buf[1024];
559 
560  if (value > 0) {
561  // It was an enabling effect. Add enabler
562  struct action_enabler *enabler;
563  struct requirement_vector *reqs;
564  struct requirement settler_req;
565 
566  enabler = action_enabler_new();
567  enabler->action = action;
568 
569  reqs = lookup_req_list(file, compat, sec_name, "reqs", "old effect");
570 
571  /* TODO: Divide requirements to actor_reqs and target_reqs depending
572  * their type. */
573  requirement_vector_copy(&enabler->actor_reqs, reqs);
574 
575  settler_req = req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL, false, true,
576  false, UTYF_SETTLERS);
577  requirement_vector_append(&enabler->actor_reqs, settler_req);
578 
579  // Add the enabler to the ruleset.
580  action_enabler_add(enabler);
581 
582  if (compat->log_cb != nullptr) {
583  fc_snprintf(buf, sizeof(buf),
584  "Converted effect %s in %s to an action enabler. Make "
585  "sure requirements "
586  "are correctly divided to actor and target requirements.",
587  type, sec_name);
588  compat->log_cb(buf);
589  }
590  } else if (value < 0) {
591  if (compat->log_cb != nullptr) {
592  fc_snprintf(buf, sizeof(buf),
593  "%s effect with negative value in %s can't be "
594  "automatically converted "
595  "to an action enabler. Do that manually.",
596  type, sec_name);
597  compat->log_cb(buf);
598  }
599  }
600 }
601 
606 bool rscompat_old_effect_3_1(const char *type, struct section_file *file,
607  const char *sec_name,
608  struct rscompat_info *compat)
609 {
610  if (compat->ver_effects < 20) {
611  if (!fc_strcasecmp(type, "Transform_Possible")) {
612  effect_to_enabler(ACTION_TRANSFORM_TERRAIN, file, sec_name, compat,
613  type);
614  return true;
615  }
616  if (!fc_strcasecmp(type, "Irrig_TF_Possible")) {
617  effect_to_enabler(ACTION_CULTIVATE, file, sec_name, compat, type);
618  return true;
619  }
620  if (!fc_strcasecmp(type, "Mining_TF_Possible")) {
621  effect_to_enabler(ACTION_PLANT, file, sec_name, compat, type);
622  return true;
623  }
624  if (!fc_strcasecmp(type, "Mining_Possible")) {
625  effect_to_enabler(ACTION_MINE, file, sec_name, compat, type);
626  return true;
627  }
628  if (!fc_strcasecmp(type, "Irrig_Possible")) {
629  effect_to_enabler(ACTION_IRRIGATE, file, sec_name, compat, type);
630  return true;
631  }
632  }
633 
634  return false;
635 }
636 
641 {
642  if (info->compat_mode) {
643  /* Upgrade existing effects. Done before new effects are added to
644  * prevent the new effects from being upgraded by accident. */
646  }
647 
648  if (info->compat_mode && info->ver_effects < 20) {
649  struct effect *peffect;
650 
651  /* Post successful action move fragment loss for "Bombard"
652  * has moved to the ruleset. */
653  peffect =
654  effect_new(EFT_ACTION_SUCCESS_MOVE_COST, MAX_MOVE_FRAGS, nullptr);
655 
656  // The reduction only applies to "Bombard".
657  effect_req_append(peffect, req_from_str("Action", "Local", false, true,
658  true, "Bombard"));
659 
660  /* Post successful action move fragment loss for "Heal Unit"
661  * has moved to the ruleset. */
662  peffect =
663  effect_new(EFT_ACTION_SUCCESS_MOVE_COST, MAX_MOVE_FRAGS, nullptr);
664 
665  // The reduction only applies to "Heal Unit".
666  effect_req_append(peffect, req_from_str("Action", "Local", false, true,
667  true, "Heal Unit"));
668 
669  /* Post successful action move fragment loss for "Expel Unit"
670  * has moved to the ruleset. */
671  peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST, SINGLE_MOVE, nullptr);
672 
673  // The reduction only applies to "Expel Unit".
674  effect_req_append(peffect, req_from_str("Action", "Local", false, true,
675  true, "Expel Unit"));
676 
677  /* Post successful action move fragment loss for "Capture Units"
678  * has moved to the ruleset. */
679  peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST, SINGLE_MOVE, nullptr);
680 
681  // The reduction only applies to "Capture Units".
682  effect_req_append(peffect, req_from_str("Action", "Local", false, true,
683  true, "Capture Units"));
684 
685  /* Post successful action move fragment loss for "Establish Embassy"
686  * has moved to the ruleset. */
687  peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST, 1, nullptr);
688 
689  // The reduction only applies to "Establish Embassy".
690  effect_req_append(peffect, req_from_str("Action", "Local", false, true,
691  true, "Establish Embassy"));
692 
693  /* Post successful action move fragment loss for "Investigate City"
694  * has moved to the ruleset. */
695  peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST, 1, nullptr);
696 
697  // The reduction only applies to "Investigate City".
698  effect_req_append(peffect, req_from_str("Action", "Local", false, true,
699  true, "Investigate City"));
700 
701  /* Post successful action move fragment loss for targets of "Expel Unit"
702  * has moved to the ruleset. */
703  peffect = effect_new(EFT_ACTION_SUCCESS_TARGET_MOVE_COST, MAX_MOVE_FRAGS,
704  nullptr);
705 
706  // The reduction only applies to "Expel Unit".
707  effect_req_append(peffect, req_from_str("Action", "Local", false, true,
708  true, "Expel Unit"));
709 
710  /* Post successful action move fragment loss for targets of
711  * "Paradrop Unit" has moved to the Action_Success_Actor_Move_Cost
712  * effect. */
713  unit_type_iterate(putype)
714  {
715  if (!utype_can_do_action(putype, ACTION_PARADROP)) {
716  // Not relevant
717  continue;
718  }
719 
720  if (putype->rscompat_cache.paratroopers_mr_sub == 0) {
721  // Not relevant
722  continue;
723  }
724 
725  // Subtract the value via the Action_Success_Actor_Move_Cost effect
726  peffect =
727  effect_new(EFT_ACTION_SUCCESS_MOVE_COST,
728  putype->rscompat_cache.paratroopers_mr_sub, nullptr);
729 
730  // The reduction only applies to "Paradrop Unit".
731  effect_req_append(peffect, req_from_str("Action", "Local", false, true,
732  false, "Paradrop Unit"));
733 
734  // The reduction only applies to this unit type.
735  effect_req_append(peffect,
736  req_from_str("UnitType", "Local", false, true, false,
737  utype_rule_name(putype)));
738  }
740 
741  // Fortifying rules have been unhardcoded to effects.
742  peffect = effect_new(EFT_FORTIFY_DEFENSE_BONUS, 50, nullptr);
743 
744  /* Unit actually fortified. This does not need checks for unit class or
745  * type flags for unit's ability to fortify as it would not be fortified
746  * if it can't. */
747  effect_req_append(peffect, req_from_str("Activity", "Local", false, true,
748  false, "Fortified"));
749 
750  // Fortify bonus in cities
751  peffect = effect_new(EFT_FORTIFY_DEFENSE_BONUS, 50, nullptr);
752 
753  // City center
754  effect_req_append(peffect, req_from_str("CityTile", "Local", false, true,
755  false, "Center"));
756  // Not cumulative with regular fortified bonus
757  effect_req_append(peffect, req_from_str("Activity", "Local", false,
758  false, false, "Fortified"));
759  // Unit flags
760  effect_req_append(peffect, req_from_str("UnitClassFlag", "Local", false,
761  true, false, "CanFortify"));
762  effect_req_append(peffect, req_from_str("UnitFlag", "Local", false,
763  false, false, "Cant_Fortify"));
764 
765  /* The probability that "Steal Maps" and "Steal Maps Escape" steals the
766  * map of a tile has moved to the ruleset. */
767  peffect = effect_new(EFT_MAPS_STOLEN_PCT, -50, nullptr);
768 
769  /* The rule that "Recycle Unit"'s unit shield value is 50% has moved to
770  * the ruleset. */
771  peffect = effect_new(EFT_UNIT_SHIELD_VALUE_PCT, -50, nullptr);
772  effect_req_append(peffect, req_from_str("Action", "Local", false, true,
773  false, "Recycle Unit"));
774 
775  /* The rule that "Upgrade Unit"'s current unit shield value is 50% when
776  * calculating unit upgrade price has moved to the ruleset. */
777  peffect = effect_new(EFT_UNIT_SHIELD_VALUE_PCT, -50, nullptr);
778  effect_req_append(peffect, req_from_str("Action", "Local", false, true,
779  false, "Upgrade Unit"));
780  }
781 
782  if (info->compat_mode && info->ver_game < 20) {
783  // New enablers
784  struct action_enabler *enabler;
785  struct requirement e_req;
786 
787  enabler = action_enabler_new();
788  enabler->action = ACTION_PILLAGE;
789  e_req = req_from_str("UnitClassFlag", "Local", false, true, false,
790  "CanPillage");
791  requirement_vector_append(&enabler->actor_reqs, e_req);
792  action_enabler_add(enabler);
793 
794  enabler = action_enabler_new();
795  enabler->action = ACTION_CLEAN_FALLOUT;
796  e_req = req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL, false, true, false,
797  UTYF_SETTLERS);
798  requirement_vector_append(&enabler->actor_reqs, e_req);
799  action_enabler_add(enabler);
800 
801  enabler = action_enabler_new();
802  enabler->action = ACTION_CLEAN_POLLUTION;
803  e_req = req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL, false, true, false,
804  UTYF_SETTLERS);
805  requirement_vector_append(&enabler->actor_reqs, e_req);
806  action_enabler_add(enabler);
807 
808  enabler = action_enabler_new();
809  enabler->action = ACTION_FORTIFY;
810  e_req = req_from_str("UnitClassFlag", "Local", false, true, true,
811  "CanFortify");
812  requirement_vector_append(&enabler->actor_reqs, e_req);
813  e_req = req_from_str("UnitFlag", "Local", false, false, true,
814  "Cant_Fortify");
815  requirement_vector_append(&enabler->actor_reqs, e_req);
816  e_req = req_from_str("TerrainFlag", "Local", false, false, true,
817  "NoFortify");
818  requirement_vector_append(&enabler->actor_reqs, e_req);
819  action_enabler_add(enabler);
820 
821  enabler = action_enabler_new();
822  enabler->action = ACTION_FORTIFY;
823  e_req = req_from_str("UnitClassFlag", "Local", false, true, true,
824  "CanFortify");
825  requirement_vector_append(&enabler->actor_reqs, e_req);
826  e_req = req_from_str("UnitFlag", "Local", false, false, true,
827  "Cant_Fortify");
828  requirement_vector_append(&enabler->actor_reqs, e_req);
829  e_req = req_from_str("CityTile", "Local", false, true, true, "Center");
830  requirement_vector_append(&enabler->actor_reqs, e_req);
831  action_enabler_add(enabler);
832 
833  enabler = action_enabler_new();
834  enabler->action = ACTION_ROAD;
835  e_req = req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL, false, true, false,
836  UTYF_SETTLERS);
837  requirement_vector_append(&enabler->actor_reqs, e_req);
838  action_enabler_add(enabler);
839 
840  enabler = action_enabler_new();
841  enabler->action = ACTION_CONVERT;
842  action_enabler_add(enabler);
843 
844  enabler = action_enabler_new();
845  enabler->action = ACTION_BASE;
846  e_req = req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL, false, true, false,
847  UTYF_SETTLERS);
848  requirement_vector_append(&enabler->actor_reqs, e_req);
849  action_enabler_add(enabler);
850 
851  enabler = action_enabler_new();
852  enabler->action = ACTION_TRANSPORT_ALIGHT;
853  action_enabler_add(enabler);
854 
855  enabler = action_enabler_new();
856  enabler->action = ACTION_TRANSPORT_BOARD;
857  action_enabler_add(enabler);
858 
859  enabler = action_enabler_new();
860  enabler->action = ACTION_TRANSPORT_EMBARK;
861  action_enabler_add(enabler);
862 
863  enabler = action_enabler_new();
864  enabler->action = ACTION_TRANSPORT_UNLOAD;
865  action_enabler_add(enabler);
866 
867  // Update action enablers.
870  {
871  /* "Attack" is split in a unit consuming and a non unit consuming
872  * version. */
873  if (ae->action == ACTION_ATTACK) {
874  // The old rule is represented with two action enablers.
875  enabler = action_enabler_copy(ae);
876 
877  // One allows regular attacks.
878  requirement_vector_append(
879  &ae->actor_reqs, req_from_str("UnitClassFlag", "Local", false,
880  false, true, "Missile"));
881 
882  // The other allows suicide attacks.
883  enabler->action = ACTION_SUICIDE_ATTACK;
884  requirement_vector_append(&enabler->actor_reqs,
885  req_from_str("UnitClassFlag", "Local",
886  false, true, true,
887  "Missile"));
888 
889  // Add after the action was changed.
890  action_enabler_add(enabler);
891  }
892 
893  /* "Explode Nuclear"'s adjacent tile attack is split to "Nuke City"
894  * and "Nuke Units". */
895  if (ae->action == ACTION_NUKE) {
896  /* The old rule is represented with three action enablers:
897  * 1) "Explode Nuclear" against the actors own tile.
898  * 2) "Nuke City" against adjacent enemy cities.
899  * 3) "Nuke Units" against adjacent enemy unit stacks. */
900 
901  struct action_enabler *city;
902  struct action_enabler *units;
903 
904  // Against city targets.
906  city->action = ACTION_NUKE_CITY;
907 
908  // Against unit stack targets.
909  units = action_enabler_copy(ae);
910  units->action = ACTION_NUKE_UNITS;
911 
912  // "Explode Nuclear" required this to target an adjacent tile.
913  /* While this isn't a real move (because of enemy city/units) at
914  * target tile it pretends to be one. */
915  requirement_vector_append(
916  &city->actor_reqs, req_from_values(VUT_MINMOVES, REQ_RANGE_LOCAL,
917  false, true, false, 1));
918  requirement_vector_append(&units->actor_reqs,
919  req_from_values(VUT_MINMOVES,
920  REQ_RANGE_LOCAL, false,
921  true, false, 1));
922 
923  /* Be slightly stricter about the relationship to target unit stacks
924  * than "Explode Nuclear" was before it would target an adjacent
925  * tile. I think the intention was that you shouldn't nuke your
926  * friends and allies. */
927  requirement_vector_append(
928  &city->actor_reqs, req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
929  false, true, false, DS_WAR));
930  requirement_vector_append(
931  &units->actor_reqs, req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
932  false, true, false, DS_WAR));
933 
934  // Only display one nuke action at once.
935  requirement_vector_append(
936  &units->target_reqs,
937  req_from_values(VUT_CITYTILE, REQ_RANGE_LOCAL, false, false,
938  false, CITYT_CENTER));
939 
940  // Add after the action was changed.
942  action_enabler_add(units);
943  }
944 
945  /* "Targeted Sabotage City" is split in a production targeted and a
946  * building targeted version. */
947  if (ae->action == ACTION_SPY_TARGETED_SABOTAGE_CITY) {
948  // The old rule is represented with two action enablers.
949  enabler = action_enabler_copy(ae);
950 
951  enabler->action = ACTION_SPY_SABOTAGE_CITY_PRODUCTION;
952 
953  // Add after the action was changed.
954  action_enabler_add(enabler);
955  }
956 
957  /* "Targeted Sabotage City Escape" is split in a production targeted
958  * and a building targeted version. */
959  if (ae->action == ACTION_SPY_TARGETED_SABOTAGE_CITY_ESC) {
960  // The old rule is represented with two action enablers.
961  enabler = action_enabler_copy(ae);
962 
963  enabler->action = ACTION_SPY_SABOTAGE_CITY_PRODUCTION_ESC;
964 
965  // Add after the action was changed.
966  action_enabler_add(enabler);
967  }
968  }
970 
971  /* The paratroopers_mr_req field has moved to the enabler for the
972  * "Paradrop Unit" action. */
973  {
974  bool generic_in_use = false;
975  struct action_enabler_list *ae_custom = action_enabler_list_new();
976 
978  action_enablers_for_action(ACTION_PARADROP), ae)
979  {
980  unit_type_iterate(putype)
981  {
983  &(ae->actor_reqs))) {
984  // This action enabler isn't for this unit type at all.
985  continue;
986  }
987 
988  requirement_vector_iterate(&ae->actor_reqs, preq)
989  {
990  if (preq->source.kind == VUT_MINMOVES) {
991  if (!preq->present) {
992  /* A max move fragments req has been found. Is it too
993  * large? */
994  if (preq->source.value.minmoves
995  < putype->rscompat_cache.paratroopers_mr_req) {
996  // Avoid self contradiciton
997  continue;
998  }
999  }
1000  }
1001  }
1003 
1004  if (putype->rscompat_cache.paratroopers_mr_req > 0) {
1005  // This unit type needs a custom enabler
1006 
1007  enabler = action_enabler_copy(ae);
1008 
1009  // This enabler is specific to the unit type
1010  e_req = req_from_values(VUT_UTYPE, REQ_RANGE_LOCAL, false, true,
1011  false, utype_number(putype));
1012  requirement_vector_append(&enabler->actor_reqs, e_req);
1013 
1014  // Add the minimum amout of move fragments
1015  e_req = req_from_values(
1016  VUT_MINMOVES, REQ_RANGE_LOCAL, false, true, false,
1017  putype->rscompat_cache.paratroopers_mr_req);
1018  requirement_vector_append(&enabler->actor_reqs, e_req);
1019 
1020  action_enabler_list_append(ae_custom, enabler);
1021 
1022  log_debug("paratroopers_mr_req upgrade: %s uses custom enabler",
1023  utype_rule_name(putype));
1024  } else {
1025  // The old one works just fine
1026 
1027  generic_in_use = true;
1028 
1029  log_debug("paratroopers_mr_req upgrade: %s uses generic enabler",
1030  utype_rule_name(putype));
1031  }
1032  }
1034 
1035  if (!generic_in_use) {
1036  // The generic enabler isn't in use any more
1038  }
1039  }
1041 
1042  action_enabler_list_iterate(ae_custom, ae)
1043  {
1044  // Append the custom enablers.
1045  action_enabler_add(ae);
1046  }
1048 
1049  action_enabler_list_destroy(ae_custom);
1050  }
1051 
1052  // Enable all clause types
1053  {
1054  int i;
1055 
1056  for (i = 0; i < CLAUSE_COUNT; i++) {
1057  struct clause_info *cinfo = clause_info_get(clause_type(i));
1058 
1059  cinfo->enabled = true;
1060  }
1061  }
1062  }
1063 
1065 
1066  /* The ruleset may need adjustments it didn't need before compatibility
1067  * post processing.
1068  *
1069  * If this isn't done a user of ruleset compatibility that ends up using
1070  * the rules risks bad rules. A user that saves the ruleset rather than
1071  * using it risks an unexpected change on the next load and save. */
1073 }
1074 
1082 static bool rscompat_vision_effect_cb(struct effect *peffect, void *data)
1083 {
1084  if (peffect->type == EFT_UNIT_VISION_RADIUS_SQ
1085  || peffect->type == EFT_CITY_VISION_RADIUS_SQ) {
1086  effect_req_append(peffect, req_from_str("VisionLayer", "Local", false,
1087  true, false, "Main"));
1088  }
1089 
1090  return true;
1091 }
1092 
1098 {
1099  for (int i = 0; i < NI_COUNT; ++i) {
1100  switch (static_cast<national_intelligence>(i)) {
1101  // Used to require being on the same team, all info gets shared with
1102  // the team now.
1103  case NI_HISTORY:
1104  case NI_MOOD:
1105  case NI_COUNT: // Never happens
1106  break;
1107  // Used to be always visible
1108  case NI_WONDERS: {
1109  auto effect = effect_new(EFT_NATION_INTELLIGENCE, 1, nullptr);
1110  effect_req_append(effect, req_from_values(VUT_NINTEL, REQ_RANGE_PLAYER,
1111  false, true, false, i));
1112  } break;
1113  // Used to be visible with simple contact
1114  case NI_DIPLOMACY:
1115  case NI_GOLD:
1116  case NI_GOVERNMENT:
1117  case NI_SCORE: {
1118  auto effect = effect_new(EFT_NATION_INTELLIGENCE, 1, nullptr);
1119  effect_req_append(effect, req_from_values(VUT_NINTEL, REQ_RANGE_PLAYER,
1120  false, true, false, i));
1122  req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL, false,
1123  true, false, DRO_HAS_CONTACT));
1124  }
1125  [[fallthrough]]; // Embassy gives contact
1126  // Used to require an embassy
1127  case NI_CULTURE:
1128  case NI_MULTIPLIERS:
1129  case NI_TAX_RATES:
1130  case NI_TECHS: {
1131  auto effect = effect_new(EFT_NATION_INTELLIGENCE, 1, nullptr);
1132  effect_req_append(effect, req_from_values(VUT_NINTEL, REQ_RANGE_PLAYER,
1133  false, true, false, i));
1135  req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL, false,
1136  true, false, DRO_HAS_EMBASSY));
1137  } break;
1138  }
1139  }
1140 }
1141 
1147 {
1148  if (!has_capability(CAP_EFT_HP_REGEN_MIN, info->cap_effects.data())) {
1149  // Create new effects to replace the old hard-coded minimum HP
1150  // recovery.
1151 
1152  // 1- 10% base recovery for units without hp_loss_pct
1153  auto effect = effect_new(EFT_HP_REGEN, 10, nullptr);
1154  unit_class_iterate(uclass)
1155  {
1156  if (uclass->hp_loss_pct > 0) {
1158  req_from_str("UnitClass", "Local", false, false,
1159  false, uclass_rule_name(uclass)));
1160  }
1161  }
1163 
1164  // 2- 10% base recovery for fortified units
1165  effect = effect_new(EFT_HP_REGEN, 10, nullptr);
1166  effect_req_append(effect, req_from_str("Activity", "Local", false, true,
1167  false, "Fortified"));
1168 
1169  // 3- At least one third in cities
1170  effect = effect_new(EFT_HP_REGEN_MIN, 33, nullptr);
1171  effect_req_append(effect, req_from_str("CityTile", "Local", false, true,
1172  false, "Center"));
1173 
1174  // 4- 10% more for units in cities without hp_loss_pct
1175  effect = effect_new(EFT_HP_REGEN_MIN, 10, nullptr);
1176  effect_req_append(effect, req_from_str("CityTile", "Local", false, true,
1177  false, "Center"));
1178  unit_class_iterate(uclass)
1179  {
1180  if (uclass->hp_loss_pct > 0) {
1182  req_from_str("UnitClass", "Local", false, false,
1183  false, uclass_rule_name(uclass)));
1184  }
1185  }
1187 
1188  // 5- 10% more for units fortified in cities
1189  effect = effect_new(EFT_HP_REGEN_MIN, 10, nullptr);
1190  effect_req_append(effect, req_from_str("CityTile", "Local", false, true,
1191  false, "Center"));
1192  effect_req_append(effect, req_from_str("Activity", "Local", false, true,
1193  false, "Fortified"));
1194  }
1195 
1197  // Create new effect to replace the old hard-coded bombard limit
1198 
1199  // 1% base bombard limit
1200  effect_new(EFT_BOMBARD_LIMIT_PCT, 1, nullptr);
1201  unit_type_iterate(putype)
1202  {
1203  if (putype->hp > 100) {
1204  qCWarning(ruleset_category,
1205  "Ruleset has units (such as '%s"
1206  "') for which bombard limit changed as hp > 100",
1207  utype_name_translation(putype));
1208  break;
1209  }
1210  }
1212  }
1213 
1214  if (!has_capability(CAP_EFT_WONDER_VISIBLE, info->cap_effects.data())) {
1215  // Make Great Wonders visible to everyone
1216  auto effect = effect_new(EFT_WONDER_VISIBLE, 1, nullptr);
1217  effect_req_append(effect, req_from_str("BuildingGenus", "Local", false,
1218  true, false, "GreatWonder"));
1219  }
1220 
1221  if (!has_capability(CAP_VUT_VISIONLAYER, info->cap_effects.data())) {
1222  // Add vlayer=Main to existing vision effects
1224  // Add effect to give cities radius 2 vision on other layers
1225  auto effect = effect_new(EFT_CITY_VISION_RADIUS_SQ, 2, nullptr);
1226  effect_req_append(effect, req_from_str("VisionLayer", "Local", false,
1227  false, false, "Main"));
1228  }
1229 
1231  info->cap_effects.data())) {
1233  }
1234 }
1235 
1240  struct action_auto_perf *auto_perf,
1241  size_t psize,
1242  enum unit_type_flag_id *protecor_flag)
1243 {
1244  int i;
1245 
1246  if (compat->ver_game < 20) {
1247  // Auto attack happens during war.
1248  requirement_vector_append(&auto_perf->reqs,
1249  req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
1250  false, true, true, DS_WAR));
1251 
1252  // Needs a movement point to auto attack.
1253  requirement_vector_append(&auto_perf->reqs,
1254  req_from_values(VUT_MINMOVES, REQ_RANGE_LOCAL,
1255  false, true, true, 1));
1256 
1257  for (i = 0; i < psize; i++) {
1258  // Add each protecor_flag as a !present requirement.
1259  requirement_vector_append(&auto_perf->reqs,
1260  req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL,
1261  false, false, true,
1262  protecor_flag[i]));
1263  }
1264 
1265  auto_perf->alternatives[0] = ACTION_CAPTURE_UNITS;
1266  auto_perf->alternatives[1] = ACTION_BOMBARD;
1267  auto_perf->alternatives[2] = ACTION_ATTACK;
1268  auto_perf->alternatives[3] = ACTION_SUICIDE_ATTACK;
1269  }
1270 
1271  return true;
1272 }
1273 
1278  bool slow_invasions)
1279 {
1280  if (compat->ver_effects < 20 && compat->ver_game < 20) {
1281  /* BeachLander and slow_invasions has moved to the ruleset. Use a "fake
1282  * generalized" Transport Disembark and Conquer City to handle it. */
1283 
1284  struct action_enabler *enabler;
1285  struct requirement e_req;
1286 
1287  enabler = action_enabler_new();
1288  enabler->action = ACTION_TRANSPORT_DISEMBARK1;
1289 
1290  if (slow_invasions) {
1291  /* Use for disembarking from native terrain so disembarking from
1292  * non native terain is handled by "Transport Disembark 2". */
1293  e_req = req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL, false, true,
1294  true, USP_NATIVE_TILE);
1295  requirement_vector_append(&enabler->actor_reqs, e_req);
1296  }
1297 
1298  action_enabler_add(enabler);
1299 
1300  if (slow_invasions) {
1301  // Make disembarking from non native terrain a different action.
1302 
1303  struct effect *peffect;
1304  struct action *paction;
1305 
1306  struct action_enabler_list *to_upgrade;
1307 
1308  // Add the actions
1309 
1310  // Use "Transport Disembark 2" for disembarking from non native.
1311  paction = action_by_number(ACTION_TRANSPORT_DISEMBARK2);
1312  /* "Transport Disembark" and "Transport Disembark 2" won't appear in
1313  * the same action selection dialog given their opposite
1314  * requirements. */
1315  paction->quiet = true;
1316  // Make what is happening clear.
1317  // TRANS: _Disembark from non native (100% chance of success).
1318  sz_strlcpy(paction->ui_name, N_("%sDisembark from non native%s"));
1319 
1320  // Use "Conquer City 2" for conquring from non native.
1321  paction = action_by_number(ACTION_CONQUER_CITY2);
1322  /* "Conquer City" and "Conquer City 2" won't appear in
1323  * the same action selection dialog given their opposite
1324  * requirements. */
1325  paction->quiet = true;
1326  // Make what is happening clear.
1327  // TRANS: _Conquer City from non native (100% chance of success).
1328  sz_strlcpy(paction->ui_name, N_("%sConquer City from non native%s"));
1329 
1330  // Enablers for disembark
1331 
1332  // City center counts as native.
1333  enabler = action_enabler_new();
1334  enabler->action = ACTION_TRANSPORT_DISEMBARK1;
1335  e_req = req_from_values(VUT_CITYTILE, REQ_RANGE_LOCAL, false, true,
1336  true, CITYT_CENTER);
1337  requirement_vector_append(&enabler->actor_reqs, e_req);
1338  action_enabler_add(enabler);
1339 
1340  // No TerrainSpeed sees everything as native.
1341  enabler = action_enabler_new();
1342  enabler->action = ACTION_TRANSPORT_DISEMBARK1;
1343  e_req = req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL, false, false,
1344  true, UCF_TERRAIN_SPEED);
1345  requirement_vector_append(&enabler->actor_reqs, e_req);
1346  action_enabler_add(enabler);
1347 
1348  // "BeachLander" sees everything as native.
1349  enabler = action_enabler_new();
1350  enabler->action = ACTION_TRANSPORT_DISEMBARK1;
1351  e_req = req_from_str("UnitFlag", "Local", false, true, true,
1352  "BeachLander");
1353  requirement_vector_append(&enabler->actor_reqs, e_req);
1354  action_enabler_add(enabler);
1355 
1356  // "Transport Disembark 2" enabler
1357  enabler = action_enabler_new();
1358  enabler->action = ACTION_TRANSPORT_DISEMBARK2;
1359 
1360  // Native terrain is native.
1361  e_req = req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL, false, false,
1362  true, USP_NATIVE_TILE);
1363  requirement_vector_append(&enabler->actor_reqs, e_req);
1364 
1365  // City is native.
1366  e_req = req_from_values(VUT_CITYTILE, REQ_RANGE_LOCAL, false, false,
1367  true, CITYT_CENTER);
1368  requirement_vector_append(&enabler->actor_reqs, e_req);
1369 
1370  // "BeachLander" sees everything as native.
1371  e_req = req_from_str("UnitFlag", "Local", false, false, true,
1372  "BeachLander");
1373  requirement_vector_append(&enabler->actor_reqs, e_req);
1374 
1375  // No TerrainSpeed sees everything as native.
1376  e_req = req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL, false, true, true,
1377  UCF_TERRAIN_SPEED);
1378  requirement_vector_append(&enabler->actor_reqs, e_req);
1379 
1380  action_enabler_add(enabler);
1381 
1382  /* Take movement for disembarking and conquering native terrain from
1383  * non native terrain */
1384 
1385  // Take movement for disembarking from non native terrain
1386  peffect =
1387  effect_new(EFT_ACTION_SUCCESS_MOVE_COST, MAX_MOVE_FRAGS, nullptr);
1388 
1389  // The reduction only applies to "Transport Disembark 2".
1390  effect_req_append(peffect,
1391  req_from_str("Action", "Local", false, true, true,
1392  "Transport Disembark 2"));
1393 
1394  // No reduction here unless disembarking to native terrain.
1395  effect_req_append(peffect,
1396  req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
1397  false, true, true, USP_NATIVE_TILE));
1398 
1399  // Take movement for conquering from non native terrain
1400  peffect =
1401  effect_new(EFT_ACTION_SUCCESS_MOVE_COST, MAX_MOVE_FRAGS, nullptr);
1402 
1403  // The reduction only applies to "Conquer City 2".
1404  effect_req_append(peffect, req_from_str("Action", "Local", false, true,
1405  true, "Conquer City 2"));
1406 
1407  // No reduction here unless disembarking to native terrain.
1408  effect_req_append(peffect,
1409  req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
1410  false, true, true, USP_NATIVE_TILE));
1411 
1412  // Upgrade exisiting Conquer City action enablers
1413  to_upgrade = action_enabler_list_copy(
1414  action_enablers_for_action(ACTION_CONQUER_CITY));
1415 
1416  action_enabler_list_iterate(to_upgrade, conquer_city_enabler)
1417  {
1418  // City center counts as native.
1419  enabler = action_enabler_copy(conquer_city_enabler);
1420  e_req = req_from_values(VUT_CITYTILE, REQ_RANGE_LOCAL, false, true,
1421  true, CITYT_CENTER);
1422  requirement_vector_append(&enabler->actor_reqs, e_req);
1423  action_enabler_add(enabler);
1424  }
1426 
1427  action_enabler_list_iterate(to_upgrade, conquer_city_enabler)
1428  {
1429  // No TerrainSpeed sees everything as native.
1430  enabler = action_enabler_copy(conquer_city_enabler);
1431  e_req = req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL, false, false,
1432  true, UCF_TERRAIN_SPEED);
1433  requirement_vector_append(&enabler->actor_reqs, e_req);
1434  action_enabler_add(enabler);
1435  }
1437 
1438  action_enabler_list_iterate(to_upgrade, conquer_city_enabler)
1439  {
1440  // "BeachLander" sees everything as native.
1441  enabler = action_enabler_copy(conquer_city_enabler);
1442  e_req = req_from_str("UnitFlag", "Local", false, true, true,
1443  "BeachLander");
1444  requirement_vector_append(&enabler->actor_reqs, e_req);
1445  action_enabler_add(enabler);
1446  }
1448 
1449  action_enabler_list_iterate(to_upgrade, conquer_city_enabler)
1450  {
1451  // Use "Conquer City 2" for conquring from non native.
1452  enabler = action_enabler_copy(conquer_city_enabler);
1453  enabler->action = ACTION_CONQUER_CITY2;
1454 
1455  // Native terrain is native.
1456  e_req = req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL, false, false,
1457  true, USP_NATIVE_TILE);
1458  requirement_vector_append(&enabler->actor_reqs, e_req);
1459 
1460  // City is native.
1461  e_req = req_from_values(VUT_CITYTILE, REQ_RANGE_LOCAL, false, false,
1462  true, CITYT_CENTER);
1463  requirement_vector_append(&enabler->actor_reqs, e_req);
1464 
1465  // No TerrainSpeed sees everything as native.
1466  e_req = req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL, false, true,
1467  true, UCF_TERRAIN_SPEED);
1468  requirement_vector_append(&enabler->actor_reqs, e_req);
1469 
1470  // "BeachLander" sees everything as native.
1471  e_req = req_from_str("UnitFlag", "Local", false, false, true,
1472  "BeachLander");
1473  requirement_vector_append(&enabler->actor_reqs, e_req);
1474 
1475  action_enabler_add(enabler);
1476  }
1478 
1479  action_enabler_list_iterate(to_upgrade, conquer_city_enabler)
1480  {
1481  /* Use for conquering from native terrain so conquest from
1482  * non native terain is handled by "Conquer City 2". */
1483  e_req = req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL, false, true,
1484  true, USP_NATIVE_TILE);
1485  requirement_vector_append(&conquer_city_enabler->actor_reqs, e_req);
1486  }
1488 
1489  action_enabler_list_destroy(to_upgrade);
1490  }
1491  }
1492 
1493  return true;
1494 }
1495 
1502 const char *rscompat_req_name_3_1(const char *type, const char *old_name)
1503 {
1504  if (!fc_strcasecmp("DiplRel", type)
1505  && !fc_strcasecmp("Is foreign", old_name)) {
1506  return "Foreign";
1507  }
1508 
1509  return old_name;
1510 }
1511 
1516  const char *old_type)
1517 {
1518  return old_type;
1519 }
1520 
1525  struct extra_type *pextra)
1526 {
1527  if (compat->compat_mode && compat->ver_terrain < 20) {
1528  // Give remove cause ERM_ENTER for huts
1529  if (is_extra_caused_by(pextra, EC_HUT)) {
1530  pextra->rmcauses |= (1 << ERM_ENTER);
1531  extra_to_removed_by_list(pextra, ERM_ENTER);
1532  }
1533  }
1534 }
const char * action_rule_name(const struct action *action)
Get the rule name of the action.
Definition: actions.cpp:1343
struct action_enabler * action_enabler_copy(const struct action_enabler *original)
Create a new copy of an existing action enabler.
Definition: actions.cpp:1839
struct req_vec_problem * action_enabler_suggest_repair(const struct action_enabler *enabler)
Returns a suggestion to fix the specified action enabler or nullptr if no fix is found to be needed.
Definition: actions.cpp:2187
struct requirement_vector * action_enabler_vector_by_number(const void *enabler, req_vec_num_in_item number)
Returns a writable pointer to the specified requirement vector in the action enabler or nullptr if th...
Definition: actions.cpp:2325
struct action_enabler * action_enabler_new()
Create a new action enabler.
Definition: actions.cpp:1810
void action_enabler_add(struct action_enabler *enabler)
Add an action enabler to the current ruleset.
Definition: actions.cpp:1854
struct action * action_by_number(action_id act_id)
Return the action with the given id.
Definition: actions.cpp:1149
bool action_enabler_remove(struct action_enabler *enabler)
Remove an action enabler from the current ruleset.
Definition: actions.cpp:1870
const char * action_enabler_vector_by_number_name(req_vec_num_in_item vec)
Returns the name of the given requirement vector number n in an action enabler or nullptr if enablers...
Definition: actions.cpp:2349
struct action_enabler_list * action_enablers_for_action(action_id action)
Get all enablers for an action in the current ruleset.
Definition: actions.cpp:1884
#define action_enablers_iterate_end
Definition: actions.h:425
#define action_enabler_list_iterate_end
Definition: actions.h:376
#define action_iterate_end
Definition: actions.h:383
#define action_enablers_iterate(_enabler_)
Definition: actions.h:417
#define action_enabler_list_iterate(action_enabler_list, aenabler)
Definition: actions.h:374
#define action_iterate(_act_)
Definition: actions.h:378
bool has_capability(const char *cap, const char *capstr)
Wrapper for fc_has_capability() for nullptr terminated strings.
Definition: capability.cpp:71
bool has_capabilities(const char *us, const char *them)
This routine returns true if all the mandatory capabilities in us appear in them.
Definition: capability.cpp:80
struct clause_info * clause_info_get(enum clause_type type)
Free memory associated with clause infos.
Definition: diptreaty.cpp:257
struct @19::@20 reqs
bool iterate_effect_cache(iec_cb cb, void *data)
Iterate through all the effects in cache, and call callback for each.
Definition: effects.cpp:1259
struct effect * effect_copy(struct effect *old)
Return new copy of the effect.
Definition: effects.cpp:186
struct effect * effect_new(enum effect_type type, int value, struct multiplier *pmul)
Add effect to ruleset cache.
Definition: effects.cpp:165
void effect_req_append(struct effect *peffect, struct requirement req)
Append requirement to effect.
Definition: effects.cpp:203
void extra_to_removed_by_list(struct extra_type *pextra, enum extra_rmcause rmcause)
Add extra type to list of extra removed by given cause.
Definition: extras.cpp:296
#define is_extra_caused_by(e, c)
Definition: extras.h:182
int action_id
Definition: fc_types.h:306
#define N_(String)
Definition: fcintl.h:52
const char * name
Definition: inputfile.cpp:118
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
#define log_debug(message,...)
Definition: log.h:65
#define SINGLE_MOVE
Definition: movement.h:17
#define MAX_MOVE_FRAGS
Definition: movement.h:20
const char * secfile_error()
Returns the last error which occurred in a string.
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
Lookup a integer value in the secfile.
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
Lookup a string value in the secfile.
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
Lookup a integer value in the secfile.
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...
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.
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.
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...
void req_vec_problem_free(struct req_vec_problem *issue)
De-allocates resources associated with the given requirement vector problem.
struct universal universal_by_number(const enum universals_n kind, const int value)
Combine values into a universal structure.
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'.
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...
#define requirement_fulfilled_by_unit_type(_ut_, _rqs_)
Definition: requirements.h:306
#define requirement_vector_iterate_end
Definition: requirements.h:80
#define requirement_vector_iterate(req_vec, preq)
Definition: requirements.h:78
#define UTYF_LAST_USER_FLAG_3_0
Definition: rscompat.cpp:40
void rscompat_enablers_add_obligatory_hard_reqs()
Update existing action enablers for new hard obligatory requirements.
Definition: rscompat.cpp:227
int rscompat_check_capabilities(struct section_file *file, const char *filename, struct rscompat_info *info)
Ruleset files should have a capabilities string datafile.options This checks the string and that the ...
Definition: rscompat.cpp:50
#define TER_LAST_USER_FLAG_3_0
Definition: rscompat.cpp:42
static int first_free_terrain_user_flag()
Find and return the first unused terrain user flag.
Definition: rscompat.cpp:299
const char * rscompat_req_name_3_1(const char *type, const char *old_name)
Replace deprecated requirement type names with currently valid ones.
Definition: rscompat.cpp:1502
void rscompat_extra_adjust_3_1(struct rscompat_info *compat, struct extra_type *pextra)
Adjust freeciv-3.0 ruleset extra definitions to freeciv-3.1.
Definition: rscompat.cpp:1524
static bool rscompat_enabler_add_obligatory_hard_reqs(struct action_enabler *ae)
Add all hard obligatory requirements to an action enabler or disable it.
Definition: rscompat.cpp:125
static bool rscompat_vision_effect_cb(struct effect *peffect, void *data)
Adds VisionLayer, Main, Local, True req to all unit/city vision reqs, as compat for missing CAP_VUT_V...
Definition: rscompat.cpp:1082
bool rscompat_auto_attack_3_1(struct rscompat_info *compat, struct action_auto_perf *auto_perf, size_t psize, enum unit_type_flag_id *protecor_flag)
Replace deprecated auto_attack configuration.
Definition: rscompat.cpp:1239
bool rscompat_old_effect_3_1(const char *type, struct section_file *file, const char *sec_name, struct rscompat_info *compat)
Check if effect name refers to one of the removed effects, and handle it if it does.
Definition: rscompat.cpp:606
bool rscompat_names(struct rscompat_info *info)
Do compatibility things with names before they are referred to.
Definition: rscompat.cpp:325
const char * rscompat_utype_flag_name_3_1(struct rscompat_info *compat, const char *old_type)
Replace deprecated unit type flag names with currently valid ones.
Definition: rscompat.cpp:1515
bool rscompat_old_slow_invasions_3_1(struct rscompat_info *compat, bool slow_invasions)
Replace slow_invasions and friends.
Definition: rscompat.cpp:1277
void rscompat_postprocess(struct rscompat_info *info)
Do compatibility things after regular ruleset loading.
Definition: rscompat.cpp:640
#define UCF_LAST_USER_FLAG_3_0
Definition: rscompat.cpp:41
static void rscompat_optional_capabilities(rscompat_info *info)
Handles compatibility with older versions when the new behavior is tied to the presence of an optiona...
Definition: rscompat.cpp:1146
static bool effect_list_compat_cb(struct effect *peffect, void *data)
Adjust effects.
Definition: rscompat.cpp:491
static int first_free_unit_type_user_flag()
Find and return the first unused unit type user flag.
Definition: rscompat.cpp:258
static int first_free_unit_class_user_flag()
Find and return the first unused unit class user flag.
Definition: rscompat.cpp:278
static void effect_to_enabler(action_id action, struct section_file *file, const char *sec_name, struct rscompat_info *compat, const char *type)
Turn old effect to an action enabler.
Definition: rscompat.cpp:553
static void rscompat_migrate_eft_nation_intelligence()
Adds effects to reproduce the traditional visibility of intelligence depending on the diplomatic stat...
Definition: rscompat.cpp:1097
static bool effect_handle_split_universal(struct effect *peffect, struct universal original, struct universal separated)
Handle a universal being separated from an original universal.
Definition: rscompat.cpp:472
struct requirement_vector * lookup_req_list(struct section_file *file, struct rscompat_info *compat, const char *sec, const char *sub, const char *rfor)
Load a requirement list.
Definition: ruleset.cpp:338
#define RULESET_COMPAT_CAP
Definition: rscompat.h:21
bool autoadjust_ruleset_data()
Apply some automatic defaults to already loaded rulesets.
Definition: rssanity.cpp:1389
#define CAP_EFT_WONDER_VISIBLE
Definition: ruleset.h:19
#define CAP_EFT_NATION_INTELLIGENCE
Definition: ruleset.h:21
#define CAP_VUT_VISIONLAYER
Definition: ruleset.h:20
#define CAP_EFT_BOMBARD_LIMIT_PCT
Definition: ruleset.h:18
#define RULESET_CAPABILITIES
Definition: ruleset.h:22
#define CAP_EFT_HP_REGEN_MIN
Definition: ruleset.h:17
static struct compatibility compat[]
Definition: savecompat.cpp:109
struct requirement_vector reqs
Definition: actions.h:461
action_id alternatives[MAX_NUM_ACTIONS]
Definition: actions.h:465
bool disabled
Definition: actions.h:363
action_id action
Definition: actions.h:364
struct requirement_vector actor_reqs
Definition: actions.h:365
struct requirement_vector target_reqs
Definition: actions.h:366
bool quiet
Definition: actions.h:327
char ui_name[MAX_LEN_NAME]
Definition: actions.h:323
Definition: city.h:291
bool enabled
Definition: diptreaty.h:48
struct requirement_vector reqs
Definition: effects.h:340
enum effect_type type
Definition: effects.h:328
uint8_t rmcauses
Definition: extras.h:80
const char * name
Definition: rscompat.cpp:36
const char * helptxt
Definition: rscompat.cpp:37
enum req_vec_change_operation operation
Definition: requirements.h:191
int num_suggested_solutions
Definition: requirements.h:203
char description[500]
Definition: requirements.h:200
struct req_vec_change * suggested_solutions
Definition: requirements.h:204
bool compat_mode
Definition: rscompat.h:24
int ver_terrain
Definition: rscompat.h:34
int ver_effects
Definition: rscompat.h:28
QByteArray cap_effects
Definition: rscompat.h:36
int ver_game
Definition: rscompat.h:29
int ver_units
Definition: rscompat.h:35
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
#define sz_strlcpy(dest, src)
Definition: support.h:140
const char * terrain_flag_id_name_cb(enum terrain_flag_id flag)
Terrain flag name callback, called from specenum code.
Definition: terrain.cpp:696
void set_user_terrain_flag_name(enum terrain_flag_id id, const char *name, const char *helptxt)
Sets user defined name for terrain flag.
Definition: terrain.cpp:673
#define MAX_NUM_USER_TER_FLAGS
Definition: terrain.h:140
const char * unit_type_flag_id_name_cb(enum unit_type_flag_id flag)
Unit type flag name callback, called from specenum code.
Definition: unittype.cpp:1577
const char * utype_rule_name(const struct unit_type *punittype)
Return the (untranslated) rule name of the unit type.
Definition: unittype.cpp:1274
const char * utype_name_translation(const struct unit_type *punittype)
Return the (translated) name of the unit type.
Definition: unittype.cpp:1256
Unit_type_id utype_number(const struct unit_type *punittype)
Return the unit type index.
Definition: unittype.cpp:91
const char * unit_class_flag_id_name_cb(enum unit_class_flag_id flag)
Unit class flag name callback, called from specenum code.
Definition: unittype.cpp:1522
void set_user_unit_class_flag_name(enum unit_class_flag_id id, const char *name, const char *helptxt)
Sets user defined name for unit class flag.
Definition: unittype.cpp:1493
const char * uclass_rule_name(const struct unit_class *pclass)
Return the (untranslated) rule name of the unit class.
Definition: unittype.cpp:1333
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Return TRUE iff units of the given type can do the specified generalized (ruleset defined) action ena...
Definition: unittype.cpp:386
void set_user_unit_type_flag_name(enum unit_type_flag_id id, const char *name, const char *helptxt)
Sets user defined name for unit flag.
Definition: unittype.cpp:1556
#define UCF_LAST_USER_FLAG
Definition: unittype.h:97
#define unit_class_iterate(_p)
Definition: unittype.h:823
#define MAX_NUM_USER_UNIT_FLAGS
Definition: unittype.h:303
#define UTYF_LAST_USER_FLAG
Definition: unittype.h:302
#define unit_type_iterate(_p)
Definition: unittype.h:785
#define unit_class_iterate_end
Definition: unittype.h:829
#define unit_type_iterate_end
Definition: unittype.h:791
#define MAX_NUM_USER_UCLASS_FLAGS
Definition: unittype.h:98