Complete.Org: Mailing Lists: Archives: freeciv-dev: September 2004:
[Freeciv-Dev] (PR#7282) Patch: connect as orders
Home

[Freeciv-Dev] (PR#7282) Patch: connect as orders

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: Gregory.Berkolaiko@xxxxxxxxxxxxx
Subject: [Freeciv-Dev] (PR#7282) Patch: connect as orders
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 2 Sep 2004 22:01:19 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=7282 >

> [glip - Tue Aug 10 15:23:11 2004]:
> 
> In the attached patch I:
> 
> * extended PF by introducing a new callback get_costs, which does
> everything: sets both MC and EC, checks if the tile is known, checks if
> we found a better path.  As a consequence it takes a whole lot of
> arguments, but I still like it.
> 
> * used this to tune the road connect.  It now takes into account 
>   - time to build road at the source tile
>   - movement bonus created after we've built a road
>   - many other little things.
> As a result it prints the correct time.
> 
> What hasn't been done:
> * other types of connect
> * ZoC is not taken into account
> * there is a little bug when you just hit ctrl-shift-r, it shows 0 for
> the tile you are on, even though it's not 0.  If you move pointer to
> another tile and then come back, it shows the correct value
> * it assumes you can build road on the tile you are standing on
> * waypoints might not work (but I think they do)
> * it doesn't take into account that engineers build twice as fast as
> workers.

Here is an update of this patch.  I didn't change anything just updated
the server and common parts.  So it's a bit shorter now.

jason

Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.334
diff -u -r1.334 aiunit.c
--- ai/aiunit.c 1 Sep 2004 11:47:25 -0000       1.334
+++ ai/aiunit.c 3 Sep 2004 04:59:42 -0000
@@ -196,7 +196,7 @@
 
   result =
       test_unit_move_to_tile(punit->type, unit_owner(punit),
-                             ACTIVITY_IDLE, FALSE, punit->x, punit->y, 
+                             ACTIVITY_IDLE, punit->x, punit->y, 
                              dest_x, dest_y, unit_flag(punit, F_IGZOC));
   if (result == MR_OK) {
     return 1;
Index: client/control.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.c,v
retrieving revision 1.139
diff -u -r1.139 control.c
--- client/control.c    2 Aug 2004 16:59:14 -0000       1.139
+++ client/control.c    3 Sep 2004 04:59:42 -0000
@@ -633,6 +633,12 @@
     /* Enter or change the hover connect state. */
     set_hover_state(punit_focus, HOVER_CONNECT, activity);
     update_unit_info_label(punit_focus);
+
+    enter_goto_state(punit_focus);
+    create_line_at_mouse_pos();
+  } else {
+    assert(goto_is_active());
+    goto_add_waypoint();
   }
 }
 
@@ -1632,13 +1638,23 @@
 void do_unit_connect(struct unit *punit, int x, int y,
                     enum unit_activity activity)
 {
-  struct packet_unit_connect req;
+  if (is_air_unit(punit)) {
+    append_output_window(_("Game: Sorry, airunit connect "
+                          "not yet implemented."));
+  } else {
+    int dest_x, dest_y;
 
-  req.activity_type = activity;
-  req.unit_id = punit->id;
-  req.dest_x = x;
-  req.dest_y = y;
-  send_packet_unit_connect(&aconnection, &req);
+    draw_line(x, y);
+    get_line_dest(&dest_x, &dest_y);
+    if (same_pos(dest_x, dest_y, x, y)) {
+      send_connect_route(punit, activity);
+    } else {
+      append_output_window(_("Game: Didn't find a route to "
+                            "the destination!"));
+    }
+  }
+
+  set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST);
 }
  
 /**************************************************************************
Index: client/goto.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/goto.c,v
retrieving revision 1.71
diff -u -r1.71 goto.c
--- client/goto.c       26 Aug 2004 18:37:51 -0000      1.71
+++ client/goto.c       3 Sep 2004 04:59:43 -0000
@@ -75,11 +75,15 @@
 static void decrement_drawn(int src_x, int src_y, enum direction8 dir);
 static void reset_last_part(void);
 
+static int get_activity_time(int map_x, int map_y, struct player *pplayer);
+
+
 /**************************************************************************
   Various stuff for the goto routes
 **************************************************************************/
 static bool is_active = FALSE;
 static bool is_init = FALSE;
+static int connect_extra;
 
 /********************************************************************** 
   Called once per game.
@@ -196,7 +200,18 @@
   p->end_x = x;
   p->end_y = y;
   p->end_moves_left = pf_last_position(p->path)->moves_left;
-  p->time = pf_last_position(p->path)->turn;
+
+  if (hover_state == HOVER_CONNECT) {
+    int move_rate = goto_map.template.move_rate;
+    int moves = pf_last_position(p->path)->total_MC;
+
+    p->time = moves / move_rate;
+    if (connect_extra > 0) {
+      p->time += connect_extra;
+    }
+  } else {
+    p->time = pf_last_position(p->path)->turn;
+  }
 
   /* Refresh tiles so turn information is shown. */
   refresh_tile_mapcanvas(old_x, old_y, FALSE);
@@ -246,6 +261,7 @@
     p->start_x = prev->end_x;
     p->start_y = prev->end_y;
     p->start_moves_left = prev->end_moves_left;
+    parameter.moves_left_initially = p->start_moves_left;
   }
   p->path = NULL;
   p->end_x = p->start_x;
