Complete.Org: Mailing Lists: Archives: freeciv-ai: August 2004:
[freeciv-ai] Re: Inprovements in settler.c
Home

[freeciv-ai] Re: Inprovements in settler.c

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-ai@xxxxxxxxxxx
Subject: [freeciv-ai] Re: Inprovements in settler.c
From: Jordi Negrevernis i Font <jorneg@xxxxxxxxxxx>
Date: Tue, 17 Aug 2004 01:02:00 +0200


   New version.

Will this enter in CVS? If yes, i can extend to check for national border, and maybe distance to enemies...

Also, while debugging i notice that the settler or enginiers can often do nothing - debug message 'could not go to ...' because they select to improve terrain a tile in a diferent continent!!!!

Also, while looking to ai_manage_hitpoint_recovery - or something like this - the damaged units that don't find a city to go to rest, doesn't look for a hill or montain to cure. Can i make a patch to use the function 'find_defending_spot' of the patch for this, or this behaviour is intentional?

Per Inge Mathisen wrote:

On Thu, 12 Aug 2004, Jordi Negrevernis i Font wrote:
 Hi, i'm trying to improve the settler code by using the bodyguards
with settlers, etc...

Cool!

 This the first attempt, and can be greatly improved.

Yes. I am not sure if I understand it. You use enemies_at() to figure out
if there are enemies at the place we are going to (or where we are), and
then request bodyguards. So far, so good. However, then you have another
check using enemies_at(), and if we found enemies now, we don't go. So why
did we acquire a bodyguard, if we aren't going anyway?
True, I've changed the behaviour. Now if we have a bodyguard don't do away.

 While looking at the code i see that you use code like this:

if (punit->ai.charge != BODYGUARD_NONE) { /* I am a bodyguard */

 Why you don't check to see if its equal to BODYGUARD_WANTED, or just
check for a value > 0.

Checks that see if we are a bodyguard should check punit->ai.charge >
BODYGUARD_NONE, yes.

+  /* If we carried a bodyguard just use it!.
+   *  Its the new defender of the city */
+  if (bodyguard > 0) {
+    if (pbody) {
+      if (ai_unit_make_homecity(pbody, pcity)) {
+       ai_unit_new_role(pbody, AIUNIT_ESCORT, -1, -1);
+      }
+    }
+  }

The first check is unnecessary. Also, you might want to check if the city
has enough shield surplus at this point to upkeep the unit.
   Ok.

diff -u -r -Xfreeciv-cvs-Aug-06/diff_ignore freeciv-cvs-Aug-06/ai/aitools.c 
freeciv-cvs-Aug-06-settler/ai/aitools.c
--- freeciv-cvs-Aug-06/ai/aitools.c     2004-08-06 07:14:59.000000000 +0200
+++ freeciv-cvs-Aug-06-settler/ai/aitools.c     2004-08-11 01:39:59.000000000 
+0200
@@ -422,7 +422,7 @@
   bodyguard has not. This is an ai_unit_* auxiliary function, do not use
   elsewhere.
 **************************************************************************/
-static void ai_unit_bodyguard_move(int unitid, int x, int y)
+void ai_unit_bodyguard_move(int unitid, int x, int y)
 {
   struct unit *bodyguard = find_unit_by_id(unitid);
   struct unit *punit;
@@ -456,7 +456,7 @@
   Repair incompletely referenced bodyguards. When the rest of the bodyguard
   mess is cleaned up, this repairing should be replaced with an assert.
 **************************************************************************/
-static bool has_bodyguard(struct unit *punit)
+bool has_bodyguard(struct unit *punit)
 {
   struct unit *guard;
   if (punit->ai.bodyguard > BODYGUARD_NONE) {
diff -u -r -Xfreeciv-cvs-Aug-06/diff_ignore freeciv-cvs-Aug-06/ai/aitools.h 
freeciv-cvs-Aug-06-settler/ai/aitools.h
--- freeciv-cvs-Aug-06/ai/aitools.h     2004-08-06 07:14:59.000000000 +0200
+++ freeciv-cvs-Aug-06-settler/ai/aitools.h     2004-08-11 01:39:49.000000000 
+0200
@@ -52,6 +52,7 @@
 bool ai_unit_make_homecity(struct unit *punit, struct city *pcity);
 bool ai_unit_attack(struct unit *punit, int x, int y);
 bool ai_unit_move(struct unit *punit, int x, int y);
+void ai_unit_bodyguard_move(int unitid, int x, int y);

 struct city *dist_nearest_city(struct player *pplayer, int x, int y,
                                bool everywhere, bool enemy);
@@ -70,4 +71,7 @@

 bool is_player_dangerous(struct player *pplayer, struct player *aplayer);

+bool has_bodyguard(struct unit *punit);
+
+
 #endif  /* FC__AITOOLS_H */
diff -u -r -Xfreeciv-cvs-Aug-06/diff_ignore freeciv-cvs-Aug-06/ai/aiunit.c 
freeciv-cvs-Aug-06-settler/ai/aiunit.c
--- freeciv-cvs-Aug-06/ai/aiunit.c      2004-08-07 07:15:05.000000000 +0200
+++ freeciv-cvs-Aug-06-settler/ai/aiunit.c      2004-08-15 19:48:43.000000000 
+0200
@@ -881,6 +881,34 @@
 }

 /*************************************************************************
+  Tries to find a land tile adjacent to a unit to defend from an attack
+  (dest_x, dest_y).  Prefers tiles which are more defensible.
+**************************************************************************/
+bool find_defending_spot(struct unit *punit, int *x, int *y)
+{
+  int ok, best = 0;
+  enum tile_terrain_type t;
+
+  CHECK_UNIT(punit);
+
+  adjc_iterate(punit->x, punit->y, x1, y1) {
+    ok = 0;
+    t = map_get_terrain(x1, y1);
+    if (!is_ocean(t) && is_my_zoc(unit_owner(punit), x1, y1)) {
+      /* accessible tile nearby */
+      ok = get_tile_type(t)->defense_bonus;
+      if (ok > best) {
+        best = ok;
+        *x = x1;
+        *y = y1;
+      }
+    }
+  } adjc_iterate_end;
+
+  return (best > 0);
+}
+
+/*************************************************************************
   Does the unit with the id given have the flag L_DEFEND_GOOD?
 **************************************************************************/
 static bool unit_role_defender(Unit_Type_id type)
diff -u -r -Xfreeciv-cvs-Aug-06/diff_ignore freeciv-cvs-Aug-06/ai/aiunit.h 
freeciv-cvs-Aug-06-settler/ai/aiunit.h
--- freeciv-cvs-Aug-06/ai/aiunit.h      2004-08-07 07:15:05.000000000 +0200
+++ freeciv-cvs-Aug-06-settler/ai/aiunit.h      2004-08-15 19:48:31.000000000 
+0200
@@ -66,6 +66,7 @@
                             int *x, int *y);
 bool find_beachhead(struct unit *punit, int dest_x, int dest_y,
                     int *x, int *y);
+bool find_defending_spot(struct unit *punit, int *x, int *y);

 int build_cost_balanced(Unit_Type_id type);
 int unittype_att_rating(Unit_Type_id type, int veteran,
diff -u -r -Xfreeciv-cvs-Aug-06/diff_ignore 
freeciv-cvs-Aug-06/server/settlers.c 
freeciv-cvs-Aug-06-settler/server/settlers.c
--- freeciv-cvs-Aug-06/server/settlers.c        2004-08-07 07:15:21.000000000 
+0200
+++ freeciv-cvs-Aug-06-settler/server/settlers.c        2004-08-15 
21:28:22.000000000 +0200
@@ -63,6 +63,8 @@
 {
   int x = punit->x, y = punit->y;
   struct city *pcity;
+  int bodyguard = punit->ai.bodyguard;
+  struct unit *pbody = find_unit_by_id(bodyguard);

   handle_unit_activity_request(punit, ACTIVITY_IDLE);

@@ -73,11 +75,19 @@
                         city_name_suggestion(pplayer, x, y));
   pcity = map_get_city(x, y);
   if (!pcity) {
-    freelog(LOG_ERROR, "%s: Failed to build city at (%d, %d)",
+    freelog(LOG_ERROR, "%s: Failed to build city at (%d, %d)",
             pplayer->name, x, y);
     return FALSE;
   }

+  /* If we carried a bodyguard just use it!.
+   *  Its the new defender of the city */
+  if (pbody) {
+    if (ai_unit_make_homecity(pbody, pcity)) {
+      ai_unit_new_role(pbody, AIUNIT_ESCORT, -1, -1);
+    }
+  }
+
   return TRUE;
 }

@@ -137,20 +147,44 @@
   Manages settlers.
 **************************************************************************/
 void ai_manage_settler(struct player *pplayer, struct unit *punit)
-{
+{ bool pos_dangerous = 0;
+#define LOG_SETTLER LOG_NORMAL
+
   punit->ai.control = TRUE;
   /* if BUILD_CITY must remain BUILD_CITY, otherwise turn into autosettler */
   if (punit->ai.ai_role == AIUNIT_NONE) {
     ai_unit_new_role(punit, AIUNIT_AUTO_SETTLER, -1, -1);
   }
+
+  /* we check for a bodyguard if our settler unit is in danger */
+
+  /* if goto is set we check for a dangerous position */
+  if (is_goto_dest_set(punit)) {
+    pos_dangerous = enemies_at(punit, goto_dest_x(punit), goto_dest_y(punit));
+  } else {
+    /* otherwise we check for the current location */
+    pos_dangerous = enemies_at(punit, punit->x, punit->y);
+  }
+
+  if (pos_dangerous > 0) {
+    if (!has_bodyguard(punit)) {
+      punit->ai.bodyguard = BODYGUARD_WANTED;
+    }
+  }
+
+  if (has_bodyguard(punit)) {
+    UNIT_LOG(LOG_SETTLER, punit, "with a bodyguard!");
+    ai_unit_bodyguard_move(punit->ai.bodyguard, punit->x, punit->y);
+  }
+
   return;
 }

 /**************************************************************************
- return 1 if there is already a unit on this square or one destined for it
+ return 1 if there is already a unit on this square or one destined for it
  (via goto)
 **************************************************************************/
-static bool is_already_assigned(struct unit *myunit, struct player *pplayer,
+static bool is_already_assigned(struct unit *myunit, struct player *pplayer,
     int x, int y)
 {
   if (same_pos(myunit->x, myunit->y, x, y)
@@ -1052,7 +1086,6 @@
 /**************************************************************************
   Find some work for our settlers and/or workers.
 **************************************************************************/
-#define LOG_SETTLER LOG_DEBUG
 static void auto_settler_findwork(struct player *pplayer, struct unit *punit)
 {
   struct cityresult result;
@@ -1080,23 +1113,38 @@
       ai_unit_new_role(punit, AIUNIT_NONE, -1, -1);
       return; /* avoid recursion at all cost */
     } else {
-      /* Go there */
-      if ((!ai_gothere(pplayer, punit, x, y) && !find_unit_by_id(sanity))
-          || punit->moves_left <= 0) {
+      if (enemies_at(punit, punit->x, punit->y) && !has_bodyguard(punit)) {
+        /* there are enemies at current location! so scatter and hide */
+        UNIT_LOG(LOG_SETTLER, punit, "enemies side by side settler!");
+        if (find_defending_spot(punit, &gx, &gy)) {
+         ai_unit_goto(punit, gx, gy);
+       }
         return;
-      }
-      if (same_pos(punit->x, punit->y, x, y)) {
-        if (!ai_do_build_city(pplayer, punit)) {
-          UNIT_LOG(LOG_ERROR, punit, "could not make city on %s",
-                   map_get_tile_info_text(punit->x, punit->y));
-          ai_unit_new_role(punit, AIUNIT_NONE, -1, -1);
-        } else {
-          return; /* We came, we saw, we built... */
-        }
       } else {
-        UNIT_LOG(LOG_SETTLER, punit, "could not go to target");
-        /* ai_unit_new_role(punit, AIUNIT_NONE, -1, -1); */
-        return;
+        if (enemies_at(punit, x, y) && !has_bodyguard(punit)) {
+          /* there are enemies at destination! */
+          UNIT_LOG(LOG_SETTLER, punit, "enemies at city founding location!");
+          return;
+       } else {
+          /* Go there */
+          if ((!ai_gothere(pplayer, punit, x, y) && !find_unit_by_id(sanity))
+              || punit->moves_left <= 0) {
+            return;
+          }
+          if (same_pos(punit->x, punit->y, x, y)) {
+            if (!ai_do_build_city(pplayer, punit)) {
+              UNIT_LOG(LOG_ERROR, punit, "could not make city on %s",
+                       map_get_tile_info_text(punit->x, punit->y));
+              ai_unit_new_role(punit, AIUNIT_NONE, -1, -1);
+            } else {
+              return; /* We came, we saw, we built... */
+            }
+          } else {
+            UNIT_LOG(LOG_SETTLER, punit, "could not go to target");
+            /* ai_unit_new_role(punit, AIUNIT_NONE, -1, -1); */
+            return;
+          }
+        }
       }
     }
   }

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