Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2002:
[Freeciv-Dev] Recover Hit Points (PR#1874)
Home

[Freeciv-Dev] Recover Hit Points (PR#1874)

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Cc: bugs@xxxxxxxxxxxxxxxxxxx
Subject: [Freeciv-Dev] Recover Hit Points (PR#1874)
From: Jordi Negrevernis i Font <jorneg@xxxxxxxxxxx>
Date: Thu, 1 Aug 2002 15:58:02 -0700 (PDT)

   This patch makes ground units go to a nearby city - preferably with
Content-Type: multipart/mixed;
 boundary="------------080504000401000404010001"

This is a multi-part message in MIME format.
--------------080504000401000404010001
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit


   This patch makes ground units go to a nearby city - preferably with 
barracks - and sealing units  go to
a city - preferably with port facility - to recover hit points.

    This one makes the unit wait in the city until they recover all the 
hit points even there isn't port or barracks.

    I think that it follows the style guide and fixes a TODO for the ai.


--------------080504000401000404010001
Content-Type: text/plain;
 name="recover_hp4.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="recover_hp4.diff"

diff -Nur -b -Xfreeciv-cvs/diff_ignore freeciv-cvs/ai/aiunit.c 
freeciv-mod1/ai/aiunit.c
--- freeciv-cvs/ai/aiunit.c     Tue Jul 16 08:51:03 2002
+++ freeciv-mod1/ai/aiunit.c    Thu Aug  1 12:14:30 2002
@@ -29,6 +29,7 @@
 #include "shared.h"
 #include "timing.h"
 #include "unit.h"
+#include "unittype.h"
 
 #include "barbarian.h"
 #include "citytools.h"
@@ -47,6 +48,9 @@
 
 #include "aiunit.h"
 
+static bool find_nearest_friendly_port(struct unit *punit);
+static bool find_nearest_friendly_city(struct unit *punit);
+
 static void ai_manage_diplomat(struct player *pplayer, struct unit *pdiplomat);
 static void ai_manage_military(struct player *pplayer,struct unit *punit);
 static void ai_manage_caravan(struct player *pplayer, struct unit *punit);
@@ -1401,6 +1405,7 @@
   struct unit *aunit;
   int val, def;
   int q = 0;
+  struct unit_type *punittype=get_unit_type(punit->type);
 
 /* tired of AI abandoning its cities! -- Syela */
   if (punit->homecity != 0 && (pcity = find_city_by_id(punit->homecity))) {
@@ -1465,6 +1470,12 @@
     }
   }
 
+  /* is the unit damaged? */
+  if ((punit->hp < punittype->hp * 0.25) || ((punit->ai.ai_role == 
AIUNIT_RECOVER_HIT_POINTS) && (punit->hp < punittype->hp))) {
+    punit->ai.ai_role = AIUNIT_RECOVER_HIT_POINTS;
+    return;
+  }
+
 /* I'm not 100% sure this is the absolute best place for this... -- Syela */
   generate_warmap(map_get_city(punit->x, punit->y), punit);
 /* I need this in order to call unit_move_turns, here and in look_for_charge */
@@ -1882,6 +1893,41 @@
   return TRUE;
 }
 
+/**********************************************************************
+  Find safe city (preferably with Barracks). An allied player's city is
+  just as good as one of our own, since both replenish our hitpoints and
+  reduce unhappiness.
+***********************************************************************/
+static bool find_nearest_friendly_city(struct unit *punit)
+{
+  struct player *pplayer = unit_owner(punit);
+  int best = 6 * THRESHOLD + 1, cur;
+
+  generate_warmap(map_get_city(punit->x, punit->y), punit);
+  players_iterate(aplayer) {
+    if (pplayers_allied(pplayer,aplayer)) {
+      city_list_iterate(aplayer->cities, pcity) {
+        cur = warmap.cost[pcity->x][pcity->y];
+        /* we favour cities which barracks */
+        if (city_got_building(pcity, B_BARRACKS)) cur /= 3;
+        if (city_got_building(pcity, B_BARRACKS2)) cur /= 3;
+        if (city_got_building(pcity, B_BARRACKS3)) cur /= 3;
+        if (cur < best) {
+          punit->goto_dest_x = pcity->x;
+          punit->goto_dest_y = pcity->y;
+          best = cur;
+        }
+      } city_list_iterate_end;
+    }
+  } players_iterate_end;
+  if (best > 6 * THRESHOLD) return FALSE;
+  freelog(LOG_DEBUG, "Friendly city nearest to (%d,%d) is %s@(%d,%d) [%d]",
+               punit->x, punit->y,
+               map_get_city(punit->goto_dest_x, punit->goto_dest_y)->name,
+               punit->goto_dest_x, punit->goto_dest_y, best);
+  return TRUE;
+}
+
 /*************************************************************************
 This seems to do the attack. First find victim on the neighbouring tiles.
 If no enemies nearby find_something_to_kill() anywhere else. If there is
@@ -2150,6 +2196,92 @@
   return;
 }
 
+/*************************************************************************
+ This function goes wait a unit in a city for the hitpoints to recover.
+ If something is attacking your city, kill it yeahhh!!!.
+**************************************************************************/
+static void ai_recover_hit_points(struct player *pplayer,struct unit *punit)
+{
+  int dest_x, dest_y;
+  int id = punit->id;
+  bool flag;
+  int ct = 10;
+  enum goto_result res;
+  struct city *pcity=map_get_city(punit->x, punit->y);
+  struct unit_type *punittype=get_unit_type(punit->type);
+
+  if (pcity) {
+    /* rest in city until the hitpoints are recovered */
+    do {
+    flag = FALSE;
+    res=ai_military_findvictim(pplayer, punit, &dest_x, &dest_y);
+    if ((dest_x == punit->x && dest_y == punit->y) || (res != 99998)) {
+      /* nothing to kill and no huts to find, so wait to recover all the 
hitpoints */
+    } else { /* goto does NOT work for fast units */
+      freelog(LOG_DEBUG, "%s's %s at (%d, %d) bashing (%d, %d) while 
recovering hit points.",
+              pplayer->name, unit_type(punit)->name,
+              punit->x, punit->y, dest_x, dest_y);
+      handle_unit_move_request(punit, dest_x, dest_y, FALSE, FALSE);
+      punit = find_unit_by_id(id);
+      if (punit) flag = punit->moves_left > 0; else flag = FALSE;
+    }
+    ct--; /* infinite loops from railroads must be stopped */
+    } while (flag && ct > 0); /* want units to attack multiple times */
+
+    if (punit)
+      freelog(LOG_DEBUG, "%s's %s(%d) at (%d, %d) recovering hit points.",
+              pplayer->name, unit_type(punit)->name, punit->id, punit->x, 
punit->y);
+
+  } else {
+    /* goto to nearest city to recover hit points */
+    /* just before, check to see if we can occupy at enemy city undefended */
+    flag = FALSE;
+    res=ai_military_findvictim(pplayer, punit, &dest_x, &dest_y);
+    if (res == 99999) {
+      /* we find and undefended city near us, occupy!!! */
+      freelog(LOG_DEBUG, "%s's %s at (%d, %d) occuping (%d, %d) while trying 
to recover hit points.",
+              pplayer->name, unit_type(punit)->name,
+              punit->x, punit->y, dest_x, dest_y);
+      handle_unit_move_request(punit, dest_x, dest_y, FALSE, FALSE);
+      punit = find_unit_by_id(id);
+      return;
+    }
+
+    /* find city to stay and wait*/
+    res = -1;
+    if (is_sailing_unit(punit)) {
+      if (find_nearest_friendly_port(punit)) {
+        res=do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
+      }
+    } else {
+      if (find_nearest_friendly_city(punit)) {
+        res=do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
+      }
+    }
+    punit = find_unit_by_id(id);
+    if (punit) {
+      if ((res != GR_FAILED) || (res == -1)) {
+        freelog(LOG_DEBUG, "%s's %s(%d) at (%d, %d) failed to go to recover 
hit points.",
+                pplayer->name, unit_type(punit)->name, punit->id, punit->x, 
punit->y);
+      } else {
+        freelog(LOG_DEBUG, "%s's %s(%d) at (%d, %d) going to (%d, %d) to 
recover hit points.",
+                pplayer->name, unit_type(punit)->name, punit->id, punit->x, 
punit->y, punit->goto_dest_x, punit->goto_dest_y);
+      }
+    } else {
+      freelog(LOG_DEBUG, "%s's unit (%d) die trying to recover hit points.",
+              pplayer->name, id);
+    }
+  }
+
+  /* is the unit damaged?, if true recover hit points, if not idle */
+  if (punit) {
+    if (punit->hp == punittype->hp) {
+      punit->ai.ai_role = AIUNIT_NONE;
+      return;
+    }
+  }
+}
+
 /**************************************************************************
 decides what to do with a military unit.
 **************************************************************************/
@@ -2162,7 +2294,12 @@
   if (punit->activity != ACTIVITY_IDLE)
     handle_unit_activity_request(punit, ACTIVITY_IDLE);
 
+  /* prevent losing the long term objective of recovering hit points */
+  if(punit->ai.ai_role == AIUNIT_RECOVER_HIT_POINTS) {
+  } else {
   punit->ai.ai_role = AIUNIT_NONE;
+  };
+
   /* was getting a bad bug where a settlers caused a defender to leave home */
   /* and then all other supported units went on DEFEND_HOME/goto */
   ai_military_findjob(pplayer, punit);
@@ -2205,6 +2342,9 @@
   case AIUNIT_EXPLORE:
     ai_manage_explorer(punit);
     break;
+  case AIUNIT_RECOVER_HIT_POINTS:
+    ai_recover_hit_points(pplayer, punit);
+    break;
   default:
     abort();
   }
diff -Nur -b -Xfreeciv-cvs/diff_ignore freeciv-cvs/common/unit.h 
freeciv-mod1/common/unit.h
--- freeciv-cvs/common/unit.h   Sat Apr 13 08:15:29 2002
+++ freeciv-mod1/common/unit.h  Mon Jul 29 11:49:52 2002
@@ -51,7 +51,7 @@
 enum ai_unit_task { AIUNIT_NONE, AIUNIT_AUTO_SETTLER, AIUNIT_BUILD_CITY,
                     AIUNIT_DEFEND_HOME, AIUNIT_ATTACK, AIUNIT_FORTIFY,
                     AIUNIT_RUNAWAY, AIUNIT_ESCORT, AIUNIT_EXPLORE,
-                    AIUNIT_PILLAGE };
+                    AIUNIT_PILLAGE, AIUNIT_RECOVER_HIT_POINTS };
 
 enum goto_move_restriction {
   GOTO_MOVE_ANY,

--------------080504000401000404010001--




[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] Recover Hit Points (PR#1874), Jordi Negrevernis i Font <=