@@ -253,7 +269,6 @@
   p->time = 0;
   parameter.start_x = p->start_x;
   parameter.start_y = p->start_y;
-  parameter.moves_left_initially = p->start_moves_left;
   p->map = pf_create_map(&parameter);
 }
 
@@ -375,6 +390,202 @@
   return TB_NORMAL;
 }
 
+/****************************************************************************
+  Return the number of MP needed to do the connect activity at this
+  position.  A negative number means it's impossible.
+****************************************************************************/
+static int get_activity_time(int map_x, int map_y, struct player *pplayer)
+{
+  struct tile *ptile = map_get_tile(map_x, map_y);
+  struct tile_type *ttype = get_tile_type(ptile->terrain);
+  int activity_mc = 0;
+
+  assert(hover_state == HOVER_CONNECT);
+
+  switch (connect_activity) {
+  case ACTIVITY_IRRIGATE:
+    if (ttype->irrigation_time == 0) {
+      return -1;
+    }
+    if (map_has_special(map_x, map_y, S_MINE)) {
+      /* Don't overwrite mines. */
+      return -1;
+    }
+
+    if (tile_has_special(ptile, S_IRRIGATION)) {
+      break;
+    }
+
+    activity_mc = ttype->irrigation_time;
+    break;
+  case ACTIVITY_ROAD:
+    assert(terrain_control.may_road);
+    if (tile_has_special(ptile, S_ROAD)) {
+      break;
+    }
+    if (ttype->road_time == 0
+       || (tile_has_special(ptile, S_RIVER)
+           && !player_knows_techs_with_flag(pplayer, TF_BRIDGE))) {
+      /* 0 means road is impossible here (??) */
+      return -1;
+    }
+    activity_mc = ttype->road_time;
+    break;
+  case ACTIVITY_RAILROAD:
+    assert(terrain_control.may_road);
+    if (!map_has_special(map_x, map_y, S_RAILROAD)
+       && (ttype->road_time == 0
+           || (map_has_special(map_x, map_y, S_RIVER)
+               && !player_knows_techs_with_flag(pplayer,
+                                                TF_BRIDGE)))) {
+      return -1;
+    }
+
+    if (tile_has_special(ptile, S_RAILROAD)) {
+      break;
+    } else {
+      if (!tile_has_special(ptile, S_ROAD)) {
+       /* Have to build road first. */
+       activity_mc += ttype->road_time;
+      }
+      activity_mc += ttype->road_time;
+    }
+    break;
+  default:
+    die("Invalid connect activity.");
+  }
+
+  return activity_mc;
+}
+
+#if 0
+/****************************************************************************
+  PF callback for the cost of a connect.  In connect mode we are primarily
+  concerned with number of steps.
+****************************************************************************/
+static int get_connect_MC(int src_x, int src_y, enum direction8 dir,
+                         int dest_x, int dest_y, struct pf_parameter *param)
+{
+  int (*original_MC) (int src_x, int src_y, enum direction8 dir,
+                     int dest_x, int dest_y,
+                     struct pf_parameter *param) = param->data;
+  int base_mc = original_MC(src_x, src_y, dir, dest_x, dest_y, param);
+  int activity_mc = get_activity_MC(dest_x, dest_y, param);
+  int activity_mc2 = 0;
+
+  if (same_pos(src_x, src_y, param->start_x, param->start_y)) {
+    activity_mc2 = get_activity_MC(src_x, src_y, param);
+  }
+
+  if (base_mc == PF_IMPOSSIBLE_MC || activity_mc < 0 || activity_mc2 < 0) {
+    return PF_IMPOSSIBLE_MC;
+  }
+
+  assert(hover_state == HOVER_CONNECT);
+  switch (connect_activity) {
+  case ACTIVITY_IRRIGATE:
+    if (!is_cardinal_dir(dir)) {
+      /* Only cardinal moves allowed. */
+      return PF_IMPOSSIBLE_MC;
+    }
+
+    /* Otherwise distance doesn't matter. */
+    return 0;
+  case ACTIVITY_ROAD:
+    /* We just want a minimal distance path. */
+    return SINGLE_MOVE;
+  case ACTIVITY_RAILROAD:
+    /* We don't care about distance, just build time. */
+    return 0;
+  default:
+    break;
+  }
+
+  assert(0);
+  return 0;
+}
+#endif
+
+/****************************************************************************
+  PF jumbo callback for the cost of a connect by road. 
+  In road-connect mode we are concerned with 
+  (1) the number of steps of the resulting path
+  (2) (the tie-breaker) time to build the path (travel plus activity time).
+****************************************************************************/
+static int get_connect_road(int src_x, int src_y, enum direction8 dir,
+                           int dest_x, int dest_y, 
+                           int src_cost, int src_extra,
+                           int *dest_cost, int *dest_extra,
+                           struct pf_parameter *param)
+{
+  int activity_time;
+  int move_cost;
+  int moves_left;
+  int total_cost, total_extra;
+
+  if (map_get_known(dest_x, dest_y, param->owner) == TILE_UNKNOWN) {
+    return -1;
+  }
+
+  activity_time = get_activity_time(dest_x, dest_y, param->owner);  
+  if (activity_time < 0) {
+    return -1;
+  }
+
+  move_cost = param->get_MC(src_x, src_y, dir, dest_x, dest_y, param);
+  if (move_cost == PF_IMPOSSIBLE_MC) {
+    return -1;
+  }
+
+  /* TODO: ZoC */
+
+  /* Ok, the move is possible.  Does it give us good results? */
+
+  /* When connecting by road, we care most about the final distance */
+  total_extra = src_extra + 1;
+  /* *dest_cost==-1 means we haven't reached dest until now */
+  if (*dest_cost != -1 && total_extra > *dest_extra) {
+    /* No, this path is worse than what we already have */
+    return -1;
+  }
+
+  /* A special case: get_MC function doesn't know that we would have built
+   * a road on src tile by that time */
+  if (map_has_special(dest_x, dest_y, S_ROAD)) {
+    move_cost = MOVE_COST_ROAD;
+  }
+
+  move_cost = MIN(move_cost, param->move_rate);
+  total_cost = src_cost;
+  moves_left = param->move_rate - (src_cost % param->move_rate);
+  if (moves_left < move_cost) {
+    /* Emulating TM_WORST_TIME */
+    total_cost += moves_left;
+  }
+  total_cost += move_cost;
+
+  /* Now need to include the activity cost.  If we have moves left, they
+   * will count as a full turn towards the activity time */
+  moves_left = param->move_rate - (total_cost % param->move_rate);
+  if (activity_time > 0) {
+    activity_time--;
+    total_cost += moves_left;
+  }
+  total_cost += activity_time * param->move_rate;
+
+  if (*dest_cost != -1 && total_extra == *dest_extra
+      && total_cost >= *dest_cost) {
+    /* New path has same length but longer construction time */
+    return -1;
+  }
+
+  /* Ok, we found a better path! */  
+  *dest_cost = total_cost;
+  *dest_extra = total_extra;
+  
+  return total_extra * PF_TURN_FACTOR + total_cost;
+}
+
 /********************************************************************** 
   Fill the PF parameter with the correct client-goto values.
 ***********************************************************************/
