[Freeciv-Dev] (PR#7282) Patch: connect as orders
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://rt.freeciv.org/Ticket/Display.html?id=7282 >
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.
G.
? connect.gz
Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.325
diff -u -r1.325 aiunit.c
--- ai/aiunit.c 7 Aug 2004 17:53:50 -0000 1.325
+++ ai/aiunit.c 10 Aug 2004 15:10:34 -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 10 Aug 2004 15:10:34 -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.70
diff -u -r1.70 goto.c
--- client/goto.c 21 Jun 2004 15:14:43 -0000 1.70
+++ client/goto.c 10 Aug 2004 15:10:34 -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(¶meter);
}
@@ -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;
}
/**********************************************************************
@@ -550,6 +780,7 @@
p.dir[i] = get_direction_for_step(old_x, old_y, new_x, new_y);
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;
@@ -608,6 +839,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 10 Aug 2004 15:10:34 -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 10 Aug 2004 15:10:34 -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.393
diff -u -r1.393 packhand.c
--- client/packhand.c 2 Aug 2004 16:59:14 -0000 1.393
+++ client/packhand.c 10 Aug 2004 15:10:34 -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) {
@@ -126,6 +125,7 @@
for (i = 0; i < punit->orders.length; i++) {
punit->orders.list[i].order = packet->orders[i];
punit->orders.list[i].dir = packet->orders_dirs[i];
+ punit->orders.list[i].activity = packet->orders_activities[i];
}
}
return punit;
@@ -1183,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.194
diff -u -r1.194 tilespec.c
--- client/tilespec.c 3 Aug 2004 00:09:44 -0000 1.194
+++ client/tilespec.c 10 Aug 2004 15:10:35 -0000
@@ -2001,13 +2001,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/capstr.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/capstr.c,v
retrieving revision 1.175
diff -u -r1.175 capstr.c
--- common/capstr.c 30 Jul 2004 20:40:49 -0000 1.175
+++ common/capstr.c 10 Aug 2004 15:10:35 -0000
@@ -78,7 +78,7 @@
"+change_production +tilespec1 +no_earth +trans " \
"+want_hack invasions bombard +killstack2 spec +spec2 " \
"+city_map startunits +turn_last_built +happyborders " \
- "+connid +love"
+ "+connid +love +connect"
/* "+1.14.delta" is the new delta protocol for 1.14.0-dev.
*
@@ -136,6 +136,8 @@
* info sent to clients.
*
* "love" means that we show the AI love for you in the client
+ *
+ * "connect" means the 'connect' function is done with client orders.
*/
void init_our_capability(void)
Index: common/map.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.h,v
retrieving revision 1.203
diff -u -r1.203 map.h
--- common/map.h 5 Aug 2004 10:41:34 -0000 1.203
+++ common/map.h 10 Aug 2004 15:10:35 -0000
@@ -575,6 +575,7 @@
struct unit_order {
enum unit_orders order;
enum direction8 dir; /* Only valid for ORDER_MOVE. */
+ enum unit_activity activity; /* Only valid for ORDER_ACTIVITY. */
};
/* return the reverse of the direction */
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.36
diff -u -r1.36 packets.def
--- common/packets.def 30 Jul 2004 20:40:49 -0000 1.36
+++ common/packets.def 10 Aug 2004 15:10:35 -0000
@@ -606,7 +606,7 @@
UINT8 veteran; add-cap(veteran)
BOOL veteran_old; remove-cap(veteran)
- BOOL ai, paradropped, connecting, transported, done_moving;
+ BOOL ai, paradropped, transported, done_moving;
UNIT_TYPE type;
UNIT transported_by; /* Only valid if transported is set. */
@@ -621,6 +621,7 @@
BOOL orders_repeat, orders_vigilant;
ORDERS orders[MAX_LEN_ROUTE:orders_length];
DIRECTION orders_dirs[MAX_LEN_ROUTE:orders_length];
+ ACTIVITY orders_activities[MAX_LEN_ROUTE:orders_length];
end
PACKET_UNIT_SHORT_INFO=50; is-info,sc,lsend
@@ -692,6 +693,7 @@
BOOL repeat, vigilant;
ORDERS orders[MAX_LEN_ROUTE:length];
DIRECTION dir[MAX_LEN_ROUTE:length];
+ ACTIVITY activity[MAX_LEN_ROUTE:length];
COORD dest_x, dest_y;
end
@@ -727,13 +729,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.214
diff -u -r1.214 unit.c
--- common/unit.c 2 Aug 2004 16:59:14 -0000 1.214
+++ common/unit.c 10 Aug 2004 15:10:35 -0000
@@ -784,9 +784,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;
@@ -1011,7 +1008,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;
@@ -1501,14 +1497,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
@@ -1523,9 +1519,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;
@@ -1533,8 +1529,7 @@
/* 1) */
if (activity != ACTIVITY_IDLE
- && activity != ACTIVITY_GOTO
- && !connecting) {
+ && activity != ACTIVITY_GOTO) {
return MR_BAD_ACTIVITY;
}
@@ -1743,7 +1738,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.121
diff -u -r1.121 unit.h
--- common/unit.h 2 Aug 2004 16:59:14 -0000 1.121
+++ common/unit.h 10 Aug 2004 15:10:35 -0000
@@ -41,7 +41,7 @@
/* Changing this enum will break savegame and network compatability. */
enum unit_orders {
- ORDER_MOVE, ORDER_FINISH_TURN,
+ ORDER_MOVE, ORDER_FINISH_TURN, ORDER_ACTIVITY,
ORDER_LAST
};
@@ -161,7 +161,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:
@@ -336,9 +335,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 10 Aug 2004 15:10:35 -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 10 Aug 2004 15:10:35 -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.19
diff -u -r1.19 pf_tools.c
--- common/aicore/pf_tools.c 6 Aug 2004 13:43:12 -0000 1.19
+++ common/aicore/pf_tools.c 10 Aug 2004 15:10:35 -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.181
diff -u -r1.181 gotohand.c
--- server/gotohand.c 9 Aug 2004 05:24:35 -0000 1.181
+++ server/gotohand.c 10 Aug 2004 15:10:35 -0000
@@ -1315,7 +1315,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;
@@ -1343,7 +1342,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;
}
@@ -1407,13 +1405,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 {
@@ -1422,17 +1413,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)) {
@@ -1443,7 +1428,6 @@
status = GR_OUT_OF_MOVEPOINTS;
}
- punit->connecting = FALSE;
send_unit_info(NULL, punit);
return status;
}
Index: server/hand_gen.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/hand_gen.c,v
retrieving revision 1.4
diff -u -r1.4 hand_gen.c
--- server/hand_gen.c 1 Apr 2004 23:46:26 -0000 1.4
+++ server/hand_gen.c 10 Aug 2004 15:10:35 -0000
@@ -228,14 +228,6 @@
((struct packet_unit_airlift *)packet)->city_id);
return TRUE;
- case PACKET_UNIT_CONNECT:
- handle_unit_connect(pplayer,
- ((struct packet_unit_connect *)packet)->unit_id,
- ((struct packet_unit_connect *)packet)->activity_type,
- ((struct packet_unit_connect *)packet)->dest_x,
- ((struct packet_unit_connect *)packet)->dest_y);
- return TRUE;
-
case PACKET_UNIT_BRIBE_INQ:
handle_unit_bribe_inq(pconn,
((struct packet_unit_bribe_inq *)packet)->unit_id);
Index: server/hand_gen.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/hand_gen.h,v
retrieving revision 1.4
diff -u -r1.4 hand_gen.h
--- server/hand_gen.h 1 Apr 2004 23:46:26 -0000 1.4
+++ server/hand_gen.h 10 Aug 2004 15:10:35 -0000
@@ -58,7 +58,6 @@
void handle_unit_nuke(struct player *pplayer, int unit_id);
void handle_unit_paradrop_to(struct player *pplayer, int unit_id, int x, int
y);
void handle_unit_airlift(struct player *pplayer, int unit_id, int city_id);
-void handle_unit_connect(struct player *pplayer, int unit_id, enum
unit_activity activity_type, int dest_x, int dest_y);
void handle_unit_bribe_inq(struct connection *pc, int unit_id);
void handle_unit_type_upgrade(struct player *pplayer, Unit_Type_id type);
void handle_unit_diplomat_action(struct player *pplayer, int diplomat_id, enum
diplomat_actions action_type, int target_id, int value);
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.175
diff -u -r1.175 savegame.c
--- server/savegame.c 8 Aug 2004 15:09:12 -0000 1.175
+++ server/savegame.c 10 Aug 2004 15:10:36 -0000
@@ -1200,9 +1200,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);
@@ -1252,7 +1249,7 @@
int len = secfile_lookup_int_default(file, 0,
"player%d.u%d.orders_length", plrno, i);
if (len > 0) {
- char *orders_buf, *dir_buf;
+ char *orders_buf, *dir_buf, *act_buf;
punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
punit->orders.length = len;
@@ -1267,14 +1264,18 @@
"player%d.u%d.orders_list", plrno, i);
dir_buf = secfile_lookup_str_default(file, "",
"player%d.u%d.dir_list", plrno, i);
+ act_buf = secfile_lookup_str_default(file, "",
+ "player%d.u%d.activity_list", plrno, i);
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);
break;
}
punit->orders.list[j].order = orders_buf[j] - 'a';
punit->orders.list[j].dir = dir_buf[j] - 'a';
+ punit->orders.list[j].activity = act_buf[j] - 'a';
}
punit->has_orders = TRUE;
} else {
@@ -2253,9 +2254,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",
@@ -2286,7 +2284,7 @@
"player%d.u%d.transported_by", plrno, i);
if (punit->has_orders) {
int len = punit->orders.length, j;
- char orders_buf[len + 1], dir_buf[len + 1];
+ char orders_buf[len + 1], dir_buf[len + 1], act_buf[len + 1];
secfile_insert_int(file, len, "player%d.u%d.orders_length", plrno, i);
secfile_insert_int(file, punit->orders.index,
@@ -2299,13 +2297,16 @@
for (j = 0; j < len; j++) {
orders_buf[j] = 'a' + punit->orders.list[j].order;
dir_buf[j] = 'a' + punit->orders.list[j].dir;
+ act_buf[j] = 'a' + punit->orders.list[j].activity;
}
- orders_buf[len] = dir_buf[len] = '\0';
+ orders_buf[len] = dir_buf[len] = act_buf[len] = '\0';
secfile_insert_str(file, orders_buf,
"player%d.u%d.orders_list", plrno, i);
secfile_insert_str(file, dir_buf,
"player%d.u%d.dir_list", plrno, i);
+ secfile_insert_str(file, act_buf,
+ "player%d.u%d.activity_list", plrno, i);
} else {
/* Put all the same fields into the savegame. Otherwise the
* registry code gets confused (although it still works). */
Index: server/unithand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
retrieving revision 1.301
diff -u -r1.301 unithand.c
--- server/unithand.c 8 Aug 2004 14:15:14 -0000 1.301
+++ server/unithand.c 10 Aug 2004 15:10:36 -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;
@@ -1619,6 +1581,7 @@
return;
}
+
for (i = 0; i < packet->length; i++) {
switch (packet->orders[i]) {
case ORDER_MOVE:
@@ -1626,6 +1589,16 @@
return;
}
break;
+ case ORDER_ACTIVITY:
+ switch (packet->activity[i]) {
+ case ACTIVITY_ROAD:
+ case ACTIVITY_RAILROAD:
+ case ACTIVITY_IRRIGATE:
+ break;
+ default:
+ return;
+ }
+ break;
case ORDER_FINISH_TURN:
break;
default:
@@ -1653,6 +1626,7 @@
for (i = 0; i < packet->length; i++) {
punit->orders.list[i].order = packet->orders[i];
punit->orders.list[i].dir = packet->dir[i];
+ punit->orders.list[i].activity = packet->activity[i];
}
if (!packet->repeat) {
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.297
diff -u -r1.297 unittools.c
--- server/unittools.c 6 Aug 2004 14:46:28 -0000 1.297
+++ server/unittools.c 10 Aug 2004 15:10:36 -0000
@@ -594,20 +594,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);
@@ -780,18 +766,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;
}
@@ -1833,7 +1809,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;
@@ -1854,6 +1829,7 @@
for (i = 0; i < punit->orders.length; i++) {
packet->orders[i] = punit->orders.list[i].order;
packet->orders_dirs[i] = punit->orders.list[i].dir;
+ packet->orders_activities[i] = punit->orders.list[i].activity;
}
} else {
packet->orders_length = packet->orders_index = 0;
@@ -2626,8 +2602,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);
}
}
@@ -2927,9 +2902,15 @@
int unitid = punit->id;
struct player *pplayer = unit_owner(punit);
int moves_made = 0;
+ enum unit_activity activity;
assert(unit_has_orders(punit));
+ if (punit->activity != ACTIVITY_IDLE) {
+ punit->done_moving = TRUE;
+ return TRUE;
+ }
+
freelog(LOG_DEBUG, "Executing orders for %s %d",
unit_name(punit->type), punit->id);
@@ -2989,6 +2970,19 @@
freelog(LOG_DEBUG, " waiting this turn");
send_unit_info(NULL, punit);
break;
+ case ORDER_ACTIVITY:
+ activity = order.activity;
+ if (!can_unit_do_activity(punit, activity)) {
+ cancel_orders(punit, " orders canceled because of failed activity");
+ notify_player_ex(pplayer, punit->x, punit->y, E_UNIT_ORDERS,
+ _("Game: Orders for %s aborted since they "
+ "give an invalid activity."),
+ unit_name(punit->type));
+ return TRUE;
+ }
+ set_unit_activity(punit, activity);
+ punit->done_moving = TRUE;
+ break;
case ORDER_MOVE:
/* Move unit */
if (!MAPSTEP(dest_x, dest_y, punit->x, punit->y, order.dir)) {
|
|