Complete.Org: Mailing Lists: Archives: freeciv-dev: February 2003:
[Freeciv-Dev] (PR#3013) gen topol safe goto in server/AI
Home

[Freeciv-Dev] (PR#3013) gen topol safe goto in server/AI

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients:;
Subject: [Freeciv-Dev] (PR#3013) gen topol safe goto in server/AI
From: "Per I. Mathisen via RT" <rt@xxxxxxxxxxxxxx>
Date: Thu, 6 Feb 2003 15:54:34 -0800
Reply-to: rt.freeciv.org@xxxxxxxxxxxxxx

This draft stage patch implements a new goto structure for units. It both
stops usage of bad/unset goto coordinates, and also makes them gen topol
safe.

Some notable things that are changed:
  - We don't send server goto info to clients. This means clients can't
show air and connect goto destination X graphic. (These kinds of goto are
implemented in server, which is very ugly. Should be moved when new goto
code hits cvs.)
  - ai_military_findjob() now does all the job, no longer sets half a role
and has this role acted on later. That was unnecessary.
  - Now roles are restricted in what kinds of goto information they can
have, and ai_unit_new_role() sets long-term goto vars for units.

This patch needs comments on overall design.

  - Per

Index: ai/aiair.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiair.c,v
retrieving revision 1.10
diff -u -r1.10 aiair.c
--- ai/aiair.c  2003/02/02 14:57:22     1.10
+++ ai/aiair.c  2003/02/06 23:17:21
@@ -165,7 +165,7 @@
 /**********************************************************************
  * Find something to bomb
  * Air-units specific victim search
- * Returns the want for the best target, records target in goto_dest_x,y
+ * Returns the want for the best target, records target in punit->go
  * TODO: take counterattack dangers into account
  * TODO: make separate handicaps for air units seeing targets
  *       IMO should be more restrictive than general H_MAP, H_FOG
@@ -174,7 +174,8 @@
 {
   struct player *pplayer = unit_owner(punit);
   int max_dist = punit->moves_left / SINGLE_MOVE;
-  int best = 0;
+  int best_x = 0, best_y = 0, best = 0;
+  bool found_something = FALSE;
 
   if ((punit->x == x) && (punit->y == y)) {
     /* Unit is attacking from here */
@@ -208,15 +209,19 @@
        && (air_can_move_between (max_dist, x, y, x1, y1, pplayer) >= 0)){
       int new_best = ai_evaluate_tile_for_air_attack(punit, x1, y1);
       if (new_best > best) {
-       punit->goto_dest_x = x1;
-       punit->goto_dest_y = y1;
+       best_x = x1;
+       best_y = y1;
        best = new_best;
+        found_something = TRUE;
        freelog(LOG_DEBUG, "%s wants to attack tile (%d, %d)", 
                unit_type(punit)->name, x1, y1);
       }
     }
 
   } iterate_outward_end;
+  if (found_something) {
+    ai_unit_new_role(punit, AIUNIT_ATTACK, best_x, best_y);
+  }
 
   return best;
 } 