@@ -385,6 +596,24 @@
   assert(parameter->get_EC == NULL);
   parameter->get_EC = get_EC;
   assert(parameter->get_TB == NULL);
+  assert(parameter->get_MC != NULL);
+  if (hover_state == HOVER_CONNECT) {
+    connect_extra = get_activity_time(punit->x, punit->y, 
+                                     unit_owner(punit));
+
+    /* FIXME: Do other activities */
+    parameter->get_costs = get_connect_road;
+    parameter->is_pos_dangerous = NULL;
+
+    assert(connect_extra >= 0);
+    if (connect_extra > 0) {
+      parameter->moves_left_initially = 0;
+      if (punit->moves_left == 0) {
+       connect_extra++;
+      }
+    } /* otherwise moves_left_initially = punit->moves_left (default) */
+  }
+
   if (is_attack_unit(punit) || is_diplomat_unit(punit)) {
     parameter->get_TB = get_TB_aggr;
   } else if (unit_flag(punit, F_TRADE_ROUTE)
@@ -393,15 +622,16 @@
   } else {
     parameter->get_TB = no_fights_or_unknown;
   }
+
+  /* Note that in connect mode the "time" does not correspond to any actual
+   * move rate. */
   parameter->turn_mode = TM_WORST_TIME;
+
   parameter->start_x = punit->x;
   parameter->start_y = punit->y;
 
   /* Omniscience is always FALSE in the client */
   parameter->omniscience = FALSE;
