Freeciv-3.1
Loading...
Searching...
No Matches
rscompat.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* ANSI */
19#ifdef HAVE_STRING_H
20#include <string.h>
21#endif
22
23/* utility */
24#include "capability.h"
25#include "log.h"
26#include "registry.h"
27
28/* common */
29#include "actions.h"
30#include "effects.h"
31#include "game.h"
32#include "movement.h"
33#include "requirements.h"
34#include "unittype.h"
35
36/* server */
37#include "rssanity.h"
38#include "ruleset.h"
39#include "settings.h"
40
41#include "rscompat.h"
42
43#define enough_new_user_flags(_new_flags_, _name_, \
44 _LAST_USER_FLAG_, _LAST_USER_FLAG_PREV_) \
45FC_STATIC_ASSERT((ARRAY_SIZE(_new_flags_) \
46 <= _LAST_USER_FLAG_ - _LAST_USER_FLAG_PREV_), \
47 not_enough_new_##_name_##_user_flags)
48
49#define UTYF_LAST_USER_FLAG_3_0 UTYF_USER_FLAG_40
50#define UCF_LAST_USER_FLAG_3_0 UCF_USER_FLAG_8
51#define TER_LAST_USER_FLAG_3_0 TER_USER_8
52
53/**********************************************************************/
57{
58 memset(info, 0, sizeof(*info));
59}
60
61/**********************************************************************/
66 const char *filename,
67 const struct rscompat_info *info)
68{
69 const char *datafile_options;
70 bool ok = FALSE;
71 int format;
72
73 if (!(datafile_options = secfile_lookup_str(file, "datafile.options"))) {
74 log_fatal("\"%s\": ruleset capability problem:", filename);
76
77 return 0;
78 }
79
80 if (info->compat_mode) {
81 /* Check alternative capstr first, so that when we do the main capstr check,
82 * we already know that failures there are fatal (error message correct, can return
83 * immediately) */
84
85 if (has_capabilities(RULESET_COMPAT_CAP, datafile_options)
86 && has_capabilities(datafile_options, RULESET_COMPAT_CAP)) {
87 ok = TRUE;
88 }
89 }
90
91 if (!ok) {
92 if (!has_capabilities(RULESET_CAPABILITIES, datafile_options)) {
93 log_fatal("\"%s\": ruleset datafile appears incompatible:", filename);
94 log_fatal(" datafile options: %s", datafile_options);
95 log_fatal(" supported options: %s", RULESET_CAPABILITIES);
96 ruleset_error(NULL, LOG_ERROR, "Capability problem");
97
98 return 0;
99 }
100 if (!has_capabilities(datafile_options, RULESET_CAPABILITIES)) {
101 log_fatal("\"%s\": ruleset datafile claims required option(s)"
102 " that we don't support:", filename);
103 log_fatal(" datafile options: %s", datafile_options);
104 log_fatal(" supported options: %s", RULESET_CAPABILITIES);
105 ruleset_error(NULL, LOG_ERROR, "Capability problem");
106
107 return 0;
108 }
109 }
110
111 if (!secfile_lookup_int(file, &format, "datafile.format_version")) {
112 log_error("\"%s\": lacking legal format_version field", filename);
113 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
114
115 return 0;
116 } else if (format == 0) {
117 log_error("\"%s\": Illegal format_version value", filename);
118 ruleset_error(NULL, LOG_ERROR, "Format version error");
119 }
120
121 return format;
122}
123
124/**********************************************************************/
132 const char *filename,
133 const struct rscompat_info *info)
134{
135 int format_version;
136
137 fc_assert_ret_val(info->version > 0, FALSE);
138
139 format_version = rscompat_check_capabilities(file, filename, info);
140 if (format_version <= 0) {
141 /* Already logged in rscompat_check_capabilities */
142 return FALSE;
143 }
144
145 if (format_version != info->version) {
146 log_fatal("\"%s\": ruleset datafile format version differs from"
147 " other ruleset datafile(s):", filename);
148 log_fatal(" datafile format version: %d", format_version);
149 log_fatal(" expected format version: %d", info->version);
150 ruleset_error(NULL, LOG_ERROR, "Inconsistent format versions");
151
152 return FALSE;
153 }
154
155 return TRUE;
156}
157
158/**********************************************************************/
164static bool
166{
167 struct req_vec_problem *problem;
168
169 struct action *paction = action_by_number(ae->action);
170 /* Some changes requires starting to process an action's enablers from
171 * the beginning. */
172 bool needs_restart = FALSE;
173
174 while ((problem = action_enabler_suggest_repair(ae)) != NULL) {
175 /* A hard obligatory requirement is missing. */
176
177 int i;
178
179 if (problem->num_suggested_solutions == 0) {
180 /* Didn't get any suggestions about how to solve this. */
181
182 log_error("While adding hard obligatory reqs to action enabler"
183 " for %s: %s"
184 " Don't know how to fix it."
185 " Dropping it.",
186 action_rule_name(paction), problem->description);
188
189 req_vec_problem_free(problem);
190 return TRUE;
191 }
192
193 /* Sanity check. */
195 needs_restart);
196
197 /* Only append is supported for upgrade */
198 for (i = 0; i < problem->num_suggested_solutions; i++) {
199 if (problem->suggested_solutions[i].operation != RVCO_APPEND) {
200 /* A problem that isn't caused by missing obligatory hard
201 * requirements has been detected.
202 *
203 * Probably an old requirement that contradicted a hard requirement
204 * that wasn't documented by making it obligatory. In that case all
205 * suggested solutions has been applied to the enabler creating a
206 * new copy for each possible fulfillment of the new obligatory hard
207 * requirement.
208 *
209 * If another copy of the original enabler has survived this isn't
210 * an error. It probably isn't event an indication of a potential
211 * problem.
212 *
213 * If no possible solution survives the enabler was never in use
214 * because the action it self would have blocked it. In that case
215 * this is an error. */
216
217 log_warn("While adding hard obligatory reqs to action enabler"
218 " for %s: %s"
219 " Dropping it.",
220 action_rule_name(paction), problem->description);
222 req_vec_problem_free(problem);
223 return TRUE;
224 }
225 }
226
227 for (i = 0; i < problem->num_suggested_solutions; i++) {
228 struct action_enabler *new_enabler;
229
230 /* There can be more than one suggestion to apply. In that case both
231 * are applied to their own copy. The original should therefore be
232 * kept for now. */
233 new_enabler = action_enabler_copy(ae);
234
235 /* Apply the solution. */
238 new_enabler)) {
239 log_error("While adding hard obligatory reqs to action enabler"
240 " for %s: %s"
241 "Failed to apply solution %s."
242 " Dropping it.",
243 action_rule_name(paction), problem->description,
245 &problem->suggested_solutions[i],
247 new_enabler->ruledit_disabled = TRUE;
248 req_vec_problem_free(problem);
249 return TRUE;
250 }
251
252 if (problem->num_suggested_solutions - 1 == i) {
253 /* The last modification is to the original enabler. */
254 ae->action = new_enabler->action;
255 ae->ruledit_disabled = new_enabler->ruledit_disabled;
256 requirement_vector_copy(&ae->actor_reqs,
257 &new_enabler->actor_reqs);
258 requirement_vector_copy(&ae->target_reqs,
259 &new_enabler->target_reqs);
260 FC_FREE(new_enabler);
261 } else {
262 /* Register the new enabler */
263 action_enabler_add(new_enabler);
264
265 /* This changes the number of action enablers. */
266 needs_restart = TRUE;
267 }
268 }
269
270 req_vec_problem_free(problem);
271
272 if (needs_restart) {
273 /* May need to apply future upgrades to the copies too. */
274 return TRUE;
275 }
276 }
277
278 return needs_restart;
279}
280
281/**********************************************************************/
286{
287 log_normal("action enablers: adding obligatory hard requirements.");
288 log_warn("More than one way to fulfill a new obligatory hard requirement"
289 " may exist."
290 " In that case the enabler is copied so each alternative"
291 " solution is applied to a copy of the enabler."
292 " If an action enabler becomes self contradicting after applying"
293 " a solution it is dropped."
294 " Note that other copies of the original enabler may have"
295 " survived even if one copy is dropped.");
296
297 action_iterate(act_id) {
298 bool restart_enablers_for_action;
299
300 do {
301 restart_enablers_for_action = FALSE;
303 if (ae->ruledit_disabled) {
304 /* Ignore disabled enablers */
305 continue;
306 }
308 /* Something important, probably the number of action enablers
309 * for this action, changed. Start over again on this action's
310 * enablers. */
311 restart_enablers_for_action = TRUE;
312 break;
313 }
315 } while (restart_enablers_for_action);
317}
318
319/**********************************************************************/
324{
325 int flag;
326
327 /* Find the first unused user defined unit type flag. */
328 for (flag = 0; flag < MAX_NUM_USER_UNIT_FLAGS; flag++) {
329 if (unit_type_flag_id_name_cb(flag + UTYF_USER_FLAG_1) == NULL) {
330 return flag;
331 }
332 }
333
334 /* All unit type user flags are taken. */
336}
337
338/**********************************************************************/
343{
344 int flag;
345
346 /* Find the first unused user defined unit class flag. */
347 for (flag = 0; flag < MAX_NUM_USER_UCLASS_FLAGS; flag++) {
348 if (unit_class_flag_id_name_cb(flag + UCF_USER_FLAG_1) == NULL) {
349 return flag;
350 }
351 }
352
353 /* All unit class user flags are taken. */
355}
356
357/**********************************************************************/
362{
363 int flag;
364
365 /* Find the first unused user defined terrain flag. */
366 for (flag = 0; flag < MAX_NUM_USER_TER_FLAGS; flag++) {
367 if (terrain_flag_id_name_cb(flag + TER_USER_1) == NULL) {
368 return flag;
369 }
370 }
371
372 /* All terrain user flags are taken. */
374}
375
376/**********************************************************************/
387{
388 if (info->version < RSFORMAT_3_1) {
389 /* Some unit type flags moved to the ruleset between 3.0 and 3.1.
390 * Add them back as user flags.
391 * XXX: ruleset might not need all of these, and may have enough
392 * flags of its own that these additional ones prevent conversion. */
393 const struct {
394 const char *name;
395 const char *helptxt;
396 } new_flags_31[] = {
397 { N_("BeachLander"), N_("Won't lose all movement when moving from"
398 " non-native terrain to native terrain.") },
399 { N_("Cant_Fortify"), NULL },
400 { N_("OneAttack"), NULL },
401 };
402 enough_new_user_flags(new_flags_31, unit_type,
404
405 /* Some unit class flags moved to the ruleset between 3.0 and 3.1.
406 * Add them back as user flags.
407 * XXX: ruleset might not need all of these, and may have enough
408 * flags of its own that these additional ones prevent conversion. */
409 const struct {
410 const char *name;
411 const char *helptxt;
412 } new_class_flags_31[] = {
413 { N_("Missile"), N_("Unit is destroyed when it attacks") },
414 { N_("CanPillage"), N_("Can pillage tile improvements.") },
415 { N_("CanFortify"), N_("Gets a 50% defensive bonus while"
416 " in cities.") },
417 { N_("HutNothing"), N_("Does nothing to huts.") },
418 };
419 enough_new_user_flags(new_class_flags_31, unit_class,
421
422 int first_free;
423 int i;
424
425 /* Unit type flags. */
426 first_free = first_free_unit_type_user_flag() + UTYF_USER_FLAG_1;
427
428 for (i = 0; i < ARRAY_SIZE(new_flags_31); i++) {
429 if (UTYF_USER_FLAG_1 + MAX_NUM_USER_UNIT_FLAGS <= first_free + i) {
430 /* Can't add the user unit type flags. */
432 "Can't upgrade the ruleset. Not enough free unit type "
433 "user flags to add user flags for the unit type flags "
434 "that used to be hardcoded.");
435 return FALSE;
436 }
437 /* Shouldn't be possible for valid old ruleset to have flag names that
438 * clash with these ones */
439 if (unit_type_flag_id_by_name(new_flags_31[i].name, fc_strcasecmp)
440 != unit_type_flag_id_invalid()) {
442 "Ruleset had illegal user unit type flag '%s'",
443 new_flags_31[i].name);
444 return FALSE;
445 }
446 set_user_unit_type_flag_name(first_free + i,
447 new_flags_31[i].name,
448 new_flags_31[i].helptxt);
449 }
450
451 /* Unit type class flags. */
452 first_free = first_free_unit_class_user_flag() + UCF_USER_FLAG_1;
453
454 for (i = 0; i < ARRAY_SIZE(new_class_flags_31); i++) {
455 if (UCF_USER_FLAG_1 + MAX_NUM_USER_UCLASS_FLAGS <= first_free + i) {
456 /* Can't add the user unit type class flags. */
458 "Can't upgrade the ruleset. Not enough free unit "
459 "type class user flags to add user flags for the "
460 "unit type class flags that used to be hardcoded.");
461 return FALSE;
462 }
463 /* Shouldn't be possible for valid old ruleset to have flag names that
464 * clash with these ones */
465 if (unit_class_flag_id_by_name(new_class_flags_31[i].name,
467 != unit_class_flag_id_invalid()) {
469 "Ruleset had illegal user unit class flag '%s'",
470 new_class_flags_31[i].name);
471 return FALSE;
472 }
473 set_user_unit_class_flag_name(first_free + i,
474 new_class_flags_31[i].name,
475 new_class_flags_31[i].helptxt);
476 }
477 }
478
479 if (info->version < RSFORMAT_3_1) {
480 /* Some terrain flags moved to the ruleset between 3.0 and 3.1.
481 * Add them back as user flags.
482 * XXX: ruleset might not need all of these, and may have enough
483 * flags of its own that these additional ones prevent conversion. */
484 const struct {
485 const char *name;
486 const char *helptxt;
487 } new_flags_31[] = {
488 { N_("NoFortify"), N_("No units can fortify on this terrain.") },
489 };
490 enough_new_user_flags(new_flags_31, terrain,
491 TER_USER_LAST, TER_LAST_USER_FLAG_3_0);
492
493 int first_free;
494 int i;
495
496 /* Terrain flags. */
497 first_free = first_free_terrain_user_flag() + TER_USER_1;
498
499 for (i = 0; i < ARRAY_SIZE(new_flags_31); i++) {
500 if (TER_USER_1 + MAX_NUM_USER_TER_FLAGS <= first_free + i) {
501 /* Can't add the user terrain flags. */
503 "Can't upgrade the ruleset. Not enough free terrain "
504 "user flags to add user flags for the terrain flags "
505 "that used to be hardcoded.");
506 return FALSE;
507 }
508 /* Shouldn't be possible for valid old ruleset to have flag names that
509 * clash with these ones */
510 if (terrain_flag_id_by_name(new_flags_31[i].name, fc_strcasecmp)
511 != terrain_flag_id_invalid()) {
513 "Ruleset had illegal user terrain flag '%s'",
514 new_flags_31[i].name);
515 return FALSE;
516 }
517 set_user_terrain_flag_name(first_free + i,
518 new_flags_31[i].name,
519 new_flags_31[i].helptxt);
520 }
521 }
522
523 /* No errors encountered. */
524 return TRUE;
525}
526
527/**********************************************************************/
531static void split_action_name_update(struct action *original,
532 struct action *copy,
533 const char *name_modification)
534{
536 name_modification, original->ui_name);
537}
538
539/**********************************************************************/
551static bool effect_handle_split_universal(struct effect *peffect,
552 struct universal original,
553 struct universal separated)
554{
555 if (universal_is_mentioned_by_requirements(&peffect->reqs, &original)) {
556 /* Copy the old effect. */
557 struct effect *peffect_copy = effect_copy(peffect);
558
559 /* Replace the original requirement with the separated requirement. */
560 return universal_replace_in_req_vec(&peffect_copy->reqs,
561 &original, &separated);
562 }
563
564 return FALSE;
565}
566
567/**********************************************************************/
570static bool effect_list_compat_cb(struct effect *peffect, void *data)
571{
572 struct rscompat_info *info = (struct rscompat_info *)data;
573
574 if (info->version < RSFORMAT_3_1) {
575 /* Attack has been split in regular "Attack" and "Suicide Attack". */
577 universal_by_number(VUT_ACTION, ACTION_ATTACK),
578 universal_by_number(VUT_ACTION, ACTION_SUICIDE_ATTACK));
579
580 /* "Nuke City" and "Nuke Units" has been split from "Explode Nuclear".
581 * "Explode Nuclear" is now only about exploding at the current tile. */
583 universal_by_number(VUT_ACTION, ACTION_NUKE),
584 universal_by_number(VUT_ACTION, ACTION_NUKE_CITY));
586 universal_by_number(VUT_ACTION, ACTION_NUKE),
587 universal_by_number(VUT_ACTION, ACTION_NUKE_UNITS));
588
589 /* Production or building targeted actions have been split in one action
590 * for each target. */
592 universal_by_number(VUT_ACTION, ACTION_SPY_TARGETED_SABOTAGE_CITY),
593 universal_by_number(VUT_ACTION, ACTION_SPY_SABOTAGE_CITY_PRODUCTION));
595 universal_by_number(VUT_ACTION, ACTION_SPY_TARGETED_SABOTAGE_CITY_ESC),
596 universal_by_number(VUT_ACTION, ACTION_SPY_SABOTAGE_CITY_PRODUCTION_ESC));
597
598 if (peffect->type == EFT_ILLEGAL_ACTION_MOVE_COST) {
599 /* Boarding a transporter became action enabler controlled in
600 * Freeciv 3.1. Old hard coded rules had no punishment for trying to
601 * do this when it is illegal according to the rules. */
602 effect_req_append(peffect, req_from_str("Action", "Local", FALSE,
603 FALSE, FALSE,
604 "Transport Board"));
605 effect_req_append(peffect, req_from_str("Action", "Local", FALSE,
606 FALSE, FALSE,
607 "Transport Embark"));
608
609 /* Disembarking became action enabler controlled in Freeciv 3.1. Old
610 * hard coded rules had no punishment for trying to do those when it
611 * is illegal according to the rules. */
612 effect_req_append(peffect, req_from_str("Action", "Local", FALSE,
613 FALSE, FALSE,
614 "Transport Disembark"));
615 effect_req_append(peffect, req_from_str("Action", "Local", FALSE,
616 FALSE, FALSE,
617 "Transport Disembark 2"));
618 }
619
620 /* "Paradrop Unit" has been split by side effects. */
622 universal_by_number(VUT_ACTION, ACTION_PARADROP),
623 universal_by_number(VUT_ACTION, ACTION_PARADROP_CONQUER));
625 universal_by_number(VUT_ACTION, ACTION_PARADROP),
626 universal_by_number(VUT_ACTION, ACTION_PARADROP_ENTER));
628 universal_by_number(VUT_ACTION, ACTION_PARADROP),
629 universal_by_number(VUT_ACTION, ACTION_PARADROP_ENTER_CONQUER));
631 universal_by_number(VUT_ACTION, ACTION_PARADROP),
632 universal_by_number(VUT_ACTION, ACTION_PARADROP_FRIGHTEN));
634 universal_by_number(VUT_ACTION, ACTION_PARADROP),
635 universal_by_number(VUT_ACTION, ACTION_PARADROP_FRIGHTEN_CONQUER));
636 }
637
638 /* Go to the next effect. */
639 return TRUE;
640}
641
642/**********************************************************************/
645static void paratroopers_mr_sub_to_effect(struct unit_type *putype,
646 struct action *paction)
647{
648 struct effect *peffect;
649
650 /* Subtract the value via the Action_Success_Actor_Move_Cost effect */
651 peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST,
653 NULL);
654
655 /* The reduction only applies to this action. */
656 effect_req_append(peffect,
657 req_from_str("Action", "Local", FALSE, TRUE, FALSE,
658 action_rule_name(paction)));
659
660 /* The reduction only applies to this unit type. */
661 effect_req_append(peffect,
662 req_from_str("UnitType", "Local", FALSE, TRUE, FALSE,
663 utype_rule_name(putype)));
664}
665
666/**********************************************************************/
670static bool ete_is_target_req(struct requirement *preq)
671{
672 switch (preq->source.kind) {
673 /* World range only - listed in actor reqs */
674 case VUT_MINYEAR:
675 case VUT_TOPO:
676 case VUT_MINCALFRAG:
677 case VUT_SERVERSETTING:
678 return FALSE;
679
680 /* Actor ones */
681 case VUT_ADVANCE:
682 case VUT_GOVERNMENT:
683 case VUT_NATION:
684 case VUT_UTYPE:
685 case VUT_UTFLAG:
686 case VUT_UCLASS:
687 case VUT_UCFLAG:
688 case VUT_AI_LEVEL:
689 case VUT_NATIONALITY:
690 case VUT_TECHFLAG:
691 case VUT_ACHIEVEMENT:
692 case VUT_DIPLREL:
693 case VUT_STYLE:
694 case VUT_MINCULTURE:
695 case VUT_UNITSTATE:
696 case VUT_MINMOVES:
697 case VUT_MINVETERAN:
698 case VUT_MINHP:
699 case VUT_NATIONGROUP:
700 case VUT_ACTION:
701 case VUT_MINTECHS:
702 case VUT_ACTIVITY:
703 case VUT_DIPLREL_UNITANY: /* ? */
704 case VUT_DIPLREL_UNITANY_O: /* ? */
705 return FALSE;
706
707 /* Target ones */
708 case VUT_IMPROVEMENT:
709 case VUT_TERRAIN:
710 case VUT_MINSIZE:
711 case VUT_TERRAINCLASS:
712 case VUT_TERRAINALTER:
713 case VUT_CITYTILE:
714 case VUT_TERRFLAG:
715 case VUT_ROADFLAG:
716 case VUT_EXTRA:
717 case VUT_MAXTILEUNITS:
718 case VUT_EXTRAFLAG:
719 case VUT_CITYSTATUS:
720 case VUT_MINFOREIGNPCT:
721 case VUT_DIPLREL_TILE: /* ? */
722 case VUT_DIPLREL_TILE_O: /* ? */
723 return TRUE;
724
725 /* Ones that are actor reqs at some range, target reqs at another range */
726 case VUT_AGE:
727 if (preq->range == REQ_RANGE_CITY) {
728 return TRUE;
729 }
730 return FALSE;
731
732 /* Ones that make equally little sense both as actor and target req */
733 case VUT_NONE:
734 case VUT_OTYPE:
735 case VUT_SPECIALIST:
736 case VUT_GOOD:
737 case VUT_IMPR_GENUS:
738 return FALSE;
739 case VUT_COUNT:
740 fc_assert(preq->source.kind != VUT_COUNT);
741 return FALSE;
742 }
743
745
746 return FALSE;
747}
748
749/**********************************************************************/
753 const char *sec_name, struct rscompat_info *compat,
754 const char *type)
755{
756 int value = secfile_lookup_int_default(file, 1, "%s.value", sec_name);
757 char buf[1024];
758
759 if (value > 0) {
760 /* It was an enabling effect. Add enabler */
761 struct action_enabler *enabler;
762 struct requirement_vector *reqs;
763 struct requirement settler_req;
764
765 enabler = action_enabler_new();
766 enabler->action = action;
767
768 reqs = lookup_req_list(file, compat, sec_name, "reqs", "old effect");
769
771 if (ete_is_target_req(preq)) {
772 requirement_vector_append(&enabler->target_reqs, *preq);
773 } else {
774 requirement_vector_append(&enabler->actor_reqs, *preq);
775 }
777
778 settler_req = req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL, FALSE, TRUE, FALSE,
779 UTYF_SETTLERS);
780 requirement_vector_append(&enabler->actor_reqs, settler_req);
781
782 /* Add the enabler to the ruleset. */
783 action_enabler_add(enabler);
784
785 if (compat->log_cb != NULL) {
786 fc_snprintf(buf, sizeof(buf),
787 "Converted effect %s in %s to an action enabler. Make sure requirements "
788 "are correctly divided to actor and target requirements.",
789 type, sec_name);
790 compat->log_cb(buf);
791 }
792 } else if (value < 0) {
793 if (compat->log_cb != NULL) {
794 fc_snprintf(buf, sizeof(buf),
795 "%s effect with negative value in %s can't be automatically converted "
796 "to an action enabler. Do that manually.", type, sec_name);
797 compat->log_cb(buf);
798 }
799 }
800}
801
802/**********************************************************************/
806bool rscompat_old_effect_3_1(const char *type, struct section_file *file,
807 const char *sec_name, struct rscompat_info *compat)
808{
809 if (compat->version < RSFORMAT_3_1) {
810 if (!fc_strcasecmp(type, "Transform_Possible")) {
811 effect_to_enabler(ACTION_TRANSFORM_TERRAIN, file, sec_name, compat, type);
812 return TRUE;
813 }
814 if (!fc_strcasecmp(type, "Irrig_TF_Possible")) {
815 effect_to_enabler(ACTION_CULTIVATE, file, sec_name, compat, type);
816 return TRUE;
817 }
818 if (!fc_strcasecmp(type, "Mining_TF_Possible")) {
819 effect_to_enabler(ACTION_PLANT, file, sec_name, compat, type);
820 return TRUE;
821 }
822 if (!fc_strcasecmp(type, "Mining_Possible")) {
823 effect_to_enabler(ACTION_MINE, file, sec_name, compat, type);
824 return TRUE;
825 }
826 if (!fc_strcasecmp(type, "Irrig_Possible")) {
827 effect_to_enabler(ACTION_IRRIGATE, file, sec_name, compat, type);
828 return TRUE;
829 }
830 }
831
832 return FALSE;
833}
834
835/**********************************************************************/
840{
841 if (!info->compat_mode) {
842 /* There isn't anything here that should be done outside of compat
843 * mode. */
844 return;
845 }
846
847 if (info->version < RSFORMAT_3_1) {
848 improvement_iterate(pimprove) {
849 if (pimprove->upkeep != 0 && is_wonder(pimprove)) {
850 pimprove->upkeep = 0;
851 }
853 }
854}
855
856/**********************************************************************/
860{
861 if (!info->compat_mode) {
862 /* There isn't anything here that should be done outside of compat
863 * mode. */
864 return;
865 }
866
867 /* Upgrade existing effects. Done before new effects are added to prevent
868 * the new effects from being upgraded by accident. */
870
871 if (info->version < RSFORMAT_3_1) {
872 struct effect *peffect;
873
874 /* Post successful action move fragment loss for "Bombard"
875 * has moved to the ruleset. */
876 peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST,
877 MAX_MOVE_FRAGS, NULL);
878
879 /* The reduction only applies to "Bombard". */
880 effect_req_append(peffect, req_from_str("Action", "Local", FALSE, TRUE,
881 TRUE, "Bombard"));
882
883 /* Post successful action move fragment loss for "Heal Unit"
884 * has moved to the ruleset. */
885 peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST,
886 MAX_MOVE_FRAGS, NULL);
887
888 /* The reduction only applies to "Heal Unit". */
889 effect_req_append(peffect, req_from_str("Action", "Local", FALSE, TRUE,
890 TRUE, "Heal Unit"));
891
892 /* Post successful action move fragment loss for "Expel Unit"
893 * has moved to the ruleset. */
894 peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST,
895 SINGLE_MOVE, NULL);
896
897 /* The reduction only applies to "Expel Unit". */
898 effect_req_append(peffect, req_from_str("Action", "Local", FALSE, TRUE,
899 TRUE, "Expel Unit"));
900
901 /* Post successful action move fragment loss for "Capture Units"
902 * has moved to the ruleset. */
903 peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST,
904 SINGLE_MOVE, NULL);
905
906 /* The reduction only applies to "Capture Units". */
907 effect_req_append(peffect, req_from_str("Action", "Local", FALSE, TRUE,
908 TRUE, "Capture Units"));
909
910 /* Post successful action move fragment loss for "Establish Embassy"
911 * has moved to the ruleset. */
912 peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST,
913 1, NULL);
914
915 /* The reduction only applies to "Establish Embassy". */
916 effect_req_append(peffect, req_from_str("Action", "Local", FALSE, TRUE,
917 TRUE, "Establish Embassy"));
918
919 /* Post successful action move fragment loss for "Investigate City"
920 * has moved to the ruleset. */
921 peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST,
922 1, NULL);
923
924 /* The reduction only applies to "Investigate City". */
925 effect_req_append(peffect, req_from_str("Action", "Local", FALSE, TRUE,
926 TRUE, "Investigate City"));
927
928 /* Post successful action move fragment loss for targets of "Expel Unit"
929 * has moved to the ruleset. */
930 peffect = effect_new(EFT_ACTION_SUCCESS_TARGET_MOVE_COST,
931 MAX_MOVE_FRAGS, NULL);
932
933 /* The reduction only applies to "Expel Unit". */
934 effect_req_append(peffect, req_from_str("Action", "Local", FALSE, TRUE,
935 TRUE, "Expel Unit"));
936
937 /* Post successful action move fragment loss for "OneAttack"
938 * has moved to the ruleset. */
939 peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST,
940 MAX_MOVE_FRAGS, NULL);
941 /* The reduction only applies to "Attack". */
942 effect_req_append(peffect, req_from_str("Action", "Local", FALSE, TRUE,
943 TRUE, "Attack"));
944 /* The reduction only applies to "OneAttack". */
945 effect_req_append(peffect, req_from_str("UnitFlag", "Local", FALSE, TRUE,
946 TRUE, "OneAttack"));
947
948 action_by_result_iterate(paction, ACTRES_ATTACK) {
949 if (paction->actor_consuming_always) {
950 /* Not relevant. */
951 continue;
952 }
953
954 peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST,
955 SINGLE_MOVE, NULL);
956 /* The reduction only applies to this action. */
957 effect_req_append(peffect, req_from_str("Action", "Local",
958 FALSE, TRUE, TRUE,
959 action_rule_name(paction)));
960 /* The reduction doesn't apply to "OneAttack". */
961 effect_req_append(peffect, req_from_str("UnitFlag", "Local",
962 FALSE, FALSE, TRUE,
963 "OneAttack"));
965
966 /* Post successful action move fragment loss for spy post action escape
967 * has moved to the ruleset. */
968 action_iterate(act_id) {
969 struct action *paction = action_by_number(act_id);
970
971 if (paction->actor.is_unit.moves_actor != MAK_ESCAPE
972 || paction->actor_consuming_always) {
973 /* Not relevant. */
974 continue;
975 }
976
977 peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST,
978 MAX_MOVE_FRAGS, NULL);
979 /* The reduction only applies to this action. */
980 effect_req_append(peffect, req_from_str("Action", "Local",
981 FALSE, TRUE, TRUE,
982 action_rule_name(paction)));
984
985 /* Post successful action move fragment loss for targets of
986 * "Paradrop Unit" has moved to the Action_Success_Actor_Move_Cost
987 * effect. */
988 unit_type_iterate(putype) {
989 if (!utype_can_do_action(putype, ACTION_PARADROP)) {
990 /* Not relevant */
991 continue;
992 }
993
994 if (putype->rscompat_cache.paratroopers_mr_sub == 0) {
995 /* Not relevant */
996 continue;
997 }
998
999 action_by_result_iterate(paction, ACTRES_PARADROP) {
1000 paratroopers_mr_sub_to_effect(putype, paction);
1002 action_by_result_iterate(paction, ACTRES_PARADROP_CONQUER) {
1003 paratroopers_mr_sub_to_effect(putype, paction);
1006
1007 /* Fortifying rules have been unhardcoded to effects. */
1008 peffect = effect_new(EFT_FORTIFY_DEFENSE_BONUS, 50, NULL);
1009
1010 /* Unit actually fortified. This does not need checks for unit class or
1011 * type flags for unit's ability to fortify as it would not be fortified
1012 * if it can't. */
1013 effect_req_append(peffect, req_from_str("Activity", "Local", FALSE, TRUE,
1014 FALSE, "Fortified"));
1015
1016 /* Fortify bonus in cities */
1017 peffect = effect_new(EFT_FORTIFY_DEFENSE_BONUS, 50, NULL);
1018
1019 /* City center */
1020 effect_req_append(peffect, req_from_str("CityTile", "Local", FALSE, TRUE,
1021 FALSE, "Center"));
1022 /* Not cumulative with regular fortified bonus */
1023 effect_req_append(peffect, req_from_str("Activity", "Local", FALSE, FALSE,
1024 FALSE, "Fortified"));
1025 /* Unit flags */
1026 effect_req_append(peffect, req_from_str("UnitClassFlag", "Local", FALSE, TRUE,
1027 FALSE, "CanFortify"));
1028 effect_req_append(peffect, req_from_str("UnitFlag", "Local", FALSE, FALSE,
1029 FALSE, "Cant_Fortify"));
1030
1031 /* The probability that "Steal Maps" and "Steal Maps Escape" steals the
1032 * map of a tile has moved to the ruleset. */
1033 effect_new(EFT_MAPS_STOLEN_PCT, -50, NULL);
1034
1035 /* The rule that "Recycle Unit"'s unit shield value is 50% has moved to
1036 * the ruleset. */
1037 peffect = effect_new(EFT_UNIT_SHIELD_VALUE_PCT, -50, NULL);
1038 effect_req_append(peffect, req_from_str("Action", "Local", FALSE, TRUE,
1039 FALSE, "Recycle Unit"));
1040
1041 /* The rule that "Upgrade Unit"'s current unit shield value is 50% when
1042 * calculating unit upgrade price has moved to the ruleset. */
1043 peffect = effect_new(EFT_UNIT_SHIELD_VALUE_PCT, -50, NULL);
1044 effect_req_append(peffect, req_from_str("Action", "Local", FALSE, TRUE,
1045 FALSE, "Upgrade Unit"));
1046
1047 /* The rule that "Heal Unit" heals up to 25% has moved to the
1048 * ruleset. */
1049 peffect = effect_new(EFT_HEAL_UNIT_PCT, -75, NULL);
1050 effect_req_append(peffect, req_from_str("Action", "Local", FALSE, TRUE,
1051 FALSE, "Heal Unit"));
1052
1053 /* The rule that unit in a city has at least 1/3 of its HP in the
1054 * beginning of the new turn has moved to the ruleset. */
1055 peffect = effect_new(EFT_MIN_HP_PCT, 33, NULL);
1056 effect_req_append(peffect, req_from_str("CityTile", "Local", FALSE, TRUE,
1057 FALSE, "Center"));
1058
1059 /* The base unit regeneration rule is in ruleset now. */
1060 peffect = effect_new(EFT_HP_REGEN_2, 10, NULL);
1061 /* Does not apply to any unit class with HP loss */
1062 unit_class_iterate(pclass) {
1063 if (pclass->hp_loss_pct) {
1064 effect_req_append(peffect, req_from_str("UnitClass", "Local", FALSE,
1065 FALSE, FALSE,
1066 uclass_rule_name(pclass)));
1067 }
1069
1070 /* The rule that fortified unit regenerates extra 10% has been moved
1071 * to the ruleset. */
1072 peffect = effect_new(EFT_HP_REGEN_2, 10, NULL);
1073 effect_req_append(peffect, req_from_str("Activity", "Local", FALSE, TRUE,
1074 FALSE, "Fortified"));
1075
1076 /* Help ruleset authors specify the new arguments to unit_move() and
1077 * unit_teleport() by introducing boolean effects */
1078 log_normal(_("Preparing user effects to help you port edit.unit_move()"
1079 " and edit.unit_teleport() Lua calls."));
1080 log_normal(_("It is safe to delete the effects if you don't use"
1081 " unit_move() or unit_teleport() or if you want to fill"
1082 " in the new parameters with your own values."));
1083 log_normal(_("Use effects.unit_bonus() and effects.unit_vs_tile_bonus()"
1084 " to get the value of the user effects"
1085 " if you wish to use them."));
1086
1087 /* EFT_USER_EFFECT_1 is if a unit may occupy a city */
1088 log_normal(_("User_Effect_1 is now if a unit can conquer a city."));
1089 peffect = effect_new(EFT_USER_EFFECT_1, 1, NULL);
1090 effect_req_append(peffect,
1091 req_from_str("UnitClassFlag", "Local",
1092 FALSE, TRUE, FALSE, "CanOccupyCity"));
1093 effect_req_append(peffect,
1094 req_from_str("UnitFlag", "Local",
1095 FALSE, FALSE, FALSE, "NonMil"));
1096 effect_req_append(peffect,
1097 req_from_str("DiplRel", "Local",
1098 FALSE, TRUE, FALSE, "War"));
1099 nations_iterate(pnation) {
1100 if (nation_barbarian_type(pnation) == ANIMAL_BARBARIAN) {
1101 effect_req_append(peffect,
1102 req_from_str("Nation", "Player",
1103 FALSE, FALSE, FALSE,
1104 nation_rule_name(pnation)));
1105 }
1107
1108 /* EFT_USER_EFFECT_2 is if a unit may occupy an extra */
1109 log_normal(_("User_Effect_2 is now if a unit can conquer an extra."));
1110 peffect = effect_new(EFT_USER_EFFECT_2, 1, NULL);
1111 effect_req_append(peffect,
1112 req_from_str("DiplRel", "Local",
1113 FALSE, TRUE, FALSE, "War"));
1114
1115 peffect = effect_new(EFT_USER_EFFECT_2, 1, NULL);
1116 effect_req_append(peffect,
1117 req_from_str("CityTile", "Local",
1118 FALSE, FALSE, FALSE, "Extras Owned"));
1119
1120 /* EFT_USER_EFFECT_3 is if a unit may enter a hut */
1121 log_normal(_("User_Effect_3 is now if a unit can enter a hut."));
1122 peffect = effect_new(EFT_USER_EFFECT_3, 1, NULL);
1123 effect_req_append(peffect,
1124 req_from_str("UnitClassFlag", "Local",
1125 FALSE, FALSE, FALSE, "HutFrighten"));
1126 effect_req_append(peffect,
1127 req_from_str("UnitClassFlag", "Local",
1128 FALSE, FALSE, FALSE, "HutNothing"));
1129
1130 /* EFT_USER_EFFECT_4 is if a unit may frighten a hut */
1131 log_normal(_("User_Effect_4 is now if a unit can frighten a hut."));
1132 peffect = effect_new(EFT_USER_EFFECT_4, 1, NULL);
1133 effect_req_append(peffect,
1134 req_from_str("UnitClassFlag", "Local",
1135 FALSE, TRUE, FALSE, "HutFrighten"));
1136 effect_req_append(peffect,
1137 req_from_str("UnitClassFlag", "Local",
1138 FALSE, FALSE, FALSE, "HutNothing"));
1139 }
1140
1141 if (info->version < RSFORMAT_3_1) {
1142 /* New enablers */
1143 struct action_enabler *enabler;
1144 struct requirement e_req;
1145 struct action *paction;
1146
1147 paction = action_by_number(ACTION_NUKE_CITY);
1148 paction->target_kind = ATK_CITY;
1149 paction->actor_consuming_always = TRUE;
1150 paction->min_distance = 1;
1152
1153 paction = action_by_number(ACTION_NUKE);
1154 paction->actor_consuming_always = TRUE;
1155 paction->min_distance = 0;
1156
1157 paction = action_by_number(ACTION_NUKE_UNITS);
1158 paction->actor_consuming_always = TRUE;
1159 paction->min_distance = 1;
1160
1161 paction = action_by_number(ACTION_FOUND_CITY);
1162 paction->actor_consuming_always = TRUE;
1163
1164 enabler = action_enabler_new();
1165 enabler->action = ACTION_PILLAGE;
1166 e_req = req_from_str("UnitClassFlag", "Local", FALSE, TRUE, FALSE,
1167 "CanPillage");
1168 requirement_vector_append(&enabler->actor_reqs, e_req);
1169 action_enabler_add(enabler);
1170
1171 enabler = action_enabler_new();
1172 enabler->action = ACTION_CLEAN_FALLOUT;
1173 e_req = req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL, FALSE, TRUE, FALSE,
1174 UTYF_SETTLERS);
1175 requirement_vector_append(&enabler->actor_reqs, e_req);
1176 action_enabler_add(enabler);
1177
1178 enabler = action_enabler_new();
1179 enabler->action = ACTION_CLEAN_POLLUTION;
1180 e_req = req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL, FALSE, TRUE, FALSE,
1181 UTYF_SETTLERS);
1182 requirement_vector_append(&enabler->actor_reqs, e_req);
1183 action_enabler_add(enabler);
1184
1185 enabler = action_enabler_new();
1186 enabler->action = ACTION_FORTIFY;
1187 e_req = req_from_str("UnitClassFlag", "Local", FALSE, TRUE, TRUE,
1188 "CanFortify");
1189 requirement_vector_append(&enabler->actor_reqs, e_req);
1190 e_req = req_from_str("UnitFlag", "Local", FALSE, FALSE, TRUE,
1191 "Cant_Fortify");
1192 requirement_vector_append(&enabler->actor_reqs, e_req);
1193 e_req = req_from_str("TerrainFlag", "Local", FALSE, FALSE, TRUE,
1194 "NoFortify");
1195 requirement_vector_append(&enabler->actor_reqs, e_req);
1196 action_enabler_add(enabler);
1197
1198 enabler = action_enabler_new();
1199 enabler->action = ACTION_FORTIFY;
1200 e_req = req_from_str("UnitClassFlag", "Local", FALSE, TRUE, TRUE,
1201 "CanFortify");
1202 requirement_vector_append(&enabler->actor_reqs, e_req);
1203 e_req = req_from_str("UnitFlag", "Local", FALSE, FALSE, TRUE,
1204 "Cant_Fortify");
1205 requirement_vector_append(&enabler->actor_reqs, e_req);
1206 e_req = req_from_str("CityTile", "Local", FALSE, TRUE, TRUE,
1207 "Center");
1208 requirement_vector_append(&enabler->actor_reqs, e_req);
1209 action_enabler_add(enabler);
1210
1211 enabler = action_enabler_new();
1212 enabler->action = ACTION_ROAD;
1213 e_req = req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL, FALSE, TRUE, FALSE,
1214 UTYF_SETTLERS);
1215 requirement_vector_append(&enabler->actor_reqs, e_req);
1216 action_enabler_add(enabler);
1217
1218 enabler = action_enabler_new();
1219 enabler->action = ACTION_CONVERT;
1220 action_enabler_add(enabler);
1221
1222 enabler = action_enabler_new();
1223 enabler->action = ACTION_BASE;
1224 e_req = req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL, FALSE, TRUE, FALSE,
1225 UTYF_SETTLERS);
1226 requirement_vector_append(&enabler->actor_reqs, e_req);
1227 action_enabler_add(enabler);
1228
1229 enabler = action_enabler_new();
1230 enabler->action = ACTION_TRANSPORT_ALIGHT;
1231 action_enabler_add(enabler);
1232
1233 enabler = action_enabler_new();
1234 enabler->action = ACTION_TRANSPORT_BOARD;
1235 action_enabler_add(enabler);
1236
1237 enabler = action_enabler_new();
1238 enabler->action = ACTION_TRANSPORT_EMBARK;
1239 action_enabler_add(enabler);
1240
1241 enabler = action_enabler_new();
1242 enabler->action = ACTION_TRANSPORT_UNLOAD;
1243 action_enabler_add(enabler);
1244
1245 /* Assume the player knows that the unit is able to move */
1246 paction = action_by_number(ACTION_UNIT_MOVE);
1247 paction->quiet = TRUE;
1248
1249 enabler = action_enabler_new();
1250 enabler->action = ACTION_UNIT_MOVE;
1251 e_req = req_from_values(VUT_MINMOVES, REQ_RANGE_LOCAL,
1252 FALSE, TRUE, FALSE, 1);
1253 requirement_vector_append(&enabler->actor_reqs, e_req);
1254 e_req = req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
1255 FALSE, FALSE, FALSE,
1256 USP_TRANSPORTED);
1257 requirement_vector_append(&enabler->actor_reqs, e_req);
1258 action_enabler_add(enabler);
1259
1260 /* Update action enablers. */
1263 /* "Attack" is split in a unit consuming and a non unit consuming
1264 * version. */
1265 if (ae->action == ACTION_ATTACK) {
1266 /* The old rule is represented with two action enablers. */
1267 enabler = action_enabler_copy(ae);
1268
1269 /* One allows regular attacks. */
1270 requirement_vector_append(&ae->actor_reqs,
1271 req_from_str("UnitClassFlag", "Local",
1272 FALSE, FALSE, TRUE,
1273 "Missile"));
1274
1275 /* The other allows suicide attacks. */
1276 enabler->action = ACTION_SUICIDE_ATTACK;
1277 requirement_vector_append(&enabler->actor_reqs,
1278 req_from_str("UnitClassFlag", "Local",
1279 FALSE, TRUE, TRUE,
1280 "Missile"));
1281
1282 /* Add after the action was changed. */
1283 action_enabler_add(enabler);
1284 }
1285
1286 /* "Explode Nuclear"'s adjacent tile attack is split to "Nuke City"
1287 * and "Nuke Units". */
1288 if (ae->action == ACTION_NUKE) {
1289 /* The old rule is represented with three action enablers:
1290 * 1) "Explode Nuclear" against the actors own tile.
1291 * 2) "Nuke City" against adjacent enemy cities.
1292 * 3) "Nuke Units" against adjacent enemy unit stacks. */
1293
1294 struct action_enabler *city;
1295 struct action_enabler *units;
1296
1297 /* Against city targets. */
1299 city->action = ACTION_NUKE_CITY;
1300
1301 /* Against unit stack targets. */
1302 units = action_enabler_copy(ae);
1303 units->action = ACTION_NUKE_UNITS;
1304
1305 /* "Explode Nuclear" required this to target an adjacent tile. */
1306 /* While this isn't a real move (because of enemy city/units) at
1307 * target tile it pretends to be one. */
1308 requirement_vector_append(&city->actor_reqs,
1309 req_from_values(VUT_MINMOVES,
1310 REQ_RANGE_LOCAL,
1311 FALSE, TRUE, FALSE, 1));
1312 requirement_vector_append(&units->actor_reqs,
1313 req_from_values(VUT_MINMOVES,
1314 REQ_RANGE_LOCAL,
1315 FALSE, TRUE, FALSE, 1));
1316
1317 /* Be slightly stricter about the relationship to target unit stacks
1318 * than "Explode Nuclear" was before it would target an adjacent
1319 * tile. I think the intention was that you shouldn't nuke your
1320 * friends and allies. */
1321 requirement_vector_append(&city->actor_reqs,
1322 req_from_values(VUT_DIPLREL,
1323 REQ_RANGE_LOCAL,
1324 FALSE, TRUE, FALSE,
1325 DS_WAR));
1326 requirement_vector_append(&units->actor_reqs,
1327 req_from_values(VUT_DIPLREL,
1328 REQ_RANGE_LOCAL,
1329 FALSE, TRUE, FALSE,
1330 DS_WAR));
1331
1332 /* Only display one nuke action at once. */
1333 requirement_vector_append(&units->target_reqs,
1334 req_from_values(VUT_CITYTILE,
1335 REQ_RANGE_LOCAL,
1336 FALSE, FALSE, FALSE,
1337 CITYT_CENTER));
1338
1339 /* Add after the action was changed. */
1341 action_enabler_add(units);
1342 }
1343
1344 /* "Targeted Sabotage City" is split in a production targeted and a
1345 * building targeted version. */
1346 if (ae->action == ACTION_SPY_TARGETED_SABOTAGE_CITY) {
1347 /* The old rule is represented with two action enablers. */
1348 enabler = action_enabler_copy(ae);
1349
1350 enabler->action = ACTION_SPY_SABOTAGE_CITY_PRODUCTION;
1351
1352 /* Add after the action was changed. */
1353 action_enabler_add(enabler);
1354 }
1355
1356 /* "Targeted Sabotage City Escape" is split in a production targeted
1357 * and a building targeted version. */
1358 if (ae->action == ACTION_SPY_TARGETED_SABOTAGE_CITY_ESC) {
1359 /* The old rule is represented with two action enablers. */
1360 enabler = action_enabler_copy(ae);
1361
1362 enabler->action = ACTION_SPY_SABOTAGE_CITY_PRODUCTION_ESC;
1363
1364 /* Add after the action was changed. */
1365 action_enabler_add(enabler);
1366 }
1368
1369 /* The paratroopers_mr_req field has moved to the enabler for the
1370 * "Paradrop Unit" action. */
1371 {
1372 bool generic_in_use = FALSE;
1373 struct action_enabler_list *ae_custom = action_enabler_list_new();
1374
1376 action_enablers_for_action(ACTION_PARADROP), ae) {
1377 unit_type_iterate(putype) {
1379 &(ae->actor_reqs))) {
1380 /* This action enabler isn't for this unit type at all. */
1381 continue;
1382 }
1383
1384 requirement_vector_iterate(&ae->actor_reqs, preq) {
1385 if (preq->source.kind == VUT_MINMOVES) {
1386 if (!preq->present) {
1387 /* A max move fragments req has been found. Is it too
1388 * large? */
1389 if (preq->source.value.minmoves
1390 < putype->rscompat_cache.paratroopers_mr_req) {
1391 /* Avoid self contradiciton */
1392 continue;
1393 }
1394 }
1395 }
1397
1398 if (putype->rscompat_cache.paratroopers_mr_req > 0) {
1399 /* This unit type needs a custom enabler */
1400
1401 enabler = action_enabler_copy(ae);
1402
1403 /* This enabler is specific to the unit type */
1404 e_req = req_from_values(VUT_UTYPE,
1405 REQ_RANGE_LOCAL,
1406 FALSE, TRUE, FALSE,
1407 utype_number(putype));
1408 requirement_vector_append(&enabler->actor_reqs, e_req);
1409
1410 /* Add the minimum amout of move fragments */
1411 e_req = req_from_values(VUT_MINMOVES,
1412 REQ_RANGE_LOCAL,
1413 FALSE, TRUE, FALSE,
1414 putype->rscompat_cache
1415 .paratroopers_mr_req);
1416 requirement_vector_append(&enabler->actor_reqs, e_req);
1417
1418 action_enabler_list_append(ae_custom, enabler);
1419
1420 log_debug("paratroopers_mr_req upgrade: %s uses custom enabler",
1421 utype_rule_name(putype));
1422 } else {
1423 /* The old one works just fine */
1424
1425 generic_in_use = TRUE;
1426
1427 log_debug("paratroopers_mr_req upgrade: %s uses generic enabler",
1428 utype_rule_name(putype));
1429 }
1431
1432 if (!generic_in_use) {
1433 /* The generic enabler isn't in use any more */
1435 }
1437
1438 action_enabler_list_iterate(ae_custom, ae) {
1439 /* Append the custom enablers. */
1442
1443 action_enabler_list_destroy(ae_custom);
1444 }
1445
1446 /* Enable all clause types */
1447 {
1448 int i;
1449
1450 for (i = 0; i < CLAUSE_COUNT; i++) {
1451 struct clause_info *cinfo = clause_info_get(i);
1452
1453 cinfo->enabled = TRUE;
1454 }
1455 }
1456
1457 /* Used to live in unit_move() and new in 3.1 so they should be non
1458 * controversial enough. */
1459 action_iterate(act_id) {
1460 if (action_id_has_result_safe(act_id, ACTRES_TRANSPORT_DISEMBARK)
1461 || action_id_has_result_safe(act_id, ACTRES_CONQUER_EXTRAS)
1462 || action_id_has_result_safe(act_id, ACTRES_HUT_ENTER)
1463 || action_id_has_result_safe(act_id, ACTRES_HUT_FRIGHTEN)) {
1464 BV_SET(action_by_number(ACTION_UNIT_MOVE)->blocked_by, act_id);
1465 }
1467
1468 {
1469 struct action_auto_perf *auto_perf;
1470 int pos;
1471
1472 /* The forced post successful action move action list has moved to the
1473 * ruleset. */
1474
1475 /* "Bribe Unit" */
1477 auto_perf->alternatives[0] = ACTION_TRANSPORT_EMBARK;
1478 auto_perf->alternatives[1] = ACTION_TRANSPORT_EMBARK2;
1479 auto_perf->alternatives[2] = ACTION_TRANSPORT_EMBARK3;
1480 auto_perf->alternatives[3] = ACTION_TRANSPORT_DISEMBARK1;
1481 auto_perf->alternatives[4] = ACTION_TRANSPORT_DISEMBARK2;
1482 auto_perf->alternatives[5] = ACTION_TRANSPORT_DISEMBARK3;
1483 auto_perf->alternatives[6] = ACTION_TRANSPORT_DISEMBARK4;
1484 auto_perf->alternatives[7] = ACTION_CONQUER_EXTRAS;
1485 auto_perf->alternatives[8] = ACTION_CONQUER_EXTRAS2;
1486 auto_perf->alternatives[9] = ACTION_CONQUER_EXTRAS3;
1487 auto_perf->alternatives[10] = ACTION_CONQUER_EXTRAS4;
1488 auto_perf->alternatives[11] = ACTION_HUT_ENTER;
1489 auto_perf->alternatives[12] = ACTION_HUT_ENTER2;
1490 auto_perf->alternatives[13] = ACTION_HUT_ENTER3;
1491 auto_perf->alternatives[14] = ACTION_HUT_ENTER4;
1492 auto_perf->alternatives[15] = ACTION_HUT_FRIGHTEN;
1493 auto_perf->alternatives[16] = ACTION_HUT_FRIGHTEN2;
1494 auto_perf->alternatives[17] = ACTION_HUT_FRIGHTEN3;
1495 auto_perf->alternatives[18] = ACTION_HUT_FRIGHTEN4;
1496 auto_perf->alternatives[19] = ACTION_UNIT_MOVE;
1497 auto_perf->alternatives[20] = ACTION_UNIT_MOVE2;
1498 auto_perf->alternatives[21] = ACTION_UNIT_MOVE3;
1499 action_list_end(auto_perf->alternatives, 22);
1500
1501 /* "Attack" */
1503 auto_perf->alternatives[0] = ACTION_CONQUER_CITY;
1504 auto_perf->alternatives[1] = ACTION_CONQUER_CITY2;
1505 auto_perf->alternatives[2] = ACTION_CONQUER_CITY3;
1506 auto_perf->alternatives[3] = ACTION_CONQUER_CITY4;
1507 auto_perf->alternatives[4] = ACTION_TRANSPORT_DISEMBARK1;
1508 auto_perf->alternatives[5] = ACTION_TRANSPORT_DISEMBARK2;
1509 auto_perf->alternatives[6] = ACTION_TRANSPORT_DISEMBARK3;
1510 auto_perf->alternatives[7] = ACTION_TRANSPORT_DISEMBARK4;
1511 auto_perf->alternatives[8] = ACTION_CONQUER_EXTRAS;
1512 auto_perf->alternatives[9] = ACTION_CONQUER_EXTRAS2;
1513 auto_perf->alternatives[10] = ACTION_CONQUER_EXTRAS3;
1514 auto_perf->alternatives[11] = ACTION_CONQUER_EXTRAS4;
1515 auto_perf->alternatives[12] = ACTION_HUT_ENTER;
1516 auto_perf->alternatives[13] = ACTION_HUT_ENTER2;
1517 auto_perf->alternatives[14] = ACTION_HUT_ENTER3;
1518 auto_perf->alternatives[15] = ACTION_HUT_ENTER4;
1519 auto_perf->alternatives[16] = ACTION_HUT_FRIGHTEN;
1520 auto_perf->alternatives[17] = ACTION_HUT_FRIGHTEN2;
1521 auto_perf->alternatives[18] = ACTION_HUT_FRIGHTEN3;
1522 auto_perf->alternatives[19] = ACTION_HUT_FRIGHTEN4;
1523 auto_perf->alternatives[20] = ACTION_UNIT_MOVE;
1524 auto_perf->alternatives[21] = ACTION_UNIT_MOVE2;
1525 auto_perf->alternatives[22] = ACTION_UNIT_MOVE3;
1526 action_list_end(auto_perf->alternatives, 23);
1527
1528
1529 /* The city that made the unit's current tile native is gone.
1530 * Evaluated against an adjacent tile. */
1532 auto_perf->alternatives[0] = ACTION_TRANSPORT_EMBARK;
1533 auto_perf->alternatives[1] = ACTION_TRANSPORT_EMBARK2;
1534 auto_perf->alternatives[2] = ACTION_TRANSPORT_EMBARK3;
1535 auto_perf->alternatives[3] = ACTION_HUT_ENTER;
1536 auto_perf->alternatives[4] = ACTION_HUT_ENTER2;
1537 auto_perf->alternatives[5] = ACTION_HUT_ENTER3;
1538 auto_perf->alternatives[6] = ACTION_HUT_ENTER4;
1539 auto_perf->alternatives[7] = ACTION_HUT_FRIGHTEN;
1540 auto_perf->alternatives[8] = ACTION_HUT_FRIGHTEN2;
1541 auto_perf->alternatives[9] = ACTION_HUT_FRIGHTEN3;
1542 auto_perf->alternatives[10] = ACTION_HUT_FRIGHTEN4;
1543 auto_perf->alternatives[11] = ACTION_UNIT_MOVE;
1544 auto_perf->alternatives[12] = ACTION_UNIT_MOVE2;
1545 auto_perf->alternatives[13] = ACTION_UNIT_MOVE3;
1546 action_list_end(auto_perf->alternatives, 14);
1547
1548
1549 /* The unit's stack has been defeated and is scheduled for execution
1550 * but the unit has the CanEscape unit type flag.
1551 * Evaluated against an adjacent tile. */
1552 pos = 0;
1555 ACTRES_TRANSPORT_EMBARK);
1557 ACTRES_CONQUER_EXTRAS);
1559 ACTRES_HUT_ENTER);
1561 ACTRES_HUT_FRIGHTEN);
1563 ACTRES_UNIT_MOVE);
1564 action_list_end(auto_perf->alternatives, pos);
1565 }
1566
1567 /* diplchance setting control over initial dice roll odds has moved to
1568 * the ruleset. */
1569 action_iterate(act_id) {
1570 struct action *act = action_by_number(act_id);
1571
1572 if (action_has_result_safe(act, ACTRES_SPY_SPREAD_PLAGUE)
1573 || action_has_result_safe(act, ACTRES_SPY_STEAL_TECH)
1574 || action_has_result_safe(act, ACTRES_SPY_TARGETED_STEAL_TECH)
1575 || action_has_result_safe(act, ACTRES_SPY_INCITE_CITY)
1576 || action_has_result_safe(act, ACTRES_SPY_SABOTAGE_CITY)
1577 || action_has_result_safe(act, ACTRES_SPY_TARGETED_SABOTAGE_CITY)
1579 ACTRES_SPY_SABOTAGE_CITY_PRODUCTION)
1580 || action_has_result_safe(act, ACTRES_SPY_STEAL_GOLD)
1581 || action_has_result_safe(act, ACTRES_STEAL_MAPS)
1582 || action_has_result_safe(act, ACTRES_SPY_NUKE)) {
1584 }
1586
1587
1588 /* "Paradrop Unit" has been split by side effects. */
1590 action_by_number(ACTION_PARADROP_CONQUER),
1591 "Contested %s");
1593 action_by_number(ACTION_PARADROP_ENTER),
1594 "Enter Hut %s");
1597 ACTION_PARADROP_ENTER_CONQUER),
1598 "Enter Hut Contested %s");
1600 action_by_number(ACTION_PARADROP_FRIGHTEN),
1601 "Frighten Hut %s");
1604 ACTION_PARADROP_FRIGHTEN_CONQUER),
1605 "Frighten Hut Contested %s");
1606
1608 action_enablers_for_action(ACTION_PARADROP), ae) {
1609 struct action_enabler *edit;
1610
1611 action_by_result_iterate(para_action, ACTRES_PARADROP_CONQUER) {
1612 /* Conquer City and/or owned Extra during war if one is there */
1614 edit->action = para_action->id;
1615 e_req = req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
1616 FALSE, TRUE, TRUE, DS_WAR);
1617 requirement_vector_append(&edit->actor_reqs, e_req);
1618 e_req = req_from_values(VUT_CITYTILE, REQ_RANGE_LOCAL,
1619 FALSE, TRUE, TRUE, CITYT_CLAIMED);
1620 if (!is_req_in_vec(&e_req, &ae->target_reqs)) {
1621 requirement_vector_append(&edit->target_reqs, e_req);
1622 }
1623 e_req = req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL,
1624 FALSE, TRUE, TRUE,
1625 UCF_CAN_OCCUPY_CITY);
1626 requirement_vector_append(&edit->actor_reqs, e_req);
1627 e_req = req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL,
1628 FALSE, FALSE, TRUE,
1629 UTYF_CIVILIAN);
1630 requirement_vector_append(&edit->actor_reqs, e_req);
1632
1633 /* Conquer owned Extra during war if there */
1635 edit->action = para_action->id;
1636 e_req = req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
1637 FALSE, TRUE, TRUE, DS_WAR);
1638 requirement_vector_append(&edit->actor_reqs, e_req);
1639 e_req = req_from_values(VUT_CITYTILE, REQ_RANGE_LOCAL,
1640 FALSE, TRUE, TRUE, CITYT_CLAIMED);
1641 if (!is_req_in_vec(&e_req, &ae->target_reqs)) {
1642 requirement_vector_append(&edit->target_reqs, e_req);
1643 }
1644 e_req = req_from_values(VUT_CITYTILE, REQ_RANGE_LOCAL,
1645 FALSE, FALSE, TRUE, CITYT_CENTER);
1646 requirement_vector_append(&edit->target_reqs, e_req);
1648
1649 /* Unowned Extra conquest */
1650 extra_type_by_cause_iterate(EC_BASE, pextra) {
1652 /* Only territory claiming bases can be conquered in 3.0 */
1653 continue;
1654 }
1655
1657 edit->action = para_action->id;
1658 e_req = req_from_values(VUT_CITYTILE, REQ_RANGE_LOCAL,
1659 FALSE, FALSE, TRUE, CITYT_CLAIMED);
1660 if (!is_req_in_vec(&e_req, &ae->target_reqs)) {
1661 requirement_vector_append(&edit->target_reqs, e_req);
1662 }
1663 e_req = req_from_values(VUT_CITYTILE, REQ_RANGE_LOCAL,
1664 FALSE, FALSE, TRUE, CITYT_CENTER);
1665 requirement_vector_append(&edit->target_reqs, e_req);
1666 e_req = req_from_values(VUT_EXTRA, REQ_RANGE_LOCAL,
1667 FALSE, TRUE, TRUE, pextra->id);
1668 requirement_vector_append(&edit->target_reqs, e_req);
1672
1673 action_by_result_iterate(para_action, ACTRES_PARADROP) {
1674 if (para_action->id == ACTION_PARADROP) {
1675 /* Use when not at war and against unclaimed tiles. */
1676 e_req = req_from_values(VUT_CITYTILE, REQ_RANGE_LOCAL,
1677 FALSE, FALSE, TRUE, CITYT_CLAIMED);
1678 if (is_req_in_vec(&e_req, &ae->target_reqs)) {
1679 /* Use Conquer version for unowned Extras */
1680 extra_type_by_cause_iterate(EC_BASE, pextra) {
1682 /* Only territory claiming bases can be conquered in 3.0 */
1683 continue;
1684 }
1685
1686 e_req = req_from_values(VUT_EXTRA, REQ_RANGE_LOCAL,
1687 FALSE, FALSE, TRUE, pextra->id);
1688 requirement_vector_append(&ae->target_reqs, e_req);
1690 } else {
1691 /* Use Conquer version during war. */
1692 e_req = req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
1693 FALSE, FALSE, TRUE, DS_WAR);
1694 requirement_vector_append(&ae->actor_reqs, e_req);
1695 }
1696 } else {
1697 /* !War req requirement added before the copy. */
1699 edit->action = para_action->id;
1701 }
1704
1705 /* The non hut popping version is only legal when hut_behavior is
1706 * "Nothing". */
1708 if (ae->action != ACTION_PARADROP
1709 && ae->action != ACTION_PARADROP_CONQUER) {
1710 /* Not relevant. */
1711 continue;
1712 }
1713
1714 e_req = req_from_str("UnitClassFlag", "local",
1715 FALSE, TRUE, FALSE, "HutNothing");
1716 requirement_vector_append(&ae->actor_reqs, e_req);
1718 }
1719
1720 if (info->version < RSFORMAT_3_1) {
1721 enum unit_class_flag_id nothing
1722 = unit_class_flag_id_by_name("HutNothing", fc_strcasecmp);
1723
1724 unit_class_iterate(uc) {
1725 if (uc->rscompat_cache_from_3_0.hut_behavior == HUT_NOTHING) {
1726 if (unit_class_flag_id_is_valid(nothing)) {
1727 BV_SET(uc->flags, nothing);
1728 }
1729 } else if (uc->rscompat_cache_from_3_0.hut_behavior == HUT_FRIGHTEN) {
1730 BV_SET(uc->flags, UCF_HUT_FRIGHTEN);
1731 }
1733 }
1734
1735 /* Make sure that all action enablers added or modified by the
1736 * compatibility post processing fulfills all hard action requirements. */
1738
1739 /* The ruleset may need adjustments it didn't need before compatibility
1740 * post processing.
1741 *
1742 * If this isn't done a user of ruleset compatibility that ends up using
1743 * the rules risks bad rules. A user that saves the ruleset rather than
1744 * using it risks an unexpected change on the next load and save. */
1746}
1747
1748/**********************************************************************/
1752 struct action_auto_perf *auto_perf,
1753 size_t psize,
1754 enum unit_type_flag_id *protecor_flag)
1755{
1756 int i;
1757
1758 if (compat->version < RSFORMAT_3_1) {
1759 /* Auto attack happens during war. */
1760 requirement_vector_append(&auto_perf->reqs,
1761 req_from_values(VUT_DIPLREL,
1762 REQ_RANGE_LOCAL,
1763 FALSE, TRUE, TRUE, DS_WAR));
1764
1765 /* Needs a movement point to auto attack. */
1766 requirement_vector_append(&auto_perf->reqs,
1767 req_from_values(VUT_MINMOVES,
1768 REQ_RANGE_LOCAL,
1769 FALSE, TRUE, TRUE, 1));
1770
1771 for (i = 0; i < psize; i++) {
1772 /* Add each protecor_flag as a !present requirement. */
1773 requirement_vector_append(&auto_perf->reqs,
1774 req_from_values(VUT_UTFLAG,
1775 REQ_RANGE_LOCAL,
1776 FALSE, FALSE, TRUE,
1777 protecor_flag[i]));
1778 }
1779
1780 auto_perf->alternatives[0] = ACTION_CAPTURE_UNITS;
1781 auto_perf->alternatives[1] = ACTION_BOMBARD;
1782 auto_perf->alternatives[2] = ACTION_ATTACK;
1783 auto_perf->alternatives[3] = ACTION_SUICIDE_ATTACK;
1784 }
1785
1786 return TRUE;
1787}
1788
1789/**********************************************************************/
1792static bool slow_invasion_enablers(action_id action_orig,
1793 action_id action_copy)
1794{
1795 struct action_enabler_list *to_upgrade;
1796
1797 struct action_enabler *enabler;
1798 struct requirement e_req;
1799
1800 /* Upgrade exisiting action enablers */
1801 to_upgrade = action_enabler_list_copy(
1802 action_enablers_for_action(action_orig));
1803
1804 action_enabler_list_iterate(to_upgrade, ae) {
1805 /* City center counts as native. */
1806 enabler = action_enabler_copy(ae);
1807 e_req = req_from_values(VUT_CITYTILE,
1808 REQ_RANGE_LOCAL,
1809 FALSE, TRUE, TRUE,
1810 CITYT_CENTER);
1811 requirement_vector_append(&enabler->actor_reqs, e_req);
1812 action_enabler_add(enabler);
1814
1815 action_enabler_list_iterate(to_upgrade, ae) {
1816 /* No TerrainSpeed sees everything as native. */
1817 enabler = action_enabler_copy(ae);
1818 e_req = req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL,
1819 FALSE, FALSE, TRUE,
1820 UCF_TERRAIN_SPEED);
1821 requirement_vector_append(&enabler->actor_reqs, e_req);
1822 action_enabler_add(enabler);
1824
1825 action_enabler_list_iterate(to_upgrade, ae) {
1826 /* "BeachLander" sees everything as native. */
1827 enabler = action_enabler_copy(ae);
1828 e_req = req_from_str("UnitFlag", "Local",
1829 FALSE, TRUE, TRUE,
1830 "BeachLander");
1831 requirement_vector_append(&enabler->actor_reqs, e_req);
1832 action_enabler_add(enabler);
1834
1835 action_enabler_list_iterate(to_upgrade, ae) {
1836 /* Use the action_copy for acting from non native. */
1837 enabler = action_enabler_copy(ae);
1838 enabler->action = action_copy;
1839
1840 /* Native terrain is native. */
1841 e_req = req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
1842 FALSE, FALSE, TRUE, USP_NATIVE_TILE);
1843 requirement_vector_append(&enabler->actor_reqs, e_req);
1844
1845 /* City is native. */
1846 e_req = req_from_values(VUT_CITYTILE,
1847 REQ_RANGE_LOCAL,
1848 FALSE, FALSE, TRUE,
1849 CITYT_CENTER);
1850 requirement_vector_append(&enabler->actor_reqs, e_req);
1851
1852 /* No TerrainSpeed sees everything as native. */
1853 e_req = req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL,
1854 FALSE, TRUE, TRUE,
1855 UCF_TERRAIN_SPEED);
1856 requirement_vector_append(&enabler->actor_reqs, e_req);
1857
1858 /* "BeachLander" sees everything as native. */
1859 e_req = req_from_str("UnitFlag", "Local",
1860 FALSE, FALSE, TRUE,
1861 "BeachLander");
1862 requirement_vector_append(&enabler->actor_reqs, e_req);
1863
1864 action_enabler_add(enabler);
1866
1867 action_enabler_list_iterate(to_upgrade, ae) {
1868 /* Use for acting from native terrain so acting from
1869 * non native terain is handled by action_copy. */
1870 e_req = req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
1871 FALSE, TRUE, TRUE, USP_NATIVE_TILE);
1872 requirement_vector_append(&ae->actor_reqs, e_req);
1874
1875 action_enabler_list_destroy(to_upgrade);
1876
1877 return TRUE;
1878}
1879
1880/**********************************************************************/
1884{
1885 struct effect *peffect;
1886
1887 /* Take movement for action from non native terrain */
1888 peffect = effect_new(EFT_ACTION_SUCCESS_MOVE_COST,
1889 MAX_MOVE_FRAGS, NULL);
1890 /* The reduction only applies to this action. */
1891 effect_req_append(peffect, req_from_str("Action", "Local",
1892 FALSE, TRUE, TRUE,
1894 /* No reduction here unless disembarking to native terrain. */
1895 effect_req_append(peffect, req_from_values(VUT_UNITSTATE,
1896 REQ_RANGE_LOCAL,
1897 FALSE, TRUE, TRUE,
1898 USP_NATIVE_TILE));
1899 /* Doesn't apply to non TerrainSpeed. */
1900 effect_req_append(peffect, req_from_str("UnitClassFlag", "Local",
1901 FALSE, TRUE, FALSE,
1902 "TerrainSpeed"));
1903
1904 return TRUE;
1905}
1906
1907/**********************************************************************/
1911 bool slow_invasions)
1912{
1914 /* BeachLander and slow_invasions has moved to the ruleset. Use a "fake
1915 * generalized" Transport Disembark, Conquer City, Enter Hut and
1916 * Frighten Hut to handle it. */
1917
1918 struct action_enabler *enabler;
1919 struct requirement e_req;
1920
1921 enabler = action_enabler_new();
1922 enabler->action = ACTION_TRANSPORT_DISEMBARK1;
1923 action_enabler_add(enabler);
1924
1925 enabler = action_enabler_new();
1926 enabler->action = ACTION_CONQUER_EXTRAS;
1927 e_req = req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
1928 FALSE, TRUE, TRUE, DS_WAR);
1929 requirement_vector_append(&enabler->actor_reqs, e_req);
1930 action_enabler_add(enabler);
1931
1932 enabler = action_enabler_new();
1933 enabler->action = ACTION_CONQUER_EXTRAS;
1934 e_req = req_from_values(VUT_CITYTILE, REQ_RANGE_LOCAL,
1935 FALSE, FALSE, TRUE,
1936 CITYT_EXTRAS_OWNED);
1937 requirement_vector_append(&enabler->target_reqs, e_req);
1938 action_enabler_add(enabler);
1939
1940 /* Hut entry and frightening is enabler controlled in 3.1. They can
1941 * involve disembarking. */
1942 enabler = action_enabler_new();
1943 enabler->action = ACTION_HUT_ENTER;
1944 e_req = req_from_str("UnitClassFlag", "Local", FALSE, FALSE, FALSE,
1945 "HutNothing");
1946 requirement_vector_append(&enabler->actor_reqs, e_req);
1947 action_enabler_add(enabler);
1948
1949 enabler = action_enabler_new();
1950 enabler->action = ACTION_HUT_FRIGHTEN;
1951 e_req = req_from_str("UnitClassFlag", "Local", FALSE, FALSE, FALSE,
1952 "HutNothing");
1953 requirement_vector_append(&enabler->actor_reqs, e_req);
1954 action_enabler_add(enabler);
1955
1956 if (slow_invasions) {
1957 /* Make disembarking from non native terrain a different action. */
1958
1959 struct action *paction;
1960
1961 /* Add the enablers */
1962 /* The city conquest enablers are really from 3.0 */
1963 slow_invasion_enablers(ACTION_CONQUER_CITY, ACTION_CONQUER_CITY2);
1964
1965 /* Enablers for entering and frightening huts and for disembarking
1966 * were added in a slow invasion neutral way.
1967 * Make them slow invasion friendly. */
1968 slow_invasion_enablers(ACTION_TRANSPORT_DISEMBARK1,
1969 ACTION_TRANSPORT_DISEMBARK2);
1970 slow_invasion_enablers(ACTION_CONQUER_EXTRAS, ACTION_CONQUER_EXTRAS2);
1971 slow_invasion_enablers(ACTION_HUT_ENTER, ACTION_HUT_ENTER2);
1972 slow_invasion_enablers(ACTION_HUT_FRIGHTEN, ACTION_HUT_FRIGHTEN2);
1973
1974 /* Add the actions */
1975
1976 /* Use "Transport Disembark 2" for disembarking from non native. */
1977 paction = action_by_number(ACTION_TRANSPORT_DISEMBARK2);
1978 /* "Transport Disembark" and "Transport Disembark 2" won't appear in
1979 * the same action selection dialog given their opposite
1980 * requirements. */
1981 paction->quiet = TRUE;
1982 /* Make what is happening clear. */
1983 /* TRANS: _Disembark from non native (100% chance of success). */
1984 sz_strlcpy(paction->ui_name, N_("%sDisembark from non native%s"));
1985
1986
1987 /* Use "Conquer City 2" for conquring from non native. */
1988 paction = action_by_number(ACTION_CONQUER_CITY2);
1989 /* "Conquer City" and "Conquer City 2" won't appear in
1990 * the same action selection dialog given their opposite
1991 * requirements. */
1992 paction->quiet = TRUE;
1993 /* Make what is happening clear. */
1994 /* TRANS: _Conquer City from non native (100% chance of success). */
1995 sz_strlcpy(paction->ui_name, N_("%sConquer City from non native%s"));
1996
1997
1998 /* Use "Conquer Extras 2" for conquring from non native. */
1999 paction = action_by_number(ACTION_CONQUER_EXTRAS2);
2000 /* "Conquer Extras" and "Conquer Extras 2" won't appear in
2001 * the same action selection dialog given their opposite
2002 * requirements. */
2003 paction->quiet = TRUE;
2004 /* Make what is happening clear. */
2005 /* TRANS: _Enter Hut from non native (100% chance of success). */
2006 sz_strlcpy(paction->ui_name, N_("%sConquer Extras from non native%s"));
2007
2008
2009 /* Use "Enter Hut 2" for conquring from non native. */
2010 paction = action_by_number(ACTION_HUT_ENTER2);
2011 /* "Enter Hut" and "Enter Hut 2" won't appear in
2012 * the same action selection dialog given their opposite
2013 * requirements. */
2014 paction->quiet = TRUE;
2015 /* Make what is happening clear. */
2016 /* TRANS: _Enter Hut from non native (100% chance of success). */
2017 sz_strlcpy(paction->ui_name, N_("%sEnter Hut from non native%s"));
2018
2019 /* Use "Frighten Hut 2" for conquring from non native. */
2020 paction = action_by_number(ACTION_HUT_FRIGHTEN2);
2021 /* "Frighten Hut" and "Frighten Hut 2" won't appear in
2022 * the same action selection dialog given their opposite
2023 * requirements. */
2024 paction->quiet = TRUE;
2025 /* Make what is happening clear. */
2026 /* TRANS: _Frighten Hut from non native (100% chance of success). */
2027 sz_strlcpy(paction->ui_name, N_("%sFrighten Hut from non native%s"));
2028
2029 /* Take movement for disembarking, conquering and hut popping to
2030 * native terrain from non native terrain */
2031 slow_invasion_effects("Transport Disembark 2");
2032 slow_invasion_effects("Conquer City 2");
2033 slow_invasion_effects("Conquer Extras 2");
2034 slow_invasion_effects("Enter Hut 2");
2035 slow_invasion_effects("Frighten Hut 2");
2036 }
2037 }
2038
2039 return TRUE;
2040}
2041
2042/**********************************************************************/
2045const char *rscompat_req_type_name_3_1(const char *old_type)
2046{
2047 if (!fc_strcasecmp("BaseFlag", old_type)) {
2048 /* Remaining BaseFlag has been turned to an extra flag */
2049 return "ExtraFlag";
2050 }
2051
2052 return old_type;
2053}
2054
2055/**********************************************************************/
2061const char *rscompat_req_name_3_1(const char *type,
2062 const char *old_name)
2063{
2064 if (!fc_strcasecmp("DiplRel", type)
2065 && !fc_strcasecmp("Is foreign", old_name)) {
2066 return "Foreign";
2067 }
2068
2069 if (!fc_strcasecmp("AI", type)
2070 && !fc_strcasecmp("Handicapped", old_name)) {
2071 return "Restricted";
2072 }
2073
2074 return old_name;
2075}
2076
2077/**********************************************************************/
2082 struct requirement_vector *preqs,
2083 int *reqs_count,
2084 const char *filename, const char *sec,
2085 const char *sub, const char *rfor)
2086{
2087 char buf[1024];
2088
2089 /* Add a missing 'alltemperate' server setting requirement to any vector
2090 * including a 'singlepole' requirement.
2091 * See also sanity_check_req_vec_singlepole() in rssanity.c
2092 *
2093 * Note that this *does* change the semantics of the given vector, so we
2094 * must inform the user of this change. */
2095 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
2096 /* heuristic: the only non-conjunctive requirement vectors are
2097 * improvement obsoletion requirements */
2098 bool conjunctive = BOOL_VAL(fc_strcasecmp(sub, "obsolete_by"));
2099 bool need_alltemperate_req = FALSE;
2100 /* "wrong" here only applies when we do in fact have a
2101 * 'singlepole' requirement */
2102 bool has_wrong_alltemperate_req = FALSE;
2103
2104 requirement_vector_iterate(preqs, preq) {
2106 struct setting *pset;
2107
2108 if (preq->source.kind != VUT_SERVERSETTING) {
2109 continue;
2110 }
2111
2112 id = ssetv_setting_get(preq->source.value.ssetval);
2114 pset = setting_by_number(id);
2115
2116 if (pset == setting_by_name("singlepole")) {
2117 need_alltemperate_req = TRUE;
2118 } else if (pset == setting_by_name("alltemperate")) {
2119 if (XOR(conjunctive, preq->present)) {
2120 need_alltemperate_req = FALSE;
2121 break;
2122 } else {
2123 has_wrong_alltemperate_req = TRUE;
2124 }
2125 }
2127
2128 if (need_alltemperate_req) {
2129 if (has_wrong_alltemperate_req) {
2130 /* Can't do anything here - already a nonsensical situation */
2131 if (compat->log_cb != NULL) {
2132 fc_snprintf(buf, sizeof(buf),
2133 "%s: Cannot update requirement vector %s.%s (for %s)"
2134 " where a 'singlepole' requirement is only relevant"
2135 " when 'alltemperate' is already active. Fix this"
2136 " manually: drop the 'singlepole' requirement, or"
2137 " flip the 'alltemperate' requirement.",
2138 filename, sec, sub, rfor);
2139 compat->log_cb(buf);
2140 }
2141 } else {
2142 struct requirement new_req = req_from_values(VUT_SERVERSETTING,
2143 REQ_RANGE_WORLD, FALSE, !conjunctive, FALSE,
2144 ssetv_by_rule_name("alltemperate"));
2145
2146 requirement_vector_append(preqs, new_req);
2147 (*reqs_count)++;
2148
2149 if (compat->log_cb != NULL) {
2150 fc_snprintf(buf, sizeof(buf),
2151 "%s: Added 'alltemperate' server setting requirement to"
2152 " requirement vector %s.%s (for %s) so that current"
2153 " 'singlepole' requirement is only relevant when"
2154 " 'alltemperate' is disabled. This likely changes the"
2155 " semantics; make sure the new rules are sensible.",
2156 filename, sec, sub, rfor);
2157 compat->log_cb(buf);
2158 }
2159 }
2160 }
2161 }
2162}
2163
2164/**********************************************************************/
2168 const char *old_type)
2169{
2170 if (compat->compat_mode) {
2171 }
2172
2173 return old_type;
2174}
2175
2176/**********************************************************************/
2180 const char *old_type)
2181{
2182 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
2183 if (!fc_strcasecmp("Firepower1", old_type)) {
2184 return combat_bonus_type_name(CBONUS_LOW_FIREPOWER);
2185 }
2186 }
2187
2188 return old_type;
2189}
2190
2191/**********************************************************************/
2195 struct unit_class *pclass)
2196{
2197 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
2198 /* Old hardcoded behavior was like all units having NonNatBombardTgt */
2199 BV_SET(pclass->flags, UCF_NONNAT_BOMBARD_TGT);
2200 }
2201}
2202
2203/**********************************************************************/
2207 struct extra_type *pextra)
2208{
2209 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
2210
2211 /* Give remove cause ERM_ENTER for huts */
2212 if (is_extra_caused_by(pextra, EC_HUT)) {
2213 pextra->rmcauses |= (1 << ERM_ENTER);
2214 extra_to_removed_by_list(pextra, ERM_ENTER);
2215 }
2216 }
2217}
2218
2219/**********************************************************************/
2222enum road_gui_type rscompat_road_gui_type_3_1(struct road_type *proad)
2223{
2224 switch (proad->compat) {
2225 case ROCO_ROAD:
2226 return ROAD_GUI_ROAD;
2227 case ROCO_RAILROAD:
2228 return ROAD_GUI_RAILROAD;
2229 case ROCO_RIVER:
2230 case ROCO_NONE:
2231 break;
2232 }
2233
2234 return ROAD_GUI_OTHER;
2235}
2236
2237/**********************************************************************/
2241 int act_id)
2242{
2243 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
2244 if (act_id == ACTION_DISBAND_UNIT_RECOVER) {
2245 return "ui_name_recycle_unit";
2246 }
2247 }
2248
2249 return NULL;
2250}
2251
2252/**********************************************************************/
2256 int act_id)
2257{
2258 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
2259 if (act_id == ACTION_DISBAND_UNIT_RECOVER) {
2260 return "recycle_unit_max_range";
2261 }
2262 }
2263
2264 return NULL;
2265}
struct action_auto_perf * action_auto_perf_slot_number(const int num)
Definition actions.c:7349
struct req_vec_problem * action_enabler_suggest_repair(const struct action_enabler *enabler)
Definition actions.c:2838
void action_list_end(action_id *act_list, int size)
Definition actions.c:7397
const char * action_enabler_vector_by_number_name(req_vec_num_in_item vec)
Definition actions.c:3015
const char * action_rule_name(const struct action *action)
Definition actions.c:1876
void action_list_add_all_by_result(action_id *act_list, int *position, enum action_result result)
Definition actions.c:7414
void action_enabler_add(struct action_enabler *enabler)
Definition actions.c:2442
struct action_enabler * action_enabler_new(void)
Definition actions.c:2396
bool action_enabler_remove(struct action_enabler *enabler)
Definition actions.c:2459
struct action_enabler * action_enabler_copy(const struct action_enabler *original)
Definition actions.c:2427
struct action_enabler_list * action_enablers_for_action(action_id action)
Definition actions.c:2475
struct requirement_vector * action_enabler_vector_by_number(const void *enabler, req_vec_num_in_item number)
Definition actions.c:2991
#define action_by_result_iterate(_paction_, _result_)
Definition actions.h:488
#define action_enablers_iterate_end
Definition actions.h:526
static struct action * action_by_number(action_id act_id)
Definition actions.h:638
#define ACTION_AUTO_ESCAPE_STACK
Definition actions.h:621
#define ACTION_AUTO_ESCAPE_CITY
Definition actions.h:620
#define action_enabler_list_iterate_end
Definition actions.h:457
#define action_by_result_iterate_end
Definition actions.h:492
#define ACTION_AUTO_POST_BRIBE
Definition actions.h:618
#define action_iterate_end
Definition actions.h:472
#define action_enablers_iterate(_enabler_)
Definition actions.h:520
#define action_has_result_safe(paction, result)
Definition actions.h:666
#define action_enabler_list_iterate(action_enabler_list, aenabler)
Definition actions.h:455
#define action_iterate(_act_)
Definition actions.h:467
#define ACTION_AUTO_POST_ATTACK
Definition actions.h:619
#define action_id_has_result_safe(act_id, result)
Definition actions.h:668
bool territory_claiming_base(const struct base_type *pbase)
Definition base.c:158
#define BV_SET(bv, bit)
Definition bitvector.h:81
bool has_capabilities(const char *us, const char *them)
Definition capability.c:86
struct clause_info * clause_info_get(enum clause_type type)
Definition diptreaty.c:273
int int id
Definition editgui_g.h:28
struct @21::@22 reqs
bool iterate_effect_cache(iec_cb cb, void *data)
Definition effects.c:1245
struct effect * effect_copy(struct effect *old)
Definition effects.c:214
struct effect * effect_new(enum effect_type type, int value, struct multiplier *pmul)
Definition effects.c:179
void effect_req_append(struct effect *peffect, struct requirement req)
Definition effects.c:229
void extra_to_removed_by_list(struct extra_type *pextra, enum extra_rmcause rmcause)
Definition extras.c:316
#define is_extra_caused_by(e, c)
Definition extras.h:196
#define extra_base_get(_e_)
Definition extras.h:184
#define extra_type_by_cause_iterate_end
Definition extras.h:315
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:309
@ ROCO_RAILROAD
Definition fc_types.h:1105
@ ROCO_NONE
Definition fc_types.h:1105
@ ROCO_RIVER
Definition fc_types.h:1105
@ ROCO_ROAD
Definition fc_types.h:1105
int server_setting_id
Definition fc_types.h:924
int action_id
Definition fc_types.h:359
#define MAX_LEN_NAME
Definition fc_types.h:66
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
struct civ_game game
Definition game.c:57
#define RS_DEFAULT_ACTION_MAX_RANGE
Definition game.h:863
static struct tile * pos
Definition finddlg.c:53
GType type
Definition repodlgs.c:1312
bool is_wonder(const struct impr_type *pimprove)
#define improvement_iterate_end
#define improvement_iterate(_p)
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:191
#define log_warn(message,...)
Definition log.h:105
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_fatal(message,...)
Definition log.h:100
#define log_debug(message,...)
Definition log.h:115
#define log_normal(message,...)
Definition log.h:107
@ LOG_ERROR
Definition log.h:30
#define log_error(message,...)
Definition log.h:103
#define FC_FREE(ptr)
Definition mem.h:41
#define SINGLE_MOVE
Definition movement.h:24
#define MAX_MOVE_FRAGS
Definition movement.h:27
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:137
enum barbarian_type nation_barbarian_type(const struct nation_type *nation)
Definition nation.c:210
#define nations_iterate_end
Definition nation.h:335
#define nations_iterate(NAME_pnation)
Definition nation.h:332
const char * secfile_error(void)
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
bool is_req_in_vec(const struct requirement *req, const struct requirement_vector *vec)
bool req_vec_change_apply(const struct req_vec_change *modification, requirement_vector_by_number getter, const void *parent_item)
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
struct requirement req_from_str(const char *type, const char *range, bool survives, bool present, bool quiet, const char *value)
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
bool universal_replace_in_req_vec(struct requirement_vector *reqs, const struct universal *to_replace, const struct universal *replacement)
void req_vec_problem_free(struct req_vec_problem *issue)
struct universal universal_by_number(const enum universals_n kind, const int value)
bool universal_is_mentioned_by_requirements(const struct requirement_vector *reqs, const struct universal *psource)
#define requirement_fulfilled_by_unit_type(_ut_, _rqs_)
#define requirement_vector_iterate_end
#define requirement_vector_iterate(req_vec, preq)
const char * rscompat_action_ui_name_S3_1(struct rscompat_info *compat, int act_id)
Definition rscompat.c:2240
#define UTYF_LAST_USER_FLAG_3_0
Definition rscompat.c:49
static int first_free_unit_class_user_flag(void)
Definition rscompat.c:342
static bool slow_invasion_enablers(action_id action_orig, action_id action_copy)
Definition rscompat.c:1792
#define TER_LAST_USER_FLAG_3_0
Definition rscompat.c:51
static bool ete_is_target_req(struct requirement *preq)
Definition rscompat.c:670
void rscompat_adjust_pre_sanity(struct rscompat_info *info)
Definition rscompat.c:839
enum road_gui_type rscompat_road_gui_type_3_1(struct road_type *proad)
Definition rscompat.c:2222
void rscompat_extra_adjust_3_1(struct rscompat_info *compat, struct extra_type *pextra)
Definition rscompat.c:2206
static bool rscompat_enabler_add_obligatory_hard_reqs(struct action_enabler *ae)
Definition rscompat.c:165
void rscompat_uclass_flags_3_1(struct rscompat_info *compat, struct unit_class *pclass)
Definition rscompat.c:2194
const char * rscompat_req_name_3_1(const char *type, const char *old_name)
Definition rscompat.c:2061
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)
Definition rscompat.c:1751
bool rscompat_old_effect_3_1(const char *type, struct section_file *file, const char *sec_name, struct rscompat_info *compat)
Definition rscompat.c:806
static void split_action_name_update(struct action *original, struct action *copy, const char *name_modification)
Definition rscompat.c:531
bool rscompat_names(struct rscompat_info *info)
Definition rscompat.c:386
const char * rscompat_utype_flag_name_3_1(struct rscompat_info *compat, const char *old_type)
Definition rscompat.c:2167
void rscompat_req_vec_adjust_3_1(struct rscompat_info *compat, struct requirement_vector *preqs, int *reqs_count, const char *filename, const char *sec, const char *sub, const char *rfor)
Definition rscompat.c:2081
static void paratroopers_mr_sub_to_effect(struct unit_type *putype, struct action *paction)
Definition rscompat.c:645
static int first_free_terrain_user_flag(void)
Definition rscompat.c:361
bool rscompat_old_slow_invasions_3_1(struct rscompat_info *compat, bool slow_invasions)
Definition rscompat.c:1910
void rscompat_postprocess(struct rscompat_info *info)
Definition rscompat.c:859
int rscompat_check_capabilities(struct section_file *file, const char *filename, const struct rscompat_info *info)
Definition rscompat.c:65
#define UCF_LAST_USER_FLAG_3_0
Definition rscompat.c:50
void rscompat_enablers_add_obligatory_hard_reqs(void)
Definition rscompat.c:285
static bool effect_list_compat_cb(struct effect *peffect, void *data)
Definition rscompat.c:570
static int first_free_unit_type_user_flag(void)
Definition rscompat.c:323
static void effect_to_enabler(action_id action, struct section_file *file, const char *sec_name, struct rscompat_info *compat, const char *type)
Definition rscompat.c:752
const char * rscompat_action_max_range_name_S3_1(struct rscompat_info *compat, int act_id)
Definition rscompat.c:2255
void rscompat_init_info(struct rscompat_info *info)
Definition rscompat.c:56
static bool slow_invasion_effects(const char *action_rule_name)
Definition rscompat.c:1883
bool rscompat_check_cap_and_version(struct section_file *file, const char *filename, const struct rscompat_info *info)
Definition rscompat.c:131
const char * rscompat_combat_bonus_name_3_1(struct rscompat_info *compat, const char *old_type)
Definition rscompat.c:2179
#define enough_new_user_flags(_new_flags_, _name_, _LAST_USER_FLAG_, _LAST_USER_FLAG_PREV_)
Definition rscompat.c:43
const char * rscompat_req_type_name_3_1(const char *old_type)
Definition rscompat.c:2045
static bool effect_handle_split_universal(struct effect *peffect, struct universal original, struct universal separated)
Definition rscompat.c:551
struct requirement_vector * lookup_req_list(struct section_file *file, struct rscompat_info *compat, const char *sec, const char *sub, const char *rfor)
Definition ruleset.c:645
#define RULESET_COMPAT_CAP
Definition rscompat.h:26
bool autoadjust_ruleset_data(void)
Definition rssanity.c:1542
#define ruleset_error(logger, level, format,...)
Definition ruleset.h:57
#define RULESET_CAPABILITIES
Definition ruleset.h:24
#define RSFORMAT_3_1
Definition ruleset.h:36
static struct compatibility compat[]
Definition savecompat.c:101
server_setting_id ssetv_setting_get(ssetv enc)
bool server_setting_exists(server_setting_id id)
ssetv ssetv_by_rule_name(const char *name)
struct setting * setting_by_name(const char *name)
Definition settings.c:3138
struct setting * setting_by_number(int id)
Definition settings.c:3130
#define ARRAY_SIZE(x)
Definition shared.h:85
#define BOOL_VAL(x)
Definition shared.h:70
#define XOR(p, q)
Definition shared.h:71
struct requirement_vector reqs
Definition actions.h:574
action_id alternatives[MAX_NUM_ACTIONS]
Definition actions.h:578
bool ruledit_disabled
Definition actions.h:445
action_id action
Definition actions.h:439
struct requirement_vector actor_reqs
Definition actions.h:440
struct requirement_vector target_reqs
Definition actions.h:441
action_id id
Definition actions.h:380
bool actor_consuming_always
Definition actions.h:412
int max_distance
Definition actions.h:395
bool quiet
Definition actions.h:402
enum moves_actor_kind moves_actor
Definition actions.h:432
struct action::@12::@13 is_unit
char ui_name[MAX_LEN_NAME]
Definition actions.h:398
union action::@12 actor
enum action_target_kind target_kind
Definition actions.h:386
int min_distance
Definition actions.h:395
Definition city.h:309
struct packet_game_info info
Definition game.h:89
bool enabled
Definition diptreaty.h:55
int value
Definition effects.h:349
struct requirement_vector reqs
Definition effects.h:353
enum effect_type type
Definition effects.h:341
uint8_t rmcauses
Definition extras.h:92
bv_actions diplchance_initial_odds
enum req_vec_change_operation operation
char description[500]
struct req_vec_change * suggested_solutions
enum req_range range
struct universal source
enum road_compat compat
Definition road.h:83
bool compat_mode
Definition rscompat.h:30
bv_unit_class_flags flags
Definition unittype.h:144
struct unit_type::@89 rscompat_cache
int paratroopers_mr_sub
Definition unittype.h:572
enum universals_n kind
Definition fc_types.h:758
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
#define sz_strlcpy(dest, src)
Definition support.h:167
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
const char * terrain_flag_id_name_cb(enum terrain_flag_id flag)
Definition terrain.c:805
void set_user_terrain_flag_name(enum terrain_flag_id id, const char *name, const char *helptxt)
Definition terrain.c:776
#define MAX_NUM_USER_TER_FLAGS
Definition terrain.h:146
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1630
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1693
const char * unit_class_flag_id_name_cb(enum unit_class_flag_id flag)
Definition unittype.c:1894
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:100
const char * unit_type_flag_id_name_cb(enum unit_type_flag_id flag)
Definition unittype.c:1957
void set_user_unit_class_flag_name(enum unit_class_flag_id id, const char *name, const char *helptxt)
Definition unittype.c:1864
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Definition unittype.c:443
void set_user_unit_type_flag_name(enum unit_type_flag_id id, const char *name, const char *helptxt)
Definition unittype.c:1928
#define UCF_LAST_USER_FLAG
Definition unittype.h:112
@ HUT_FRIGHTEN
Definition unittype.h:129
@ HUT_NOTHING
Definition unittype.h:129
#define unit_class_iterate(_p)
Definition unittype.h:879
#define MAX_NUM_USER_UNIT_FLAGS
Definition unittype.h:316
#define UTYF_LAST_USER_FLAG
Definition unittype.h:315
#define unit_type_iterate(_p)
Definition unittype.h:841
#define unit_class_iterate_end
Definition unittype.h:886
#define unit_type_iterate_end
Definition unittype.h:848
#define MAX_NUM_USER_UCLASS_FLAGS
Definition unittype.h:113
#define edit(pedit)
Definition widget_edit.h:34