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

See RM #165

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 common/actions.c          | 44 +++++++++++++++++++++++++++++++++++--
 common/actions.h          | 28 ++++++++++++++----------
 common/fc_types.h         |  1 +
 doc/README.actions        | 46 +++++++++++++++++++++++++++++++++++++--
 server/advisors/advdata.c |  1 +
 server/citytools.c        |  4 +++-
 server/ruleset.c          |  4 ++++
 7 files changed, 111 insertions(+), 17 deletions(-)

diff --git a/common/actions.c b/common/actions.c
index b13c6cba15..da3edf70d2 100644
--- a/common/actions.c
+++ b/common/actions.c
@@ -1513,6 +1513,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_USER_ACTION1] =
       unit_action_new(ACTION_USER_ACTION1, ACTRES_NONE,
                       FALSE, TRUE,
@@ -6671,6 +6683,10 @@ const char *action_ui_name_ruleset_var_name(int act)
     return "ui_name_teleport";
   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:
@@ -6992,8 +7008,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");
@@ -7149,6 +7171,10 @@ const char *action_min_range_ruleset_var_name(int act)
     return "teleport_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:
@@ -7308,6 +7334,10 @@ const char *action_max_range_ruleset_var_name(int act)
     return "teleport_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:
@@ -7448,6 +7478,8 @@ const char *action_target_kind_ruleset_var_name(int act)
   case ACTION_UNIT_MOVE3:
   case ACTION_TELEPORT:
   case ACTION_TELEPORT_CONQUER:
+  case ACTION_TELEPORT_ENTER:
+  case ACTION_TELEPORT_ENTER_CONQUER:
   case ACTION_SPY_ESCAPE:
     /* Target kind is not ruleset changeable */
     return NULL;
@@ -7804,6 +7836,8 @@ const char *action_actor_consuming_always_ruleset_var_name(action_id act)
   case ACTION_UNIT_MOVE3:
   case ACTION_TELEPORT:
   case ACTION_TELEPORT_CONQUER:
+  case ACTION_TELEPORT_ENTER:
+  case ACTION_TELEPORT_ENTER_CONQUER:
   case ACTION_SPY_ESCAPE:
     /* Actor consuming always is not ruleset changeable */
     return NULL;
@@ -7896,6 +7930,10 @@ const char *action_blocked_by_ruleset_var_name(const struct action *act)
     return "teleport_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:
@@ -8141,6 +8179,8 @@ action_post_success_forced_ruleset_var_name(const struct action *act)
   case ACTION_UNIT_MOVE3:
   case ACTION_TELEPORT:
   case ACTION_TELEPORT_CONQUER:
+  case ACTION_TELEPORT_ENTER:
+  case ACTION_TELEPORT_ENTER_CONQUER:
   case ACTION_SPY_ESCAPE:
   case ACTION_USER_ACTION1:
   case ACTION_USER_ACTION2:
diff --git a/common/actions.h b/common/actions.h
index e6a0d5e9e6..2e0bdc23ef 100644
--- a/common/actions.h
+++ b/common/actions.h
@@ -276,18 +276,22 @@ const char *gen_action_name_update_cb(const char *old_name);
 #define SPECENUM_VALUE112NAME "Teleport"
 #define SPECENUM_VALUE113 ACTION_TELEPORT_CONQUER
 #define SPECENUM_VALUE113NAME "Teleport Conquer"
-#define SPECENUM_VALUE114 ACTION_CLEAN
-#define SPECENUM_VALUE114NAME "Clean"
-#define SPECENUM_VALUE115 ACTION_COLLECT_RANSOM
-#define SPECENUM_VALUE115NAME "Collect Ransom"
-#define SPECENUM_VALUE116 ACTION_USER_ACTION1
-#define SPECENUM_VALUE116NAME "User Action 1"
-#define SPECENUM_VALUE117 ACTION_USER_ACTION2
-#define SPECENUM_VALUE117NAME "User Action 2"
-#define SPECENUM_VALUE118 ACTION_USER_ACTION3
-#define SPECENUM_VALUE118NAME "User Action 3"
-#define SPECENUM_VALUE119 ACTION_USER_ACTION4
-#define SPECENUM_VALUE119NAME "User Action 4"
+#define SPECENUM_VALUE114 ACTION_TELEPORT_ENTER
+#define SPECENUM_VALUE114NAME "Teleport Enter"
+#define SPECENUM_VALUE115 ACTION_TELEPORT_ENTER_CONQUER
+#define SPECENUM_VALUE115NAME "Teleport Enter Conquer"
+#define SPECENUM_VALUE116 ACTION_CLEAN
+#define SPECENUM_VALUE116NAME "Clean"
+#define SPECENUM_VALUE117 ACTION_COLLECT_RANSOM
+#define SPECENUM_VALUE117NAME "Collect Ransom"
+#define SPECENUM_VALUE118 ACTION_USER_ACTION1
+#define SPECENUM_VALUE118NAME "User Action 1"
+#define SPECENUM_VALUE119 ACTION_USER_ACTION2
+#define SPECENUM_VALUE119NAME "User Action 2"
+#define SPECENUM_VALUE120 ACTION_USER_ACTION3
+#define SPECENUM_VALUE120NAME "User Action 3"
+#define SPECENUM_VALUE121 ACTION_USER_ACTION4
+#define SPECENUM_VALUE121NAME "User Action 4"
 #define SPECENUM_BITVECTOR bv_actions
 #define SPECENUM_COUNT ACTION_COUNT
 #define SPECENUM_NAME_UPDATER
diff --git a/common/fc_types.h b/common/fc_types.h
index 2f58cac4c8..b5c2e66c04 100644
--- a/common/fc_types.h
+++ b/common/fc_types.h
@@ -318,6 +318,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 e65f7a3b2d..80e3b4af7d 100644
--- a/doc/README.actions
+++ b/doc/README.actions
@@ -1432,7 +1432,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
@@ -1450,7 +1450,7 @@ 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 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
@@ -1468,6 +1468,48 @@ 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
+* any action listed in teleport_blocked_by must be impossible
+* the range of legal distance between actor unit and target tile
+  must be between teleport_min_range and teleport_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_conquer
+* any action listed in teleport_conquer_blocked_by must be impossible
+* the range of legal distance between actor unit and target tile
+  must be between teleport_conquer_min_range and teleport_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/server/advisors/advdata.c b/server/advisors/advdata.c
index e24e6717cc..56714bcedb 100644
--- a/server/advisors/advdata.c
+++ b/server/advisors/advdata.c
@@ -224,6 +224,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 52348d5710..1faa0cf093 100644
--- a/server/citytools.c
+++ b/server/citytools.c
@@ -1989,7 +1989,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.c b/server/ruleset.c
index 3536f48c1f..b6868fddc0 100644
--- a/server/ruleset.c
+++ b/server/ruleset.c
@@ -7890,6 +7890,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