-
-  /* May be overwritten by the caller. */
-  parameter->moves_left_initially = punit->moves_left;
 }
 
 /********************************************************************** 
@@ -551,6 +781,7 @@
       p.activity[i] = ACTIVITY_LAST;
       freelog(PACKET_LOG_LEVEL, "  packet[%d] = move %s: %d,%d => %d,%d",
              i, dir_get_name(p.dir[i]), old_x, old_y, new_x, new_y);
+      p.activity[i] = ACTIVITY_LAST;
     }
     old_x = new_x;
     old_y = new_y;
@@ -609,6 +840,87 @@
 }
 
 /**************************************************************************
+  Send the current connect route (i.e., the one generated via HOVER_STATE)
+  to the server.
+**************************************************************************/
+void send_connect_route(struct unit *punit, enum unit_activity activity)
+{
+  struct pf_path *path = NULL;
+  int i;
+  struct packet_unit_orders p;
+  int old_x, old_y;
+
+  assert(is_active);
+  assert(punit->id == goto_map.unit_id);
+
+  memset(&p, 0, sizeof(p));
+
+  for (i = 0; i < goto_map.num_parts; i++) {
+    path = pft_concat(path, goto_map.parts[i].path);
+  }
+
+  p.unit_id = punit->id;
+  p.repeat = FALSE;
+  p.vigilant = FALSE; /* Should be TRUE? */
+
+  p.length = 0;
+  old_x = path->positions[0].x;
+  old_y = path->positions[0].y;
+
+  for (i = 0; i < path->length; i++) {
+    switch (activity) {
+    case ACTIVITY_IRRIGATE:
+      if (!map_has_special(old_x, old_y, S_IRRIGATION)) {
+       /* Assume the unit can irrigate or we wouldn't be here. */
+       p.orders[p.length] = ORDER_ACTIVITY;
+       p.activity[p.length] = ACTIVITY_IRRIGATE;
+       p.length++;
+      }
+      break;
+    case ACTIVITY_ROAD:
+    case ACTIVITY_RAILROAD:
+      if (!map_has_special(old_x, old_y, S_ROAD)) {
+       /* Assume the unit can build the road or we wouldn't be here. */
+       p.orders[p.length] = ORDER_ACTIVITY;
+       p.activity[p.length] = ACTIVITY_ROAD;
+       p.length++;
+      }
+      if (activity == ACTIVITY_RAILROAD) {
+       if (!map_has_special(old_x, old_y, S_RAILROAD)) {
+         /* Assume the unit can build the rail or we wouldn't be here. */
+         p.orders[p.length] = ORDER_ACTIVITY;
+         p.activity[p.length] = ACTIVITY_RAILROAD;
+         p.length++;
+       }
+      }
+      break;
+    default:
+      die("Invalid connect activity.");
+      break;
+    }
+
+    if (i != path->length - 1) {
+      int new_x = path->positions[i + 1].x;
+      int new_y = path->positions[i + 1].y;
+
+      assert(!same_pos(new_x, new_y, old_x, old_y));
+
+      p.orders[p.length] = ORDER_MOVE;
+      p.dir[p.length] = get_direction_for_step(old_x, old_y, new_x, new_y);
+      p.length++;
+
+      old_x = new_x;
+      old_y = new_y;
+    }
+  }
+
+  p.dest_x = old_x;
+  p.dest_y = old_y;
+
+  send_packet_unit_orders(&aconnection, &p);
+}
+
+/**************************************************************************
   Send the current goto route (i.e., the one generated via
   HOVER_STATE) to the server.  The route might involve more than one
   part if waypoints were used.  FIXME: danger paths are not supported.
Index: client/goto.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/goto.h,v
retrieving revision 1.13
diff -u -r1.13 goto.h
--- client/goto.h       21 Jun 2004 15:14:43 -0000      1.13
+++ client/goto.h       3 Sep 2004 04:59:43 -0000
@@ -36,6 +36,7 @@
 void send_goto_path(struct unit *punit, struct pf_path *path);
 void send_patrol_route(struct unit *punit);
 void send_goto_route(struct unit *punit);
+void send_connect_route(struct unit *punit, enum unit_activity activity);
 
 struct pf_path *path_to_nearest_allied_city(struct unit *punit);
 
Index: client/mapctrl_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapctrl_common.c,v
retrieving revision 1.39
diff -u -r1.39 mapctrl_common.c
--- client/mapctrl_common.c     2 Aug 2004 16:59:14 -0000       1.39
+++ client/mapctrl_common.c     3 Sep 2004 04:59:43 -0000
@@ -625,7 +625,9 @@
 **************************************************************************/
 void update_line(int canvas_x, int canvas_y)
 {
-  if ((hover_state == HOVER_GOTO || hover_state == HOVER_PATROL)
+  if ((hover_state == HOVER_GOTO
+       || hover_state == HOVER_PATROL
+       || hover_state == HOVER_CONNECT)
       && draw_goto_line) {
     int x, y, old_x, old_y;
 
@@ -645,7 +647,9 @@
 ****************************************************************************/
 void overview_update_line(int overview_x, int overview_y)
 {
-  if ((hover_state == HOVER_GOTO || hover_state == HOVER_PATROL)
+  if ((hover_state == HOVER_GOTO
+       || hover_state == HOVER_PATROL
+       || hover_state == HOVER_CONNECT)
       && draw_goto_line) {
     int x, y, old_x, old_y;
 
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.400
diff -u -r1.400 packhand.c
--- client/packhand.c   31 Aug 2004 04:40:48 -0000      1.400
+++ client/packhand.c   3 Sep 2004 04:59:43 -0000
@@ -105,7 +105,6 @@
   }
   punit->activity_target = packet->activity_target;
   punit->paradropped = packet->paradropped;
-  punit->connecting = packet->connecting;
   punit->done_moving = packet->done_moving;
   punit->occupy = packet->occupy;
   if (packet->transported) {
@@ -1184,7 +1183,6 @@
       clear_goto_dest(punit);
     }
     punit->paradropped = packet_unit->paradropped;
-    punit->connecting = packet_unit->connecting;
     if (punit->done_moving != packet_unit->done_moving) {
       punit->done_moving = packet_unit->done_moving;
       check_focus = TRUE;
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.196
diff -u -r1.196 tilespec.c
--- client/tilespec.c   25 Aug 2004 18:24:18 -0000      1.196
+++ client/tilespec.c   3 Sep 2004 04:59:44 -0000
@@ -2002,13 +2002,11 @@
     }
   }
 
-  if (punit->connecting) {
-    ADD_SPRITE_FULL(sprites.unit.connect);
-  }
-
   if (unit_has_orders(punit)) {
     if (punit->orders.repeat) {
       ADD_SPRITE_FULL(sprites.unit.patrol);
+    } else if (punit->activity != ACTIVITY_IDLE) {
+      ADD_SPRITE_SIMPLE(sprites.unit.connect);
     } else {
       ADD_SPRITE_FULL(sprites.unit.go_to);
     }
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.45
diff -u -r1.45 packets.def
--- common/packets.def  3 Sep 2004 03:56:58 -0000       1.45
+++ common/packets.def  3 Sep 2004 04:59:44 -0000
@@ -727,13 +727,6 @@
   CITY city_id;
 end
 
-PACKET_UNIT_CONNECT=66;cs
-  UNIT unit_id;
-  ACTIVITY activity_type;
-  COORD dest_x;
-  COORD dest_y;
-end
-
 PACKET_UNIT_BRIBE_INQ=67;cs,handle-per-conn,dsend
   UNIT unit_id;
 end
Index: common/unit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.c,v
retrieving revision 1.216
diff -u -r1.216 unit.c
--- common/unit.c       31 Aug 2004 04:40:50 -0000      1.216
+++ common/unit.c       3 Sep 2004 04:59:45 -0000
@@ -785,9 +785,6 @@
               (current == ACTIVITY_FORTIFIED) ? ACTIVITY_FORTIFYING : current;
   bool result;
 
-  if (punit->connecting)
-    return can_unit_do_connect(punit, current);
-
   punit->activity = ACTIVITY_IDLE;
   punit->activity_target = S_NO_SPECIAL;
 
@@ -1012,7 +1009,6 @@
   punit->activity=new_activity;
   punit->activity_count=0;
   punit->activity_target = S_NO_SPECIAL;
-  punit->connecting = FALSE;
   if (new_activity == ACTIVITY_IDLE && punit->moves_left > 0) {
     /* No longer done. */
     punit->done_moving = FALSE;
@@ -1502,14 +1498,14 @@
                           bool igzoc)
 {
   return MR_OK == test_unit_move_to_tile(punit->type, unit_owner(punit),
-                                        punit->activity, punit->connecting,
+                                        punit->activity,
                                         punit->x, punit->y, dest_x, dest_y,
                                         igzoc);
 }
 
 /**************************************************************************
   unit can be moved if:
-  1) the unit is idle or on goto or connecting.
+  1) the unit is idle or on server goto.
   2) the target location is on the map
   3) the target location is next to the unit
   4) there are no non-allied units on the target tile
@@ -1524,9 +1520,9 @@
 enum unit_move_result test_unit_move_to_tile(Unit_Type_id type,
                                             struct player *unit_owner,
                                             enum unit_activity activity,
-                                            bool connecting, int src_x,
-                                            int src_y, int dest_x,
-                                            int dest_y, bool igzoc)
+                                            int src_x, int src_y,
+                                            int dest_x, int dest_y,
+                                            bool igzoc)
 {
   struct tile *pfromtile, *ptotile;
   bool zoc;
@@ -1534,8 +1530,7 @@
 
   /* 1) */
   if (activity != ACTIVITY_IDLE
-      && activity != ACTIVITY_GOTO
-      && !connecting) {
+      && activity != ACTIVITY_GOTO) {
     return MR_BAD_ACTIVITY;
   }
 
@@ -1744,7 +1739,6 @@
   punit->moves_left = unit_move_rate(punit);
   punit->moved = FALSE;
   punit->paradropped = FALSE;
-  punit->connecting = FALSE;
   punit->done_moving = FALSE;
   if (is_barbarian(pplayer)) {
     punit->fuel = BARBARIAN_LIFE;
Index: common/unit.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.h,v
retrieving revision 1.123
diff -u -r1.123 unit.h
--- common/unit.h       3 Sep 2004 04:22:37 -0000       1.123
+++ common/unit.h       3 Sep 2004 04:59:45 -0000
@@ -160,7 +160,6 @@
   bool debug;
   bool moved;
   bool paradropped;
-  bool connecting;
 
   /* This value is set if the unit is done moving for this turn. This
    * information is used by the client.  The invariant is:
@@ -335,9 +334,9 @@
 enum unit_move_result test_unit_move_to_tile(Unit_Type_id type,
                                             struct player *unit_owner,
                                             enum unit_activity activity,
-                                            bool connecting, int src_x,
-                                            int src_y, int dest_x,
-                                            int dest_y, bool igzoc);
+                                            int src_x, int src_y,
+                                            int dest_x, int dest_y,
+                                            bool igzoc);
 bool unit_type_really_ignores_zoc(Unit_Type_id type);
 bool zoc_ok_move(struct unit *punit, int x, int y);
 
Index: common/aicore/path_finding.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/aicore/path_finding.c,v
retrieving revision 1.21
diff -u -r1.21 path_finding.c
--- common/aicore/path_finding.c        6 Aug 2004 13:43:12 -0000       1.21
+++ common/aicore/path_finding.c        3 Sep 2004 04:59:45 -0000
@@ -106,7 +106,6 @@
   struct pf_node *lattice;      /* Lattice of nodes */
   utiny_t *status;             /* Array of node statuses 
                                 * (enum pf_node_status really) */
-  bool extras;                  /* Are any extra-cost callbacks supplied? */
   struct pqueue *danger_queue; /* Dangerous positions go there */
   struct danger_node *d_lattice;       /* Lattice with danger stuff */
 };
@@ -189,7 +188,7 @@
   Calculates cached values of the target node: 
   node_known_type and zoc
 ******************************************************************/
-static void init_node(struct pf_map *pf_map, struct pf_node * node, 
+static void init_node(struct pf_map *pf_map, struct pf_node *node, 
                          int x, int y)
 {
   struct pf_parameter *params = pf_map->params;
@@ -232,7 +231,6 @@
   }
 }
 
-
 /*****************************************************************
   Obtain cost-of-path from pure cost and extra cost
 *****************************************************************/
@@ -241,6 +239,72 @@
   return PF_TURN_FACTOR * cost + extra * pf_map->params->move_rate;
 }
 
+/**************************************************************************
+  Bare-bones PF iterator.  All Freeciv rules logic is hidden in get_costs
+  callback (compare to pf_next function).
+  Plan: 1. Process previous position
+        2. Get new nearest position and return it
+**************************************************************************/
+static bool jumbo_iterate_map(struct pf_map *pf_map)
+{
+  mapindex_t index;
+  struct pf_node *node = &pf_map->lattice[pf_map->index];
+
+  pf_map->status[pf_map->index] = NS_PROCESSED;
+
+  /* Processing Stage */
+  /* The previous position is contained in {x,y} fields of map */
+
+  adjc_dir_iterate(pf_map->x, pf_map->y, x1, y1, dir) {
+    mapindex_t index1 = map_pos_to_index(x1, y1);
+    struct pf_node *node1 = &pf_map->lattice[index1];
+    utiny_t *status = &pf_map->status[index1];
+    int priority;    
+
+
+    if (*status == NS_PROCESSED) {
+      /* This gives 15% speedup */
+      continue;
+    }
+
+    if (*status == NS_UNINIT) {
+      node1->cost = -1;
+    }
+
+    /* User-supplied callback get_costs takes care of everything (ZOC, 
+     * known, costs etc).  See explanations in path_finding.h */
+    priority = pf_map->params->get_costs(pf_map->x, pf_map->y, dir, x1, y1, 
+                                        node->cost, node->extra_cost,
+                                        &node1->cost, &node1->extra_cost, 
+                                        pf_map->params);
+    if (priority >= 0) {
+      /* We found a better route to xy1, record it 
+       * (the costs are recorded already) */
+      *status = NS_NEW;
+      node1->dir_to_here = dir;
+      pq_insert(pf_map->queue, index1, -priority);
+    }
+
+  } adjc_dir_iterate_end;
+
+  /* Get the next nearest node */
+  for (;;) {
+    bool removed = pq_remove(pf_map->queue, &index);
+
+    if (!removed) {
+      return FALSE;
+    }
+    if (pf_map->status[index] == NS_NEW) {
+      break;
+    }
+    /* If the node has already been processed, get the next one. */
+  }
+
+  pf_map->index = index;
+  index_to_map_pos(&(pf_map->x), &(pf_map->y), index);
+
+  return TRUE;
+}
 
 /*****************************************************************
   Primary method for iterative path-finding.
@@ -257,6 +321,11 @@
     return danger_iterate_map(pf_map);
   }
 
+  if (pf_map->params->get_costs) {
+    /* It is somewhat different when we have the jumbo callback */
+    return jumbo_iterate_map(pf_map);
+  }
+
   pf_map->status[pf_map->index] = NS_PROCESSED;
 
   /* There is no exit from DONT_LEAVE tiles! */
@@ -308,17 +377,10 @@
       cost += node->cost;
 
       /* Evaluate the extra cost if it's relevant */
-      if (pf_map->extras) {
+      if (pf_map->params->get_EC) {
         extra = node->extra_cost;
-        if (pf_map->params->get_EC) {
-          /* Add the cached value */
-          extra += node1->extra_tile;
-        }
-        if (pf_map->params->get_moveEC) {
-          /* This one cannot be cached */
-          extra += pf_map->params->get_moveEC(pf_map->x, pf_map->y, dir, 
-                                              x1, y1, pf_map->params);
-        }
+       /* Add the cached value */
+       extra += node1->extra_tile;
       }
 
       /* Update costs and add to queue, if we found a better route to xy1. */
@@ -336,8 +398,7 @@
        }
       }
 
-    }
-    adjc_dir_iterate_end;
+    } adjc_dir_iterate_end;
   }
 
   /* Get the next nearest node */