@@ -294,8 +299,6 @@
  ***********************************************************************/
 void ai_manage_airunit(struct player *pplayer, struct unit *punit)
 {
-  enum goto_result result = GR_FAILED;
-
   CHECK_UNIT(punit);
 
   if (!is_airunit_refuel_point(punit->x, punit->y, 
@@ -303,24 +306,27 @@
     /* We are out in the open, what shall we do? */
     int refuel_x, refuel_y;
 
-    if (punit->activity == ACTIVITY_GOTO
+    if (punit->activity == ACTIVITY_GOTO && punit->go
       /* We are on a GOTO.  Check if it will get us anywhere */
-       && is_airunit_refuel_point(punit->goto_dest_x, punit->goto_dest_y, 
+       && is_airunit_refuel_point(punit->go->x, punit->go->y, 
                                   pplayer, punit->type, FALSE)
        && air_can_move_between (punit->moves_left/SINGLE_MOVE, 
                                  punit->x, punit->y, 
-                                punit->goto_dest_x, punit->goto_dest_y,
+                                punit->go->x, punit->go->y,
                                 pplayer) >= 0) {
       /* It's an ok GOTO, just go there */
-      result = do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
+      (void) ai_unit_gothere(punit);
     } else if (find_nearest_airbase(punit->x, punit->y, punit, 
                             &refuel_x, &refuel_y)) {
       /* Go refuelling */
-      punit->goto_dest_x = refuel_x;
-      punit->goto_dest_y = refuel_y;
+      ai_unit_new_role(punit, AIUNIT_RECOVER, refuel_x, refuel_y);
       freelog(LOG_DEBUG, "Sent %s to refuel", unit_type(punit)->name);
-      set_unit_activity(punit, ACTIVITY_GOTO);
-      result = do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
+      if (!ai_unit_gothere(punit)) {
+        return;
+      }
+      if (!same_pos(refuel_x, refuel_y, punit->x, punit->y)) {
+        freelog(LOG_DEBUG, "Something happened to our unit along the way");
+      }
     } else {
       if (punit->fuel == 1) {
        freelog(LOG_DEBUG, "Oops, %s is fallin outta sky", 
@@ -328,19 +334,13 @@
       }
       return;
     }
-
-    /* Check if we got there okay */
-    if (result != GR_ARRIVED) {
-      freelog(LOG_DEBUG, "Something happened to our unit along the way");
-      /* TODO: some rescuing, but not running into dead-loop */
-    }
-
   } else if (punit->fuel == unit_type(punit)->fuel
             && find_something_to_bomb(punit, punit->x, punit->y) > 0) {
 
-    /* Found target, coordinates are in punit->goto_dest_[xy]
+    /* Found target, coordinates are in punit->go->[xy]
      * TODO: separate attacking into a function, check for the best 
      * tile to attack from */
+    assert(punit->go != NULL);
     set_unit_activity(punit, ACTIVITY_GOTO);
     if (!ai_unit_gothere(punit)) {
       return; /* died */
@@ -349,13 +349,12 @@
      * now actually need to attack */
 
     /* We could use ai_military_findvictim here, but I don't trust it... */
-    set_unit_activity(punit, ACTIVITY_IDLE);
     if (is_tiles_adjacent(punit->x, punit->y, 
-                         punit->goto_dest_x, punit->goto_dest_y)) {
-      int id = punit->id;
-      (void) handle_unit_move_request(punit, punit->goto_dest_x,
-                                     punit->goto_dest_y, TRUE, FALSE);
-      if ((punit = find_unit_by_id(id)) != NULL && punit->moves_left > 0) {
+                         punit->go->x, punit->go->y)) {
+      if (!ai_unit_move(punit, punit->go->x, punit->go->y)) {
+        return;
+      }
+      if (punit->moves_left > 0) {
        /* Fly home now */
        ai_manage_airunit(pplayer, punit);
       }
@@ -372,14 +371,11 @@
               unit_type(punit)->name, dest_x, dest_y, 
               (map_get_city(dest_x, dest_y) ? 
                map_get_city(dest_x, dest_y)->name : ""));
-      punit->goto_dest_x = dest_x;
-      punit->goto_dest_y = dest_y;
-      set_unit_activity(punit, ACTIVITY_GOTO);
-      result = do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
+      (void) ai_unit_goto(punit, dest_x, dest_y);
     } else {
       freelog(LOG_DEBUG, "%s cannot find anything to kill and is staying put", 
               unit_type(punit)->name);
-      set_unit_activity(punit, ACTIVITY_IDLE);
+      ai_unit_new_role(punit, AIUNIT_NONE, -1, -1);
     }
   }
 
Index: ai/aidiplomat.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidiplomat.c,v
retrieving revision 1.10
diff -u -r1.10 aidiplomat.c
--- ai/aidiplomat.c     2003/02/02 13:21:50     1.10
+++ ai/aidiplomat.c     2003/02/06 23:17:21
@@ -576,7 +576,8 @@
   /* If we have a role, we have a valid goto. Check if we have a valid city. */
   if (punit->ai.ai_role == AIUNIT_ATTACK
       || punit->ai.ai_role == AIUNIT_DEFEND_HOME) {
-    ctarget = map_get_city(punit->goto_dest_x, punit->goto_dest_y);
+    assert(punit->go != NULL);
+    ctarget = map_get_city(punit->go->x, punit->go->y);
   }
 
   /* Check if existing target still makes sense */
@@ -629,10 +630,6 @@
       UNIT_LOG(LOG_DIPLOMAT, punit, "could not find a job");
       return;
     }
-
-    /* TODO: following lines to be absorbed in a goto wrapper */
-    punit->goto_dest_x = ctarget->x;
-    punit->goto_dest_y = ctarget->y;
     ai_unit_new_role(punit, task, ctarget->x, ctarget->y);
   }
 
@@ -654,12 +651,12 @@
   /* Check if we can do something with our destination now. */
   if (punit->ai.ai_role == AIUNIT_ATTACK) {
     int dist = real_map_distance(punit->x, punit->y,
-                                 punit->goto_dest_x,
-                                 punit->goto_dest_y);
+                                 punit->go->x,
+                                 punit->go->y);
     UNIT_LOG(LOG_DIPLOMAT, punit, "attack, dist %d to %s (%s goto)"
              "[%d mc]", dist, ctarget ? ctarget->name : "(none)", 
              punit->activity == ACTIVITY_GOTO ? "has" : "no",
-             WARMAP_COST(punit->goto_dest_x, punit->goto_dest_y));
+             WARMAP_COST(punit->go->x, punit->go->y));
     if (dist == 1) {
       /* Do our stuff */
       ai_unit_new_role(punit, AIUNIT_NONE, -1, -1);
Index: ai/ailog.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/ailog.c,v
retrieving revision 1.4
diff -u -r1.4 ailog.c
--- ai/ailog.c  2002/11/14 09:14:50     1.4
+++ ai/ailog.c  2003/02/06 23:17:21
@@ -73,11 +73,18 @@
     return;
   }
 
-  my_snprintf(buffer, sizeof(buffer), "%s's %s[%d] (%d,%d)->(%d,%d){%d} ",
-              unit_owner(punit)->name, unit_type(punit)->name,
-              punit->id, punit->x, punit->y,
-              punit->goto_dest_x, punit->goto_dest_y, 
-              punit->ai.bodyguard);
+  if (punit->go) {
+    my_snprintf(buffer, sizeof(buffer), "%s's %s[%d] (%d,%d)->(%d,%d){%d} ",
+                unit_owner(punit)->name, unit_type(punit)->name,
+                punit->id, punit->x, punit->y,
+                punit->go->x, punit->go->y, 
+                punit->ai.bodyguard);
+  } else {
+    my_snprintf(buffer, sizeof(buffer), "%s's %s[%d] (%d,%d){%d} ",
+                unit_owner(punit)->name, unit_type(punit)->name,
+                punit->id, punit->x, punit->y,
+                punit->ai.bodyguard);
+  }
 
   va_start(ap, msg);
   my_vsnprintf(buffer2, sizeof(buffer2), msg, ap);
@@ -85,36 +92,6 @@
 
   cat_snprintf(buffer, sizeof(buffer), buffer2);
   freelog(minlevel, buffer);
-}
-
-/**************************************************************************
-  Log goto message if the goto fails. They will appear like this
-    2: a's Explorer[105] on GOTO (3,25)->(5,23) failed : exploring territory
-**************************************************************************/
-void GOTO_LOG(int level, struct unit *punit, enum goto_result result, 
-              const char *msg, ...)
-{
-  int minlevel = MIN(LOGLEVEL_GOTO, level);
-
-  if (minlevel <= fc_log_level && (result == GR_FAILED || result == 
GR_FOUGHT)) {
-    char buffer[500];
-    char buffer2[500];
-    va_list ap;
-
-    my_snprintf(buffer, sizeof(buffer),
-                "%s's %s[%d] on GOTO (%d,%d)->(%d,%d) %s : ",
-                unit_owner(punit)->name, unit_type(punit)->name,
-                punit->id, punit->x, punit->y,
-                punit->goto_dest_x, punit->goto_dest_y,
-               (result == GR_FAILED) ? "failed" : "fought");
-
-    va_start(ap, msg);
-    my_vsnprintf(buffer2, sizeof(buffer2), msg, ap);
-    va_end(ap);
-
-    cat_snprintf(buffer, sizeof(buffer), buffer2);
-    freelog(minlevel, buffer);
-  }
 }
 
 /**************************************************************************
Index: ai/aitools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitools.c,v
retrieving revision 1.77
diff -u -r1.77 aitools.c
--- ai/aitools.c        2003/01/26 18:32:47     1.77
+++ ai/aitools.c        2003/02/06 23:17:21
@@ -87,8 +87,7 @@
   CHECK_MAP_POS(pcity->x, pcity->y);
   punit->x = pcity->x;
   punit->y = pcity->y;
-  punit->goto_dest_x = 0;
-  punit->goto_dest_y = 0;
+  punit->go = NULL;
   punit->veteran = make_veteran;
   punit->homecity = pcity->id;
   punit->upkeep = 0;
@@ -144,8 +143,9 @@
 bool ai_unit_gothere(struct unit *punit)
 {
   CHECK_UNIT(punit);
-  assert(punit->goto_dest_x != -1 && punit->goto_dest_y != -1);
-  if (ai_unit_goto(punit, punit->goto_dest_x, punit->goto_dest_y)) {
+  assert(punit->go);
+  punit->go->counter++;
+  if (ai_unit_goto(punit, punit->go->x, punit->go->y)) {
     return TRUE; /* ... and survived */
   } else {
     return FALSE; /* we died */
@@ -156,24 +156,20 @@
   Go to specified destination but do not disturb existing role or activity
   and do not clear the role's destination. Return FALSE iff we died.
 
-  FIXME: add some logging functionality to replace GOTO_LOG()
+  FIXME: add some logging functionality
 **************************************************************************/
 bool ai_unit_goto(struct unit *punit, int x, int y)
 {
   enum goto_result result;
-  int oldx = punit->goto_dest_x, oldy = punit->goto_dest_y;
   enum unit_activity activity = punit->activity;
 
+
   CHECK_UNIT(punit);
   /* TODO: log error on same_pos with punit->x|y */
-  punit->goto_dest_x = x;
-  punit->goto_dest_y = y;
   handle_unit_activity_request(punit, ACTIVITY_GOTO);
-  result = do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
+  result = do_unit_goto(punit, GOTO_MOVE_ANY, FALSE, x, y);
   if (result != GR_DIED) {
     handle_unit_activity_request(punit, activity);
-    punit->goto_dest_x = oldx;
-    punit->goto_dest_y = oldy;
     return TRUE;
   }
   return FALSE;
@@ -183,20 +179,26 @@
   Ensure unit sanity by telling charge that we won't bodyguard it anymore,
   tell bodyguard it can roam free if our job is done, add and remove city 
   spot reservation, and set destination.
+
+  For AIUNIT_NONE and AIUNIT_EXPLORE, set x and y to (-1, -1). This is 
+  just a convention, the numbers mean nothing.
 **************************************************************************/
 void ai_unit_new_role(struct unit *punit, enum ai_unit_task task, int x, int y)
 {
   struct unit *charge = find_unit_by_id(punit->ai.charge);
   struct unit *bodyguard = find_unit_by_id(punit->ai.bodyguard);
 
+  assert(task != AIUNIT_PILLAGE);
+
   if (punit->activity == ACTIVITY_GOTO) {
     /* It would indicate we're going somewhere otherwise */
     handle_unit_activity_request(punit, ACTIVITY_IDLE);
   }
 
   if (punit->ai.ai_role == AIUNIT_BUILD_CITY) {
-    assert(is_normal_map_pos(punit->goto_dest_x, punit->goto_dest_y));
-    remove_city_from_minimap(punit->goto_dest_x, punit->goto_dest_y);
+    assert(punit->go != NULL);
+    assert(is_normal_map_pos(punit->go->x, punit->go->y));
+    remove_city_from_minimap(punit->go->x, punit->go->y);
   }
 
   if (charge && (charge->ai.bodyguard == punit->id)) {
@@ -206,9 +208,32 @@
   punit->ai.charge = BODYGUARD_NONE;
 
   punit->ai.ai_role = task;
-/* TODO:
-  punit->goto_dest_x = x;
-  punit->goto_dest_y = y; */
+
+  switch (task) {
+    case AIUNIT_NONE:
+    case AIUNIT_EXPLORE:
+    case AIUNIT_AUTO_SETTLER:
+      /* No valid coordinates expected */
+      assert(x == -1 && y == -1);
+      punit->go = NULL;
+      break;
+    case AIUNIT_DEFEND_HOME:
+    case AIUNIT_BUILD_CITY:
+    case AIUNIT_ATTACK:
+    case AIUNIT_ESCORT:
+    case AIUNIT_RECOVER:
+    case AIUNIT_TRANSPORT:
+      assert(is_normal_map_pos(x, y));
+      punit->go = &punit->goto_struct;
+      punit->go->x = x;
+      punit->go->y = y;
+      punit->go->origin_x = punit->x;
+      punit->go->origin_y = punit->y;
+      break;
+    default:
+      assert(FALSE);
+      break;
+  }
 
   if (punit->ai.ai_role == AIUNIT_NONE && bodyguard) {
     ai_unit_new_role(bodyguard, AIUNIT_NONE, -1, -1);
Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.259
diff -u -r1.259 aiunit.c
--- ai/aiunit.c 2003/02/02 13:21:50     1.259
+++ ai/aiunit.c 2003/02/06 23:17:22
@@ -61,6 +61,7 @@
 static void ai_manage_caravan(struct player *pplayer, struct unit *punit);
 static void ai_manage_barbarian_leader(struct player *pplayer,
                                       struct unit *leader);
+static void ai_manage_hitpoint_recovery(struct unit *punit);
 
 static void ai_military_findjob(struct player *pplayer,struct unit *punit);
 static void ai_military_gohome(struct player *pplayer,struct unit *punit);
@@ -338,6 +339,7 @@
   int range;
 
   CHECK_UNIT(punit);
+  ai_unit_new_role(punit, AIUNIT_EXPLORE, -1, -1);
 
   /* Get the range */
   /* FIXME: The vision range should NOT take into account watchtower benefit.
@@ -621,7 +623,8 @@
           ai_military_gohome(pplayer, punit);
         } else {
           /* Also try take care of deliberately homeless units */
-          (void) ai_unit_goto(punit, pcity->x, pcity->y);
+          ai_unit_new_role(punit, AIUNIT_DEFEND_HOME, pcity->x, pcity->y);
+          (void) ai_unit_gothere(punit);
         }
       } else {
         /* Sea travel */
@@ -631,7 +634,8 @@
           ai_military_gohome(pplayer, punit); /* until then go home */
         } else {
           UNIT_LOG(LOG_DEBUG, punit, "sending explorer home by boat");
-          (void) ai_unit_goto(punit, x, y);
+          ai_unit_new_role(punit, AIUNIT_DEFEND_HOME, x, y);
+          (void) ai_unit_gothere(punit);
         }
       }
     }
@@ -702,8 +706,6 @@
   if (!has_defense && pcity->ai.danger > 0) {
     /* change homecity to this city */
     if (ai_unit_make_homecity(punit, pcity)) {
-      /* Very important, or will not stay -- Syela */
-      ai_unit_new_role(punit, AIUNIT_DEFEND_HOME, pcity->x, pcity->y);
       return TRUE;
     }
   }
@@ -1101,6 +1103,7 @@
   int x, y;
 
   CHECK_UNIT(punit);
+  assert(punit->id == 0 || punit->ai.ai_role == AIUNIT_ESCORT);
 
   if (aunit && aunit->owner == punit->owner) {
     /* protect a unit */
@@ -1287,10 +1290,9 @@
         handle_unit_activity_request(punit, ACTIVITY_SENTRY);
         ferryboat->ai.passenger = punit->id;
 /* the code that worked for settlers wasn't good for piles of cannons */
-        if (find_beachhead(punit, dest_x, dest_y, &ferryboat->goto_dest_x,
-               &ferryboat->goto_dest_y) != 0) {
-          punit->goto_dest_x = dest_x;
-          punit->goto_dest_y = dest_y;
+        if (ferryboat->go
+            && find_beachhead(punit, dest_x, dest_y, &ferryboat->go->x,
+                              &ferryboat->go->y) != 0) {
           handle_unit_activity_request(punit, ACTIVITY_SENTRY);
          if (ground_unit_transporter_capacity(punit->x, punit->y, pplayer)
              <= 0) {
@@ -1325,9 +1327,6 @@
 bodyguard, or 3) we are going to an empty city.  Previously, cannons
 would disembark before the cruisers arrived and die. -- Syela */
 
-      punit->goto_dest_x = dest_x;
-      punit->goto_dest_y = dest_y;
-
 /* The following code block is supposed to stop units from running away from 
their
 bodyguards, and not interfere with those that don't have bodyguards nearby -- 
Syela */
 /* The case where the bodyguard has moves left and could meet us en route is 
not
@@ -1462,6 +1461,8 @@
 ***********************************************************************/
 static void ai_military_findjob(struct player *pplayer,struct unit *punit)
 {
+  struct ai_data *ai = ai_data_get(pplayer);
+  struct tile *ptile = map_get_tile(punit->x, punit->y);
   struct city *pcity = NULL, *acity = NULL;
   struct unit *aunit;
   int val, def;
@@ -1501,22 +1502,16 @@
     } /* end if home is in danger */
   } /* end if we have a home */
 
-  /* keep barbarians aggresive and primitive */
-  if (is_barbarian(pplayer)) {
-    if (can_unit_do_activity(punit, ACTIVITY_PILLAGE)
-       && is_land_barbarian(pplayer)) {
-      /* land barbarians pillage */
-      ai_unit_new_role(punit, AIUNIT_PILLAGE, -1, -1);
-    } else {
-      ai_unit_new_role(punit, AIUNIT_ATTACK, -1, -1);
-    }
-    return;
-  }
+  /*** Part 1: Check existing assignments, and keep them if possible ***/
 
-  if (punit->ai.charge != BODYGUARD_NONE) { /* I am a bodyguard */
+if (punit->ai.charge != BODYGUARD_NONE) assert(punit->ai.ai_role == 
AIUNIT_ESCORT);
+  if (punit->ai.ai_role == AIUNIT_ESCORT) {
+    /* I am a bodyguard, check validity of assignment */
     aunit = player_find_unit_by_id(pplayer, punit->ai.charge);
     acity = find_city_by_id(punit->ai.charge);
 
+    assert(punit->ai.ai_role == AIUNIT_ESCORT);
+
     /* Check if city we are on our way to rescue is still in danger,
      * or unit we should protect is still alive */
     if ((aunit && aunit->ai.bodyguard != BODYGUARD_NONE 
@@ -1524,7 +1519,7 @@
          unit_vulnerability_virtual(aunit)) ||
          (acity && acity->owner == punit->owner && acity->ai.urgency != 0 &&
           acity->ai.danger > assess_defense_quadratic(acity))) {
-      assert(punit->ai.ai_role == AIUNIT_ESCORT);
+      ai_military_bodyguard(pplayer, punit);
       return;
     } else {
       ai_unit_new_role(punit, AIUNIT_NONE, -1, -1);
@@ -1538,8 +1533,26 @@
     return;
   }
 
+  /*** Part 2: Give new assignments ***/
+
+  ai_unit_new_role(punit, AIUNIT_NONE, -1, -1);
+
+  /* keep barbarians aggresive and primitive */
+  if (is_barbarian(pplayer)) {
+    if (can_unit_do_activity(punit, ACTIVITY_PILLAGE)
+       && is_land_barbarian(pplayer)) {
+      /* land barbarians pillage */
+      handle_unit_activity_request(punit, ACTIVITY_PILLAGE);
+    }
+    if (punit->moves_left > 0) {
+      ai_military_attack(pplayer, punit);
+    }
+    return;
+  }
+
+  /* Home city in danger, defend it! */
   if (q > 0 && pcity->ai.urgency > 0) {
-    ai_unit_new_role(punit, AIUNIT_DEFEND_HOME, pcity->x, pcity->y);
+    ai_military_gohome(pplayer, punit);
     return;
   }
 
@@ -1547,8 +1560,8 @@
   if ((punit->ai.ai_role == AIUNIT_RECOVER
        && punit->hp < punittype->hp)
       || punit->hp < punittype->hp * 0.25) { /* WAG */
-    UNIT_LOG(LOGLEVEL_RECOVERY, punit, "set to hp recovery");
-    ai_unit_new_role(punit, AIUNIT_RECOVER, -1, -1);
+    UNIT_LOG(LOGLEVEL_RECOVERY, punit, "suggesting hp recovery");
+    ai_manage_hitpoint_recovery(punit);
     return;
   }
 
@@ -1572,7 +1585,7 @@
     val = look_for_charge(pplayer, punit, &aunit, &acity);
   }
   if (q > val) {
-    ai_unit_new_role(punit, AIUNIT_DEFEND_HOME, pcity->x, pcity->y);
+    ai_military_gohome(pplayer, punit);
     return;
   }
   /* this is bad; riflemen might rather attack if val is low -- Syela */
@@ -1580,15 +1593,19 @@
     ai_unit_new_role(punit, AIUNIT_ESCORT, acity->x, acity->y);
     punit->ai.charge = acity->id;
     BODYGUARD_LOG(LOG_DEBUG, punit, "going to defend city");
+    ai_military_bodyguard(pplayer, punit);
   } else if (aunit) {
     ai_unit_new_role(punit, AIUNIT_ESCORT, aunit->x, aunit->y);
     punit->ai.charge = aunit->id;
     BODYGUARD_LOG(LOG_DEBUG, punit, "going to defend unit");
+    ai_military_bodyguard(pplayer, punit);
   } else if (ai_unit_attack_desirability(punit->type) != 0 ||
       (pcity && !same_pos(pcity->x, pcity->y, punit->x, punit->y))) {
-     ai_unit_new_role(punit, AIUNIT_ATTACK, -1, -1);
+    ai_military_attack(pplayer, punit);
+  } else if (ai->explore.continent[ptile->continent]) {
+    ai_manage_explorer(punit);
   } else {
-    ai_unit_new_role(punit, AIUNIT_DEFEND_HOME, -1, -1); /* for default */
+    ai_military_gohome(pplayer, punit); /* for default */
   }
 }
 
@@ -1611,8 +1628,9 @@
       /* aggro defense goes here -- Syela */
       (void) ai_military_rampage(punit, 2); /* 2 is better than pillage */
     } else {
+      ai_unit_new_role(punit, AIUNIT_DEFEND_HOME, pcity->x, pcity->y);
       UNIT_LOG(LOG_DEBUG, punit, "GOHOME");
-      (void) ai_unit_goto(punit, pcity->x, pcity->y);
+      (void) ai_unit_gothere(punit);
     }
   }
 }
