From c9b37786114617dbdb6a1a669c529a49b14c271b Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Tue, 30 Jan 2024 19:26:02 +0200
Subject: [PATCH 27/27] AI: Stop attempts to recover Helicopter HP in the open

They would be losing HP instead.

See RM #207

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 ai/default/daiunit.c | 27 ++++++++++++++-------------
 common/unit.c        | 12 ++++++++++++
 common/unit.h        |  1 +
 3 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/ai/default/daiunit.c b/ai/default/daiunit.c
index 58fd64e4a2..1ad5e12a5c 100644
--- a/ai/default/daiunit.c
+++ b/ai/default/daiunit.c
@@ -2433,24 +2433,24 @@ static void dai_manage_hitpoint_recovery(struct ai_type *ait,
 
   CHECK_UNIT(punit);
 
-  if (pcity) {
-    /* rest in city until the hitpoints are recovered, but attempt
-       to protect city from attack (and be opportunistic too)*/
+  if (pcity != NULL) {
+    /* Rest in the city until the hitpoints are recovered, but attempt
+     * to protect city from attack (and be opportunistic too)*/
     if (dai_military_rampage(punit, RAMPAGE_ANYTHING, 
                              RAMPAGE_FREE_CITY_OR_BETTER)) {
       UNIT_LOG(LOGLEVEL_RECOVERY, punit, "recovering hit points.");
     } else {
-      return; /* we died heroically defending our city */
+      return; /* We died heroically defending our city */
     }
   } else {
-    /* goto to nearest city to recover hit points */
-    /* just before, check to see if we can occupy an undefended enemy city */
+    /* Goto to nearest city to recover hit points */
+    /* Just before, check to see if we can occupy an undefended enemy city */
     if (!dai_military_rampage(punit, RAMPAGE_FREE_CITY_OR_BETTER, 
                               RAMPAGE_FREE_CITY_OR_BETTER)) { 
-      return; /* oops, we died */
+      return; /* Oops, we died */
     }
 
-    /* find city to stay and go there */
+    /* Find a city to stay and go there */
     safe = find_nearest_safe_city(punit);
     if (safe) {
       UNIT_LOG(LOGLEVEL_RECOVERY, punit, "going to %s to recover",
@@ -2460,7 +2460,7 @@ static void dai_manage_hitpoint_recovery(struct ai_type *ait,
         return;
       }
     } else {
-      /* oops */
+      /* Oops */
       UNIT_LOG(LOGLEVEL_RECOVERY, punit, "didn't find a city to recover in!");
       dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
       dai_military_attack(ait, pplayer, punit);
@@ -2468,14 +2468,15 @@ static void dai_manage_hitpoint_recovery(struct ai_type *ait,
     }
   }
 
-  /* is the unit still damaged? if true recover hit points, if not idle */
-  if (punit->hp == punittype->hp) {
-    /* we are ready to go out and kick ass again */
+  /* Is the unit still damaged? If true, and could recover hit points, do so.
+   * Don't wait if would be losing hitpoints that way! */
+  if (punit->hp == punittype->hp || !is_gaining_hp(punit)) {
+    /* We are ready to go out and kick ass again */
     UNIT_LOG(LOGLEVEL_RECOVERY, punit, "ready to kick ass again!");
     dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);  
     return;
   } else {
-    def_ai_unit_data(punit, ait)->done = TRUE; /* sit tight */
+    def_ai_unit_data(punit, ait)->done = TRUE; /* Sit tight */
   }
 }
 
diff --git a/common/unit.c b/common/unit.c
index 0666aacf94..fea75ff094 100644
--- a/common/unit.c
+++ b/common/unit.c
@@ -2226,6 +2226,18 @@ bool is_losing_hp(const struct unit *punit)
        utype_class(punittype)->hp_loss_pct / 100);
 }
 
+/**********************************************************************//**
+  Does unit gain hitpoints each turn?
+**************************************************************************/
+bool is_gaining_hp(const struct unit *punit)
+{
+  const struct unit_type *punittype = unit_type_get(punit);
+
+  return get_unit_bonus(punit, EFT_UNIT_RECOVER)
+    > (punittype->hp *
+       utype_class(punittype)->hp_loss_pct / 100);
+}
+
 /**********************************************************************//**
   Does unit lose hitpoints each turn?
 **************************************************************************/
diff --git a/common/unit.h b/common/unit.h
index 82dea5a96a..3d7f0124d6 100644
--- a/common/unit.h
+++ b/common/unit.h
@@ -523,6 +523,7 @@ int hp_gain_coord(struct unit *punit);
 bool is_losing_hp(const struct unit *punit);
 bool unit_type_is_losing_hp(const struct player *pplayer,
                             const struct unit_type *punittype);
+bool is_gaining_hp(const struct unit *punit);
 
 bool unit_is_alive(int id);
 
-- 
2.43.0