@@ -417,13 +478,9 @@
     pf_map->d_lattice[pf_map->index].step = 0;
   }
 
-  pf_map->extras = (parameter->get_EC != NULL 
-                    || parameter->get_moveEC != NULL);
-
   return pf_map;
 }
 
-
 /*********************************************************************
   After usage the map must be destroyed.
 *********************************************************************/
Index: common/aicore/path_finding.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/aicore/path_finding.h,v
retrieving revision 1.8
diff -u -r1.8 path_finding.h
--- common/aicore/path_finding.h        6 Aug 2004 13:43:12 -0000       1.8
+++ common/aicore/path_finding.h        3 Sep 2004 04:59:45 -0000
@@ -324,11 +324,6 @@
   int (*get_EC) (int x, int y, enum known_type known,
                 struct pf_parameter * param);
 
-  /* Same as above but this extra cost may depend on both origin and target
-   * tiles. Can be NULL. */
-  int (*get_moveEC) (int from_x, int from_y, enum direction8 dir,
-                     int to_x, int to_y, struct pf_parameter * param);
-
   /* Although the rules governing ZoC are universal, the amount of
    * information available at server and client is different. To 
    * compensate for it, we might need to supply our own version 
@@ -344,6 +339,32 @@
   bool (*is_pos_dangerous) (int x, int y, enum known_type,
                             struct pf_parameter * param);
 
+  /* This is a jumbo callback which overrides all previous ones.  It takes 
+   * care of everything (ZOC, known, costs etc).  
+   * Variables:
+   *   from_x, from_y        -- position of the source tile
+   *   from_cost, from_extra -- costs of the source tile
+   *   to_x, to_y            -- position of the dest tile
+   *   to_cost, to_extra     -- costs of the dest tile
+   *   dir                   -- direction from source to dest
+   *   param                 -- a pointer to this struct
+   * If the dest tile hasn't been reached before, to_cost is -1.
+   *
+   * The callback should:
+   * - evaluate the costs of the move
+   * - calculate the cost of the whole path
+   * - compare it to the ones recorded at dest tile
+   * - if new cost are not better, return -1
+   * - if new costs are better, record them in to_cost/to_extra and return
+   *   the cost-of-the-path which is the overall measure of goodness of the 
+   *   path (less is better) and used to order newly discovered locations. */
+  int (*get_costs) (int from_x, int from_y, 
+                   enum direction8 dir,
+                   int to_x, int to_y, 
+                   int from_cost, int from_extra,
+                   int *to_cost, int *to_extra,
+                   struct pf_parameter *param);
+
   /* User provided data. Can be used to attach arbitrary information
    * to the map. */
   void *data;
