From 8010c0b8f72a1bd1237d5d6c16506cad1dfaf1b4 Mon Sep 17 00:00:00 2001
From: Sveinung Kvilhaugsvik <sveinung84@users.sourceforge.net>
Date: Mon, 8 Feb 2021 03:25:04 +0100
Subject: [PATCH] Fake generalize "Conquer Extras"

Introduce "Conquer Extras 2" - a perfect copy of "Conquer Extras". Any
difference between them should be ruleset defined.

See osdn #41513
---
 ai/default/aitools.c      |  6 ++++++
 client/gui-qt/dialogs.cpp | 16 ++++++++++++++++
 client/packhand.c         |  1 +
 common/actions.c          | 16 ++++++++++++++++
 common/actions.h          | 30 ++++++++++++++++--------------
 doc/README.actions        |  5 +++++
 server/diplomats.c        | 11 +++++++++++
 server/unithand.c         |  7 +++++++
 8 files changed, 78 insertions(+), 14 deletions(-)

diff --git a/ai/default/aitools.c b/ai/default/aitools.c
index f3d2d1e5a9..a87753b20a 100644
--- a/ai/default/aitools.c
+++ b/ai/default/aitools.c
@@ -926,6 +926,12 @@ bool dai_unit_attack(struct ai_type *ait, struct unit *punit, struct tile *ptile
     /* Choose "Conquer Extras". */
     unit_do_action(unit_owner(punit), punit->id, tile_index(ptile),
                    0, "", ACTION_CONQUER_EXTRAS);
+  } else if (tile_has_claimable_base(ptile, unit_type_get(punit))
+             && is_action_enabled_unit_on_extras(ACTION_CONQUER_EXTRAS2,
+                                                 punit, ptile, NULL)) {
+    /* Choose "Conquer Extras 2". */
+    unit_do_action(unit_owner(punit), punit->id, tile_index(ptile),
+                   0, "", ACTION_CONQUER_EXTRAS2);
   } else if (is_action_enabled_unit_on_tile(ACTION_HUT_ENTER,
                                             punit, ptile, NULL)) {
     /* Choose "Enter Hut". */
diff --git a/client/gui-qt/dialogs.cpp b/client/gui-qt/dialogs.cpp
index 510aafde11..32fe8304bd 100644
--- a/client/gui-qt/dialogs.cpp
+++ b/client/gui-qt/dialogs.cpp
@@ -148,6 +148,7 @@ static void airlift(QVariant data1, QVariant data2);
 static void conquer_city(QVariant data1, QVariant data2);
 static void conquer_city2(QVariant data1, QVariant data2);
 static void conquer_extras(QVariant data1, QVariant data2);
+static void conquer_extras2(QVariant data1, QVariant data2);
 static void heal_unit(QVariant data1, QVariant data2);
 static void transport_board(QVariant data1, QVariant data2);
 static void transport_embark(QVariant data1, QVariant data2);
@@ -268,6 +269,7 @@ static const QHash<action_id, pfcn_void> af_map_init(void)
 
   /* Unit acting against all tile extras. */
   action_function[ACTION_CONQUER_EXTRAS] = conquer_extras;
+  action_function[ACTION_CONQUER_EXTRAS2] = conquer_extras2;
 
   /* Unit acting with no target except itself. */
   action_function[ACTION_DISBAND_UNIT] = disband_unit;
@@ -1830,6 +1832,20 @@ static void conquer_extras(QVariant data1, QVariant data2)
   }
 }
 
+/***********************************************************************//**
+  Action "Conquer Extras 2" for choice dialog
+***************************************************************************/
+static void conquer_extras2(QVariant data1, QVariant data2)
+{
+  int actor_id = data1.toInt();
+  int target_id = data2.toInt();
+
+  if (NULL != game_unit_by_number(actor_id)) {
+    request_do_action(ACTION_CONQUER_EXTRAS2,
+                      actor_id, target_id, 0, "");
+  }
+}
+
 /***********************************************************************//**
   Delay selection of what action to take.
 ***************************************************************************/
