diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/ai/aiunit.c codeciv/ai/aiunit.c
--- freeciv/ai/aiunit.c	Tue Apr 17 18:13:57 2001
+++ codeciv/ai/aiunit.c	Wed Apr 18 00:17:56 2001
@@ -206,28 +206,24 @@
 }
 
 /********************************************************************** 
-  ...
+Returns how many turn it would take punit to reach x,y. IE, if the unit
+can arrive this turn it returns 0.
+The warmap must be created beforehand.
 ***********************************************************************/
 static int unit_move_turns(struct unit *punit, int x, int y)
 {
-  int m, d;
-  m = unit_types[punit->type].move_rate;
-  if (unit_flag(punit->type, F_IGTER)) m *= SINGLE_MOVE;
-  if(is_sailing_unit(punit)) {
-    struct player *pplayer = get_player(punit->owner);
-    if (player_owns_active_wonder(pplayer, B_LIGHTHOUSE)) 
-      m += SINGLE_MOVE;
-    if (player_owns_active_wonder(pplayer, B_MAGELLAN))
-      m += (improvement_variant(B_MAGELLAN)==1) ? SINGLE_MOVE : 2 * SINGLE_MOVE;
-    m += player_knows_techs_with_flag(pplayer,TF_BOAT_FAST)*3;
-  }   
+  int move_rate = unit_move_rate(punit);
+  int cost;
 
   if (unit_types[punit->type].move_type == LAND_MOVING)
-    d = warmap.cost[x][y] / m;
+    cost = warmap.cost[x][y];
   else if (unit_types[punit->type].move_type == SEA_MOVING)
-    d = warmap.seacost[x][y] / m;
-  else d = real_map_distance(punit->x, punit->y, x, y) * 3 / m;
-  return(d);
+    cost = warmap.seacost[x][y];
+  else cost = real_map_distance(punit->x, punit->y, x, y) * 3;
+
+  cost = MAX(0, cost - punit->moves_left);
+
+  return (cost + move_rate - 1)/move_rate;
 }
 
 /**************************************************************************
@@ -669,9 +665,10 @@
 
 work of Syela - mostly to fix the ZOC/goto strangeness
 **************************************************************************/
-static int ai_military_findvictim(struct player *pplayer, struct unit *punit,
+static int ai_military_findvictim(struct unit *punit,
 				  int *dest_x, int *dest_y)
 {
+  struct player *pplayer = unit_owner(punit);
   int x, y, x1, y1, k;
   int best = 0, a, b, c, d, e, f;
   struct unit *pdef;
@@ -796,7 +793,7 @@
       do_unit_goto(punit, GOTO_MOVE_ANY, 0);
     } else punit->ai.charge = 0; /* can't possibly get there to help */
   } else { /* I had these guys set to just fortify, which is so dumb. -- Syela */
-    i = ai_military_findvictim(pplayer, punit, &x, &y);
+    i = ai_military_findvictim(punit, &x, &y);
     freelog(LOG_DEBUG,
 	    "Stationary escort @(%d,%d) received %d best @(%d,%d)",
 	    punit->x, punit->y, i, x, y);
@@ -1156,6 +1153,11 @@
     }
   }
 
+  if (punit->hp < unit_types[punit->type].hp) {
+    punit->ai.ai_role = AIUNIT_REGENERATE;
+    return;
+  }
+
 /* I'm not 100% sure this is the absolute best place for this... -- Syela */
   generate_warmap(map_get_city(punit->x, punit->y), punit);
 /* I need this in order to call unit_move_turns, here and in look_for_charge */
