Complete.Org: Mailing Lists: Archives: freeciv-ai: August 2002:
[freeciv-ai] Re: [Freeciv-Dev] Re: Patch for units recovering hit points
Home

[freeciv-ai] Re: [Freeciv-Dev] Re: Patch for units recovering hit points

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-ai@xxxxxxxxxxx
Subject: [freeciv-ai] Re: [Freeciv-Dev] Re: Patch for units recovering hit points
From: Jordi Negrevernis i Font <jorneg@xxxxxxxxxxx>
Date: Sun, 11 Aug 2002 20:55:14 +0200


    Patch atached for yesterday's cvs.

    Now the patch also makes the ferryboats wait to recover hitpoints.

    Does not select a better tile to fortify.
 
Per I. Mathisen wrote:
On Fri, 9 Aug 2002, Jordi Negrevernis i Font wrote:
 > > Also, if a unit's in a city, it only goes after huts.
You might want to change that to also attack enemies that it really wants to
fight (> 70000?).
    Yes.

Sorry, i don't undestand fight (> 70000?) ??????!!!!!!!

Oh. I think Baumans wanted a fight only if the value of findvictim was
over 70000, but I don't think that is a good idea. If the value is > 1, a
fight is good for you.

  I'll try to implement your ideas in another modification of the patch. Anyway, i
think that you don't look at the last patch I send to the mailinglist.

If you want the patch to use the ai_unit_attac() i'll wait for the patch to go into
cvs. Any idea when?

I have already committed it to cvs. So you don't need to wait :)

Yours
Per




diff -Nur -b -Xfreeciv-cvs-Aug-10/diff_ignore freeciv-cvs-Aug-10/ai/aiunit.c 
freeciv-cvs-Aug-10-mod/ai/aiunit.c
--- freeciv-cvs-Aug-10/ai/aiunit.c      Fri Aug  9 13:33:46 2002
+++ freeciv-cvs-Aug-10-mod/ai/aiunit.c  Sun Aug 11 20:32:13 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_barrack(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);
@@ -1402,6 +1406,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))) {
@@ -1466,6 +1471,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 */
@@ -1884,6 +1895,43 @@
   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.
+  Returns TRUE with punit->goto_dest_* set or FALSE.
+  Be aware that the function destroys punit->goto_dest_*
+***********************************************************************/
+static bool find_nearest_friendly_barrack(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
@@ -2042,6 +2090,7 @@
   struct unit *bodyguard;
   int best = 4 * unit_type(punit)->move_rate, x = punit->x, y = punit->y;
   int n = 0, p = 0;
+  struct unit_type *punittype=get_unit_type(punit->type);
 
   if (!unit_list_find(&map_get_tile(punit->x, punit->y)->units, 
punit->ai.passenger))
     punit->ai.passenger = 0;
@@ -2065,6 +2114,15 @@
       }
     }
   unit_list_iterate_end;
+
+  /* we try to recover hitpoints, if we are in a city, before leave */
+  if ((punit->hp < punittype->hp) && (pcity = map_get_city(punit->x, 
punit->y))) {
+    /* don't do nothing, just wait in the city */
+    freelog(LOG_DEBUG, "Waiting in %s to recover hitpoints before ferrying to 
(%d,%d).", pcity->name,
+            punit->goto_dest_x, punit->goto_dest_y);
+    return;
+  }
+
   if (p != 0) {
     freelog(LOG_DEBUG, "%s#%d@(%d,%d), p=%d, n=%d",
                  unit_name(punit->type), punit->id, punit->x, punit->y, p, n);
@@ -2152,6 +2210,97 @@
   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_manage_hitpoint_recovery(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 ((res <= 1) || (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);
+      ai_unit_attack(punit, dest_x, dest_y);
+      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 > 1) {
+      /* we find and undefended city near us, occupy!!! */
+      /* or we find something to kill */
+      freelog(LOG_DEBUG, "%s's %s at (%d, %d) attacking (%d, %d) while trying 
to recover hit points.",
+              pplayer->name, unit_type(punit)->name,
+              punit->x, punit->y, dest_x, dest_y);
+      ai_unit_attack(punit, dest_x, dest_y);
+      punit = find_unit_by_id(id);
+      return;
+    }
+
+    /* find city to stay and go there */
+    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_barrack(punit)) {
+        res=do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
+      }
+    }
+    punit = find_unit_by_id(id);
+    if (punit) {
+      if (res == -1) {
+        freelog(LOG_DEBUG, "%s's %s(%d) at (%d, %d) failed to go to recover 
hit points, fortying.",
+                pplayer->name, unit_type(punit)->name, punit->id,
+                punit->x, punit->y);
+        /* TODO: find best tile to fortify */
+        handle_unit_activity_request(punit, ACTIVITY_FORTIFYING);
+      } 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) died trying to recover hit points.",
+              pplayer->name, id);
+    }
+  }
+
+  /* is the unit stil 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.
 **************************************************************************/
@@ -2164,7 +2313,12 @@
   if (punit->activity != ACTIVITY_IDLE)
     handle_unit_activity_request(punit, ACTIVITY_IDLE);
 
-  punit->ai.ai_role = AIUNIT_NONE;
+  /* 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);
@@ -2207,6 +2361,9 @@
   case AIUNIT_EXPLORE:
     ai_manage_explorer(punit);
     break;
+  case AIUNIT_RECOVER_HIT_POINTS:
+    ai_manage_hitpoint_recovery(pplayer, punit);
+    return;
   default:
     abort();
   }
diff -Nur -b -Xfreeciv-cvs-Aug-10/diff_ignore freeciv-cvs-Aug-10/common/unit.h 
freeciv-cvs-Aug-10-mod/common/unit.h
--- freeciv-cvs-Aug-10/common/unit.h    Wed Aug  7 13:21:49 2002
+++ freeciv-cvs-Aug-10-mod/common/unit.h        Sun Aug 11 12:00:37 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,

[Prev in Thread] Current Thread [Next in Thread]