diff --git a/client/packhand.c b/client/packhand.c
index 459d7697b7..5fa23e8354 100644
--- a/client/packhand.c
+++ b/client/packhand.c
@@ -4780,6 +4780,7 @@ static action_id auto_attack_act(const struct act_prob *act_probs)
       case ACTION_CONQUER_CITY2:
       case ACTION_STRIKE_PRODUCTION:
       case ACTION_CONQUER_EXTRAS:
+      case ACTION_CONQUER_EXTRAS2:
         /* An attack. */
         if (attack_action == ACTION_NONE) {
           /* No previous attack action found. */
diff --git a/common/actions.c b/common/actions.c
index 97d98384d8..105fb7c014 100644
--- a/common/actions.c
+++ b/common/actions.c
@@ -1003,6 +1003,10 @@ static void hard_code_actions(void)
       unit_action_new(ACTION_CONQUER_EXTRAS, ACTRES_CONQUER_EXTRAS,
                       FALSE, TRUE,
                       MAK_REGULAR, 1, 1, FALSE);
+  actions[ACTION_CONQUER_EXTRAS2] =
+      unit_action_new(ACTION_CONQUER_EXTRAS2, ACTRES_CONQUER_EXTRAS,
+                      FALSE, TRUE,
+                      MAK_REGULAR, 1, 1, FALSE);
   actions[ACTION_HEAL_UNIT] =
       unit_action_new(ACTION_HEAL_UNIT, ACTRES_HEAL_UNIT,
                       FALSE, TRUE,
@@ -6755,6 +6759,8 @@ const char *action_ui_name_ruleset_var_name(int act)
     return "ui_name_conquer_city_2";
   case ACTION_CONQUER_EXTRAS:
     return "ui_name_conquer_extras";
+  case ACTION_CONQUER_EXTRAS2:
+    return "ui_name_conquer_extras_2";
   case ACTION_HEAL_UNIT:
     return "ui_name_heal_unit";
   case ACTION_TRANSFORM_TERRAIN:
@@ -6989,6 +6995,9 @@ const char *action_ui_name_default(int act)
   case ACTION_CONQUER_EXTRAS:
     /* TRANS: _Conquer Extras (100% chance of success). */
     return N_("%sConquer Extras%s");
+  case ACTION_CONQUER_EXTRAS2:
+    /* TRANS: _Conquer Extras 2 (100% chance of success). */
+    return N_("%sConquer Extras 2%s");
   case ACTION_HEAL_UNIT:
     /* TRANS: Heal _Unit (3% chance of success). */
     return N_("Heal %sUnit%s");
@@ -7155,6 +7164,7 @@ const char *action_min_range_ruleset_var_name(int act)
   case ACTION_NUKE:
   case ACTION_SPY_ATTACK:
   case ACTION_CONQUER_EXTRAS:
+  case ACTION_CONQUER_EXTRAS2:
   case ACTION_HUT_ENTER:
   case ACTION_HUT_ENTER2:
   case ACTION_HUT_FRIGHTEN:
@@ -7256,6 +7266,7 @@ int action_min_range_default(int act)
   case ACTION_NUKE:
   case ACTION_SPY_ATTACK:
   case ACTION_CONQUER_EXTRAS:
+  case ACTION_CONQUER_EXTRAS2:
   case ACTION_HUT_ENTER:
   case ACTION_HUT_ENTER2:
   case ACTION_HUT_FRIGHTEN:
@@ -7350,6 +7361,7 @@ const char *action_max_range_ruleset_var_name(int act)
   case ACTION_TRANSPORT_DISEMBARK2:
   case ACTION_SPY_ATTACK:
   case ACTION_CONQUER_EXTRAS:
+  case ACTION_CONQUER_EXTRAS2:
   case ACTION_HUT_ENTER:
   case ACTION_HUT_ENTER2:
   case ACTION_HUT_FRIGHTEN:
@@ -7460,6 +7472,7 @@ int action_max_range_default(int act)
   case ACTION_TRANSPORT_DISEMBARK2:
   case ACTION_SPY_ATTACK:
   case ACTION_CONQUER_EXTRAS:
+  case ACTION_CONQUER_EXTRAS2:
   case ACTION_HUT_ENTER:
   case ACTION_HUT_ENTER2:
   case ACTION_HUT_FRIGHTEN:
@@ -7576,6 +7589,7 @@ const char *action_target_kind_ruleset_var_name(int act)
   case ACTION_NUKE:
   case ACTION_SPY_ATTACK:
   case ACTION_CONQUER_EXTRAS:
+  case ACTION_CONQUER_EXTRAS2:
   case ACTION_HUT_ENTER:
   case ACTION_HUT_ENTER2:
   case ACTION_HUT_FRIGHTEN:
@@ -8046,6 +8060,7 @@ const char *action_actor_consuming_always_ruleset_var_name(action_id act)
   case ACTION_NUKE:
   case ACTION_SPY_ATTACK:
   case ACTION_CONQUER_EXTRAS:
+  case ACTION_CONQUER_EXTRAS2:
   case ACTION_HUT_ENTER:
   case ACTION_HUT_ENTER2:
   case ACTION_HUT_FRIGHTEN:
@@ -8166,6 +8181,7 @@ const char *action_blocked_by_ruleset_var_name(const struct action *act)
   case ACTION_SPY_SPREAD_PLAGUE:
   case ACTION_SPY_ATTACK:
   case ACTION_CONQUER_EXTRAS:
+  case ACTION_CONQUER_EXTRAS2:
   case ACTION_HUT_ENTER:
   case ACTION_HUT_ENTER2:
   case ACTION_HUT_FRIGHTEN:
diff --git a/common/actions.h b/common/actions.h
index 8934457c97..46bad3b902 100644
--- a/common/actions.h
+++ b/common/actions.h
@@ -214,20 +214,22 @@ extern "C" {
 #define SPECENUM_VALUE73NAME "Spy Attack"
 #define SPECENUM_VALUE74 ACTION_CONQUER_EXTRAS
 #define SPECENUM_VALUE74NAME "Conquer Extras"
-#define SPECENUM_VALUE75 ACTION_HUT_ENTER
-#define SPECENUM_VALUE75NAME "Enter Hut"
-#define SPECENUM_VALUE76 ACTION_HUT_ENTER2
-#define SPECENUM_VALUE76NAME "Enter Hut 2"
-#define SPECENUM_VALUE77 ACTION_HUT_FRIGHTEN
-#define SPECENUM_VALUE77NAME "Frighten Hut"
-#define SPECENUM_VALUE78 ACTION_HUT_FRIGHTEN2
-#define SPECENUM_VALUE78NAME "Frighten Hut 2"
-#define SPECENUM_VALUE79 ACTION_USER_ACTION1
-#define SPECENUM_VALUE79NAME "User Action 1"
-#define SPECENUM_VALUE80 ACTION_USER_ACTION2
-#define SPECENUM_VALUE80NAME "User Action 2"
-#define SPECENUM_VALUE81 ACTION_USER_ACTION3
-#define SPECENUM_VALUE81NAME "User Action 3"
+#define SPECENUM_VALUE75 ACTION_CONQUER_EXTRAS2
+#define SPECENUM_VALUE75NAME "Conquer Extras 2"
+#define SPECENUM_VALUE76 ACTION_HUT_ENTER
+#define SPECENUM_VALUE76NAME "Enter Hut"
+#define SPECENUM_VALUE77 ACTION_HUT_ENTER2
+#define SPECENUM_VALUE77NAME "Enter Hut 2"
+#define SPECENUM_VALUE78 ACTION_HUT_FRIGHTEN
+#define SPECENUM_VALUE78NAME "Frighten Hut"
+#define SPECENUM_VALUE79 ACTION_HUT_FRIGHTEN2
+#define SPECENUM_VALUE79NAME "Frighten Hut 2"
+#define SPECENUM_VALUE80 ACTION_USER_ACTION1
+#define SPECENUM_VALUE80NAME "User Action 1"
+#define SPECENUM_VALUE81 ACTION_USER_ACTION2
+#define SPECENUM_VALUE81NAME "User Action 2"
+#define SPECENUM_VALUE82 ACTION_USER_ACTION3
+#define SPECENUM_VALUE82NAME "User Action 3"
 #define SPECENUM_BITVECTOR bv_actions
 #define SPECENUM_COUNT ACTION_COUNT
 #include "specenum_gen.h"
diff --git a/doc/README.actions b/doc/README.actions
index a004dc7a13..73529d522e 100644
--- a/doc/README.actions
+++ b/doc/README.actions
@@ -1018,6 +1018,11 @@ Actions done by a unit against all extras at a tile
 * the target tile isn't blocked for the actor unit by some other unit's
   zone of control (ZOC)
 
+"Conquer Extras 2" - Claim ownership of an extra.
+* UI name can be set using ui_name_conquer_extras
+* A copy of "Conquer Extras"
+* See "Conquer Extras" for everything else.
+
 Actions done by a unit to it self
 =================================
 "Disband Unit" - Disband the unit.
diff --git a/server/diplomats.c b/server/diplomats.c
index debc0ce6cb..562b51713e 100644
--- a/server/diplomats.c
+++ b/server/diplomats.c
@@ -727,6 +727,17 @@ bool diplomat_bribe(struct player *pplayer, struct unit *pdiplomat,
                                       ACT_REQ_RULES)))
       /* May have died while trying to conquer extra. */
       && unit_is_alive(diplomat_id)
+      /* Post bribe extras conquest. */
+      && (!tile_has_claimable_base(victim_tile, unit_type_get(pdiplomat))
+          || !(is_action_enabled_unit_on_extras(ACTION_CONQUER_EXTRAS2,
+                                                pdiplomat, victim_tile,
+                                                NULL)
+               && unit_perform_action(unit_owner(pdiplomat), pdiplomat->id,
+                                      tile_index(victim_tile), 0, "",
+                                      ACTION_CONQUER_EXTRAS2,
+                                      ACT_REQ_RULES)))
+      /* May have died while trying to conquer extra. */
+      && unit_is_alive(diplomat_id)
       /* Post bribe hut entry. */
       && (!unit_can_enter_hut(pdiplomat, victim_tile)
           || !(is_action_enabled_unit_on_tile(ACTION_HUT_ENTER,
diff --git a/server/unithand.c b/server/unithand.c
index 22b3ee2a6a..8001666a15 100644
--- a/server/unithand.c
+++ b/server/unithand.c
@@ -4531,6 +4531,13 @@ static bool do_attack(struct unit *punit, struct tile *def_tile,
                                    tile_index(def_tile), 0, "",
                                    ACTION_CONQUER_EXTRAS,
                                    ACT_REQ_RULES))
+        || (tile_has_claimable_base(def_tile, unit_type_get(punit))
+            && is_action_enabled_unit_on_extras(ACTION_CONQUER_EXTRAS2,
+                                                punit, def_tile, NULL)
+            && unit_perform_action(unit_owner(punit), punit->id,
+                                   tile_index(def_tile), 0, "",
+                                   ACTION_CONQUER_EXTRAS2,
+                                   ACT_REQ_RULES))
         || (unit_can_enter_hut(punit, def_tile)
             && is_action_enabled_unit_on_tile(ACTION_HUT_ENTER,
                                               punit, def_tile, NULL)
-- 
2.20.1