Complete.Org: Mailing Lists: Archives: freeciv-ai: September 2003:
[freeciv-ai] Re: (PR#6308) Cleanup of ferry handling
Home

[freeciv-ai] Re: (PR#6308) Cleanup of ferry handling

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [freeciv-ai] Re: (PR#6308) Cleanup of ferry handling
From: "Gregory Berkolaiko" <Gregory.Berkolaiko@xxxxxxxxxxxx>
Date: Sun, 28 Sep 2003 05:06:28 -0700
Reply-to: rt@xxxxxxxxxxxxxx

On Sun, 28 Sep 2003, Gregory Berkolaiko wrote:

> I will attach a patch (in the next email) which cleans and rewrites two
> functions:  ai_manage_ferryboat and ai_military_gothere.

And the patch.

G.


? core.11877
? eee.gz
? rrr.gz
? ttt.gz
Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.297
diff -u -r1.297 aiunit.c
--- ai/aiunit.c 2003/09/28 09:33:21     1.297
+++ ai/aiunit.c 2003/09/28 11:41:24
@@ -59,8 +59,10 @@
 
 #include "aiunit.h"
 
+#define FERRY_WANTED      -1
 #define LOGLEVEL_RECOVERY LOG_DEBUG
 
+static void ai_manage_unit(struct player *pplayer, struct unit *punit);
 static void ai_manage_military(struct player *pplayer,struct unit *punit);
 static void ai_manage_caravan(struct player *pplayer, struct unit *punit);
 static void ai_manage_barbarian_leader(struct player *pplayer,
@@ -1292,118 +1294,167 @@
   /* What if we have a bodyguard, but don't need one? */
 }
 
-/**************************************************************************
-  Return values: FALSE if died or stuck, TRUE otherwise. (This function
-  is not server-side autoattack safe.)
-**************************************************************************/
-static bool ai_military_gothere(struct player *pplayer, struct unit *punit,
-                                int dest_x, int dest_y)
+#define LOGLEVEL_GOTHERE LOG_NORMAL
+/****************************************************************************
+  Return values: TRUE if got to or next to our destination, FALSE otherwise. 
+
+  TODO: A big one is rendez-vous points.  When this is implemented, we won't
+  have to be at the coast to ask for a boat to come to us.
+****************************************************************************/
+bool ai_military_gothere(struct player *pplayer, struct unit *punit,
+                         int dest_x, int dest_y)
 {
-  int id, x, y, boatid = 0, bx = -1, by = -1;
-  struct unit *ferryboat = NULL;
-  struct unit *def;
-  struct tile *ptile;
-  bool boat_arrived;
-
   CHECK_UNIT(punit);
-
-  id = punit->id; x = punit->x; y = punit->y;
 
-  if (same_pos(dest_x, dest_y, x, y)) {
+  if (same_pos(dest_x, dest_y, punit->x, punit->y)) {
     /* Nowhere to go */
-    return FALSE;
-  }
-
-  if (is_ground_unit(punit)) { 
-    boatid = find_boat(pplayer, &bx, &by, 2);
-    /* NB: ferryboat is set only if the boat is where we are */
-    ferryboat = unit_list_find(&(map_get_tile(x, y)->units), boatid);
+    return TRUE;
   }
 
   /* See if we need a bodyguard at our destination */
+  /* FIXME: If bodyguard is _really_ necessary, don't go anywhere */
   ai_gothere_bodyguard(punit, dest_x, dest_y);
-  
-  if (!goto_is_sane(punit, dest_x, dest_y, TRUE) 
-      || (ferryboat && goto_is_sane(ferryboat, dest_x, dest_y, TRUE))) {
+
+  /* If we can, we will walk, take boat only if necessary */
+  if (punit->transported_by > 0 
+      || !goto_is_sane(punit, dest_x, dest_y, TRUE)) {
+    int boatid = punit->transported_by;
+    struct unit *ferryboat = NULL;
+
+    UNIT_LOG(LOGLEVEL_GOTHERE, punit, "will have to go to (%d,%d) by boat",
+             dest_x, dest_y);
+
+    if (boatid <= 0) {
+      int bx, by;
+      boatid = find_boat(pplayer, &bx, &by, 2);
+    } 
+    ferryboat = find_unit_by_id(boatid);
+
+    if (!ferryboat) {
+      UNIT_LOG(LOGLEVEL_GOTHERE, punit, "No boat found.");
+      if (is_at_coast(punit->x, punit->y)) {
+        punit->ai.ferryboat = FERRY_WANTED;
+      }
+      return FALSE;
+    } else {
+      UNIT_LOG(LOGLEVEL_GOTHERE, punit, "Found boat at (%d,%d)",
+               ferryboat->x, ferryboat->y);
+    }
+
     punit->ai.ferryboat = boatid;
-    UNIT_LOG(LOG_DEBUG, punit, "Looking for boat[%d].", boatid);
-    if (boatid > 0 && !same_pos(x, y, bx, by)) {
-      /* Go to the boat */
+    if (!same_pos(punit->x, punit->y, ferryboat->x, ferryboat->y)
+        && (!is_at_coast(punit->x, punit->y) 
+            || is_tiles_adjacent(punit->x, punit->y, 
+                                 ferryboat->x, ferryboat->y))) {
+      /* Go to the boat only if it cannot reach us or it's parked 
+       * next to us.  Otherwise just wait (boats are normally faster) */
+      /* FIXME: agree on a rendez-vous point */
       /* FIXME: this can lose bodyguard */
-      if (!ai_unit_goto(punit, bx, by)) {
+      UNIT_LOG(LOGLEVEL_GOTHERE, punit, "going to boat[%d](%d,%d).", boatid,
+               ferryboat->x, ferryboat->y);
+      if (!ai_unit_goto(punit, ferryboat->x, ferryboat->y)) { 
         /* Died. */
         return FALSE;
       }
+    }
+    
+    if (!same_pos(punit->x, punit->y, ferryboat->x, ferryboat->y)) {
+      /* Didn't get to the boat */
+      if (is_at_coast(punit->x, punit->y)) {
+        /* At least got to the coast, wave to the boats! */
+        UNIT_LOG(LOGLEVEL_GOTHERE, punit, "asking a boat to come nearer");
+        punit->ai.ferryboat = FERRY_WANTED;
+      }
+      return FALSE;
     }
-    ptile = map_get_tile(punit->x, punit->y);
-    ferryboat = unit_list_find(&ptile->units, punit->ai.ferryboat);
 
-    if (ferryboat && (ferryboat->ai.passenger == 0 
-                      || ferryboat->ai.passenger == punit->id)) {
-      int boat_x, boat_y;
+    /* Check if we are the passenger-in-charge */
+    if (ferryboat->ai.passenger == 0
+        || ferryboat->ai.passenger == punit->id) {
+      struct tile *ptile;
+      int beach_x, beach_y;     /* Destination for the boat */
+      struct tile *dest_tile = map_get_tile(dest_x, dest_y);
+      struct unit *def;
 
-      UNIT_LOG(LOG_DEBUG, punit, "Found boat[%d], going (%d,%d)",
+      UNIT_LOG(LOGLEVEL_GOTHERE, punit, "got boat[%d], going (%d,%d)",
                ferryboat->id, dest_x, dest_y);
       handle_unit_activity_request(punit, ACTIVITY_SENTRY);
       ferryboat->ai.passenger = punit->id;
 
-      /* Last ingredient: a beachhead. */
-      if (find_beachhead(punit, dest_x, dest_y, &boat_x, &boat_y)) {
-        UNIT_LOG(LOG_DEBUG, punit, "Found beachhead (%d,%d), all aboard", 
-                 boat_x, boat_y);
-       set_goto_dest(ferryboat, boat_x, boat_y);
-       set_goto_dest(punit, dest_x, dest_y);
-        unit_list_iterate(ptile->units, mypass) {
-          if (mypass->ai.ferryboat == ferryboat->id
-              && punit->owner == mypass->owner) {
-            handle_unit_activity_request(mypass, ACTIVITY_SENTRY);
-            def = unit_list_find(&ptile->units, mypass->ai.bodyguard);
-            if (def) {
-              handle_unit_activity_request(def, ACTIVITY_SENTRY);
-            }
-          }
-        } unit_list_iterate_end; /* passengers are safely stowed away */
-        if (!ai_unit_goto(ferryboat, dest_x, dest_y)) {
-          return FALSE; /* died */
+      /* If the location is not accessible directly from sea
+       * or is defended and we are not marines, we will need a 
+       * landing beach */
+      if (!is_at_coast(dest_x, dest_y)
+          ||((is_non_allied_city_tile(dest_tile, pplayer) 
+              || is_non_allied_unit_tile(dest_tile, pplayer))
+             && !unit_flag(punit, F_MARINES))) {
+        if (!find_beachhead(punit, dest_x, dest_y, &beach_x, &beach_y)) {
+          /* Nowhere to go */
+          return FALSE;
         }
+        UNIT_LOG(LOGLEVEL_GOTHERE, punit, 
+                 "Found beachhead (%d,%d)", beach_x, beach_y);
+      } else {
+        beach_x = dest_x;
+        beach_y = dest_y;
       }
-    } 
-  }
 
-  if (ferryboat && is_goto_dest_set(ferryboat)) {
-    /* we are on a ferry! did we arrive? */
-    boat_arrived = same_pos(ferryboat->x, ferryboat->y,
-                            goto_dest_x(ferryboat), goto_dest_y(ferryboat))
-      || is_tiles_adjacent(ferryboat->x, ferryboat->y,
-                           goto_dest_x(ferryboat), goto_dest_y(ferryboat));
-  } else {
-    boat_arrived = FALSE;
-  }
+      UNIT_LOG(LOGLEVEL_GOTHERE, punit, "All aboard!");
+      set_goto_dest(ferryboat, beach_x, beach_y);
+      set_goto_dest(punit, dest_x, dest_y);
+      /* Sentry the passengers */
+      ptile = map_get_tile(punit->x, punit->y);
+      unit_list_iterate(ptile->units, mypass) {
+        if (mypass->ai.ferryboat == ferryboat->id
+            && punit->owner == mypass->owner) {
+          handle_unit_activity_request(mypass, ACTIVITY_SENTRY);
+          def = unit_list_find(&ptile->units, mypass->ai.bodyguard);
+          if (def) {
+            handle_unit_activity_request(def, ACTIVITY_SENTRY);
+          }
+        }
+      } unit_list_iterate_end;
 
-  if (boat_arrived) {
+      if (!ai_unit_goto(ferryboat, beach_x, beach_y)) {
+        /* died */
+        return FALSE;
+      }
+      if (!is_tiles_adjacent(ferryboat->x, ferryboat->y, beach_x, beach_y)
+          && !same_pos(ferryboat->x, ferryboat->y, beach_x, beach_y)) {
+        /* We are in still transit */
+        return FALSE;
+      }
+    } else {
+      /* Waiting for the boss to load and move us */
+      UNIT_LOG(LOGLEVEL_GOTHERE, punit, "Cannot command boat [%d]", 
+               ferryboat->id);
+      return FALSE;
+    }
+
+    UNIT_LOG(LOGLEVEL_GOTHERE, punit, "Our boat has arrived");
     handle_unit_activity_request(punit, ACTIVITY_IDLE);
-    UNIT_LOG(LOG_DEBUG, punit, "Our boat has arrived");
   }
 
   /* Go where we should be going if we can, and are at our destination 
    * if we are on a ferry */
-  if (goto_is_sane(punit, dest_x, dest_y, TRUE) && punit->moves_left > 0
-      && (!ferryboat || boat_arrived)) {
+  if (goto_is_sane(punit, dest_x, dest_y, TRUE) && punit->moves_left > 0) {
     set_goto_dest(punit, dest_x, dest_y);
-    UNIT_LOG(LOG_DEBUG, punit, "Attempt to walk to (%d,%d)", dest_x, dest_y);
+    UNIT_LOG(LOGLEVEL_GOTHERE, punit, "Walking to (%d,%d)", dest_x, dest_y);
     if (!ai_unit_goto(punit, dest_x, dest_y)) {
       /* died */
       return FALSE;
     }
     /* liable to bump into someone that will kill us.  Should avoid? */
   } else {
-    UNIT_LOG(LOG_DEBUG, punit, "Not moving");
+    UNIT_LOG(LOGLEVEL_GOTHERE, punit, "Not moving");
+    return FALSE;
   }
   
   /* Dead unit shouldn't reach this point */
   CHECK_UNIT(punit);
   
-  return (!same_pos(punit->x, punit->y, x, y));
+  return (same_pos(punit->x, punit->y, dest_x, dest_y) 
+          || is_tiles_adjacent(punit->x, punit->y, dest_x, dest_y));
 }
 
 /*************************************************************************
@@ -2249,32 +2300,28 @@
     /* Then find enemies the hard way */
     find_something_to_kill(pplayer, punit, &dest_x, &dest_y);
     if (!same_pos(punit->x, punit->y, dest_x, dest_y)) {
-     int repeat;
-
-     for(repeat = 0; repeat < 2; repeat++) {
 
       if (!is_tiles_adjacent(punit->x, punit->y, dest_x, dest_y)
-          || !can_unit_attack_tile(punit, dest_x, dest_y)
-          || (could_unit_move_to_tile(punit, dest_x, dest_y) == 0)) {
-        /* Can't attack or move usually means we are adjacent but
-         * on a ferry. This fixes the problem (usually). */
+          || !can_unit_attack_tile(punit, dest_x, dest_y)) {
+        /* Adjacent and can't attack usually means we are not marines
+         * and on a ferry. This fixes the problem (usually). */
         UNIT_LOG(LOG_DEBUG, punit, "mil att gothere -> (%d,%d)", 
                  dest_x, dest_y);
         if (!ai_military_gothere(pplayer, punit, dest_x, dest_y)) {
           /* Died or got stuck */
           return;
         }
-      } else {
-        /* Close combat. fstk sometimes want us to attack an adjacent
-         * enemy that rampage wouldn't */
-        UNIT_LOG(LOG_DEBUG, punit, "mil att bash -> %d, %d", dest_x, dest_y);
-        if (!ai_unit_attack(punit, dest_x, dest_y)) {
-          /* Died */
+        /* Must be adjacent now. */
+      }
+      
+      /* Close combat. fstk sometimes want us to attack an adjacent
+       * enemy that rampage wouldn't */
+      UNIT_LOG(LOG_DEBUG, punit, "mil att bash -> %d, %d", dest_x, dest_y);
+      if (!ai_unit_attack(punit, dest_x, dest_y)) {
+        /* Died */
           return;
-        }
       }
 
-     } /* for-loop */
     } else {
       /* FIXME: This happens a bit too often! */
       UNIT_LOG(LOG_DEBUG, punit, "fstk didn't find us a worthy target!");
@@ -2406,164 +2453,168 @@
   }
 }
 
-/**************************************************************************
-This seems to manage the ferryboat. When it carries units on their way
-to invade something, it goes there. If it carries other units, it returns home.
-When empty, it tries to find some units to carry or goes home or explores.
-Military units handled by ai_manage_military()
-**************************************************************************/
+#define LOGLEVEL_FERRY LOG_NORMAL
+/****************************************************************************
+  It's about 12 feet square and has a capacity of almost 1000 pounds.
+  It is well constructed of teak, and looks seaworthy.
+
+  Manage ferryboat.  If there is a passenger-in-charge, we let it drive the 
+  boat.  If there isn't, appoint one from those we have on board.
+
+  If there is no one aboard, look for potential cargo.  If none found, 
+  explore and then go to the nearest port.
+****************************************************************************/
 static void ai_manage_ferryboat(struct player *pplayer, struct unit *punit)
-{ /* It's about 12 feet square and has a capacity of almost 1000 pounds.
-     It is well constructed of teak, and looks seaworthy. */
+{
   struct city *pcity;
-  struct city *port = NULL;
-  struct unit *bodyguard = NULL;
-  struct unit_type *punittype = get_unit_type(punit->type);
-  int best = 4 * punittype->move_rate, x = punit->x, y = punit->y;
-  int n = 0, p = 0;
+  struct tile *ptile = map_get_tile(punit->x, punit->y);
 
   CHECK_UNIT(punit);
-
-  if (!unit_list_find(&map_get_tile(punit->x, punit->y)->units, 
punit->ai.passenger)) {
-    punit->ai.passenger = 0;
-  }
-
-  unit_list_iterate(map_get_tile(punit->x, punit->y)->units, aunit)
-    if (punit->owner != aunit->owner) {
-      continue;
-    }
-    if (aunit->ai.ferryboat == punit->id) {
-      if (punit->ai.passenger == 0) {
-        punit->ai.passenger = aunit->id; /* oops */
-      }
-      if (is_military_unit(aunit) && punit->ai.bodyguard == BODYGUARD_NONE) {
-        /* Acquire some protection as we deliver an invasion army */
-        UNIT_LOG(LOG_DEBUG, punit, "shout out for a bodyguard");
-        punit->ai.bodyguard = BODYGUARD_WANTED;
-      }
-      p++;
-      bodyguard = unit_list_find(&map_get_tile(punit->x, punit->y)->units, 
aunit->ai.bodyguard);
-      if (is_goto_dest_set(aunit)) { /* HACK */
-       pcity = map_get_city(goto_dest_x(aunit), goto_dest_y(aunit));
-      } else {
-       pcity = NULL;
-      }
-      if (aunit->ai.bodyguard == BODYGUARD_NONE || bodyguard ||
-         (pcity && pcity->ai.invasion >= 2)) {
-       if (pcity) {
-         UNIT_LOG(LOG_DEBUG, punit, "Ferrying to %s to %s, invasion = %d, body 
= %d",
-                 unit_name(aunit->type), pcity->name,
-                 pcity->ai.invasion, aunit->ai.bodyguard);
-       }
-        n++;
-        handle_unit_activity_request(aunit, ACTIVITY_SENTRY);
-        if (bodyguard) {
-          handle_unit_activity_request(bodyguard, ACTIVITY_SENTRY);
-        }
-      }
-    }
-  unit_list_iterate_end;
 
-  /* we try to recover hitpoints if we are in a city, before we leave */
-  if (punit->hp < punittype->hp 
+  /* Try to recover hitpoints if we are in a city, before we do anything */
+  if (punit->hp < unit_type(punit)->hp 
       && (pcity = map_get_city(punit->x, punit->y))) {
-    /* Don't do anything, just wait in the city */
-    UNIT_LOG(LOG_DEBUG, punit, "waiting in %s to recover hitpoints "
-            "before ferrying", pcity->name);
+    UNIT_LOG(LOGLEVEL_FERRY, punit, "waiting in %s to recover hitpoints", 
+             pcity->name);
     return;
   }
 
-  if (p != 0) {
-    UNIT_LOG(LOG_DEBUG, punit, "in manage_ferryboat p=%d, n=%d", p, n);
-    if (is_goto_dest_set(punit) && punit->moves_left > 0 && n != 0) {
-      (void) ai_unit_gothere(punit);
-    } else if (n == 0 && !map_get_city(punit->x, punit->y)) { /* rest in a 
city, for unhap */
-      port = find_nearest_safe_city(punit);
-      if (port && !ai_unit_goto(punit, port->x, port->y)) {
-        return; /* oops! */
-      }
-      send_unit_info(pplayer, punit); /* to get the crosshairs right -- Syela 
*/
-    } else {
-      UNIT_LOG(LOG_DEBUG, punit, "Ferryboat %d@(%d,%d) stalling.",
-                   punit->id, punit->x, punit->y);
-      if(is_barbarian(pplayer)) /* just in case */
-        (void) ai_manage_explorer(punit);
-    }
+  /* Check if we are an empty barbarian boat and so not needed */
+  if (is_barbarian(pplayer) 
+      && unit_list_size(&ptile->units) < 2 ) {
+    wipe_unit(punit);
     return;
   }
 
-  /* check if barbarian boat is empty and so not needed - the crew has landed 
*/
-  if( is_barbarian(pplayer) && unit_list_size(&map_get_tile(punit->x, 
punit->y)->units)<2 ) {
-    wipe_unit(punit);
-    return;
+  /* Do we have the passenger-in-charge on board? */
+  if (punit->ai.passenger != 0 
+      && !unit_list_find(&ptile->units, punit->ai.passenger)) {
+    UNIT_LOG(LOGLEVEL_FERRY, punit, "lost psngr-in-charge [%d], resetting",
+             punit->ai.passenger);
+    punit->ai.passenger = 0;
   }
 
-  /* ok, not carrying anyone, even the ferryman */
-  punit->ai.passenger = 0;
-  UNIT_LOG(LOG_DEBUG, punit, "Ferryboat is lonely.");
-  handle_unit_activity_request(punit, ACTIVITY_IDLE);
-
-  /* Release bodyguard and let it roam */
-  ai_unit_new_role(punit, AIUNIT_NONE, -1, -1);
-  if (bodyguard) {
-    ai_military_attack(pplayer, bodyguard);
+  if (punit->ai.passenger == 0) {
+    struct unit *bodyguard = NULL;
+    
+    /* Try to select passanger-in-charge from among their passengers */
+    unit_list_iterate(ptile->units, aunit) {
+      if (aunit->ai.ferryboat != punit->id) {
+        continue;
+      }
+      
+      if (aunit->ai.ai_role != AIUNIT_ESCORT) {
+        /* Bodyguards shouldn't be in charge of boats... */
+        UNIT_LOG(LOGLEVEL_FERRY, punit, 
+                 "appointed %s[%d] our psngr-in-charge",
+                 unit_type(aunit)->name, aunit->id);
+        punit->ai.passenger = aunit->id;
+        break;
+      } else {
+        bodyguard = aunit;
+      }
+    } unit_list_iterate_end;
+    
+    if (punit->ai.passenger == 0 && bodyguard) {
+      UNIT_LOG(LOGLEVEL_FERRY, punit, 
+               "has to take %s[%d] as our psngr-in-charge",
+               unit_type(bodyguard)->name, bodyguard->id);
+      punit->ai.passenger = bodyguard->id;
+    }
   }
 
-  if (IS_ATTACKER(punit)) {
-    if (punit->moves_left > 0) ai_manage_military(pplayer, punit);
-    return;
-  } /* AI used to build frigates to attack and then use them as ferries -- 
Syela */
+  if (punit->ai.passenger != 0) {
+    int bossid = punit->ai.passenger;    /* For reference */
+    struct unit *boss = find_unit_by_id(bossid);
+    int id = punit->id;                  /* To check if survived */
+    int moves_left = punit->moves_left;  /* Loop prevention */
+    
+    assert(boss);
 
-  /*** Find work ***/
-  CHECK_UNIT(punit);
+    if (unit_flag(boss, F_SETTLERS) || unit_flag(boss, F_CITIES)) {
+      /* Temporary hack: settlers all go in the end, forcing them 
+       * earlier might mean uninitialised cache, so just wait for them */
+      return;
+    }
 
-  generate_warmap(map_get_city(punit->x, punit->y), punit);
-  p = 0; /* yes, I know it's already zero. -- Syela */
-  best = 9999;
-  x = -1; y = -1;
-  unit_list_iterate(pplayer->units, aunit) {
-    if (aunit->ai.ferryboat != 0
-       && WARMAP_SEACOST(aunit->x, aunit->y) < best
-       && ground_unit_transporter_capacity(aunit->x, aunit->y, pplayer) <= 0
-        && is_at_coast(aunit->x, aunit->y)) {
-      UNIT_LOG(LOG_DEBUG, punit, "Found a potential pickup %d@(%d, %d)",
-                   aunit->id, aunit->x, aunit->y);
-      x = aunit->x;
-      y = aunit->y;
-      best = WARMAP_SEACOST(x, y);
-    }
-    if (is_sailing_unit(aunit)
-       && is_ocean(map_get_terrain(aunit->x, aunit->y))) {
-      p++;
+    UNIT_LOG(LOGLEVEL_FERRY, punit, "passing control to %s[%d]",
+             unit_type(boss)->name, bossid);
+    ai_manage_unit(pplayer, boss);
+    
+    if (!find_unit_by_id(id) || punit->moves_left < moves_left) {
+      return;
     }
-  } unit_list_iterate_end;
-  if (best < 4 * unit_type(punit)->move_rate) {
-    /* Pickup is within 4 turns to grab, so move it! */
-    set_goto_dest(punit, x, y);
-    UNIT_LOG(LOG_DEBUG, punit, "Found a friend and going to him @(%d, %d)",
-             x, y);
-    (void) ai_unit_gothere(punit);
-    return;
-  }
+    /* We are alive and didn't spend any moves.  We are stuck! 
+     * NB: it can be that punit->ai.passenger has changed by now,
+     * for example if the boss has landed */
+    UNIT_LOG(LOGLEVEL_FERRY, punit, "taking control back from [%d]", 
+             bossid);
 
-  /* do cool stuff here */
-  CHECK_UNIT(punit);
+  } else {
+    /* Not carrying anyone, even the ferryman */
 
-  if (punit->moves_left == 0) return;
-  pcity = find_city_by_id(punit->homecity);
-  if (pcity) {
-    if (!ai_handicap(pplayer, H_TARGETS) ||
-        unit_move_turns(punit, pcity->x, pcity->y) < p) {
-      set_goto_dest(punit, pcity->x, pcity->y);
-      UNIT_LOG(LOG_DEBUG, punit, "No friends.  Going home.");
-      (void) ai_unit_gothere(punit);
+    /* Path-finding stuff */
+    struct pf_map *map;
+    struct pf_parameter parameter;
+
+    if (IS_ATTACKER(punit) && punit->moves_left > 0) {
+      /* AI used to build frigates to attack and then use them as ferries 
+       * -- Syela */
+      ai_manage_military(pplayer, punit);
       return;
     }
+
+    UNIT_LOG(LOGLEVEL_FERRY, punit, "Ferryboat is looking for cargo.");
+    handle_unit_activity_request(punit, ACTIVITY_IDLE);
+    CHECK_UNIT(punit);
+    
+    pft_fill_default_parameter(&parameter);
+    pft_fill_unit_overlap_param(&parameter, punit);
+    /* We are looking for our units, no need to look into the unknown */
+    parameter.get_TB = no_fights_or_unknown;
+    parameter.omniscience = FALSE;
+    
+    map = pf_create_map(&parameter);
+    while (pf_next(map)) {
+      struct pf_position pos;
+      
+      pf_next_get_position(map, &pos);
+
+      unit_list_iterate(map_get_tile(pos.x, pos.y)->units, aunit) {
+        if (aunit->ai.ferryboat == FERRY_WANTED) {
+          UNIT_LOG(LOGLEVEL_FERRY, punit, 
+                   "Found a potential cargo %s[%d](%d,%d), going there",
+                   unit_type(aunit)->name, aunit->id, aunit->x, aunit->y);
+          set_goto_dest(punit, aunit->x, aunit->y);
+          aunit->ai.ferryboat = punit->id;
+          pf_destroy_map(map);
+          /* FIXME: lift the path off the map */
+          (void) ai_unit_gothere(punit);
+          return;
+        }
+      } unit_list_iterate_end;
+    }
+
+    pf_destroy_map(map);
   }
-  if (is_ocean(map_get_terrain(punit->x, punit->y))) {
-    /* thanks, Tony */
-    (void) ai_manage_explorer(punit);
+    
+  CHECK_UNIT(punit);
+  
+  if (punit->moves_left == 0 
+      || !is_ocean(map_get_terrain(punit->x, punit->y))) {
+    return;
   }
+  
+  (void) ai_manage_explorer(punit);
+  if (punit->moves_left > 0) {
+    struct city *pcity = find_nearest_safe_city(punit);
+    if (pcity) {
+      set_goto_dest(punit, pcity->x, pcity->y);
+        UNIT_LOG(LOGLEVEL_FERRY, punit, "No work, going home");
+        (void) ai_unit_gothere(punit);
+    }
+  }
+ 
   return;
 }
 
Index: ai/aiunit.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.h,v
retrieving revision 1.49
diff -u -r1.49 aiunit.h
--- ai/aiunit.h 2003/09/27 11:22:40     1.49
+++ ai/aiunit.h 2003/09/28 11:41:24
@@ -46,6 +46,8 @@
 
 extern Unit_Type_id simple_ai_types[U_LAST];
 
+bool ai_military_gothere(struct player *pplayer, struct unit *punit,
+                         int dest_x, int dest_y);
 void ai_manage_units(struct player *pplayer); 
 int could_unit_move_to_tile(struct unit *punit, int dest_x, int dest_y);
 int look_for_charge(struct player *pplayer, struct unit *punit,
Index: server/settlers.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/settlers.c,v
retrieving revision 1.173
diff -u -r1.173 settlers.c
--- server/settlers.c   2003/09/23 15:59:05     1.173
+++ server/settlers.c   2003/09/28 11:41:25
@@ -54,6 +54,8 @@
 BV_DEFINE(enemy_mask, MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS);
 static enemy_mask enemies[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS];
 
+static void auto_settler_findwork(struct player *pplayer, 
+                                  struct unit *punit);
 static void auto_settlers_player(struct player *pplayer); 
 static bool is_already_assigned(struct unit *myunit, struct player *pplayer,
                                int x, int y);
@@ -1187,6 +1189,7 @@
   return best_newv;
 }
 
+#if 0
 /**************************************************************************
   Handles GOTO for settlers. Only ever used in auto_settler_findwork 
   below.
@@ -1255,6 +1258,7 @@
 
   return TRUE;
 }
+#endif /* ifdef 0 */
 
 /**************************************************************************
   find some work for the settler
@@ -1311,8 +1315,8 @@
   }
 
   /* We've now worked out what to do; go to it! */
-  if (!ai_gothere(punit, gx, gy, ferryboat)) {
-    /* died */
+  if (!ai_military_gothere(pplayer, punit, gx, gy)) {
+    /* Died or got stuck */
     return;
   }
 
@@ -1384,7 +1388,7 @@
   freelog(LOG_DEBUG, "Warmth = %d, game.globalwarming=%d",
          pplayer->ai.warmth, game.globalwarming);
   unit_list_iterate(pplayer->units, punit) {
-    if (punit->ai.control
+    if ((punit->ai.control || pplayer->ai.control)
        && (unit_flag(punit, F_SETTLERS)
            || unit_flag(punit, F_CITIES))) {
       freelog(LOG_DEBUG, "%s's settler at (%d, %d) is ai controlled.",

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