From 8295fa4c6ece95b263a858be56a52a51f8fc3327 Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Sat, 26 Sep 2026 03:54:39 +0300
Subject: [PATCH 74/74] Add action type "Scout"

See RM #2184

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 client/gui-qt/dialogs.cpp           | 17 +++++++++++++++++
 common/actions.c                    | 15 +++++++++++++++
 doc/README.actions                  |  4 ++++
 gen_headers/enums/actions_enums.def |  1 +
 4 files changed, 37 insertions(+)

diff --git a/client/gui-qt/dialogs.cpp b/client/gui-qt/dialogs.cpp
index e834f19424..af286b2349 100644
--- a/client/gui-qt/dialogs.cpp
+++ b/client/gui-qt/dialogs.cpp
@@ -183,6 +183,7 @@ static void frighten_hut4(QVariant data1, QVariant data2);
 static void regular_move(QVariant data1, QVariant data2);
 static void regular_move2(QVariant data1, QVariant data2);
 static void regular_move3(QVariant data1, QVariant data2);
+static void scout(QVariant data1, QVariant data2);
 static void convert_unit(QVariant data1, QVariant data2);
 static void fortify(QVariant data1, QVariant data2);
 static void fortify2(QVariant data1, QVariant data2);
@@ -381,6 +382,7 @@ static const QHash<action_id, pfcn_void> af_map_init(void)
   action_function[ACTION_UNIT_MOVE] = regular_move;
   action_function[ACTION_UNIT_MOVE2] = regular_move2;
   action_function[ACTION_UNIT_MOVE3] = regular_move3;
+  action_function[ACTION_SCOUT] = scout;
 
   // Unit acting against all tile extras.
   action_function[ACTION_CONQUER_EXTRAS] = conquer_extras;
@@ -4339,6 +4341,21 @@ static void regular_move3(QVariant data1, QVariant data2)
   }
 }
 
+/***********************************************************************//**
+  Action "Scout" for choice dialog
+***************************************************************************/
+static void scout(QVariant data1, QVariant data2)
+{
+  int actor_id = data1.toInt();
+  int target_id = data2.toInt();
+
+  if (game_unit_by_number(actor_id) != nullptr
+      && index_to_tile(&(wld.map), target_id) != nullptr) {
+    request_do_action(ACTION_SCOUT,
+                      actor_id, target_id, 0, "");
+  }
+}
+
 /***********************************************************************//**
   Popup a window asking a diplomatic unit if it wishes to incite the
   given enemy city.
diff --git a/common/actions.c b/common/actions.c
index d3184d491b..1c1fb466c2 100644
--- a/common/actions.c
+++ b/common/actions.c
@@ -782,6 +782,11 @@ static void hard_code_actions(void)
                       TRUE, TRUE,
                       MAK_TELEPORT, 1,
                       ACTION_DISTANCE_MAX, FALSE);
+  actions[ACTION_SCOUT] =
+      unit_action_new(ACTION_SCOUT, ACTRES_SCOUT,
+                      TRUE, TRUE,
+                      MAK_TELEPORT, 1,
+                      ACTION_DISTANCE_MAX, FALSE);
   actions[ACTION_GAIN_VETERANCY] =
       unit_action_new(ACTION_GAIN_VETERANCY, ACTRES_ENABLER_CHECK,
                       TRUE, FALSE,
@@ -6373,6 +6378,9 @@ const char *action_ui_name_default(int act)
   case ACTION_SPY_ESCAPE:
     /* TRANS: _Escape To Nearest City (100% chance of success). */
     return N_("%sEscape To Nearest City%s");
+  case ACTION_SCOUT:
+    /* TRANS: _Scout (100% chance of success). */
+    return N_("%sScout%s");
   case ACTION_USER_ACTION1:
     /* TRANS: _User Action 1 (100% chance of success). */
     return N_("%sUser Action 1%s");
@@ -6535,6 +6543,7 @@ const char *action_min_range_ruleset_var_name(int act)
   case ACTION_UNIT_MOVE2:
   case ACTION_UNIT_MOVE3:
   case ACTION_SPY_ESCAPE:
+  case ACTION_SCOUT:
   case ACTION_GAIN_VETERANCY:
   case ACTION_ESCAPE:
   case ACTION_CIVIL_WAR:
@@ -6753,6 +6762,8 @@ const char *action_max_range_ruleset_var_name(int act)
     return "teleport_enter_max_range";
   case ACTION_TELEPORT_ENTER_CONQUER:
     return "teleport_enter_conquer_max_range";
+  case ACTION_SCOUT:
+    return "scout_max_range";
   case ACTION_USER_ACTION1:
     return "user_action_1_max_range";
   case ACTION_USER_ACTION2:
@@ -6911,6 +6922,7 @@ const char *action_target_kind_ruleset_var_name(int act)
   case ACTION_TELEPORT_ENTER:
   case ACTION_TELEPORT_ENTER_CONQUER:
   case ACTION_SPY_ESCAPE:
+  case ACTION_SCOUT:
   case ACTION_GAIN_VETERANCY:
   case ACTION_ESCAPE:
   case ACTION_CIVIL_WAR:
@@ -7084,6 +7096,7 @@ const char *action_actor_consuming_always_ruleset_var_name(action_id act)
   case ACTION_TELEPORT_ENTER:
   case ACTION_TELEPORT_ENTER_CONQUER:
   case ACTION_SPY_ESCAPE:
+  case ACTION_SCOUT:
   case ACTION_GAIN_VETERANCY:
   case ACTION_ESCAPE:
   case ACTION_CIVIL_WAR:
@@ -7297,6 +7310,7 @@ const char *action_blocked_by_ruleset_var_name(const struct action *act)
   case ACTION_HUT_FRIGHTEN2:
   case ACTION_HUT_FRIGHTEN3:
   case ACTION_HUT_FRIGHTEN4:
+  case ACTION_SCOUT:
   case ACTION_GAIN_VETERANCY:
   case ACTION_CIVIL_WAR:
   case ACTION_FINISH_UNIT:
@@ -7477,6 +7491,7 @@ action_post_success_forced_ruleset_var_name(const struct action *act)
   case ACTION_TELEPORT_ENTER:
   case ACTION_TELEPORT_ENTER_CONQUER:
   case ACTION_SPY_ESCAPE:
+  case ACTION_SCOUT:
   case ACTION_GAIN_VETERANCY:
   case ACTION_ESCAPE:
   case ACTION_CIVIL_WAR:
diff --git a/doc/README.actions b/doc/README.actions
index a6ac2449c0..224c60bbe9 100644
--- a/doc/README.actions
+++ b/doc/README.actions
@@ -1504,6 +1504,10 @@ Actions done by a unit against a tile
    - the target tile has an extra with "Enter" in its rmcauses (a Hut)
    - the target tile's Hut's rmreqs are fulfilled
 
+"Scout" - Reveal area around a tile until turn change
+ * max legal distance to the target (center tile of the area to scout)
+   can be set using scout_max_range
+
 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 5ebf4d733b..30f7dad312 100644
--- a/gen_headers/enums/actions_enums.def
+++ b/gen_headers/enums/actions_enums.def
@@ -140,6 +140,7 @@ values
   ACTION_PLANT2                           "Plant 2"
   ACTION_TRANSFORM_TERRAIN                "Transform Terrain"
   ACTION_TRANSFORM_TERRAIN2               "Transform Terrain 2"
+  ACTION_SCOUT                            "Scout"
 
   # Enabler checks only
   ACTION_GAIN_VETERANCY                   "Gain Veterancy"
-- 
2.53.0