@@ -1210,7 +1212,7 @@
     if ((punit->x == pcity->x)&&(punit->y == pcity->y)) {
       freelog(LOG_DEBUG, "INHOUSE. GOTO AI_NONE(%d)", punit->id);
       /* aggro defense goes here -- Syela */
-      ai_military_findvictim(pplayer, punit, &dest_x, &dest_y);
+      ai_military_findvictim(punit, &dest_x, &dest_y);
       punit->ai.ai_role=AIUNIT_NONE;
       handle_unit_move_request(punit, dest_x, dest_y, FALSE, FALSE);
                                        /* might bash someone */
@@ -1558,7 +1560,7 @@
     id = punit->id;
     do {
       flag = 0;
-      ai_military_findvictim(pplayer, punit, &dest_x, &dest_y);  
+      ai_military_findvictim(punit, &dest_x, &dest_y);  
       if (dest_x == punit->x && dest_y == punit->y) {
 /* no one to bash here.  Will try to move onward */
         find_something_to_kill(pplayer, punit, &dest_x, &dest_y);
@@ -1798,6 +1800,74 @@
 }
 
 /**************************************************************************
+The unit does not have full HP. Regenerate!
+The criteria for doing this is minimalizing the number of turns before the
+unit is up to full hp, fx by moving the unit into a city. We do not take
+into account the usefullness of the new unit pos.
+
+FIXME: it would be nice to prefer to regenerate on a tile with high
+defense value!
+**************************************************************************/
+static void ai_regenerate_unit(struct unit *punit)
+{
+  int best_x, best_y;
+  struct player *pplayer = unit_owner(punit);
+  int full_hp = unit_types[punit->type].hp;
+  int need_hp = full_hp - punit->hp;
+  int hp_gain = hp_gain_coord(punit, punit->x, punit->y);
+  int best_turns = (need_hp+hp_gain-1)/hp_gain;
+  int id = punit->id;
+
+  assert(need_hp > 0);
+
+  /* See if there is any obvious goodies adjacent. */
+  if (ai_military_findvictim(punit, &best_x, &best_y)) {
+    /* FIXME: This only checks the adjacent tiles.
+       We could check a bit further. */
+    handle_unit_move_request(punit, best_x, best_y, 0, 1);
+    return;
+  } else { /* Nope. Continue regeneration. */
+    best_x = punit->x;
+    best_y = punit->y;
+  }
+
+  /* Determine best place to go. */
+  generate_warmap(NULL, punit);
+  whole_map_iterate(x, y) {
+    int regen_turns;
+    if (is_non_allied_city_tile(map_get_tile(x, y), punit->owner)
+	|| is_non_allied_unit_tile(map_get_tile(x, y), punit->owner))
+      continue;
+
+    hp_gain = hp_gain_coord(punit, x, y);
+    regen_turns = unit_move_turns(punit, x, y) + 1 + (need_hp+hp_gain-1)/hp_gain;
+
+    if (regen_turns < best_turns) {
+      best_turns = regen_turns;
+      best_x = x;
+      best_y = y;
+    }
+  } whole_map_iterate_end;
+
+  /* Go there! */
+  if (best_x != punit->x || best_y != punit->y) {
+    punit->goto_dest_x = best_x;
+    punit->goto_dest_y = best_y;
+    do_unit_goto(punit, GOTO_MOVE_ANY, 0);
+  }
+
+  if (!player_find_unit_by_id(pplayer, id))
+    return; /* died. */
+
+  /* Fortifying is always good. You also gain HP's faster that way! */
+  if (punit->x == best_x && punit->y == punit->y) {
+    if (can_unit_do_activity(punit, ACTIVITY_FORTIFYING)) {
+      handle_unit_activity_request(punit, ACTIVITY_FORTIFYING);
+    }
+  }
+}
+
+/**************************************************************************
 decides what to do with a military unit.
 **************************************************************************/
 static void ai_manage_military(struct player *pplayer, struct unit *punit)
@@ -1852,6 +1922,9 @@
     break;
   case AIUNIT_EXPLORE:
     ai_manage_explorer(punit);
+    break;
+  case AIUNIT_REGENERATE:
+    ai_regenerate_unit(punit);
     break;
   default:
     abort();
diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/common/unit.h codeciv/common/unit.h
--- freeciv/common/unit.h	Tue Apr 17 18:14:24 2001
+++ codeciv/common/unit.h	Wed Apr 18 00:15:50 2001
@@ -50,7 +50,7 @@
 enum ai_unit_task { AIUNIT_NONE, AIUNIT_AUTO_SETTLER, AIUNIT_BUILD_CITY,
                     AIUNIT_DEFEND_HOME, AIUNIT_ATTACK, AIUNIT_FORTIFY,
                     AIUNIT_RUNAWAY, AIUNIT_ESCORT, AIUNIT_EXPLORE,
-                    AIUNIT_PILLAGE };
+                    AIUNIT_PILLAGE, AIUNIT_REGENERATE };
 
 enum goto_move_restriction {
   GOTO_MOVE_ANY, GOTO_MOVE_CARDINAL_ONLY, GOTO_MOVE_STRAIGHTEST
diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/server/unittools.c codeciv/server/unittools.c
--- freeciv/server/unittools.c	Tue Apr 17 18:14:35 2001
+++ codeciv/server/unittools.c	Wed Apr 18 00:15:50 2001
@@ -1053,12 +1053,9 @@
   was_lower=(punit->hp < get_unit_type(punit->type)->hp);
 
   if(!punit->moved) {
-    punit->hp+=hp_gain_coord(punit);
+    punit->hp+=hp_gain_coord(punit, punit->x, punit->y);
   }
   
-  if (player_owns_active_wonder(pplayer, B_UNITED)) 
-    punit->hp+=2;
-    
   if(is_heli_unit(punit)) {
     struct city *pcity = map_get_city(punit->x,punit->y);
     if(!pcity) {
@@ -1106,15 +1103,16 @@
   ports    will regen navalunits completely
   fortify will add a little extra.
 ***************************************************************************/
-int hp_gain_coord(struct unit *punit)
+int hp_gain_coord(struct unit *punit, int x, int y)
 {
   int hp;
   struct city *pcity;
+  struct player *pplayer = unit_owner(punit);
   if (unit_on_fortress(punit))
     hp=get_unit_type(punit->type)->hp/4;
   else
     hp=0;
-  if((pcity=map_get_city(punit->x,punit->y))) {
+  if ((pcity=map_get_city(x, y))) {
     if ((city_got_barracks(pcity) &&
 	 (is_ground_unit(punit) || improvement_variant(B_BARRACKS)==1)) ||
 	(city_got_building(pcity, B_AIRPORT) && is_air_unit(punit)) || 
@@ -1130,7 +1128,10 @@
 
   if(punit->activity==ACTIVITY_FORTIFIED)
     hp++;
-  
+
+  if (player_owns_active_wonder(pplayer, B_UNITED)) 
+    hp += 2;
+
   return hp;
 }
 
diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/server/unittools.h codeciv/server/unittools.h
--- freeciv/server/unittools.h	Tue Apr 17 18:14:35 2001
+++ codeciv/server/unittools.h	Wed Apr 18 00:15:50 2001
@@ -53,7 +53,7 @@
 /* turn update related */
 void player_restore_units(struct player *pplayer);
 void update_unit_activities(struct player *pplayer);
-int hp_gain_coord(struct unit *punit);
+int hp_gain_coord(struct unit *punit, int x, int y);
 
 
 /* various */