@@ -1723,8 +1741,9 @@
   CHECK_UNIT(punit);
 
   if (dest) {
-    x = punit->goto_dest_x;
-    y = punit->goto_dest_y;
+    assert(punit->go != NULL);
+    x = punit->go->x;
+    y = punit->go->y;
   } else {
     x = punit->x;
     y = punit->y;
@@ -1829,8 +1848,9 @@
     /* dealing with invasion stuff */
     if (IS_ATTACKER(aunit)) {
       if (aunit->activity == ACTIVITY_GOTO) {
+        assert(punit->go != NULL);
         invasion_funct(aunit, TRUE, 0, (COULD_OCCUPY(aunit) ? 1 : 2));
-        if ((pcity = map_get_city(aunit->goto_dest_x, aunit->goto_dest_y))) {
+        if ((pcity = map_get_city(aunit->go->x, aunit->go->y))) {
           pcity->ai.attack += unit_belligerence_basic(aunit);
           pcity->ai.bcost += unit_type(aunit)->build_cost;
         } 
@@ -2214,6 +2234,7 @@
           || (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). */
+        ai_unit_new_role(punit, AIUNIT_ATTACK, dest_x, dest_y);
         UNIT_LOG(LOG_DEBUG, punit, "mil att gothere -> %d, %d", 
                  dest_x, dest_y);
         if (ai_military_gothere(pplayer, punit, dest_x, dest_y) <= 0) {
@@ -2248,7 +2269,8 @@
   pcity = find_nearest_safe_city(punit);
   if (is_sailing_unit(punit) && pcity) {
     /* Sail somewhere */
-    (void) ai_unit_goto(punit, pcity->x, pcity->y);
+    ai_unit_new_role(punit, AIUNIT_DEFEND_HOME, pcity->x, pcity->y);
+    (void) ai_unit_gothere(punit);
   } else if (!is_barbarian(pplayer)) {
     /* Nothing else to do. Worst case, this function
        will send us back home */
@@ -2261,12 +2283,14 @@
     if ((pc = dist_nearest_city(pplayer, punit->x, punit->y, FALSE, TRUE))) {
       if (!is_ocean(map_get_terrain(punit->x, punit->y))) {
         UNIT_LOG(LOG_DEBUG, punit, "Barbarian marching to conquer %s", 
pc->name);
+        ai_unit_new_role(punit, AIUNIT_ATTACK, pc->x, pc->y);
         ai_military_gothere(pplayer, punit, pc->x, pc->y);
       } else {
         /* sometimes find_beachhead is not enough */
         if (find_beachhead(punit, pc->x, pc->y, &fx, &fy) == 0) {
           find_city_beach(pc, punit, &fx, &fy);
           freelog(LOG_DEBUG, "Barbarian sailing to city");
+          ai_unit_new_role(punit, AIUNIT_ATTACK, fx, fy);
           ai_military_gothere(pplayer, punit, fx, fy);
        }
       }
@@ -2386,7 +2410,7 @@
       }
       p++;
       bodyguard = unit_list_find(&map_get_tile(punit->x, punit->y)->units, 
aunit->ai.bodyguard);
-      pcity = map_get_city(aunit->goto_dest_x, aunit->goto_dest_y);
+      pcity = aunit->go ? map_get_city(aunit->go->x, aunit->go->y) : NULL;
       if (aunit->ai.bodyguard == BODYGUARD_NONE || bodyguard ||
          (pcity && pcity->ai.invasion >= 2)) {
        if (pcity) {
@@ -2418,12 +2442,10 @@
     if (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 */
-      x = punit->goto_dest_x; y = punit->goto_dest_y;
       port = find_nearest_safe_city(punit);
       if (port && !ai_unit_goto(punit, port->x, port->y)) {
         return; /* oops! */
       }
-      punit->goto_dest_x = x; punit->goto_dest_y = y;
       send_unit_info(pplayer, punit); /* to get the crosshairs right -- Syela 
*/
     } else {
       UNIT_LOG(LOG_DEBUG, punit, "Ferryboat %d@(%d,%d) stalling.",
@@ -2444,8 +2466,6 @@
   punit->ai.passenger = 0;
   UNIT_LOG(LOG_DEBUG, punit, "Ferryboat is lonely.");
   handle_unit_activity_request(punit, ACTIVITY_IDLE);
-  punit->goto_dest_x = 0; /* FIXME: -1 */
-  punit->goto_dest_y = 0; /* FIXME: -1 */
 
   /* Release bodyguard and let it roam */
   ai_unit_new_role(punit, AIUNIT_NONE, -1, -1);
@@ -2483,8 +2503,7 @@
   } unit_list_iterate_end;
   if (best < 4 * unit_type(punit)->move_rate) {
     /* Pickup is within 4 turns to grab, so move it! */
-    punit->goto_dest_x = x;
-    punit->goto_dest_y = y;
+    ai_unit_new_role(punit, AIUNIT_TRANSPORT, x, y);
     UNIT_LOG(LOG_DEBUG, punit, "Found a friend and going to him @(%d, %d)",
              x, y);
     (void) ai_unit_gothere(punit);
@@ -2499,8 +2518,7 @@
   if (pcity) {
     if (!ai_handicap(pplayer, H_TARGETS) ||
         unit_move_turns(punit, pcity->x, pcity->y) < p) {
-      punit->goto_dest_x = pcity->x;
-      punit->goto_dest_y = pcity->y;
+      ai_unit_new_role(punit, AIUNIT_RECOVER, pcity->x, pcity->y);
       UNIT_LOG(LOG_DEBUG, punit, "No friends.  Going home.");
       (void) ai_unit_gothere(punit);
       return;
@@ -2578,42 +2596,8 @@
 
   CHECK_UNIT(punit);
 
-  /* 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);
 
-  switch (punit->ai.ai_role) {
-  case AIUNIT_AUTO_SETTLER:
-  case AIUNIT_BUILD_CITY:
-    ai_unit_new_role(punit, AIUNIT_NONE, -1, -1);
-    break;
-  case AIUNIT_DEFEND_HOME:
-    ai_military_gohome(pplayer, punit);
-    break;
-  case AIUNIT_ATTACK:
-    ai_military_attack(pplayer, punit);
-    break;
-  case AIUNIT_FORTIFY:
-    ai_military_gohome(pplayer, punit);
-    break;
-  case AIUNIT_RUNAWAY: 
-    break;
-  case AIUNIT_ESCORT: 
-    ai_military_bodyguard(pplayer, punit);
-    break;
-  case AIUNIT_PILLAGE:
-    handle_unit_activity_request(punit, ACTIVITY_PILLAGE);
-    return; /* when you pillage, you have moves left, avoid later fortify */
-  case AIUNIT_EXPLORE:
-    (void) ai_manage_explorer(punit);
-    break;
-  case AIUNIT_RECOVER:
-    ai_manage_hitpoint_recovery(punit);
-    break;
-  default:
-    assert(FALSE);
-  }
-
   /* If we are still alive, either sentry or fortify. */
   if ((punit = find_unit_by_id(id))) {
     if (unit_list_find(&(map_get_tile(punit->x, punit->y)->units),
@@ -2685,7 +2669,7 @@
   if (!bodyguard && punit->ai.bodyguard > BODYGUARD_NONE) {
     UNIT_LOG(LOGLEVEL_BODYGUARD, punit, "lost bodyguard, asking for new");
     punit->ai.bodyguard = BODYGUARD_WANTED;
-  }  
+  }
 
   if ((unit_flag(punit, F_DIPLOMAT))
       || (unit_flag(punit, F_SPY))) {
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.284
diff -u -r1.284 packhand.c
--- client/packhand.c   2003/02/04 23:12:30     1.284
+++ client/packhand.c   2003/02/06 23:17:22
@@ -97,8 +97,6 @@
   punit->upkeep_gold = packet->upkeep_gold;
   punit->ai.control = packet->ai;
   punit->fuel = packet->fuel;
-  punit->goto_dest_x = packet->goto_dest_x;
-  punit->goto_dest_y = packet->goto_dest_y;
   punit->activity_target = packet->activity_target;
   punit->paradropped = packet->paradropped;
   punit->connecting = packet->connecting;
@@ -990,9 +988,6 @@
         if((unit_flag(punit, F_TRADE_ROUTE) || unit_flag(punit, F_HELP_WONDER))
           && (!game.player_ptr->ai.control || ai_popup_windows)
           && punit->owner==game.player_idx
-          && (punit->activity!=ACTIVITY_GOTO ||
-              same_pos(punit->goto_dest_x, punit->goto_dest_y,
-                       pcity->x, pcity->y))
           && (unit_can_help_build_wonder_here(punit)
               || unit_can_est_traderoute_here(punit))) {
          process_caravan_arrival(punit);
@@ -1027,8 +1022,6 @@
     punit->moves_left=packet->movesleft;
     punit->bribe_cost=0;
     punit->fuel=packet->fuel;
-    punit->goto_dest_x=packet->goto_dest_x;
-    punit->goto_dest_y=packet->goto_dest_y;
     punit->paradropped=packet->paradropped;
     punit->connecting=packet->connecting;
   
Index: client/gui-gtk/mapctrl.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/mapctrl.c,v
retrieving revision 1.73
diff -u -r1.73 mapctrl.c
--- client/gui-gtk/mapctrl.c    2003/01/28 00:40:42     1.73
+++ client/gui-gtk/mapctrl.c    2003/02/06 23:17:22
@@ -155,12 +155,6 @@
                    ptype->attack_strength, 
                    ptype->defense_strength, ptype->firepower, punit->hp, 
                    ptype->hp, punit->veteran ? _(" V") : "", uc);
-
-        if(punit->activity == ACTIVITY_GOTO || punit->connecting)  {
-         cross_head->x = punit->goto_dest_x;
-         cross_head->y = punit->goto_dest_y;
-         cross_head++;
-        }
       } else {
         struct unit *apunit;
         
Index: client/gui-gtk-2.0/mapctrl.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/mapctrl.c,v
retrieving revision 1.15
diff -u -r1.15 mapctrl.c
--- client/gui-gtk-2.0/mapctrl.c        2003/01/26 18:31:06     1.15
+++ client/gui-gtk-2.0/mapctrl.c        2003/02/06 23:17:22
@@ -165,12 +165,6 @@
                    ptype->attack_strength, 
                    ptype->defense_strength, ptype->firepower, punit->hp, 
                    ptype->hp, punit->veteran ? _(" V") : "", uc);
-
-        if(punit->activity == ACTIVITY_GOTO || punit->connecting)  {
-         cross_head->x = punit->goto_dest_x;
-         cross_head->y = punit->goto_dest_y;
-         cross_head++;
-        }
       } else {
         struct unit *apunit;
         
Index: client/gui-win32/mapctrl.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/mapctrl.c,v
retrieving revision 1.18
diff -u -r1.18 mapctrl.c
--- client/gui-win32/mapctrl.c  2003/01/23 21:39:32     1.18
+++ client/gui-win32/mapctrl.c  2003/02/06 23:17:22
@@ -191,12 +191,6 @@
                  ptype->attack_strength, 
                  ptype->defense_strength, ptype->firepower, punit->hp, 
                  ptype->hp, punit->veteran?_(" V"):"", uc);
-      
-      if(punit->activity==ACTIVITY_GOTO || punit->connecting)  {
-       cross_head->x = punit->goto_dest_x;
-       cross_head->y = punit->goto_dest_y;
-       cross_head++;
-      }
     } else {
       my_snprintf(s, sizeof(s), _("A:%d D:%d FP:%d HP:%d0%%"),
                  ptype->attack_strength, 
Index: client/gui-xaw/mapctrl.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/mapctrl.c,v
retrieving revision 1.62
diff -u -r1.62 mapctrl.c
--- client/gui-xaw/mapctrl.c    2003/01/09 19:21:17     1.62
+++ client/gui-xaw/mapctrl.c    2003/02/06 23:17:22
@@ -165,12 +165,6 @@
                _("A:%d D:%d FP:%d HP:%d/%d%s%s"), ptype->attack_strength, 
                ptype->defense_strength, ptype->firepower, punit->hp, 
                ptype->hp, punit->veteran?_(" V"):"", uc);
-
-        if(punit->activity==ACTIVITY_GOTO)  {
-         cross_head->x = punit->goto_dest_x;
-         cross_head->y = punit->goto_dest_y;
-         cross_head++;
-        }
       } else {
         my_snprintf(s, sizeof(s),
                    _("A:%d D:%d FP:%d HP:%d0%%"), ptype->attack_strength, 
Index: common/capstr.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/capstr.c,v
retrieving revision 1.122
diff -u -r1.122 capstr.c
--- common/capstr.c     2003/02/04 23:12:31     1.122
+++ common/capstr.c     2003/02/06 23:17:22
@@ -76,7 +76,7 @@
 
 #define CAPABILITY "+1.14.0 conn_info +occupied team tech_impr_gfx " \
                    "city_struct_minor_cleanup obsolete_last class_legend" \
-                   "+impr_req +waste +fastfocus"
+                   "+impr_req +waste +fastfocus +goto"
   
 /* "+1.14.0" is protocol for 1.14.0 release.
  *
@@ -107,6 +107,9 @@
  * on distance from capital city, varying by government type.
  *
  * "fastfocus" removes the server from client unit focus.
+ *
+ * "goto" makes server goto gen topol safe, and also better. But removes
+ * goto information from the client in regards to connecting and air units.
  */
 
 void init_our_capability(void)
Index: common/packets.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.c,v
retrieving revision 1.235
diff -u -r1.235 packets.c
--- common/packets.c    2003/02/04 23:12:31     1.235
+++ common/packets.c    2003/02/06 23:17:22
@@ -1263,8 +1263,6 @@
   dio_put_uint8(&dout, req->unhappiness);
   dio_put_uint8(&dout, req->activity);
   dio_put_uint8(&dout, req->activity_count);
-  dio_put_uint8(&dout, req->goto_dest_x);
-  dio_put_uint8(&dout, req->goto_dest_y);
   dio_put_uint16(&dout, req->activity_target);
   dio_put_uint8(&dout, req->packet_use);
   dio_put_uint16(&dout, req->info_city_id);
@@ -1541,8 +1539,6 @@
   dio_get_uint8(&din, &packet->unhappiness);
   dio_get_uint8(&din, &packet->activity);
   dio_get_uint8(&din, &packet->activity_count);
-  dio_get_uint8(&din, &packet->goto_dest_x);
-  dio_get_uint8(&din, &packet->goto_dest_y);
   dio_get_uint16(&din, (int *) &packet->activity_target);
   dio_get_uint8(&din, &packet->packet_use);
   dio_get_uint16(&din, &packet->info_city_id);
Index: common/packets.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.h,v
retrieving revision 1.136
diff -u -r1.136 packets.h
--- common/packets.h    2003/02/04 23:12:31     1.136
+++ common/packets.h    2003/02/06 23:17:22
@@ -309,7 +309,6 @@
   int upkeep_gold;
   bool ai;
   int fuel;
-  int goto_dest_x, goto_dest_y;
   enum tile_special_type activity_target;
   bool paradropped;
   bool connecting;
Index: common/unit.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.h,v
retrieving revision 1.93
diff -u -r1.93 unit.h
--- common/unit.h       2003/01/05 20:22:52     1.93
+++ common/unit.h       2003/02/06 23:17:22
@@ -47,10 +47,18 @@
   DIPLOMAT_CLIENT_POPUP_DIALOG
 };
 
-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_RECOVER };
+enum ai_unit_task {
+  AIUNIT_NONE,          /* default */
+  AIUNIT_AUTO_SETTLER,  /* make terrain improvements */
+  AIUNIT_BUILD_CITY,    /* build a city */
+  AIUNIT_DEFEND_HOME,   /* go to a city to _defend_ it */
+  AIUNIT_ATTACK,        /* attack designated target */
+  AIUNIT_ESCORT,        /* protect unit or city */
+  AIUNIT_EXPLORE,       /* explore */
+  AIUNIT_PILLAGE,       /* pseudo-role indicating pillage */
+  AIUNIT_RECOVER,       /* go to a place to recover or rest */
+  AIUNIT_TRANSPORT     /* transport other units */
+};
 
 enum goto_move_restriction {
   GOTO_MOVE_ANY,
@@ -103,6 +111,12 @@
   int charge; /* the unit this unit is bodyguarding */
 };
 
+struct unit_goto {
+  int x, y;               /* where are we going? */
+  int origin_x, origin_y; /* from where did we start? */
+  int counter;            /* how long has this taken? */
+};
+
 struct unit {
   Unit_Type_id type;
   int id;
@@ -121,7 +135,8 @@
   int bribe_cost;
   struct unit_ai ai;
   enum unit_activity activity;
-  int goto_dest_x, goto_dest_y;
+  struct unit_goto goto_struct; /* never refer to this directly */
+  struct unit_goto *go;
   int activity_count;
   enum tile_special_type activity_target;
   enum unit_focus_status focus_status;
@@ -132,7 +147,7 @@
   bool paradropped;
   bool connecting;
   int transported_by;
-  struct goto_route *pgr;
+  struct goto_route *pgr; /* client-side goto */
 };
 
 
Index: server/autoattack.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/autoattack.c,v
retrieving revision 1.40
diff -u -r1.40 autoattack.c
--- server/autoattack.c 2002/09/30 13:08:56     1.40
+++ server/autoattack.c 2003/02/06 23:17:22
@@ -166,21 +166,17 @@
                   unit_owner(enemy)->name, unit_name(enemy->type));
   
   set_unit_activity(punit, ACTIVITY_GOTO);
-  punit->goto_dest_x=enemy->x;
-  punit->goto_dest_y=enemy->y;
   
   send_unit_info(NULL, punit);
-  (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
+  (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE, enemy->x, enemy->y);
   
   punit = find_unit_by_id(id);
   
   if (punit) {
     set_unit_activity(punit, ACTIVITY_GOTO);
-    punit->goto_dest_x=pcity->x;
-    punit->goto_dest_y=pcity->y;
     send_unit_info(NULL, punit);
     
-    (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
+    (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE, pcity->x, pcity->y);
     
     if (unit_list_find(&map_get_tile(pcity->x, pcity->y)->units, id)) {
       handle_unit_activity_request(punit, ACTIVITY_IDLE);
@@ -231,8 +227,10 @@
     if(punit->ai.control
        && is_military_unit(punit)
        && punit->activity == ACTIVITY_GOTO
-       && punit->moves_left == unit_type(punit)->move_rate) {
-      (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
+       && punit->moves_left == unit_type(punit)->move_rate
+       && punit->go) {
+      (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE,
+                          punit->go->x, punit->go->y);
     }
   }
   unit_list_iterate_end;
Index: server/gotohand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gotohand.c,v
retrieving revision 1.162
diff -u -r1.162 gotohand.c
--- server/gotohand.c   2003/02/04 23:12:31     1.162
+++ server/gotohand.c   2003/02/06 23:17:22
@@ -736,7 +736,7 @@
          freelog(LOG_DEBUG, "%s#%d@(%d,%d) dissuaded from (%d,%d) -> (%d,%d)",
                  unit_type(punit)->name, punit->id,
                  punit->x, punit->y, x1, y1,
-                 punit->goto_dest_x, punit->goto_dest_y);
+                 dest_x, dest_y);
        }
        break;
 
@@ -1257,7 +1257,7 @@
 **************************************************************************/
 enum goto_result do_unit_goto(struct unit *punit,
                              enum goto_move_restriction restriction,
-                             bool trigger_special_ability)
+                             bool trigger_special_ability, int gx, int gy)
 {
   struct player *pplayer = unit_owner(punit);
   int unit_id, dest_x, dest_y, waypoint_x, waypoint_y;
@@ -1270,8 +1270,8 @@
   }
 
   unit_id = punit->id;
-  dest_x = waypoint_x = punit->goto_dest_x;
-  dest_y = waypoint_y = punit->goto_dest_y;
+  dest_x = waypoint_x = gx;
+  dest_y = waypoint_y = gy;
 
   if (same_pos(punit->x, punit->y, dest_x, dest_y) ||
       !goto_is_sane(punit, dest_x, dest_y, FALSE)) {
@@ -1334,7 +1334,7 @@
       penemy = is_enemy_unit_tile(map_get_tile(x, y), unit_owner(punit));
       assert(punit->moves_left > 0);
 
-      last_tile = same_pos(x, y, punit->goto_dest_x, punit->goto_dest_y);
+      last_tile = same_pos(x, y, gx, gy);
 
       /* Call handle_unit_move_request for humans and ai_unit_move for AI */
       success = (!pplayer->ai.control 
Index: server/gotohand.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gotohand.h,v
retrieving revision 1.23
diff -u -r1.23 gotohand.h
--- server/gotohand.h   2003/02/02 13:21:50     1.23
+++ server/gotohand.h   2003/02/06 23:17:22
@@ -30,7 +30,7 @@
 
 enum goto_result do_unit_goto(struct unit *punit,
                              enum goto_move_restriction restriction,
-                             bool trigger_special_ability);
+                             bool trigger_special_ability, int gx, int gy);
 void generate_warmap(struct city *pcity, struct unit *punit);
 void really_generate_warmap(struct city *pcity, struct unit *punit,
                            enum unit_move_type move_type);
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.109
diff -u -r1.109 savegame.c
--- server/savegame.c   2003/02/04 17:07:44     1.109
+++ server/savegame.c   2003/02/06 23:17:22
@@ -981,10 +981,17 @@
                                                "player%d.u%d.connecting",
                                                plrno, i);
 
-    punit->goto_dest_x=secfile_lookup_int(file, 
+    { // goto
+      bool has_goto = secfile_lookup_bool_default(file, TRUE, 
"player%d.u%d.go",
+                                                  plrno, i);
+      if (has_goto) {
+        punit->go = &punit->goto_struct;
+        punit->go->x = secfile_lookup_int(file, 
                                          "player%d.u%d.goto_x", plrno,i);
-    punit->goto_dest_y=secfile_lookup_int(file, 
+        punit->go->y = secfile_lookup_int(file, 
                                          "player%d.u%d.goto_y", plrno,i);
+      }
+    }
     punit->ai.control=secfile_lookup_bool(file, "player%d.u%d.ai", plrno,i);
     punit->ai.ai_role = AIUNIT_NONE;
     punit->ai.ferryboat = 0;
@@ -1414,8 +1421,16 @@
     secfile_insert_int(file, punit->fuel, "player%d.u%d.fuel",
                                plrno, i);
 
-    secfile_insert_int(file, punit->goto_dest_x, "player%d.u%d.goto_x", plrno, 
i);
-    secfile_insert_int(file, punit->goto_dest_y, "player%d.u%d.goto_y", plrno, 
i);
+    if (punit->go) {
+      secfile_insert_bool(file, TRUE, "player%d.u%d.go", plrno, i);
+      secfile_insert_int(file, punit->go->x, "player%d.u%d.goto_x", plrno, i);
+      secfile_insert_int(file, punit->go->y, "player%d.u%d.goto_y", plrno, i);
+    } else {
+      secfile_insert_bool(file, FALSE, "player%d.u%d.go", plrno, i);
+      /* for compatility with older servers */
+      secfile_insert_int(file, 0, "player%d.u%d.goto_x", plrno, i);
+      secfile_insert_int(file, 0, "player%d.u%d.goto_y", plrno, i);
+    }
     secfile_insert_bool(file, punit->ai.control, "player%d.u%d.ai", plrno, i);
     secfile_insert_int(file, punit->ord_map, "player%d.u%d.ord_map", plrno, i);
     secfile_insert_int(file, punit->ord_city, "player%d.u%d.ord_city", plrno, 
i);
Index: server/settlers.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/settlers.c,v
retrieving revision 1.162
diff -u -r1.162 settlers.c
--- server/settlers.c   2003/02/02 13:21:50     1.162
+++ server/settlers.c   2003/02/06 23:17:22
@@ -458,8 +458,8 @@
 static bool is_already_assigned(struct unit *myunit, struct player *pplayer, 
     int x, int y)
 {
-  if (same_pos(myunit->x, myunit->y, x, y) ||
-      same_pos(myunit->goto_dest_x, myunit->goto_dest_y, x, y)) {
+  if (same_pos(myunit->x, myunit->y, x, y)
+      || (myunit->go && same_pos(myunit->go->x, myunit->go->y, x, y))) {
 /* I'm still not sure this is exactly right -- Syela */
     unit_list_iterate(map_get_tile(x, y)->units, punit)
       if (myunit==punit) continue;
@@ -1223,18 +1223,20 @@
     }
     ferryboat = unit_list_find(&(map_get_tile(punit->x, punit->y)->units),
                                punit->ai.ferryboat);
-    punit->goto_dest_x = gx;
-    punit->goto_dest_y = gy;
 
+    /* FIXME: _gross_ hack */
+    punit->go = &punit->goto_struct;
+    punit->go->x = gx;
+    punit->go->y = gy;
+
     if (ferryboat && (ferryboat->ai.passenger == 0
                       || ferryboat->ai.passenger == punit->id)) {
       UNIT_LOG(LOG_DEBUG, punit, "We have FOUND BOAT %d, ABOARD",
                ferryboat->id);
       handle_unit_activity_request(punit, ACTIVITY_SENTRY);
+      ai_unit_new_role(ferryboat, AIUNIT_TRANSPORT, gx, gy);
       ferryboat->ai.passenger = punit->id;
-      ferryboat->goto_dest_x = gx;
-      ferryboat->goto_dest_y = gy;
-      if (!ai_unit_goto(ferryboat, gx, gy)) {
+      if (!ai_unit_gothere(ferryboat)) {
         return FALSE; /* died */
       }
       handle_unit_activity_request(punit, ACTIVITY_IDLE);
@@ -1250,8 +1252,10 @@
       && (!ferryboat
           || (is_tiles_adjacent(punit->x, punit->y, gx, gy)
               && could_unit_move_to_tile(punit, gx, gy) != 0))) {
-    punit->goto_dest_x = gx;
-    punit->goto_dest_y = gy;
+    /* FIXME: _gross_ hack */
+    punit->go = &punit->goto_struct;
+    punit->go->x = gx;
+    punit->go->y = gy;
     if (!ai_unit_goto(punit, gx, gy)) {
       return FALSE; /* died */
     }
@@ -1312,7 +1316,7 @@
       best_act == ACTIVITY_UNKNOWN /* flag */) {
     ai_unit_new_role(punit, AIUNIT_BUILD_CITY, gx, gy);
   } else {
-    ai_unit_new_role(punit, AIUNIT_AUTO_SETTLER, gx, gy);
+    ai_unit_new_role(punit, AIUNIT_AUTO_SETTLER, -1, -1);
   }
 
   /* We've now worked out what to do; go to it! */
@@ -1427,7 +1431,7 @@
     if (unit_flag(punit, F_SETTLERS)
        || unit_flag(punit, F_CITIES)) {
       if (punit->activity == ACTIVITY_GOTO) {
-        ptile = map_get_tile(punit->goto_dest_x, punit->goto_dest_y);
+        ptile = map_get_tile(punit->go->x, punit->go->y);
         ptile->assigned = ptile->assigned | i; /* assigned for us only */
       } else {
         ptile = map_get_tile(punit->x, punit->y);
Index: server/unithand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
retrieving revision 1.252
diff -u -r1.252 unithand.c
--- server/unithand.c   2003/02/04 23:12:31     1.252
+++ server/unithand.c   2003/02/06 23:17:23
@@ -76,8 +76,9 @@
     return;
   }
 
-  punit->goto_dest_x = req->x;
-  punit->goto_dest_y = req->y;
+  punit->go = &punit->goto_struct;
+  punit->go->x = req->x;
+  punit->go->y = req->y;
 
   set_unit_activity(punit, ACTIVITY_GOTO);
 
@@ -92,7 +93,7 @@
     assign_units_to_transporter(punit, TRUE);
   }
 
-  (void) do_unit_goto(punit, GOTO_MOVE_ANY, TRUE);
+  (void) do_unit_goto(punit, GOTO_MOVE_ANY, TRUE, req->x, req->y);
 }
 
 /**************************************************************************
@@ -133,8 +134,9 @@
     return;
   }
 
-  punit->goto_dest_x = req->dest_x;
-  punit->goto_dest_y = req->dest_y;
+  punit->go = &punit->goto_struct;
+  punit->go->x = req->dest_x;
+  punit->go->y = req->dest_y;
 
   set_unit_activity(punit, req->activity_type);
   punit->connecting = TRUE;
@@ -148,7 +150,7 @@
   if (!can_unit_do_activity(punit, req->activity_type)) {
     (void) do_unit_goto(punit,
                        get_activity_move_restriction(req->activity_type),
-                       FALSE);
+                       FALSE, req->dest_x, req->dest_y);
   }
 }
 
@@ -1034,7 +1036,7 @@
      * human players the server-side goto implementation should be
      * obsoleted for client usage. So in time, remove the code below. */
     if (punit->activity == ACTIVITY_GOTO && 
-        !same_pos(punit->goto_dest_x, punit->goto_dest_y, dest_x, dest_y)) {
+        !same_pos(punit->go->x, punit->go->y, dest_x, dest_y)) {
       notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
                       _("Game: %s aborted GOTO as there are units in the 
way."),
                       unit_type(punit)->name);
@@ -1445,8 +1447,8 @@
 #endif
 
   if (punit->activity == ACTIVITY_GOTO) {
-    punit->goto_dest_x = pgr->pos[pgr->last_index-1].x;
-    punit->goto_dest_y = pgr->pos[pgr->last_index-1].y;
+    punit->go->x = pgr->pos[pgr->last_index-1].x;
+    punit->go->y = pgr->pos[pgr->last_index-1].y;
     send_unit_info(pplayer, punit);
   }
 
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.208
diff -u -r1.208 unittools.c
--- server/unittools.c  2003/02/04 23:12:31     1.208
+++ server/unittools.c  2003/02/06 23:17:23
@@ -520,10 +520,8 @@
              (air_can_move_between
               (punit->moves_left / 3, punit->x, punit->y, x_itr, y_itr,
                unit_owner(punit)) >= 0)) {
-           punit->goto_dest_x = x_itr;
-           punit->goto_dest_y = y_itr;
            set_unit_activity(punit, ACTIVITY_GOTO);
-           (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
+           (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE, x_itr, y_itr);
            notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, 
                             _("Game: Your %s has returned to refuel."),
                             unit_name(punit->type));
@@ -721,10 +719,11 @@
 
   unit_restore_movepoints(pplayer, punit);
 
-  if (punit->connecting && !can_unit_do_activity(punit, activity)) {
+  if (punit->connecting && !can_unit_do_activity(punit, activity)
+      && punit->go) {
     punit->activity_count = 0;
-    if (do_unit_goto(punit, get_activity_move_restriction(activity), FALSE)
-       == GR_DIED) {
+    if (do_unit_goto(punit, get_activity_move_restriction(activity), 
+                     FALSE, punit->go->x, punit->go->y) == GR_DIED) {
       return;
     }
   }
@@ -900,11 +899,12 @@
     unit_list_iterate (map_get_tile(punit->x, punit->y)->units, punit2) {
       if (punit2->activity == activity) {
        bool alive = TRUE;
-       if (punit2->connecting) {
+       if (punit2->connecting && punit->go) {
          punit2->activity_count = 0;
          alive = (do_unit_goto(punit2,
                                get_activity_move_restriction(activity),
-                               FALSE) != GR_DIED);
+                               FALSE, punit->go->x, punit->go->y)
+                  != GR_DIED);
        } else {
          set_unit_activity(punit2, ACTIVITY_IDLE);
        }
@@ -922,11 +922,13 @@
   }
 
   if (activity==ACTIVITY_GOTO) {
-    if (!punit->ai.control && (!is_military_unit(punit) ||
-       punit->ai.passenger != 0 || !pplayer->ai.control)) {
+    assert(punit->go != NULL);
+    if (punit->go && !punit->ai.control && (!is_military_unit(punit)
+        || punit->ai.passenger != 0 || !pplayer->ai.control)) {
 /* autosettlers otherwise waste time; idling them breaks assignment */
 /* Stalling infantry on GOTO so I can see where they're GOing TO. -- Syela */
-      (void) do_unit_goto(punit, GOTO_MOVE_ANY, TRUE);
+      (void) do_unit_goto(punit, GOTO_MOVE_ANY, TRUE, punit->go->x, 
+                          punit->go->y);
     }
     return;
   }
@@ -1561,8 +1563,7 @@
   punit->x = x;
   punit->y = y;
 
-  punit->goto_dest_x=0;
-  punit->goto_dest_y=0;
+  punit->go = NULL;
   
   pcity=find_city_by_id(homecity_id);
   punit->veteran=make_veteran;
@@ -1916,8 +1917,6 @@
   packet->upkeep_gold = punit->upkeep_gold;
   packet->ai = punit->ai.control;
   packet->fuel = punit->fuel;
-  packet->goto_dest_x = punit->goto_dest_x;
-  packet->goto_dest_y = punit->goto_dest_y;
   packet->activity_target = punit->activity_target;
   packet->paradropped = punit->paradropped;
   packet->connecting = punit->connecting;
@@ -2902,9 +2901,9 @@
     }
   }
   /* A transporter should not take units with it when on an attack goto -- 
fisch */
-  if ((punit->activity == ACTIVITY_GOTO) &&
-      get_defender(punit, punit->goto_dest_x, punit->goto_dest_y) &&
-      !is_ocean(psrctile->terrain)) {
+  if ((punit->activity == ACTIVITY_GOTO || punit->go)
+      && get_defender(punit, punit->go->x, punit->go->y)
+      && !is_ocean(psrctile->terrain)) {
     transport_units = FALSE;
   }
 
@@ -2979,8 +2978,8 @@
       && is_ocean(pdesttile->terrain)
       && !(pplayer->ai.control)
       && !(punit->activity == ACTIVITY_GOTO      /* if unit is GOTOing and the 
ship */ 
-          && (dest_x != punit->goto_dest_x      /* isn't the final destination 
*/
-              || dest_y != punit->goto_dest_y)) /* then don't go to sleep */
+          && (dest_x != punit->go->x      /* isn't the final destination */
+              || dest_y != punit->go->y)) /* then don't go to sleep */
       ) {
     set_unit_activity(punit, ACTIVITY_SENTRY);
   }

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