Index: common/aicore/pf_tools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/aicore/pf_tools.c,v
retrieving revision 1.20
diff -u -r1.20 pf_tools.c
--- common/aicore/pf_tools.c    25 Aug 2004 18:24:20 -0000      1.20
+++ common/aicore/pf_tools.c    3 Sep 2004 04:59:45 -0000
@@ -544,7 +544,6 @@
   parameter->turn_mode = TM_CAPPED;
   parameter->get_TB = NULL;
   parameter->get_EC = NULL;
-  parameter->get_moveEC = NULL;
   parameter->is_pos_dangerous = NULL;
   parameter->get_zoc = NULL;
   BV_CLR_ALL(parameter->unit_flags);
Index: server/gotohand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gotohand.c,v
retrieving revision 1.183
diff -u -r1.183 gotohand.c
--- server/gotohand.c   1 Sep 2004 19:54:18 -0000       1.183
+++ server/gotohand.c   3 Sep 2004 04:59:46 -0000
@@ -1314,7 +1314,6 @@
   if (same_pos(punit->x, punit->y, dest_x, dest_y) ||
       !goto_is_sane(punit, dest_x, dest_y, FALSE)) {
     punit->activity = ACTIVITY_IDLE;
-    punit->connecting = FALSE;
     send_unit_info(NULL, punit);
     if (same_pos(punit->x, punit->y, dest_x, dest_y)) {
       return GR_ARRIVED;
@@ -1342,7 +1341,6 @@
              pplayer->name, unit_type(punit)->name,
              punit->x, punit->y, dest_x, dest_y);
       punit->activity = ACTIVITY_IDLE;
-      punit->connecting = FALSE;
       send_unit_info(NULL, punit);
       return GR_FAILED;
     }
