From 986be48e28fade7a50e2ab276c5d5e8f44695f72 Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Mon, 1 Apr 2024 02:46:53 +0300
Subject: [PATCH 49/49] Replace CanEscape unit type flag with internal action

See RM #391

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 client/helpdata.c                   |   4 -
 common/actions.c                    |  17 +++-
 common/unittype.h                   | 126 ++++++++++++++--------------
 data/alien/actions.ruleset          |   2 +-
 data/alien/units.ruleset            |  12 +--
 data/civ1/actions.ruleset           |   2 +-
 data/civ1/units.ruleset             |  12 +--
 data/civ2/actions.ruleset           |   2 +-
 data/civ2/units.ruleset             |  12 +--
 data/civ2civ3/actions.ruleset       |   2 +-
 data/civ2civ3/units.ruleset         |  12 +--
 data/classic/actions.ruleset        |   2 +-
 data/classic/units.ruleset          |  12 +--
 data/goldkeep/actions.ruleset       |   2 +-
 data/goldkeep/units.ruleset         |  12 +--
 data/granularity/actions.ruleset    |   2 +-
 data/granularity/units.ruleset      |  12 +--
 data/multiplayer/actions.ruleset    |   2 +-
 data/multiplayer/units.ruleset      |  12 +--
 data/ruledit/comments-3.3.txt       |  12 +--
 data/sandbox/actions.ruleset        |   2 +-
 data/sandbox/units.ruleset          |  12 +--
 data/stub/actions.ruleset           |   2 +-
 data/stub/units.ruleset             |  12 +--
 data/webperimental/actions.ruleset  |   2 +-
 data/webperimental/units.ruleset    |  12 +--
 gen_headers/enums/actions_enums.def |   1 +
 server/ruleset/rscompat.c           |  13 ++-
 server/unittools.c                  |   2 +-
 29 files changed, 126 insertions(+), 203 deletions(-)

diff --git a/client/helpdata.c b/client/helpdata.c
index 56e70cf9bd..6b61ac117c 100644
--- a/client/helpdata.c
+++ b/client/helpdata.c
@@ -2051,10 +2051,6 @@ char *helptext_unit(char *buf, size_t bufsz, struct player *pplayer,
                        BULLET_SPACE);
   } requirement_vector_iterate_end;
 
