From 80372cf83554ab18c47435ded8f41e4c668ff292 Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Wed, 10 Jan 2024 07:28:08 +0200
Subject: [PATCH 11/29] Add hut entering variants of teleport actions

See RM #165

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 common/actions.c                    | 44 +++++++++++++++++++++++--
 common/fc_types.h                   |  1 +
 doc/README.actions                  | 51 ++++++++++++++++++++++++++---
 gen_headers/enums/actions_enums.def |  2 ++
 server/advisors/advdata.c           |  1 +
 server/citytools.c                  |  4 ++-
 server/ruleset/ruleload.c           |  4 +++
 7 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/common/actions.c b/common/actions.c
index 7ffc046f0d..8a691b15b2 100644
--- a/common/actions.c
+++ b/common/actions.c
@@ -728,6 +728,18 @@ static void hard_code_actions(void)
                       TRUE, TRUE,
                       MAK_TELEPORT, 1,
                       ACTION_DISTANCE_MAX, FALSE);
+  actions[ACTION_TELEPORT_ENTER] =
+      unit_action_new(ACTION_TELEPORT_ENTER,
+                      ACTRES_TELEPORT,
+                      TRUE, TRUE,
+                      MAK_TELEPORT, 1,
+                      ACTION_DISTANCE_MAX, FALSE);
+  actions[ACTION_TELEPORT_ENTER_CONQUER] =
+      unit_action_new(ACTION_TELEPORT_ENTER_CONQUER,
+                      ACTRES_TELEPORT_CONQUER,
+                      TRUE, TRUE,
+                      MAK_TELEPORT, 1,
+                      ACTION_DISTANCE_MAX, FALSE);
   actions[ACTION_GAIN_VETERANCY] =
       unit_action_new(ACTION_GAIN_VETERANCY, ACTRES_ENABLER_CHECK,
                       TRUE, FALSE,
@@ -5909,6 +5921,10 @@ const char *action_ui_name_ruleset_var_name(int act)
     return "ui_name_teleport_3";
   case ACTION_TELEPORT_CONQUER:
     return "ui_name_teleport_conquer";
+  case ACTION_TELEPORT_ENTER:
+    return "ui_name_teleport_enter";
+  case ACTION_TELEPORT_ENTER_CONQUER:
+    return "ui_name_teleport_enter_conquer";
   case ACTION_SPY_ESCAPE:
     return "ui_name_escape";
   case ACTION_USER_ACTION1:
@@ -6242,8 +6258,14 @@ const char *action_ui_name_default(int act)
     /* TRANS: _Teleport (100% chance of success). */
     return N_("%sTeleport%s");
   case ACTION_TELEPORT_CONQUER:
-    /* TRANS: _Teleport to Conquer (100% chance of success). */
-    return N_("%sTeleport to Conquer%s");
+    /* TRANS: _Teleport (100% chance of success). */
+    return N_("%sTeleport%s");
+  case ACTION_TELEPORT_ENTER:
+    /* TRANS: _Teleport (100% chance of success). */
+    return N_("%sTeleport%s");
+  case ACTION_TELEPORT_ENTER_CONQUER:
+    /* TRANS: _Teleport (100% chance of success). */
+    return N_("%sTeleport%s");
   case ACTION_SPY_ESCAPE:
     /* TRANS: _Escape To Nearest City (100% chance of success). */
     return N_("%sEscape To Nearest City%s");
@@ -6413,6 +6435,10 @@ const char *action_min_range_ruleset_var_name(int act)
     return "teleport_3_min_range";
   case ACTION_TELEPORT_CONQUER:
     return "teleport_conquer_min_range";
+  case ACTION_TELEPORT_ENTER:
+    return "teleport_enter_min_range";
+  case ACTION_TELEPORT_ENTER_CONQUER:
+    return "teleport_enter_conquer_min_range";
   case ACTION_USER_ACTION1:
     return "user_action_1_min_range";
   case ACTION_USER_ACTION2:
@@ -6584,6 +6610,10 @@ const char *action_max_range_ruleset_var_name(int act)
     return "teleport_3_max_range";
   case ACTION_TELEPORT_CONQUER:
     return "teleport_conquer_max_range";
+  case ACTION_TELEPORT_ENTER:
+    return "teleport_enter_max_range";
+  case ACTION_TELEPORT_ENTER_CONQUER:
+    return "teleport_enter_conquer_max_range";
   case ACTION_USER_ACTION1:
     return "user_action_1_max_range";
   case ACTION_USER_ACTION2:
@@ -6733,6 +6763,8 @@ const char *action_target_kind_ruleset_var_name(int act)
   case ACTION_TELEPORT2:
   case ACTION_TELEPORT3:
   case ACTION_TELEPORT_CONQUER:
+  case ACTION_TELEPORT_ENTER:
+  case ACTION_TELEPORT_ENTER_CONQUER:
   case ACTION_SPY_ESCAPE:
   case ACTION_GAIN_VETERANCY:
     /* Target kind is not ruleset changeable */
@@ -7099,6 +7131,8 @@ const char *action_actor_consuming_always_ruleset_var_name(action_id act)
   case ACTION_TELEPORT2:
   case ACTION_TELEPORT3:
   case ACTION_TELEPORT_CONQUER:
+  case ACTION_TELEPORT_ENTER:
+  case ACTION_TELEPORT_ENTER_CONQUER:
   case ACTION_GAIN_VETERANCY:
   case ACTION_SPY_ESCAPE:
     /* Actor consuming always is not ruleset changeable */
@@ -7196,6 +7230,10 @@ const char *action_blocked_by_ruleset_var_name(const struct action *act)
     return "teleport_3_blocked_by";
   case ACTION_TELEPORT_CONQUER:
     return "teleport_conquer_blocked_by";
+  case ACTION_TELEPORT_ENTER:
+    return "teleport_enter_blocked_by";
+  case ACTION_TELEPORT_ENTER_CONQUER:
+    return "teleport_enter_conquer_blocked_by";
   case ACTION_SPY_ESCAPE:
   case ACTION_SPY_POISON:
   case ACTION_SPY_POISON_ESC:
@@ -7458,6 +7496,8 @@ action_post_success_forced_ruleset_var_name(const struct action *act)
   case ACTION_TELEPORT2:
   case ACTION_TELEPORT3:
   case ACTION_TELEPORT_CONQUER:
+  case ACTION_TELEPORT_ENTER:
+  case ACTION_TELEPORT_ENTER_CONQUER:
   case ACTION_GAIN_VETERANCY:
   case ACTION_SPY_ESCAPE:
   case ACTION_USER_ACTION1:
diff --git a/common/fc_types.h b/common/fc_types.h
index 1d1eef7066..cdae58dce1 100644
--- a/common/fc_types.h
+++ b/common/fc_types.h
@@ -319,6 +319,7 @@ enum counter_target { CTGT_CITY };
 #define SPECENUM_VALUE65 ACTRES_TELEPORT
 #define SPECENUM_VALUE65NAME "Teleport"
 #define SPECENUM_VALUE66 ACTRES_TELEPORT_CONQUER
+#define SPECENUM_VALUE66NAME "Teleport Conquer"
 /* Hardcoded action that's just controlled by enablers */
 #define SPECENUM_VALUE67 ACTRES_ENABLER_CHECK
 /* All consequences are handled as (ruleset) action data. */
diff --git a/doc/README.actions b/doc/README.actions
index b9f5f15661..3d098e3e9d 100644
--- a/doc/README.actions
+++ b/doc/README.actions
@@ -1465,7 +1465,7 @@ Actions done by a unit against a tile
 * A copy of "Unit Move"
 * See "Unit Move" for everything else.
 
-"Teleport" - telepor unit to the target tile.
+"Teleport" - teleport unit to the target tile.
 * UI name can be set using ui_name_teleport
 * any action listed in teleport_blocked_by must be impossible
 * the range of legal distance between actor unit and target tile
@@ -1483,21 +1483,21 @@ Actions done by a unit against a tile
 * the target tile can't contain any city or units not allied to the actor
   unit and all its cargo.
 
-"Teleport 2" - telepor unit to the target tile.
+"Teleport 2" - teleport unit to the target tile.
 * UI name can be set using ui_name_teleport_2
 * any action listed in teleport_2_blocked_by must be impossible
 * the range of legal distance between actor unit and target tile
   must be between teleport_2_min_range and teleport_2_max_range
 * See "Teleport" for everything else.
 
-"Teleport 3" - telepor unit to the target tile.
+"Teleport 3" - teleport unit to the target tile.
 * UI name can be set using ui_name_teleport_3
 * any action listed in teleport_3_blocked_by must be impossible
 * the range of legal distance between actor unit and target tile
   must be between teleport_3_min_range and teleport_3_max_range
 * See "Teleport" for everything else.
 
-"Teleport Conquer" - telepor unit to the target tile and conquer it
+"Teleport Conquer" - teleport unit to the target tile and conquer it
 * UI name can be set using ui_name_teleport_conquer
 * any action listed in teleport_conquer_blocked_by must be impossible
 * the range of legal distance between actor unit and target tile
@@ -1515,6 +1515,49 @@ Actions done by a unit against a tile
 * the target tile can't contain any units not allied to the actor
   unit and all its cargo.
 
+"Teleport Enter" - teleport unit to the target tile.
+* UI name can be set using ui_name_teleport_enter
+* any action listed in teleport_enter_blocked_by must be impossible
+* the range of legal distance between actor unit and target tile
+  must be between teleport_enter_min_range and teleport_enter_max_range
+* the actor unit may not be transported (!)
+* the actor unit's type must be the target tile's terrain animal if the
+  player's nation is an animal barbarian.
+* the actor unit must be able to exist outside of a transport at the target
+  tile.
+* the actor unit doesn't have the "CoastStrict" unit type flag or the
+  target tile is on or adjacent to a tile that doesn't have the
+  "UnsafeCoast" terrain flag.
+* the actor unit can't be diplomatically forbidden from entering the target
+  tile.
+* the target tile can't contain any city or units not allied to the actor
+  unit and all its cargo.
+* can result in hut entry if
+   - the target tile has an extra with "Enter" in its rmcauses (a Hut)
+   - the target tile's Hut's rmreqs are fulfilled
+
+"Teleport Enter Conquer" - teleport unit to the target tile and conquer it
+* UI name can be set using ui_name_teleport_enter_conquer
+* any action listed in teleport_enter_conquer_blocked_by must be impossible
+* the range of legal distance between actor unit and target tile
+  must be between teleport_enter_conquer_min_range and
+  teleport_enter_conquer_max_range
+* the actor unit may not be transported (!)
+* the actor unit's type must be the target tile's terrain animal if the
+  player's nation is an animal barbarian.
+* the actor unit must be able to exist outside of a transport at the target
+  tile.
+* the actor unit doesn't have the "CoastStrict" unit type flag or the
+  target tile is on or adjacent to a tile that doesn't have the
+  "UnsafeCoast" terrain flag.
+* the actor unit can't be diplomatically forbidden from entering the target
+  tile.
+* the target tile can't contain any units not allied to the actor
+  unit and all its cargo.
+* can result in hut entry if
+   - the target tile has an extra with "Enter" in its rmcauses (a Hut)
+   - the target tile's Hut's rmreqs are fulfilled
+
 Actions done by a unit against all extras at a tile
 ===================================================
 "Conquer Extras" - Claim ownership of an extra.
diff --git a/gen_headers/enums/actions_enums.def b/gen_headers/enums/actions_enums.def
index 9ba6fd0671..6312af9fcf 100644
--- a/gen_headers/enums/actions_enums.def
+++ b/gen_headers/enums/actions_enums.def
@@ -122,6 +122,8 @@ values
   ACTION_TELEPORT2                        "Teleport2"
   ACTION_TELEPORT3                        "Teleport3"
   ACTION_TELEPORT_CONQUER                 "Teleport Conquer"
+  ACTION_TELEPORT_ENTER                   "Teleport Unit Enter"
+  ACTION_TELEPORT_ENTER_CONQUER           "Teleport Unit Enter Conquer"
   ACTION_CLEAN                            "Clean"
   ACTION_COLLECT_RANSOM                   "Collect Ransom"
   ACTION_FORTIFY                          "Fortify"
diff --git a/server/advisors/advdata.c b/server/advisors/advdata.c
index decfa2a73a..22c95eba66 100644
--- a/server/advisors/advdata.c
+++ b/server/advisors/advdata.c
@@ -223,6 +223,7 @@ static void count_my_units(struct player *pplayer)
         || unit_can_do_action(punit, ACTION_PARADROP_FRIGHTEN_CONQUER)
         || unit_can_do_action(punit, ACTION_PARADROP_ENTER)
         || unit_can_do_action(punit, ACTION_PARADROP_ENTER_CONQUER)) {
+      /* TODO: Cover also teleporting */
       adv->stats.units.paratroopers++;
     }
     if (utype_can_do_action(punit->utype, ACTION_AIRLIFT)) {
diff --git a/server/citytools.c b/server/citytools.c
index 87917e0b77..640c928546 100644
--- a/server/citytools.c
+++ b/server/citytools.c
@@ -1990,7 +1990,9 @@ bool unit_conquer_city(struct unit *punit, struct city *pcity)
                         || utype_can_do_action(unit_type_get(punit),
                                                ACTION_PARADROP_FRIGHTEN_CONQUER)
                         || utype_can_do_action(unit_type_get(punit),
-                                               ACTION_PARADROP_ENTER_CONQUER),
+                                               ACTION_PARADROP_ENTER_CONQUER)
+                        || utype_can_do_action(unit_type_get(punit),
+                                               ACTION_TELEPORT_ENTER_CONQUER),
                         FALSE, "Bad unit for city occupation.");
 
   /* A transported unit trying to conquer a city should already have been
diff --git a/server/ruleset/ruleload.c b/server/ruleset/ruleload.c
index a6674e959b..89c5a9278e 100644
--- a/server/ruleset/ruleload.c
+++ b/server/ruleset/ruleload.c
@@ -7706,6 +7706,10 @@ static bool load_ruleset_actions(struct section_file *file,
              ACT_SUB_RES_HUT_ENTER);
       BV_SET(action_by_number(ACTION_PARADROP_ENTER_CONQUER)->sub_results,
              ACT_SUB_RES_HUT_ENTER);
+      BV_SET(action_by_number(ACTION_TELEPORT_ENTER)->sub_results,
+             ACT_SUB_RES_HUT_ENTER);
+      BV_SET(action_by_number(ACTION_TELEPORT_ENTER_CONQUER)->sub_results,
+             ACT_SUB_RES_HUT_ENTER);
 
       /* Unit Frighten Hut */
       action_by_result_iterate(paction, ACTRES_HUT_FRIGHTEN) {
-- 
2.43.0