@@ -1406,13 +1404,6 @@
        return GR_OUT_OF_MOVEPOINTS;
       }
 
-      /* single step connecting unit when it can do it's activity */
-      if (punit->connecting
-         && can_unit_do_activity(punit, punit->activity)) {
-       /* for connecting unit every step is a destination */
-       return GR_ARRIVED;
-      }
-
       freelog(LOG_DEBUG, "Moving on.");
     } while(!same_pos(x, y, waypoint_x, waypoint_y));
   } else {
@@ -1421,17 +1412,11 @@
            pplayer->name, unit_type(punit)->name,
            punit->x, punit->y, dest_x, dest_y);
     handle_unit_activity_request(punit, ACTIVITY_IDLE);
-    punit->connecting = FALSE;
     send_unit_info(NULL, punit);
     return GR_FAILED;
   }
   /** Finished moving the unit for this turn **/
 
-  /* ensure that the connecting unit will perform it's activity
-     on the destination file too. */
-  if (punit->connecting && can_unit_do_activity(punit, punit->activity))
-    return GR_ARRIVED;
-
   /* normally we would just do this unconditionally, but if we had an
      airplane goto we might not be finished even if the loop exited */
   if (same_pos(punit->x, punit->y, dest_x, dest_y)) {
@@ -1442,7 +1427,6 @@
     status = GR_OUT_OF_MOVEPOINTS;
   }
 
-  punit->connecting = FALSE;
   send_unit_info(NULL, punit);
   return status;
 }
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.183
diff -u -r1.183 savegame.c
--- server/savegame.c   3 Sep 2004 01:21:03 -0000       1.183
+++ server/savegame.c   3 Sep 2004 04:59:47 -0000
@@ -1289,9 +1289,6 @@
       = secfile_lookup_int_default(file, (int) S_NO_SPECIAL,
                                   "player%d.u%d.activity_target", plrno, i);
 
-    punit->connecting
-      = secfile_lookup_bool_default(file, FALSE,
-                                   "player%d.u%d.connecting", plrno, i);
     punit->done_moving = secfile_lookup_bool_default(file,
        (punit->moves_left == 0), "player%d.u%d.done_moving", plrno, i);
 