-  if (utype_has_flag(utype, UTYF_CANESCAPE)) {
-    CATLSTR(buf, bufsz, _("%s Can escape once stack defender is lost.\n"),
-            BULLET);
-  }
   if (utype_has_flag(utype, UTYF_CANKILLESCAPING)) {
     CATLSTR(buf, bufsz, _("%s Can pursue escaping units and kill them.\n"),
             BULLET);
diff --git a/common/actions.c b/common/actions.c
index c4712b02cc..e218e74a5b 100644
--- a/common/actions.c
+++ b/common/actions.c
@@ -765,6 +765,10 @@ static void hard_code_actions(void)
       unit_action_new(ACTION_GAIN_VETERANCY, ACTRES_ENABLER_CHECK,
                       TRUE, FALSE,
                       MAK_STAYS, 0, 0, FALSE);
+  actions[ACTION_ESCAPE] =
+      unit_action_new(ACTION_ESCAPE, ACTRES_ENABLER_CHECK,
+                      TRUE, FALSE,
+                      MAK_STAYS, 0, 0, FALSE);
   actions[ACTION_USER_ACTION1] =
       unit_action_new(ACTION_USER_ACTION1, ACTRES_NONE,
                       FALSE, TRUE,
@@ -6013,6 +6017,7 @@ const char *action_ui_name_ruleset_var_name(int act)
   case ACTION_USER_ACTION4:
     return "ui_name_user_action_4";
   case ACTION_GAIN_VETERANCY:
+  case ACTION_ESCAPE:
     fc_assert(!action_id_is_internal(act)); /* Fail always */
     break;
   case ACTION_COUNT:
@@ -6369,6 +6374,8 @@ const char *action_ui_name_default(int act)
     return N_("%sUser Action 4%s");
   case ACTION_GAIN_VETERANCY:
     return N_("%sGain Veterancy%s");
+  case ACTION_ESCAPE:
+    return N_("%sEscape%s");
   case ACTION_COUNT:
     fc_assert(act != ACTION_COUNT);
     break;
@@ -6508,6 +6515,7 @@ const char *action_min_range_ruleset_var_name(int act)
   case ACTION_UNIT_MOVE3:
   case ACTION_SPY_ESCAPE:
   case ACTION_GAIN_VETERANCY:
+  case ACTION_ESCAPE:
     /* Min range is not ruleset changeable */
     return NULL;
   case ACTION_NUKE:
@@ -6674,6 +6682,7 @@ const char *action_max_range_ruleset_var_name(int act)
   case ACTION_UNIT_MOVE3:
   case ACTION_SPY_ESCAPE:
   case ACTION_GAIN_VETERANCY:
+  case ACTION_ESCAPE:
     /* Max range is not ruleset changeable */
     return NULL;
   case ACTION_HELP_WONDER:
@@ -6871,6 +6880,7 @@ const char *action_target_kind_ruleset_var_name(int act)
   case ACTION_TELEPORT_ENTER_CONQUER:
   case ACTION_SPY_ESCAPE:
   case ACTION_GAIN_VETERANCY:
+  case ACTION_ESCAPE:
     /* Target kind is not ruleset changeable */
     return NULL;
   case ACTION_NUKE:
@@ -7036,8 +7046,9 @@ const char *action_actor_consuming_always_ruleset_var_name(action_id act)
   case ACTION_TELEPORT_FRIGHTEN_CONQUER:
   case ACTION_TELEPORT_ENTER:
   case ACTION_TELEPORT_ENTER_CONQUER:
-  case ACTION_GAIN_VETERANCY:
   case ACTION_SPY_ESCAPE:
+  case ACTION_GAIN_VETERANCY:
+  case ACTION_ESCAPE:
     /* Actor consuming always is not ruleset changeable */
     return NULL;
   case ACTION_FOUND_CITY:
@@ -7244,6 +7255,7 @@ const char *action_blocked_by_ruleset_var_name(const struct action *act)
   case ACTION_HUT_FRIGHTEN3:
   case ACTION_HUT_FRIGHTEN4:
   case ACTION_GAIN_VETERANCY:
+  case ACTION_ESCAPE:
   case ACTION_USER_ACTION1:
   case ACTION_USER_ACTION2:
   case ACTION_USER_ACTION3:
@@ -7414,8 +7426,9 @@ action_post_success_forced_ruleset_var_name(const struct action *act)
   case ACTION_TELEPORT_FRIGHTEN_CONQUER:
   case ACTION_TELEPORT_ENTER:
   case ACTION_TELEPORT_ENTER_CONQUER:
-  case ACTION_GAIN_VETERANCY:
   case ACTION_SPY_ESCAPE:
+  case ACTION_GAIN_VETERANCY:
+  case ACTION_ESCAPE:
   case ACTION_USER_ACTION1:
   case ACTION_USER_ACTION2:
   case ACTION_USER_ACTION3:
diff --git a/common/unittype.h b/common/unittype.h
index 4113c37e5e..aac0afe3f6 100644
--- a/common/unittype.h
+++ b/common/unittype.h
@@ -268,75 +268,73 @@ const char *unit_type_flag_id_name_update_cb(const char *old_name);
 /* Unit can't be built in scenarios where founding new cities is prevented. */
 #define SPECENUM_VALUE26 UTYF_NEWCITY_GAMES_ONLY
 #define SPECENUM_VALUE26NAME N_("?unitflag:NewCityGamesOnly")
-/* Can escape when killstack occours */
-#define SPECENUM_VALUE27 UTYF_CANESCAPE
-#define SPECENUM_VALUE27NAME N_("?unitflag:CanEscape")
 /* Can kill escaping units */
-#define SPECENUM_VALUE28 UTYF_CANKILLESCAPING
-#define SPECENUM_VALUE28NAME N_("?unitflag:CanKillEscaping")
+#define SPECENUM_VALUE27 UTYF_CANKILLESCAPING
+#define SPECENUM_VALUE27NAME N_("?unitflag:CanKillEscaping")
 /* Makes random movement, not under player control */
-#define SPECENUM_VALUE29 UTYF_RANDOM_MOVEMENT
-#define SPECENUM_VALUE29NAME N_("?unitflag:RandomMovement")
+#define SPECENUM_VALUE28 UTYF_RANDOM_MOVEMENT
+#define SPECENUM_VALUE28NAME N_("?unitflag:RandomMovement")
 /* Do not show flag for the unit */
-#define SPECENUM_VALUE30 UTYF_FLAGLESS
-#define SPECENUM_VALUE30NAME N_("?unitflag:Flagless")
-#define SPECENUM_VALUE31 UTYF_PROVIDES_RANSOM
-#define SPECENUM_VALUE31NAME N_("?unitflag:ProvidesRansom")
-
-#define SPECENUM_VALUE32 UTYF_USER_FLAG_1
-#define SPECENUM_VALUE33 UTYF_USER_FLAG_2
-#define SPECENUM_VALUE34 UTYF_USER_FLAG_3
-#define SPECENUM_VALUE35 UTYF_USER_FLAG_4
-#define SPECENUM_VALUE36 UTYF_USER_FLAG_5
-#define SPECENUM_VALUE37 UTYF_USER_FLAG_6
-#define SPECENUM_VALUE38 UTYF_USER_FLAG_7
-#define SPECENUM_VALUE39 UTYF_USER_FLAG_8
-#define SPECENUM_VALUE40 UTYF_USER_FLAG_9
-#define SPECENUM_VALUE41 UTYF_USER_FLAG_10
-#define SPECENUM_VALUE42 UTYF_USER_FLAG_11
-#define SPECENUM_VALUE43 UTYF_USER_FLAG_12
-#define SPECENUM_VALUE44 UTYF_USER_FLAG_13
-#define SPECENUM_VALUE45 UTYF_USER_FLAG_14
-#define SPECENUM_VALUE46 UTYF_USER_FLAG_15
-#define SPECENUM_VALUE47 UTYF_USER_FLAG_16
-#define SPECENUM_VALUE48 UTYF_USER_FLAG_17
-#define SPECENUM_VALUE49 UTYF_USER_FLAG_18
-#define SPECENUM_VALUE50 UTYF_USER_FLAG_19
-#define SPECENUM_VALUE51 UTYF_USER_FLAG_20
-#define SPECENUM_VALUE52 UTYF_USER_FLAG_21
-#define SPECENUM_VALUE53 UTYF_USER_FLAG_22
-#define SPECENUM_VALUE54 UTYF_USER_FLAG_23
-#define SPECENUM_VALUE55 UTYF_USER_FLAG_24
-#define SPECENUM_VALUE56 UTYF_USER_FLAG_25
-#define SPECENUM_VALUE57 UTYF_USER_FLAG_26
-#define SPECENUM_VALUE58 UTYF_USER_FLAG_27
-#define SPECENUM_VALUE59 UTYF_USER_FLAG_28
-#define SPECENUM_VALUE60 UTYF_USER_FLAG_29
-#define SPECENUM_VALUE61 UTYF_USER_FLAG_30
-#define SPECENUM_VALUE62 UTYF_USER_FLAG_31
-#define SPECENUM_VALUE63 UTYF_USER_FLAG_32
-#define SPECENUM_VALUE64 UTYF_USER_FLAG_33
-#define SPECENUM_VALUE65 UTYF_USER_FLAG_34
-#define SPECENUM_VALUE66 UTYF_USER_FLAG_35
-#define SPECENUM_VALUE67 UTYF_USER_FLAG_36
-#define SPECENUM_VALUE68 UTYF_USER_FLAG_37
-#define SPECENUM_VALUE69 UTYF_USER_FLAG_38
-#define SPECENUM_VALUE70 UTYF_USER_FLAG_39
-#define SPECENUM_VALUE71 UTYF_USER_FLAG_40
-#define SPECENUM_VALUE72 UTYF_USER_FLAG_41
-#define SPECENUM_VALUE73 UTYF_USER_FLAG_42
-#define SPECENUM_VALUE74 UTYF_USER_FLAG_43
-#define SPECENUM_VALUE75 UTYF_USER_FLAG_44
-#define SPECENUM_VALUE76 UTYF_USER_FLAG_45
-#define SPECENUM_VALUE77 UTYF_USER_FLAG_46
-#define SPECENUM_VALUE78 UTYF_USER_FLAG_47
-#define SPECENUM_VALUE79 UTYF_USER_FLAG_48
-#define SPECENUM_VALUE80 UTYF_USER_FLAG_49
-#define SPECENUM_VALUE81 UTYF_USER_FLAG_50
-#define SPECENUM_VALUE82 UTYF_USER_FLAG_51
+#define SPECENUM_VALUE29 UTYF_FLAGLESS
+#define SPECENUM_VALUE29NAME N_("?unitflag:Flagless")
+#define SPECENUM_VALUE30 UTYF_PROVIDES_RANSOM
+#define SPECENUM_VALUE30NAME N_("?unitflag:ProvidesRansom")
+
+#define SPECENUM_VALUE31 UTYF_USER_FLAG_1
+#define SPECENUM_VALUE32 UTYF_USER_FLAG_2
+#define SPECENUM_VALUE33 UTYF_USER_FLAG_3
+#define SPECENUM_VALUE34 UTYF_USER_FLAG_4
+#define SPECENUM_VALUE35 UTYF_USER_FLAG_5
+#define SPECENUM_VALUE36 UTYF_USER_FLAG_6
+#define SPECENUM_VALUE37 UTYF_USER_FLAG_7
+#define SPECENUM_VALUE38 UTYF_USER_FLAG_8
+#define SPECENUM_VALUE39 UTYF_USER_FLAG_9
+#define SPECENUM_VALUE40 UTYF_USER_FLAG_10
+#define SPECENUM_VALUE41 UTYF_USER_FLAG_11
+#define SPECENUM_VALUE42 UTYF_USER_FLAG_12
+#define SPECENUM_VALUE43 UTYF_USER_FLAG_13
+#define SPECENUM_VALUE44 UTYF_USER_FLAG_14
+#define SPECENUM_VALUE45 UTYF_USER_FLAG_15
+#define SPECENUM_VALUE46 UTYF_USER_FLAG_16
+#define SPECENUM_VALUE47 UTYF_USER_FLAG_17
+#define SPECENUM_VALUE48 UTYF_USER_FLAG_18
+#define SPECENUM_VALUE49 UTYF_USER_FLAG_19
+#define SPECENUM_VALUE50 UTYF_USER_FLAG_20
+#define SPECENUM_VALUE51 UTYF_USER_FLAG_21
+#define SPECENUM_VALUE52 UTYF_USER_FLAG_22
+#define SPECENUM_VALUE53 UTYF_USER_FLAG_23
+#define SPECENUM_VALUE54 UTYF_USER_FLAG_24
+#define SPECENUM_VALUE55 UTYF_USER_FLAG_25
+#define SPECENUM_VALUE56 UTYF_USER_FLAG_26
+#define SPECENUM_VALUE57 UTYF_USER_FLAG_27
+#define SPECENUM_VALUE58 UTYF_USER_FLAG_28
+#define SPECENUM_VALUE59 UTYF_USER_FLAG_29
+#define SPECENUM_VALUE60 UTYF_USER_FLAG_30
+#define SPECENUM_VALUE61 UTYF_USER_FLAG_31
+#define SPECENUM_VALUE62 UTYF_USER_FLAG_32
+#define SPECENUM_VALUE63 UTYF_USER_FLAG_33
+#define SPECENUM_VALUE64 UTYF_USER_FLAG_34
+#define SPECENUM_VALUE65 UTYF_USER_FLAG_35
+#define SPECENUM_VALUE66 UTYF_USER_FLAG_36
+#define SPECENUM_VALUE67 UTYF_USER_FLAG_37
+#define SPECENUM_VALUE68 UTYF_USER_FLAG_38
+#define SPECENUM_VALUE69 UTYF_USER_FLAG_39
+#define SPECENUM_VALUE70 UTYF_USER_FLAG_40
+#define SPECENUM_VALUE71 UTYF_USER_FLAG_41
+#define SPECENUM_VALUE72 UTYF_USER_FLAG_42
+#define SPECENUM_VALUE73 UTYF_USER_FLAG_43
+#define SPECENUM_VALUE74 UTYF_USER_FLAG_44
+#define SPECENUM_VALUE75 UTYF_USER_FLAG_45
+#define SPECENUM_VALUE76 UTYF_USER_FLAG_46
+#define SPECENUM_VALUE77 UTYF_USER_FLAG_47
+#define SPECENUM_VALUE78 UTYF_USER_FLAG_48
+#define SPECENUM_VALUE79 UTYF_USER_FLAG_49
+#define SPECENUM_VALUE80 UTYF_USER_FLAG_50
+#define SPECENUM_VALUE81 UTYF_USER_FLAG_51
+#define SPECENUM_VALUE82 UTYF_USER_FLAG_52
 /* Note that first role must have value next to last flag */
 
-#define UTYF_LAST_USER_FLAG UTYF_USER_FLAG_51
+#define UTYF_LAST_USER_FLAG UTYF_USER_FLAG_52
 #define MAX_NUM_USER_UNIT_FLAGS (UTYF_LAST_USER_FLAG - UTYF_USER_FLAG_1 + 1)
 #define SPECENUM_NAMEOVERRIDE
 #define SPECENUM_NAME_UPDATER
diff --git a/data/alien/actions.ruleset b/data/alien/actions.ruleset
index cd706107f7..9a1769c106 100644
--- a/data/alien/actions.ruleset
+++ b/data/alien/actions.ruleset
@@ -92,7 +92,7 @@ collect_ransom_post_success_forced_actions =
 escape_city = "Transport Embark", "Enter Hut", "Enter Hut 2", "Unit Move"
 
 ; The unit`s stack has been defeated and is scheduled for execution but the
-; unit has the CanEscape unit type flag. Evaluated against an adjacent tile.
+; unit can do Escape action. Evaluated against an adjacent tile.
 ;unit_stack_death = "Transport Embark", "Enter Hut", "Enter Hut 2",
 ;                   "Unit Move"
 
diff --git a/data/alien/units.ruleset b/data/alien/units.ruleset
index 5b6b1aa2d2..31ebf1da29 100644
--- a/data/alien/units.ruleset
+++ b/data/alien/units.ruleset
@@ -17,7 +17,7 @@ options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
 format_version = 40
 
 [control]
-; Names for custom unit type flags. There can be up to 51 of these.
+; Names for custom unit type flags. There can be up to 52 of these.
 ; name          = rule name; In some circumstances user may see this
 ;                 as part of some sentences, so try to make it descriptive
 ;                 and sensible.
@@ -367,15 +367,7 @@ flags         = "Missile", "DoesntOccupyTile"
 ; "NewCityGamesOnly" = unit can't be built on scenarios where founding new cities
 ;                 is not allowed. Give this flag to units that would make no sense
 ;                 to have in a game with such a scenario
-; "CanEscape"   = this unit has, given that certain conditions are
-;                 fulfilled, a 50% chance to escape rather than being
-;                 killed when killstack is enabled and the defender of its
-;                 tile is defeated. The conditions are that it has more move
-;                 points than required to move to an adjacent tile plus the
-;                 attackers move points and that the attacker doesn't have
-;                 the "CanKillEscaping" unit type flag.
-; "CanKillEscaping" = an attack from this unit ignores the "CanEscape" unit
-;                 type flag.
+; "CanKillEscaping" = an attack from this unit prevents the "Escape" action.
 ; "Provoking" =   a unit considering to auto attack this unit will choose to
 ;                 do so even if has better odds when defending against it
 ;                 then when attacking it. Applies when the autoattack server
diff --git a/data/civ1/actions.ruleset b/data/civ1/actions.ruleset
index 6bfde80508..6589734871 100644
--- a/data/civ1/actions.ruleset
+++ b/data/civ1/actions.ruleset
@@ -90,7 +90,7 @@ collect_ransom_post_success_forced_actions =
 escape_city = "Transport Embark", "Enter Hut", "Enter Hut 2", "Unit Move"
 
 ; The unit`s stack has been defeated and is scheduled for execution but the
-; unit has the CanEscape unit type flag. Evaluated against an adjacent tile.
+; unit can do Escape action. Evaluated against an adjacent tile.
 ;unit_stack_death = "Transport Embark", "Enter Hut", "Enter Hut 2",
 ;                   "Unit Move"
 
diff --git a/data/civ1/units.ruleset b/data/civ1/units.ruleset
index c4e3b64e94..e92aa3b434 100644
--- a/data/civ1/units.ruleset
+++ b/data/civ1/units.ruleset
@@ -14,7 +14,7 @@ options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
 format_version = 40
 
 [control]
-; Names for custom unit type flags. There can be up to 51 of these.
+; Names for custom unit type flags. There can be up to 52 of these.
 ; name          = rule name; In some circumstances user may see this
 ;                 as part of some sentences, so try to make it descriptive
 ;                 and sensible.
@@ -342,15 +342,7 @@ flags         = "Missile", "Unreachable", "HutNothing"
 ; "NewCityGamesOnly" = unit can't be built on scenarios where founding new cities
 ;                 is not allowed. Give this flag to units that would make no sense
 ;                 to have in a game with such a scenario
-; "CanEscape"   = this unit has, given that certain conditions are
-;                 fulfilled, a 50% chance to escape rather than being
-;                 killed when killstack is enabled and the defender of its
-;                 tile is defeated. The conditions are that it has more move
-;                 points than required to move to an adjacent tile plus the
-;                 attackers move points and that the attacker doesn't have
-;                 the "CanKillEscaping" unit type flag.
-; "CanKillEscaping" = an attack from this unit ignores the "CanEscape" unit
-;                 type flag.
+; "CanKillEscaping" = an attack from this unit prevents the "Escape" action.
 ; "Provoking" =   a unit considering to auto attack this unit will choose to
 ;                 do so even if has better odds when defending against it
 ;                 then when attacking it. Applies when the autoattack server
diff --git a/data/civ2/actions.ruleset b/data/civ2/actions.ruleset
index b4e25dadcf..70a87100f2 100644
--- a/data/civ2/actions.ruleset
+++ b/data/civ2/actions.ruleset
@@ -94,7 +94,7 @@ escape_city = "Transport Embark", "Enter Hut", "Enter Hut 2",
               "Frighten Hut", "Frighten Hut 2", "Unit Move"
 
 ; The unit`s stack has been defeated and is scheduled for execution but the
-; unit has the CanEscape unit type flag. Evaluated against an adjacent tile.
+; unit can do Escape action. Evaluated against an adjacent tile.
 ;unit_stack_death = "Transport Embark", "Enter Hut", "Enter Hut 2",
 ;                   "Frighten Hut", "Unit Move"
 
diff --git a/data/civ2/units.ruleset b/data/civ2/units.ruleset
index 5f25e5b77e..4e75128315 100644
--- a/data/civ2/units.ruleset
+++ b/data/civ2/units.ruleset
@@ -14,7 +14,7 @@ options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
 format_version = 40
 
 [control]
-; Names for custom unit type flags. There can be up to 51 of these.
+; Names for custom unit type flags. There can be up to 52 of these.
 ; name          = rule name; In some circumstances user may see this
 ;                 as part of some sentences, so try to make it descriptive
 ;                 and sensible.
@@ -360,15 +360,7 @@ flags         = "Unreachable", "DoesntOccupyTile", "HutFrighten"
 ; "NewCityGamesOnly" = unit can't be built on scenarios where founding new cities
 ;                 is not allowed. Give this flag to units that would make no sense
 ;                 to have in a game with such a scenario
-; "CanEscape"   = this unit has, given that certain conditions are
-;                 fulfilled, a 50% chance to escape rather than being
-;                 killed when killstack is enabled and the defender of its
-;                 tile is defeated. The conditions are that it has more move
-;                 points than required to move to an adjacent tile plus the
-;                 attackers move points and that the attacker doesn't have
-;                 the "CanKillEscaping" unit type flag.
-; "CanKillEscaping" = an attack from this unit ignores the "CanEscape" unit
-;                 type flag.
+; "CanKillEscaping" = an attack from this unit prevents the "Escape" action.
 ; "Provoking" =   a unit considering to auto attack this unit will choose to
 ;                 do so even if has better odds when defending against it
 ;                 then when attacking it. Applies when the autoattack server
diff --git a/data/civ2civ3/actions.ruleset b/data/civ2civ3/actions.ruleset
index 147a6bf6cc..f7f82c3901 100644
--- a/data/civ2civ3/actions.ruleset
+++ b/data/civ2civ3/actions.ruleset
@@ -112,7 +112,7 @@ escape_city = "Transport Embark", "Enter Hut", "Enter Hut 2",
               "Frighten Hut", "Frighten Hut 2", "Unit Move"
 
 ; The unit`s stack has been defeated and is scheduled for execution but the
-; unit has the CanEscape unit type flag. Evaluated against an adjacent tile.
+; unit can do Escape action. Evaluated against an adjacent tile.
 ;unit_stack_death = "Transport Embark",
 ;                   "Enter Hut", "Enter Hut 2",
 ;                   "Frighten Hut", "Unit Move"
diff --git a/data/civ2civ3/units.ruleset b/data/civ2civ3/units.ruleset
index b9d7b4da2b..ca90f67d88 100644
--- a/data/civ2civ3/units.ruleset
+++ b/data/civ2civ3/units.ruleset
@@ -20,7 +20,7 @@ options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24 web-compatible"
 format_version = 40
 
 [control]
-; Names for custom unit type flags. There can be up to 51 of these.
+; Names for custom unit type flags. There can be up to 52 of these.
 ; name          = rule name; In some circumstances user may see this
 ;                 as part of some sentences, so try to make it descriptive
 ;                 and sensible.
@@ -404,15 +404,7 @@ flags         = "Unreachable", "DoesntOccupyTile", "CanPillage",
 ; "NewCityGamesOnly" = unit can't be built on scenarios where founding new cities
 ;                 is not allowed. Give this flag to units that would make no sense
 ;                 to have in a game with such a scenario
-; "CanEscape"   = this unit has, given that certain conditions are
-;                 fulfilled, a 50% chance to escape rather than being
-;                 killed when killstack is enabled and the defender of its
-;                 tile is defeated. The conditions are that it has more move
-;                 points than required to move to an adjacent tile plus the
-;                 attackers move points and that the attacker doesn't have
-;                 the "CanKillEscaping" unit type flag.
-; "CanKillEscaping" = an attack from this unit ignores the "CanEscape" unit
-;                 type flag.
+; "CanKillEscaping" = an attack from this unit prevents the "Escape" action.
 ; "Provoking" =   a unit considering to auto attack this unit will choose to
 ;                 do so even if has better odds when defending against it
 ;                 then when attacking it. Applies when the autoattack server
diff --git a/data/classic/actions.ruleset b/data/classic/actions.ruleset
index 847a952c4a..b47a54cd20 100644
--- a/data/classic/actions.ruleset
+++ b/data/classic/actions.ruleset
@@ -102,7 +102,7 @@ escape_city = "Transport Embark", "Enter Hut", "Enter Hut 2",
               "Frighten Hut", "Frighten Hut 2", "Unit Move"
 
 ; The unit`s stack has been defeated and is scheduled for execution but the
-; unit has the CanEscape unit type flag. Evaluated against an adjacent tile.
+; unit can do Escape action. Evaluated against an adjacent tile.
 ;unit_stack_death = "Transport Embark",
 ;                   "Conquer Extras", "Conquer Extras 2",
 ;                   "Enter Hut", "Enter Hut 2",
diff --git a/data/classic/units.ruleset b/data/classic/units.ruleset
index 1261dc88eb..7a7554caca 100644
--- a/data/classic/units.ruleset
+++ b/data/classic/units.ruleset
@@ -20,7 +20,7 @@ options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24 web-compatible"
 format_version = 40
 
 [control]
-; Names for custom unit type flags. There can be up to 51 of these.
+; Names for custom unit type flags. There can be up to 52 of these.
 ; name          = rule name; In some circumstances user may see this
 ;                 as part of some sentences, so try to make it descriptive
 ;                 and sensible.
@@ -370,15 +370,7 @@ flags         = "Unreachable", "DoesntOccupyTile", "HutFrighten"
 ; "NewCityGamesOnly" = unit can't be built on scenarios where founding new cities
 ;                 is not allowed. Give this flag to units that would make no sense
 ;                 to have in a game with such a scenario
-; "CanEscape"   = this unit has, given that certain conditions are
-;                 fulfilled, a 50% chance to escape rather than being
-;                 killed when killstack is enabled and the defender of its
-;                 tile is defeated. The conditions are that it has more move
-;                 points than required to move to an adjacent tile plus the
-;                 attackers move points and that the attacker doesn't have
-;                 the "CanKillEscaping" unit type flag.
-; "CanKillEscaping" = an attack from this unit ignores the "CanEscape" unit
-;                 type flag.
+; "CanKillEscaping" = an attack from this unit prevents the "Escape" action.
 ; "Provoking" =   a unit considering to auto attack this unit will choose to
 ;                 do so even if has better odds when defending against it
 ;                 then when attacking it. Applies when the autoattack server
diff --git a/data/goldkeep/actions.ruleset b/data/goldkeep/actions.ruleset
index 59203ae404..ae00283024 100644
--- a/data/goldkeep/actions.ruleset
+++ b/data/goldkeep/actions.ruleset
@@ -102,7 +102,7 @@ escape_city = "Transport Embark", "Enter Hut", "Enter Hut 2",
               "Frighten Hut", "Frighten Hut 2", "Unit Move"
 
 ; The unit's stack has been defeated and is scheduled for execution but the
-; unit has the CanEscape unit type flag. Evaluated against an adjacent tile.
+; unit can do Escape action. Evaluated against an adjacent tile.
 ;unit_stack_death = "Transport Embark",
 ;                   "Conquer Extras", "Conquer Extras 2",
 ;                   "Enter Hut", "Enter Hut 2",
diff --git a/data/goldkeep/units.ruleset b/data/goldkeep/units.ruleset
index fea2a4fa5e..a240b11ee7 100644
--- a/data/goldkeep/units.ruleset
+++ b/data/goldkeep/units.ruleset
@@ -23,7 +23,7 @@ options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
 format_version = 40
 
 [control]
-; Names for custom unit type flags. There can be up to 51 of these.
+; Names for custom unit type flags. There can be up to 52 of these.
 ; name          = rule name; In some circumstances user may see this
 ;                 as part of some sentences, so try to make it descriptive
 ;                 and sensible.
@@ -382,15 +382,7 @@ flags         = "Unreachable", "DoesntOccupyTile", "HutFrighten"
 ; "NewCityGamesOnly" = unit can't be built on scenarios where founding new cities
 ;                 is not allowed. Give this flag to units that would make no sense
 ;                 to have in a game with such a scenario
-; "CanEscape"   = this unit has, given that certain conditions are
-;                 fulfilled, a 50% chance to escape rather than being
-;                 killed when killstack is enabled and the defender of its
-;                 tile is defeated. The conditions are that it has more move
-;                 points than required to move to an adjacent tile plus the
-;                 attackers move points and that the attacker doesn't have
-;                 the "CanKillEscaping" unit type flag.
-; "CanKillEscaping" = an attack from this unit ignores the "CanEscape" unit
-;                 type flag.
+; "CanKillEscaping" = an attack from this unit prevents the "Escape" action.
 ; "Provoking" =   a unit considering to auto attack this unit will choose to
 ;                 do so even if has better odds when defending against it
 ;                 then when attacking it. Applies when the autoattack server
diff --git a/data/granularity/actions.ruleset b/data/granularity/actions.ruleset
index f1cb16a766..374601d374 100644
--- a/data/granularity/actions.ruleset
+++ b/data/granularity/actions.ruleset
@@ -64,7 +64,7 @@ collect_ransom_post_success_forced_actions = "Unit Move"
 escape_city = "Transport Embark", "Unit Move"
 
 ; The unit`s stack has been defeated and is scheduled for execution but the
-; unit has the CanEscape unit type flag. Evaluated against an adjacent tile.
+; unit can do Escape action. Evaluated against an adjacent tile.
 ;unit_stack_death = "Transport Embark", "Unit Move"
 
 ; If poison_empties_food_stock is set to TRUE a successful "Poison City"
diff --git a/data/granularity/units.ruleset b/data/granularity/units.ruleset
index 03d78a13d4..9c94ebb148 100644
--- a/data/granularity/units.ruleset
+++ b/data/granularity/units.ruleset
@@ -20,7 +20,7 @@ options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
 format_version = 40
 
 [control]
-; Names for custom unit type flags. There can be up to 51 of these.
+; Names for custom unit type flags. There can be up to 52 of these.
 ; name          = rule name; In some circumstances user may see this
 ;                 as part of some sentences, so try to make it descriptive
 ;                 and sensible.
@@ -317,15 +317,7 @@ flags         = "BuildAnywhere"
 ; "NewCityGamesOnly" = unit can't be built on scenarios where founding new cities
 ;                 is not allowed. Give this flag to units that would make no sense
 ;                 to have in a game with such a scenario
-; "CanEscape"   = this unit has, given that certain conditions are
-;                 fulfilled, a 50% chance to escape rather than being
-;                 killed when killstack is enabled and the defender of its
-;                 tile is defeated. The conditions are that it has more move
-;                 points than required to move to an adjacent tile plus the
-;                 attackers move points and that the attacker doesn't have
-;                 the "CanKillEscaping" unit type flag.
-; "CanKillEscaping" = an attack from this unit ignores the "CanEscape" unit
-;                 type flag.
+; "CanKillEscaping" = an attack from this unit prevents the "Escape" action.
 ; "Provoking" =   a unit considering to auto attack this unit will choose to
 ;                 do so even if has better odds when defending against it
 ;                 then when attacking it. Applies when the autoattack server
diff --git a/data/multiplayer/actions.ruleset b/data/multiplayer/actions.ruleset
index 95a5694e6d..c87e353760 100644
--- a/data/multiplayer/actions.ruleset
+++ b/data/multiplayer/actions.ruleset
@@ -99,7 +99,7 @@ escape_city = "Transport Embark", "Enter Hut", "Enter Hut 2",
               "Frighten Hut", "Frighten Hut 2", "Unit Move"
 
 ; The unit`s stack has been defeated and is scheduled for execution but the
-; unit has the CanEscape unit type flag. Evaluated against an adjacent tile.
+; unit can do Escape action. Evaluated against an adjacent tile.
 ;unit_stack_death = "Transport Embark",
 ;                   "Conquer Extras", "Conquer Extras 2",
 ;                   "Enter Hut", "Enter Hut 2",
diff --git a/data/multiplayer/units.ruleset b/data/multiplayer/units.ruleset
index 8a8f485ed4..e6f7a703f7 100644
--- a/data/multiplayer/units.ruleset
+++ b/data/multiplayer/units.ruleset
@@ -20,7 +20,7 @@ options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24 web-compatible"
 format_version = 40
 
 [control]
-; Names for custom unit type flags. There can be up to 51 of these.
+; Names for custom unit type flags. There can be up to 52 of these.
 ; name          = rule name; In some circumstances user may see this
 ;                 as part of some sentences, so try to make it descriptive
 ;                 and sensible.
@@ -370,15 +370,7 @@ flags         = "Unreachable", "DoesntOccupyTile", "HutFrighten"
 ; "NewCityGamesOnly" = unit can't be built on scenarios where founding new cities
 ;                 is not allowed. Give this flag to units that would make no sense
 ;                 to have in a game with such a scenario
-; "CanEscape"   = this unit has, given that certain conditions are
-;                 fulfilled, a 50% chance to escape rather than being
-;                 killed when killstack is enabled and the defender of its
-;                 tile is defeated. The conditions are that it has more move
-;                 points than required to move to an adjacent tile plus the
-;                 attackers move points and that the attacker doesn't have
-;                 the "CanKillEscaping" unit type flag.
-; "CanKillEscaping" = an attack from this unit ignores the "CanEscape" unit
-;                 type flag.
+; "CanKillEscaping" = an attack from this unit prevents the "Escape" action.
 ; "Provoking" =   a unit considering to auto attack this unit will choose to
 ;                 do so even if has better odds when defending against it
 ;                 then when attacking it. Applies when the autoattack server
diff --git a/data/ruledit/comments-3.3.txt b/data/ruledit/comments-3.3.txt
index a63252331e..3068883d1c 100644
--- a/data/ruledit/comments-3.3.txt
+++ b/data/ruledit/comments-3.3.txt
@@ -488,15 +488,7 @@ utypes = "\
 ; \"NewCityGamesOnly\" = unit can\'t be built on scenarios where founding new cities\n\
 ;                 is not allowed. Give this flag to units that would make no sense\n\
 ;                 to have in a game with such a scenario\n\
-; \"CanEscape\"   = this unit has, given that certain conditions are\n\
-;                 fulfilled, a 50% chance to escape rather than being\n\
-;                 killed when killstack is enabled and the defender of its\n\
-;                 tile is defeated. The conditions are that it has more move\n\
-;                 points than required to move to an adjacent tile plus the\n\
-;                 attackers move points and that the attacker doesn\'t have\n\
-;                 the \"CanKillEscaping\" unit type flag.\n\
-; \"CanKillEscaping\" = an attack from this unit ignores the \"CanEscape\" unit\n\
-;                 type flag.\n\
+; \"CanKillEscaping\" = an attack from this unit prevents the \"Escape\" action.\n\
 ; \"Provoking\"   =   a unit considering to auto attack this unit will choose to\n\
 ;                 do so even if has better odds when defending against it\n\
 ;                 then when attacking it. Applies when the autoattack server\n\
@@ -1295,7 +1287,7 @@ counters = "\n\
 ; This section has comments documenting user (custom) flag types
 
 utype = "\
-; Names for custom unit type flags. There can be up to 51 of these.\n\
+; Names for custom unit type flags. There can be up to 52 of these.\n\
 ; name          = rule name; In some circumstances user may see this\n\
 ;                 as part of some sentences, so try to make it descriptive\n\
 ;                 and sensible.\n\
diff --git a/data/sandbox/actions.ruleset b/data/sandbox/actions.ruleset
index 03c03a2ca4..837bf14732 100644
--- a/data/sandbox/actions.ruleset
+++ b/data/sandbox/actions.ruleset
@@ -126,7 +126,7 @@ escape_city = "Transport Embark", "Enter Hut", "Enter Hut 2",
               "Frighten Hut", "Frighten Hut 2", "Unit Move"
 
 ; The unit`s stack has been defeated and is scheduled for execution but the
-; unit has the CanEscape unit type flag. Evaluated against an adjacent tile.
+; unit can do Escape action. Evaluated against an adjacent tile.
 ;unit_stack_death = "Transport Embark",
 ;                   "Enter Hut", "Enter Hut 2",
 ;                   "Frighten Hut", "Unit Move"
diff --git a/data/sandbox/units.ruleset b/data/sandbox/units.ruleset
index ce6a21f409..aeac5fa47f 100644
--- a/data/sandbox/units.ruleset
+++ b/data/sandbox/units.ruleset
@@ -20,7 +20,7 @@ options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
 format_version = 40
 
 [control]
-; Names for custom unit type flags. There can be up to 51 of these.
+; Names for custom unit type flags. There can be up to 52 of these.
 ; name          = rule name; In some circumstances user may see this
 ;                 as part of some sentences, so try to make it descriptive
 ;                 and sensible.
@@ -417,15 +417,7 @@ flags         = "Unreachable", "DoesntOccupyTile", "CanPillage",
 ; "NewCityGamesOnly" = unit can't be built on scenarios where founding new cities
 ;                 is not allowed. Give this flag to units that would make no sense
 ;                 to have in a game with such a scenario
-; "CanEscape"   = this unit has, given that certain conditions are
-;                 fulfilled, a 50% chance to escape rather than being
-;                 killed when killstack is enabled and the defender of its
-;                 tile is defeated. The conditions are that it has more move
-;                 points than required to move to an adjacent tile plus the
-;                 attackers move points and that the attacker doesn't have
-;                 the "CanKillEscaping" unit type flag.
-; "CanKillEscaping" = an attack from this unit ignores the "CanEscape" unit
-;                 type flag.
+; "CanKillEscaping" = an attack from this unit prevents the "Escape" action.
 ; "Provoking" =   a unit considering to auto attack this unit will choose to
 ;                 do so even if has better odds when defending against it
 ;                 then when attacking it. Applies when the autoattack server
diff --git a/data/stub/actions.ruleset b/data/stub/actions.ruleset
index d14cf2c69b..6ff30e9371 100644
--- a/data/stub/actions.ruleset
+++ b/data/stub/actions.ruleset
@@ -50,7 +50,7 @@ format_version = 40
 ; escape_city = "Enter Hut", "Frighten Hut", "Unit Move"
 
 ; The unit`s stack has been defeated and is scheduled for execution but the
-; unit has the CanEscape unit type flag. Evaluated against an adjacent tile.
+; unit can do Escape action. Evaluated against an adjacent tile.
 ;unit_stack_death = "Transport Embark", "Unit Move"
 
 ; If poison_empties_food_stock is set to TRUE a successful "Poison City"
diff --git a/data/stub/units.ruleset b/data/stub/units.ruleset
index 9d7d025f33..422b96ef5f 100644
--- a/data/stub/units.ruleset
+++ b/data/stub/units.ruleset
@@ -7,7 +7,7 @@ options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
 format_version = 40
 
 [control]
-; Names for custom unit type flags. There can be up to 51 of these.
+; Names for custom unit type flags. There can be up to 52 of these.
 ; name          = rule name; In some circumstances user may see this
 ;                 as part of some sentences, so try to make it descriptive
 ;                 and sensible.
@@ -290,15 +290,7 @@ flags         = ""
 ; "NewCityGamesOnly" = unit can't be built on scenarios where founding new cities
 ;                 is not allowed. Give this flag to units that would make no sense
 ;                 to have in a game with such a scenario
-; "CanEscape"   = this unit has, given that certain conditions are
-;                 fulfilled, a 50% chance to escape rather than being
-;                 killed when killstack is enabled and the defender of its
-;                 tile is defeated. The conditions are that it has more move
-;                 points than required to move to an adjacent tile plus the
-;                 attackers move points and that the attacker doesn't have
-;                 the "CanKillEscaping" unit type flag.
-; "CanKillEscaping" = an attack from this unit ignores the "CanEscape" unit
-;                 type flag.
+; "CanKillEscaping" = an attack from this unit prevents the "Escape" action.
 ; "Provoking" =   a unit considering to auto attack this unit will choose to
 ;                 do so even if has better odds when defending against it
 ;                 then when attacking it. Applies when the autoattack server
diff --git a/data/webperimental/actions.ruleset b/data/webperimental/actions.ruleset
index 40a77d289a..89f061b4dd 100644
--- a/data/webperimental/actions.ruleset
+++ b/data/webperimental/actions.ruleset
@@ -86,7 +86,7 @@ collect_ransom_post_success_forced_actions =
 escape_city = "Transport Embark", "Enter Hut", "Frighten Hut", "Unit Move"
 
 ; The unit`s stack has been defeated and is scheduled for execution but the
-; unit has the CanEscape unit type flag. Evaluated against an adjacent tile.
+; unit can do Escape action. Evaluated against an adjacent tile.
 ;unit_stack_death = "Transport Embark", "Conquer Extras",
 ;                   "Enter Hut", "Frighten Hut", "Unit Move"
 
diff --git a/data/webperimental/units.ruleset b/data/webperimental/units.ruleset
index 5eac31e3cf..a5714ef761 100644
--- a/data/webperimental/units.ruleset
+++ b/data/webperimental/units.ruleset
@@ -20,7 +20,7 @@ options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24 web-compatible"
 format_version = 40
 
 [control]
-; Names for custom unit type flags. There can be up to 51 of these.
+; Names for custom unit type flags. There can be up to 52 of these.
 ; name          = rule name; In some circumstances user may see this
 ;                 as part of some sentences, so try to make it descriptive
 ;                 and sensible.
@@ -374,15 +374,7 @@ flags         = "Unreachable", "DoesntOccupyTile", "HutFrighten"
 ; "NewCityGamesOnly" = unit can't be built on scenarios where founding new cities
 ;                 is not allowed. Give this flag to units that would make no sense
 ;                 to have in a game with such a scenario
-; "CanEscape"   = this unit has, given that certain conditions are
-;                 fulfilled, a 50% chance to escape rather than being
-;                 killed when killstack is enabled and the defender of its
-;                 tile is defeated. The conditions are that it has more move
-;                 points than required to move to an adjacent tile plus the
-;                 attackers move points and that the attacker doesn't have
-;                 the "CanKillEscaping" unit type flag.
-; "CanKillEscaping" = an attack from this unit ignores the "CanEscape" unit
-;                 type flag.
+; "CanKillEscaping" = an attack from this unit prevents the "Escape" action.
 ; "Provoking" =   a unit considering to auto attack this unit will choose to
 ;                 do so even if has better odds when defending against it
 ;                 then when attacking it. Applies when the autoattack server
diff --git a/gen_headers/enums/actions_enums.def b/gen_headers/enums/actions_enums.def
index 0b9eed166c..08585aeb27 100644
--- a/gen_headers/enums/actions_enums.def
+++ b/gen_headers/enums/actions_enums.def
@@ -141,6 +141,7 @@ values
 
   # Enabler checks only
   ACTION_GAIN_VETERANCY                   "Gain Veterancy"
+  ACTION_ESCAPE                           "Escape"
 
   # User actions
   ACTION_USER_ACTION1                     "User Action 1"
diff --git a/server/ruleset/rscompat.c b/server/ruleset/rscompat.c
index 3674ecf216..25f564b27e 100644
--- a/server/ruleset/rscompat.c
+++ b/server/ruleset/rscompat.c
@@ -352,7 +352,8 @@ bool rscompat_names(struct rscompat_info *info)
       const char *name;
       const char *helptxt;
     } new_flags_33[] = {
-      { N_("NoVeteran"), N_("May acquire veteran status.") }
+      { N_("NoVeteran"), N_("May acquire veteran status.") },
+      { N_("CanEscape"), N_("Can try to escape stack death.") }
     };
 
     enough_new_user_flags(new_flags_33, unit_type,
@@ -403,6 +404,9 @@ static bool effect_list_compat_cb(struct effect *peffect, void *data)
 **************************************************************************/
 void rscompat_postprocess(struct rscompat_info *info)
 {
+  struct action_enabler *enabler;
+  struct requirement e_req;
+
   if (!info->compat_mode || info->version >= RSFORMAT_CURRENT) {
     /* There isn't anything here that should be done outside of compat
      * mode. */
@@ -415,6 +419,13 @@ void rscompat_postprocess(struct rscompat_info *info)
     }
   } unit_type_iterate_end;
 
+  enabler = action_enabler_new();
+  enabler->action = ACTION_ESCAPE;
+  e_req = req_from_str("UnitFlag", "Local", FALSE, TRUE, FALSE,
+                       "CanEscape");
+  requirement_vector_append(&enabler->actor_reqs, e_req);
+  action_enabler_add(enabler);
+
   /* Upgrade existing effects. Done before new effects are added to prevent
    * the new effects from being upgraded by accident. */
   iterate_effect_cache(effect_list_compat_cb, info);
diff --git a/server/unittools.c b/server/unittools.c
index 72fcae7a27..f23807c552 100644
--- a/server/unittools.c
+++ b/server/unittools.c
@@ -2318,7 +2318,7 @@ void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
           && is_unit_reachable_at(vunit, pkiller, deftile)) {
         escaped = FALSE;
 
-        if (unit_has_type_flag(vunit, UTYF_CANESCAPE)
+        if (is_action_enabled_unit_on_self(ACTION_ESCAPE, vunit)
             && !unit_has_type_flag(pkiller, UTYF_CANKILLESCAPING)
             && vunit->hp > 0
             && vunit->moves_left > pkiller->moves_left
-- 
2.43.0