@@ -1360,7 +1357,7 @@
                        "player%d.u%d.activity_list", plrno, i);
        punit->has_orders = TRUE;
        for (j = 0; j < len; j++) {
-         if (orders_buf[j] == '\0' || dir_buf == '\0'
+         if (orders_buf[j] == '\0' || dir_buf[j] == '\0'
              || act_buf[j] == '\0') {
            freelog(LOG_ERROR, _("Savegame error: invalid unit orders."));
            free_unit_orders(punit);
@@ -2405,9 +2402,6 @@
     secfile_insert_int(file, punit->activity_target, 
                                "player%d.u%d.activity_target",
                                plrno, i);
-    secfile_insert_bool(file, punit->connecting, 
-                               "player%d.u%d.connecting",
-                               plrno, i);
     secfile_insert_bool(file, punit->done_moving,
                        "player%d.u%d.done_moving", plrno, i);
     secfile_insert_int(file, punit->moves_left, "player%d.u%d.moves",
Index: server/unithand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
retrieving revision 1.303
diff -u -r1.303 unithand.c
--- server/unithand.c   26 Aug 2004 18:37:52 -0000      1.303
+++ server/unithand.c   3 Sep 2004 04:59:47 -0000
@@ -101,44 +101,6 @@
 }
 
 /**************************************************************************
-Handler for PACKET_UNIT_CONNECT request. The unit is send on way and will 
-build something (roads only for now) along the way, using server-side
-path-finding. 
-
-FIXME: This should be rewritten to use client-side path finding along so 
-that we can show in the client where the road-to-be-built will be and 
-enable the use of waypoints to alter this route. - Per
-**************************************************************************/
-void handle_unit_connect(struct player *pplayer, int unit_id,
-                        enum unit_activity activity_type, int dest_x,
-                        int dest_y)
-{
-  struct unit *punit = player_find_unit_by_id(pplayer, unit_id);
-
-  if (!is_normal_map_pos(dest_x, dest_y) || !punit
-      || !can_unit_do_connect(punit, activity_type)) {
-    return;
-  }
-
-  set_goto_dest(punit, dest_x, dest_y);
-
-  set_unit_activity(punit, activity_type);
-  punit->connecting = TRUE;
-
-  send_unit_info(NULL, punit);
-
-  /* 
-   * Avoid wasting first turn if unit cannot do the activity on the
-   * starting tile.
-   */
-  if (!can_unit_do_activity(punit, activity_type)) {
-    (void) do_unit_goto(punit,
-                       get_activity_move_restriction(activity_type),
-                       FALSE);
-  }
-}
-
-/**************************************************************************
  Upgrade all units of a given type.
 **************************************************************************/
 void handle_unit_type_upgrade(struct player *pplayer, Unit_Type_id type)
@@ -947,7 +909,7 @@
 
   reason =
       test_unit_move_to_tile(punit->type, unit_owner(punit),
-                            punit->activity, punit->connecting,
+                            punit->activity,
                             punit->x, punit->y, dest_x, dest_y, igzoc);
   if (reason == MR_OK)
     return TRUE;
@@ -1625,6 +1587,7 @@
     return;
   }
 
+
   for (i = 0; i < packet->length; i++) {
     switch (packet->orders[i]) {
     case ORDER_MOVE:
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.301
diff -u -r1.301 unittools.c
--- server/unittools.c  3 Sep 2004 03:56:59 -0000       1.301
+++ server/unittools.c  3 Sep 2004 04:59:48 -0000
@@ -593,20 +593,6 @@
 
   unit_restore_movepoints(pplayer, punit);
 
-  if (punit->connecting && !can_unit_do_activity(punit, activity)) {
-    punit->activity_count = 0;
-    if (do_unit_goto(punit, get_activity_move_restriction(activity), FALSE)
-       == GR_DIED) {
-      return;
-    }
-  }
-
-  /* if connecting, automagically build prerequisities first */
-  if (punit->connecting && activity == ACTIVITY_RAILROAD &&
-      !map_has_special(punit->x, punit->y, S_ROAD)) {
-    activity = ACTIVITY_ROAD;
-  }
-
   if (activity == ACTIVITY_EXPLORE) {
     bool more_to_explore = ai_manage_explorer(punit);
 
@@ -779,18 +765,8 @@
     send_tile_info(NULL, punit->x, punit->y);
     unit_list_iterate (map_get_tile(punit->x, punit->y)->units, punit2) {
       if (punit2->activity == activity) {
-       bool alive = TRUE;
-       if (punit2->connecting) {
-         punit2->activity_count = 0;
-         alive = (do_unit_goto(punit2,
-                               get_activity_move_restriction(activity),
-                               FALSE) != GR_DIED);
-       } else {
-         set_unit_activity(punit2, ACTIVITY_IDLE);
-       }
-       if (alive) {
-         send_unit_info(NULL, punit2);
-       }
+       set_unit_activity(punit2, ACTIVITY_IDLE);
+       send_unit_info(NULL, punit2);
       }
     } unit_list_iterate_end;
   }
@@ -1831,7 +1807,6 @@
   }
   packet->activity_target = punit->activity_target;
   packet->paradropped = punit->paradropped;
-  packet->connecting = punit->connecting;
   packet->done_moving = punit->done_moving;
   if (punit->transported_by == -1) {
     packet->transported = FALSE;
@@ -2625,8 +2600,7 @@
   if (punit->activity != ACTIVITY_IDLE
       && punit->activity != ACTIVITY_SENTRY
       && punit->activity != ACTIVITY_EXPLORE
-      && punit->activity != ACTIVITY_GOTO
-      && !punit->connecting) {
+      && punit->activity != ACTIVITY_GOTO) {
     set_unit_activity(punit, ACTIVITY_IDLE);
   }
 }

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#7282) Patch: connect as orders, Jason Short <=