[Freeciv-Dev] Re: (PR#7131) client orders to replace client goto
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: |
undisclosed-recipients: ; |
Subject: |
[Freeciv-Dev] Re: (PR#7131) client orders to replace client goto |
From: |
"Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx> |
Date: |
Mon, 19 Jan 2004 00:38:54 -0800 |
Reply-to: |
rt@xxxxxxxxxxx |
<URL: http://rt.freeciv.org/Ticket/Display.html?id=7131 >
Raimar Falke wrote:
> I have no more problems with the patch. But I haven't tested it.
Four bugs fixed:
- Don't clear orders when changing the activity. In the future it will
be possible to have an activity while under orders.
- Don't sentry a unit when boarding a ship unless the orders are over.
This check is now duplicated in move_unit and execute_orders (since
orders code shouldn't go into move_unit). In the future it can be
removed from move_unit.
- Don't focus a unit when it's under orders. One additional place in
find_best_focus_candidate had to check for unit_has_orders(). Otherwise
if _every_ unit had orders one of them would be focused.
- Reinstate the enum activity_type enumeration. Since these values are
put in the savegame we can't just remove ACTIVITY_PATROL without
completely breaking things. Instead it's renamed as
ACTIVITY_PATROL_UNUSED and checked for when loading savegames.
Savegame behavior is now like this:
- When loading an old game, patrol routes are lost.
- When loading an old game, goto routes are changed into server goto.
- When loading a new game in an old server, patrol and goto routes are lost.
jason
Index: client/control.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.c,v
retrieving revision 1.123
diff -u -r1.123 control.c
--- client/control.c 2004/01/09 16:59:50 1.123
+++ client/control.c 2004/01/19 08:36:17
@@ -129,6 +129,10 @@
punit->focus_status=FOCUS_AVAIL;
refresh_tile_mapcanvas(punit->x, punit->y, FALSE);
+ if (unit_has_orders(punit)) {
+ /* Clear the focus unit's orders. */
+ request_orders_cleared(punit);
+ }
if (punit->activity != ACTIVITY_IDLE || punit->ai.control) {
punit->activity = ACTIVITY_IDLE;
punit->ai.control = FALSE;
@@ -180,6 +184,7 @@
{
if (!punit_focus
|| (punit_focus->activity != ACTIVITY_IDLE
+ && !unit_has_orders(punit_focus)
&& punit_focus->activity != ACTIVITY_GOTO)
|| punit_focus->done_moving
|| punit_focus->moves_left == 0
@@ -269,6 +274,7 @@
if ((punit != punit_focus || accept_current)
&& punit->focus_status == FOCUS_AVAIL
&& punit->activity == ACTIVITY_IDLE
+ && !unit_has_orders(punit)
&& punit->moves_left > 0
&& !punit->done_moving
&& !punit->ai.control) {
@@ -392,18 +398,23 @@
void update_unit_pix_label(struct unit *punit)
{
static enum unit_activity prev_activity = ACTIVITY_UNKNOWN;
+ static bool prev_has_orders = FALSE;
static Unit_Type_id prev_unit_type = U_LAST;
static int prev_hp = -1; /* or could store ihp cf tilespec.c */
int i;
-
+
+ /* Check for any change in the unit's state. This assumes that a unit's
+ * orders cannot be changed directly but must be removed and then reset. */
if (punit && get_client_state() != CLIENT_GAME_OVER_STATE) {
if (punit->type != prev_unit_type
|| punit->activity != prev_activity
+ || punit->has_orders != prev_has_orders
|| punit->hp != prev_hp) {
set_unit_icon(-1, punit);
prev_unit_type = punit->type;
prev_activity = punit->activity;
+ prev_has_orders = punit->has_orders;
prev_hp = punit->hp;
}
@@ -430,6 +441,7 @@
else {
prev_unit_type = U_LAST;
prev_activity = ACTIVITY_UNKNOWN;
+ prev_has_orders = FALSE;
prev_hp = -1;
for(i=-1; i<num_units_below; i++) {
set_unit_icon(i, NULL);
@@ -1194,6 +1206,7 @@
if (game.player_idx == punit->owner
&& auto_center_on_unit
+ && !unit_has_orders(punit)
&& punit->activity != ACTIVITY_GOTO
&& punit->activity != ACTIVITY_SENTRY
&& !tile_visible_and_not_on_border_mapcanvas(target_unit->x,
Index: client/goto.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/goto.c,v
retrieving revision 1.65
diff -u -r1.65 goto.c
--- client/goto.c 2004/01/10 13:05:59 1.65
+++ client/goto.c 2004/01/19 08:36:18
@@ -464,30 +464,72 @@
update_last_part(dest_x, dest_y);
}
+/****************************************************************************
+ Send a packet to the server to request that the current orders be
+ cleared.
+****************************************************************************/
+void request_orders_cleared(struct unit *punit)
+{
+ struct packet_unit_orders p;
+
+ /* Clear the orders by sending an empty orders path. */
+ freelog(PACKET_LOG_LEVEL, "Clearing orders for unit %d.", punit->id);
+ p.unit_id = punit->id;
+ p.repeat = p.vigilant = FALSE;
+ p.length = 0;
+ p.dest_x = punit->x;
+ p.dest_y = punit->y;
+ send_packet_unit_orders(&aconnection, &p);
+}
+
/**************************************************************************
Send a path as a goto or patrol route to the server.
**************************************************************************/
-static void send_path_route(struct unit *punit, struct pf_path *path,
- enum unit_activity activity)
+static void send_path_orders(struct unit *punit, struct pf_path *path,
+ bool repeat, bool vigilant)
{
- struct packet_unit_route p;
- int i;
+ struct packet_unit_orders p;
+ int i, old_x, old_y;
p.unit_id = punit->id;
- p.activity = activity;
+ p.repeat = repeat;
+ p.vigilant = vigilant;
+
+ freelog(PACKET_LOG_LEVEL, "Orders for unit %d:", punit->id);
- /* we skip the start position */
+ /* We skip the start position. */
p.length = path->length - 1;
assert(p.length < MAX_LEN_ROUTE);
+ old_x = path->positions[0].x;
+ old_y = path->positions[0].y;
+
+ freelog(PACKET_LOG_LEVEL, " Repeat: %d. Vigilant: %d. Length: %d",
+ p.repeat, p.vigilant, p.length);
+ /* If the path has n positions it takes n-1 steps. */
for (i = 0; i < path->length - 1; i++) {
- p.x[i] = path->positions[i + 1].x;
- p.y[i] = path->positions[i + 1].y;
- freelog(PACKET_LOG_LEVEL, " packet[%d] = (%d,%d)",
- i, p.x[i], p.y[i]);
+ int new_x = path->positions[i + 1].x;
+ int new_y = path->positions[i + 1].y;
+
+ if (same_pos(new_x, new_y, old_x, old_y)) {
+ p.orders[i] = ORDER_FINISH_TURN;
+ p.dir[i] = -1;
+ freelog(PACKET_LOG_LEVEL, " packet[%d] = wait: %d,%d",
+ i, old_x, old_y);
+ } else {
+ p.orders[i] = ORDER_MOVE;
+ 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);
+ }
+ old_x = new_x;
+ old_y = new_y;
}
+
+ p.dest_x = old_x;
+ p.dest_y = old_y;
- send_packet_unit_route(&aconnection, &p);
+ send_packet_unit_orders(&aconnection, &p);
}
/**************************************************************************
@@ -495,7 +537,7 @@
**************************************************************************/
void send_goto_path(struct unit *punit, struct pf_path *path)
{
- send_path_route(punit, path, ACTIVITY_GOTO);
+ send_path_orders(punit, path, FALSE, FALSE);
}
/**************************************************************************
@@ -531,7 +573,7 @@
pf_destroy_map(map);
pf_destroy_path(return_path);
- send_path_route(punit, path, ACTIVITY_PATROL);
+ send_path_orders(punit, path, TRUE, TRUE);
pf_destroy_path(path);
}
Index: client/goto.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/goto.h,v
retrieving revision 1.10
diff -u -r1.10 goto.h
--- client/goto.h 2003/08/11 02:31:38 1.10
+++ client/goto.h 2004/01/19 08:36:18
@@ -29,6 +29,7 @@
void draw_line(int dest_x, int dest_y);
int get_drawn(int x, int y, int dir);
+void request_orders_cleared(struct unit *punit);
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);
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.344
diff -u -r1.344 packhand.c
--- client/packhand.c 2004/01/18 17:55:26 1.344
+++ client/packhand.c 2004/01/19 08:36:18
@@ -116,6 +116,9 @@
} else {
punit->transported_by = 0;
}
+ punit->has_orders = packet->has_orders;
+ punit->orders.repeat = packet->repeat;
+ punit->orders.vigilant = packet->vigilant;
return punit;
}
@@ -936,14 +939,18 @@
}
if (punit->activity != packet_unit->activity
- || punit->activity_target != packet_unit->activity_target) {
+ || punit->activity_target != packet_unit->activity_target
+ || punit->has_orders != packet_unit->has_orders
+ || punit->orders.repeat != packet_unit->orders.repeat
+ || punit->orders.vigilant != packet_unit->orders.vigilant) {
/*** Change in activity or activity's target. ***/
/* May change focus if focus unit gets a new activity.
* But if new activity is Idle, it means user specifically selected
* the unit */
if (punit == get_unit_in_focus()
- && packet_unit->activity != ACTIVITY_IDLE) {
+ && (packet_unit->activity != ACTIVITY_IDLE
+ || packet_unit->has_orders)) {
check_focus = TRUE;
}
@@ -972,6 +979,9 @@
punit->activity = packet_unit->activity;
punit->activity_target = packet_unit->activity_target;
+ punit->has_orders = packet_unit->has_orders;
+ punit->orders.repeat = packet_unit->orders.repeat;
+ punit->orders.vigilant = packet_unit->orders.vigilant;
if (punit->owner == game.player_idx) {
refresh_unit_city_dialogs(punit);
@@ -1072,9 +1082,7 @@
if((unit_flag(punit, F_TRADE_ROUTE) || unit_flag(punit, F_HELP_WONDER))
&& (!game.player_ptr->ai.control || ai_popup_windows)
&& punit->owner==game.player_idx
- && (punit->activity!=ACTIVITY_GOTO
- || same_pos(goto_dest_x(punit), goto_dest_y(punit),
- pcity->x, pcity->y))
+ && !unit_has_orders(punit)
&& (unit_can_help_build_wonder_here(punit)
|| unit_can_est_traderoute_here(punit))) {
process_caravan_arrival(punit);
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.136
diff -u -r1.136 tilespec.c
--- client/tilespec.c 2004/01/16 16:01:25 1.136
+++ client/tilespec.c 2004/01/19 08:36:19
@@ -1509,8 +1509,12 @@
ADD_SPRITE_SIMPLE(sprites.unit.connect);
}
- if (punit->activity == ACTIVITY_PATROL) {
- ADD_SPRITE_SIMPLE(sprites.unit.patrol);
+ if (unit_has_orders(punit)) {
+ if (punit->orders.repeat) {
+ ADD_SPRITE_SIMPLE(sprites.unit.patrol);
+ } else {
+ ADD_SPRITE_SIMPLE(sprites.unit.go_to);
+ }
}
if (stack) {
Index: client/gui-gtk/menu.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/menu.c,v
retrieving revision 1.80
diff -u -r1.80 menu.c
--- client/gui-gtk/menu.c 2003/11/06 11:54:34 1.80
+++ client/gui-gtk/menu.c 2004/01/19 08:36:19
@@ -1146,8 +1146,6 @@
can_unit_do_activity(punit, ACTIVITY_EXPLORE));
menus_set_sensitive("<main>/_Orders/_Connect",
can_unit_do_connect(punit, ACTIVITY_IDLE));
- menus_set_sensitive("<main>/_Orders/Patrol (_Q)",
- can_unit_do_activity(punit, ACTIVITY_PATROL));
menus_set_sensitive("<main>/_Orders/Return to nearest city",
!(is_air_unit(punit) || is_heli_unit(punit)));
menus_set_sensitive("<main>/_Orders/_Disband Unit",
Index: client/gui-gtk-2.0/menu.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/menu.c,v
retrieving revision 1.25
diff -u -r1.25 menu.c
--- client/gui-gtk-2.0/menu.c 2003/11/09 04:06:50 1.25
+++ client/gui-gtk-2.0/menu.c 2004/01/19 08:36:19
@@ -1175,8 +1175,6 @@
can_unit_do_activity(punit, ACTIVITY_EXPLORE));
menus_set_sensitive("<main>/_Orders/_Connect",
can_unit_do_connect(punit, ACTIVITY_IDLE));
- menus_set_sensitive("<main>/_Orders/Patrol (_Q)",
- can_unit_do_activity(punit, ACTIVITY_PATROL));
menus_set_sensitive("<main>/_Orders/Return to nearest city",
!(is_air_unit(punit) || is_heli_unit(punit)));
menus_set_sensitive("<main>/_Orders/Diplomat\\/Spy Actions",
Index: client/gui-mui/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-mui/gui_main.c,v
retrieving revision 1.79
diff -u -r1.79 gui_main.c
--- client/gui-mui/gui_main.c 2003/11/19 17:30:51 1.79
+++ client/gui-mui/gui_main.c 2004/01/19 08:36:19
@@ -1259,7 +1259,6 @@
menu_entry_sensitive(MENU_ORDER_AUTO_ATTACK, (can_unit_do_auto(punit) &&
!unit_flag(punit, F_SETTLERS)));
menu_entry_sensitive(MENU_ORDER_AUTO_EXPLORE,
can_unit_do_activity(punit, ACTIVITY_EXPLORE));
menu_entry_sensitive(MENU_ORDER_CONNECT, can_unit_do_connect(punit,
ACTIVITY_IDLE));
- menu_entry_sensitive(MENU_ORDER_PATROL, can_unit_do_activity(punit,
ACTIVITY_PATROL));
menu_entry_sensitive(MENU_ORDER_GOTO_CITY, any_cities);
menu_entry_sensitive(MENU_ORDER_BUILD_WONDER,
unit_can_help_build_wonder_here(punit));
menu_entry_sensitive(MENU_ORDER_TRADEROUTE,
unit_can_est_traderoute_here(punit));
Index: client/gui-sdl/menu.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-sdl/menu.c,v
retrieving revision 1.23
diff -u -r1.23 menu.c
--- client/gui-sdl/menu.c 2003/10/02 21:37:44 1.23
+++ client/gui-sdl/menu.c 2004/01/19 08:36:20
@@ -1198,12 +1198,6 @@
local_hide(ID_UNIT_ORDER_CONNECT);
}
- if (can_unit_do_activity(pUnit, ACTIVITY_PATROL)) {
- local_show(ID_UNIT_ORDER_PATROL);
- } else {
- local_hide(ID_UNIT_ORDER_PATROL);
- }
-
if (is_diplomat_unit(pUnit) &&
diplomat_can_do_action(pUnit, DIPLOMAT_ANY_ACTION, pUnit->x,
pUnit->y)) {
Index: client/gui-xaw/menu.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/menu.c,v
retrieving revision 1.58
diff -u -r1.58 menu.c
--- client/gui-xaw/menu.c 2003/12/01 19:32:04 1.58
+++ client/gui-xaw/menu.c 2004/01/19 08:36:20
@@ -369,8 +369,6 @@
can_unit_do_activity(punit, ACTIVITY_EXPLORE));
menu_entry_sensitive(MENU_ORDER, MENU_ORDER_CONNECT,
can_unit_do_connect(punit, ACTIVITY_IDLE));
- menu_entry_sensitive(MENU_ORDER, MENU_ORDER_PATROL,
- can_unit_do_activity(punit, ACTIVITY_PATROL));
menu_entry_sensitive(MENU_ORDER, MENU_ORDER_GOTO_CITY,
any_cities);
menu_entry_sensitive(MENU_ORDER, MENU_ORDER_BUILD_WONDER,
Index: common/capstr.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/capstr.c,v
retrieving revision 1.151
diff -u -r1.151 capstr.c
--- common/capstr.c 2004/01/11 17:45:03 1.151
+++ common/capstr.c 2004/01/19 08:36:20
@@ -74,13 +74,15 @@
* are not directly related to the capability strings discussed here.)
*/
-#define CAPABILITY "+1.14.delta +last_turns_shield_surplus veteran"
+#define CAPABILITY "+1.14.delta +last_turns_shield_surplus veteran +orders"
/* "+1.14.delta" is the new delta protocol for 1.14.0-dev.
*
* "last_turns_shield_surplus" means the surplus from the previous turn is
* tracked by the server and sent to the client. This information is used
* in determining penalties when switching production.
+ *
+ * "orders" means client orders is used for client-side goto and patrol.
*/
void init_our_capability(void)
Index: common/map.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.h,v
retrieving revision 1.168
diff -u -r1.168 map.h
--- common/map.h 2004/01/18 16:49:17 1.168
+++ common/map.h 2004/01/19 08:36:20
@@ -36,17 +36,6 @@
int x,y;
};
-struct goto_route {
- int first_index; /* first valid tile pos */
- int last_index; /* point to the first non_legal pos. Note that the pos
- is always alloced in the pos array (for coding reasons) */
- int length; /* length of pos array (use this as modulus when iterating)
- Note that this is always at least 1 greater than the number
- of valid positions, to make comparing first_index with
- last_index during wrapped iteration easier. */
- struct map_position *pos;
-};
-
/* For client Area Selection */
enum tile_hilite {
HILITE_NONE = 0, HILITE_CITY
@@ -558,6 +547,11 @@
};
BV_DEFINE(dir_vector, 8);
+
+struct unit_order {
+ enum unit_orders order;
+ enum direction8 dir; /* Only valid for ORDER_MOVE. */
+};
/* return the reverse of the direction */
#define DIR_REVERSE(dir) (7 - (dir))
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.6
diff -u -r1.6 packets.def
--- common/packets.def 2004/01/14 11:58:12 1.6
+++ common/packets.def 2004/01/19 08:36:20
@@ -174,6 +174,8 @@
type REPORT_TYPE = uint8(enum report_type)
type AUTH_TYPE = uint8(enum authentication_type)
type IMPR_RANGE = uint8(enum impr_range)
+type DIRECTION = uint8(enum direction8)
+type ORDERS = uint8(enum unit_orders)
# typedefs for IDs
type PLAYER = UINT8
@@ -596,6 +598,7 @@
UINT8 veteran; add-cap(veteran)
BOOL veteran_old; remove-cap(veteran)
BOOL ai, paradropped, connecting, carried, done_moving;
+ BOOL has_orders, repeat, vigilant;
UNIT_TYPE type;
UINT8 movesleft, hp, fuel, activity_count;
@@ -661,18 +664,20 @@
UNIT unit_id;
end
+# used for server-side goto (air units only)
PACKET_UNIT_GOTO=58;cs
UNIT unit_id;
COORD x, y;
end
-# used for ACTIVITY_GOTO and ACTIVITY_PATROL
-PACKET_UNIT_ROUTE=59;cs
+# used for client orders: currently client-side goto and patrol
+PACKET_UNIT_ORDERS=59;cs
UNIT unit_id;
- ACTIVITY activity;
UINT16 length;
- COORD x[MAX_LEN_ROUTE:length];
- COORD y[MAX_LEN_ROUTE:length];
+ BOOL repeat, vigilant;
+ ORDERS orders[MAX_LEN_ROUTE:length];
+ DIRECTION dir[MAX_LEN_ROUTE:length];
+ COORD dest_x, dest_y;
end
PACKET_UNIT_AUTO=60;cs
Index: common/unit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.c,v
retrieving revision 1.195
diff -u -r1.195 unit.c
--- common/unit.c 2004/01/19 06:01:21 1.195
+++ common/unit.c 2004/01/19 08:36:21
@@ -214,6 +214,14 @@
return TRUE;
}
+/****************************************************************************
+ Return TRUE iff the unit is following client-side orders.
+****************************************************************************/
+bool unit_has_orders(struct unit *punit)
+{
+ return punit->has_orders;
+}
+
/**************************************************************************
...
**************************************************************************/
@@ -579,7 +587,6 @@
case ACTIVITY_TRANSFORM: text = _("Transform"); break;
case ACTIVITY_AIRBASE: text = _("Airbase"); break;
case ACTIVITY_FALLOUT: text = _("Fallout"); break;
- case ACTIVITY_PATROL: text = _("Patrol"); break;
default: text = _("Unknown"); break;
}
@@ -671,7 +678,6 @@
switch(activity) {
case ACTIVITY_IDLE:
case ACTIVITY_GOTO:
- case ACTIVITY_PATROL:
return TRUE;
case ACTIVITY_POLLUTION:
@@ -931,7 +937,6 @@
case ACTIVITY_SENTRY:
case ACTIVITY_GOTO:
case ACTIVITY_EXPLORE:
- case ACTIVITY_PATROL:
return get_activity_text (punit->activity);
case ACTIVITY_PILLAGE:
if(punit->activity_target == S_NO_SPECIAL) {
@@ -1303,7 +1308,7 @@
/* 1) */
if (activity != ACTIVITY_IDLE
&& activity != ACTIVITY_GOTO
- && activity != ACTIVITY_PATROL && !connecting) {
+ && !connecting) {
return MR_BAD_ACTIVITY;
}
@@ -1497,12 +1502,12 @@
punit->ai.charge = 0;
punit->bribe_cost = -1; /* flag value */
punit->transported_by = -1;
- punit->pgr = NULL;
punit->focus_status = FOCUS_AVAIL;
punit->ord_map = 0;
punit->ord_city = 0;
set_unit_activity(punit, ACTIVITY_IDLE);
punit->occupy = 0;
+ punit->has_orders = FALSE;
return punit;
}
@@ -1513,7 +1518,7 @@
**************************************************************************/
void destroy_unit_virtual(struct unit *punit)
{
- free_unit_goto_route(punit);
+ free_unit_orders(punit);
free(punit);
}
@@ -1521,13 +1526,13 @@
Free and reset the unit's goto route (punit->pgr). Only used by the
server.
**************************************************************************/
-void free_unit_goto_route(struct unit *punit)
+void free_unit_orders(struct unit *punit)
{
- if (punit->pgr) {
- free(punit->pgr->pos);
- free(punit->pgr);
- punit->pgr = NULL;
+ if (punit->has_orders) {
+ free(punit->orders.list);
+ punit->orders.list = NULL;
}
+ punit->has_orders = FALSE;
}
/****************************************************************************
Index: common/unit.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.h,v
retrieving revision 1.108
diff -u -r1.108 unit.h
--- common/unit.h 2004/01/11 17:45:04 1.108
+++ common/unit.h 2004/01/19 08:36:21
@@ -19,20 +19,28 @@
struct player;
struct city;
-struct goto_route;
struct tile;
+struct unit_order;
#define BARBARIAN_LIFE 5
+/* Changing this enum will break savegame and network compatability. */
enum unit_activity {
ACTIVITY_IDLE, ACTIVITY_POLLUTION, ACTIVITY_ROAD, ACTIVITY_MINE,
ACTIVITY_IRRIGATE, ACTIVITY_FORTIFIED, ACTIVITY_FORTRESS, ACTIVITY_SENTRY,
ACTIVITY_RAILROAD, ACTIVITY_PILLAGE, ACTIVITY_GOTO, ACTIVITY_EXPLORE,
ACTIVITY_TRANSFORM, ACTIVITY_UNKNOWN, ACTIVITY_AIRBASE, ACTIVITY_FORTIFYING,
- ACTIVITY_FALLOUT, ACTIVITY_PATROL,
+ ACTIVITY_FALLOUT,
+ ACTIVITY_PATROL_UNUSED, /* Needed for savegame compatability. */
ACTIVITY_LAST /* leave this one last */
};
+/* Changing this enum will break savegame and network compatability. */
+enum unit_orders {
+ ORDER_MOVE, ORDER_FINISH_TURN,
+ ORDER_LAST
+};
+
enum unit_focus_status {
FOCUS_AVAIL, FOCUS_WAIT, FOCUS_DONE
};
@@ -153,7 +161,14 @@
int transported_by;
int occupy; /* number of units that occupy transporter */
- struct goto_route *pgr;
+
+ bool has_orders;
+ struct {
+ int length, index; /* server only */
+ bool repeat; /* The path is to be repeated on completion. */
+ bool vigilant; /* Orders should be cleared if an enemy is met. */
+ struct unit_order *list; /* server only */
+ } orders;
};
/* Wrappers for accessing the goto destination of a unit. This goto_dest
@@ -222,6 +237,7 @@
bool unit_can_est_traderoute_here(struct unit *punit);
bool unit_can_defend_here(struct unit *punit);
bool unit_can_airlift_to(struct unit *punit, struct city *pcity);
+bool unit_has_orders(struct unit *punit);
bool can_unit_paradrop(struct unit *punit);
bool can_unit_change_homecity(struct unit *punit);
@@ -303,7 +319,7 @@
struct unit *create_unit_virtual(struct player *pplayer, struct city *pcity,
Unit_Type_id type, int veteran_level);
void destroy_unit_virtual(struct unit *punit);
-void free_unit_goto_route(struct unit *punit);
+void free_unit_orders(struct unit *punit);
int get_transporter_occupancy(struct unit *ptrans);
Index: server/gotohand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gotohand.c,v
retrieving revision 1.177
diff -u -r1.177 gotohand.c
--- server/gotohand.c 2004/01/11 17:45:05 1.177
+++ server/gotohand.c 2004/01/19 08:36:21
@@ -1279,10 +1279,7 @@
enum goto_result status;
int x, y;
- if (punit->pgr) {
- /* we have a precalculated goto route */
- return goto_route_execute(punit);
- }
+ assert(!unit_has_orders(punit));
unit_id = punit->id;
dest_x = waypoint_x = goto_dest_x(punit);
@@ -1412,9 +1409,7 @@
/* 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)) {
- if (punit->activity != ACTIVITY_PATROL) {
- punit->activity = ACTIVITY_IDLE;
- }
+ punit->activity = ACTIVITY_IDLE;
status = GR_ARRIVED;
} else {
/* we have a plane refueling at a waypoint */
Index: server/hand_gen.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/hand_gen.c,v
retrieving revision 1.2
diff -u -r1.2 hand_gen.c
--- server/hand_gen.c 2004/01/06 20:19:17 1.2
+++ server/hand_gen.c 2004/01/19 08:36:21
@@ -184,13 +184,8 @@
((struct packet_unit_goto *)packet)->y);
return TRUE;
- case PACKET_UNIT_ROUTE:
- handle_unit_route(pplayer,
- ((struct packet_unit_route *)packet)->unit_id,
- ((struct packet_unit_route *)packet)->activity,
- ((struct packet_unit_route *)packet)->length,
- ((struct packet_unit_route *)packet)->x,
- ((struct packet_unit_route *)packet)->y);
+ case PACKET_UNIT_ORDERS:
+ handle_unit_orders(pplayer, packet);
return TRUE;
case PACKET_UNIT_AUTO:
Index: server/hand_gen.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/hand_gen.h,v
retrieving revision 1.2
diff -u -r1.2 hand_gen.h
--- server/hand_gen.h 2003/12/06 19:23:51 1.2
+++ server/hand_gen.h 2004/01/19 08:36:21
@@ -49,7 +49,8 @@
void handle_unit_establish_trade(struct player *pplayer, int unit_id);
void handle_unit_help_build_wonder(struct player *pplayer, int unit_id);
void handle_unit_goto(struct player *pplayer, int unit_id, int x, int y);
-void handle_unit_route(struct player *pplayer, int unit_id, enum unit_activity
activity, int length, int *x, int *y);
+struct packet_unit_orders;
+void handle_unit_orders(struct player *pplayer, struct packet_unit_orders
*packet);
void handle_unit_auto(struct player *pplayer, int unit_id);
void handle_unit_unload(struct player *pplayer, int unit_id);
void handle_unit_upgrade(struct player *pplayer, int unit_id);
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.144
diff -u -r1.144 savegame.c
--- server/savegame.c 2004/01/12 16:59:17 1.144
+++ server/savegame.c 2004/01/19 08:36:22
@@ -175,7 +175,7 @@
and rulesets */
#define SAVEFILE_OPTIONS "startoptions spacerace2 rulesets" \
" diplchance_percent worklists2 map_editor known32fix turn " \
-"attributes watchtower rulesetdir client_worklists"
+"attributes watchtower rulesetdir client_worklists orders"
static const char hex_chars[] = "0123456789abcdef";
static const char terrain_chars[] = "adfghjm prstu";
@@ -597,6 +597,7 @@
int i, j, x, y, nunits, ncities, c_s;
char *p;
char *savefile_options = secfile_lookup_str(file, "savefile.options");
+ enum unit_activity activity;
server_player_init(plr, TRUE);
@@ -1043,7 +1044,18 @@
punit->moves_left=secfile_lookup_int(file, "player%d.u%d.moves", plrno, i);
punit->fuel= secfile_lookup_int(file, "player%d.u%d.fuel", plrno, i);
- set_unit_activity(punit, secfile_lookup_int(file,
"player%d.u%d.activity",plrno, i));
+ activity = secfile_lookup_int(file, "player%d.u%d.activity",plrno, i);
+ if (activity == ACTIVITY_PATROL_UNUSED) {
+ /* Previously ACTIVITY_PATROL and ACTIVITY_GOTO were used for
+ * client-side goto. Now client-side goto is handled by setting
+ * a special flag, and units with orders generally have ACTIVITY_IDLE.
+ * Old orders are lost. Old client-side goto units will still have
+ * ACTIVITY_GOTO and will goto the correct position via server goto.
+ * Old client-side patrol units lose their patrol routes and are put
+ * into idle mode. */
+ activity = ACTIVITY_IDLE;
+ }
+ set_unit_activity(punit, activity);
/* need to do this to assign/deassign settlers correctly -- Syela */
/* was punit->activity=secfile_lookup_int(file, "player%d.u%d.activity",plrno,
i); */
punit->activity_count=secfile_lookup_int(file,
@@ -1090,58 +1102,42 @@
etc may use junk values).
*/
- /* load the goto route */
- {
- int len = secfile_lookup_int_default(file, 0,
"player%d.u%d.goto_length", plrno, i);
+ /* load the unit orders */
+ if (has_capability("orders", savefile_options)) {
+ int len = secfile_lookup_int_default(file, 0,
+ "player%d.u%d.orders_length", plrno, i);
if (len > 0) {
- char *goto_buf, *goto_buf_ptr;
- struct goto_route *pgr = fc_malloc(sizeof(struct goto_route));
- pgr->pos = fc_malloc((len+1) * sizeof(struct map_position));
- pgr->first_index = 0;
- pgr->length = len+1;
- pgr->last_index = len;
- punit->pgr = pgr;
-
- /* get x coords */
- goto_buf = secfile_lookup_str(file, "player%d.u%d.goto_route_x", plrno,
i);
- goto_buf_ptr = goto_buf;
- for (j = 0; j < len; j++) {
- if (sscanf(goto_buf_ptr, "%d", &pgr->pos[j].x) == 0) {
- die("not an int");
- }
- while (*goto_buf_ptr != ',') {
- goto_buf_ptr++;
- if (*goto_buf_ptr == '\0') {
- die("byebye");
- }
- }
- goto_buf_ptr++;
- }
- /* get y coords */
- goto_buf = secfile_lookup_str(file, "player%d.u%d.goto_route_y", plrno,
i);
- goto_buf_ptr = goto_buf;
+ char *orders_buf, *dir_buf;
+
+ punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
+ punit->orders.length = len;
+ punit->orders.index = secfile_lookup_int_default(file, 0,
+ "player%d.u%d.orders_index", plrno, i);
+ punit->orders.repeat = secfile_lookup_bool_default(file, FALSE,
+ "player%d.u%d.orders_repeat", plrno, i);
+ punit->orders.vigilant = secfile_lookup_bool_default(file, FALSE,
+ "player%d.u%d.orders_vigilant", plrno, i);
+
+ orders_buf = secfile_lookup_str_default(file, "",
+ "player%d.u%d.orders_list", plrno, i);
+ dir_buf = secfile_lookup_str_default(file, "",
+ "player%d.u%d.dir_list", plrno, i);
for (j = 0; j < len; j++) {
- if (sscanf(goto_buf_ptr, "%d", &pgr->pos[j].y) == 0) {
- die("not an int");
- }
- while (*goto_buf_ptr != ',') {
- goto_buf_ptr++;
- if (*goto_buf_ptr == '\0') {
- die("byebye");
- }
+ if (orders_buf[j] == '\0' || dir_buf == '\0') {
+ freelog(LOG_ERROR, _("Savegame error: invalid unit orders."));
+ free_unit_orders(punit);
+ break;
}
- goto_buf_ptr++;
+ punit->orders.list[j].order = orders_buf[j] - 'a';
+ punit->orders.list[j].dir = dir_buf[j] - 'a';
}
+ punit->has_orders = TRUE;
} else {
- /* mark unused strings as read to avoid warnings */
- (void) secfile_lookup_str_default(file, "",
- "player%d.u%d.goto_route_x", plrno,
- i);
- (void) secfile_lookup_str_default(file, "",
- "player%d.u%d.goto_route_y", plrno,
- i);
- punit->pgr = NULL;
+ punit->has_orders = FALSE;
+ punit->orders.list = NULL;
}
+ } else {
+ /* Old-style goto routes get discarded. */
}
{
@@ -1543,42 +1539,30 @@
secfile_insert_bool(file, punit->paradropped, "player%d.u%d.paradropped",
plrno, i);
secfile_insert_int(file, punit->transported_by,
"player%d.u%d.transported_by", plrno, i);
- if (punit->pgr && punit->pgr->first_index != punit->pgr->last_index) {
- struct goto_route *pgr = punit->pgr;
- int index = pgr->first_index;
- int len = 0;
- while (pgr && index != pgr->last_index) {
- len++;
- index = (index + 1) % pgr->length;
+ if (punit->has_orders) {
+ int len = punit->orders.length, j;
+ char orders_buf[len + 1], dir_buf[len + 1];
+
+ secfile_insert_int(file, len, "player%d.u%d.orders_length", plrno, i);
+ secfile_insert_int(file, punit->orders.index,
+ "player%d.u%d.orders_index", plrno, i);
+ secfile_insert_bool(file, punit->orders.repeat,
+ "player%d.u%d.orders_repeat", plrno, i);
+ secfile_insert_bool(file, punit->orders.vigilant,
+ "player%d.u%d.orders_vigilant", plrno, i);
+
+ for (j = 0; j < len; j++) {
+ orders_buf[j] = 'a' + punit->orders.list[j].order;
+ dir_buf[j] = 'a' + punit->orders.list[j].dir;
}
- assert(len > 0);
- secfile_insert_int(file, len, "player%d.u%d.goto_length", plrno, i);
- /* assumption about the chars per map position */
- assert(MAP_MAX_HEIGHT < 1000 && MAP_MAX_WIDTH < 1000);
- {
- char *goto_buf = fc_malloc(4 * len + 1);
- char *goto_buf_ptr = goto_buf;
- index = pgr->first_index;
- while (index != pgr->last_index) {
- goto_buf_ptr += sprintf(goto_buf_ptr, "%d,", pgr->pos[index].x);
- index = (index + 1) % pgr->length;
- }
- *goto_buf_ptr = '\0';
- secfile_insert_str(file, goto_buf, "player%d.u%d.goto_route_x", plrno,
i);
+ orders_buf[len] = dir_buf[len] = '\0';
- goto_buf_ptr = goto_buf;
- index = pgr->first_index;
- while (index != pgr->last_index) {
- goto_buf_ptr += sprintf(goto_buf_ptr, "%d,", pgr->pos[index].y);
- index = (index + 1) % pgr->length;
- }
- *goto_buf_ptr = '\0';
- secfile_insert_str(file, goto_buf, "player%d.u%d.goto_route_y", plrno,
i);
- }
+ 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);
} else {
- secfile_insert_int(file, 0, "player%d.u%d.goto_length", plrno, i);
- secfile_insert_str(file, "", "player%d.u%d.goto_route_x", plrno, i);
- secfile_insert_str(file, "", "player%d.u%d.goto_route_y", plrno, i);
+ secfile_insert_int(file, 0, "player%d.u%d.orders_length", plrno, i);
}
}
unit_list_iterate_end;
Index: server/unithand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
retrieving revision 1.283
diff -u -r1.283 unithand.c
--- server/unithand.c 2004/01/12 16:34:44 1.283
+++ server/unithand.c 2004/01/19 08:36:22
@@ -847,10 +847,6 @@
}
}
- if (pwinner == punit && punit->activity != ACTIVITY_IDLE) {
- /* Ensure we remove ACTIVITY_GOTO here */
- set_unit_activity(punit, ACTIVITY_IDLE);
- }
send_unit_info(NULL, pwinner);
}
@@ -1402,7 +1398,6 @@
enum tile_special_type old_target = punit->activity_target;
set_unit_activity(punit, new_activity);
- free_unit_goto_route(punit);
send_unit_info(NULL, punit);
handle_unit_activity_dependencies(punit, old_activity, old_target);
}
@@ -1422,7 +1417,7 @@
enum tile_special_type old_target = punit->activity_target;
set_unit_activity_targeted(punit, new_activity, new_target);
- free_unit_goto_route(punit);
+ free_unit_orders(punit);
send_unit_info(NULL, punit);
handle_unit_activity_dependencies(punit, old_activity, old_target);
}
@@ -1495,66 +1490,69 @@
}
/**************************************************************************
-Receives goto route packages.
+Receives route packages.
**************************************************************************/
-static void handle_route(struct player *pplayer, struct unit *punit,
- int length, int *x, int *y)
+void handle_unit_orders(struct player *pplayer,
+ struct packet_unit_orders *packet)
{
- struct goto_route *pgr = NULL;
+ struct unit *punit = player_find_unit_by_id(pplayer, packet->unit_id);
int i;
- free_unit_goto_route(punit);
+ if (!punit || packet->length < 0 || punit->activity != ACTIVITY_IDLE) {
+ return;
+ }
- /*
- * pgr->pos is implemented as a circular buffer of positions, and
- * this circular buffer requires an extra "empty" spot. Hence we
- * increase the length by one.
- */
- pgr = fc_malloc(sizeof(struct goto_route));
- pgr->length = length + 1;
- pgr->first_index = 0;
- pgr->last_index = length;
- pgr->pos = fc_malloc(pgr->length * sizeof(*pgr->pos));
-
- for (i = 0; i < length; i++) {
- pgr->pos[i].x = x[i];
- pgr->pos[i].y = y[i];
+ for (i = 0; i < packet->length; i++) {
+ switch (packet->orders[i]) {
+ case ORDER_MOVE:
+ if (!is_valid_dir(packet->dir[i])) {
+ return;
+ }
+ break;
+ case ORDER_FINISH_TURN:
+ break;
+ default:
+ /* An invalid order. This is handled in execute_orders. */
+ packet->orders[i] = ORDER_LAST;
+ break;
+ }
}
- punit->pgr = pgr;
+ free_unit_orders(punit);
-#ifdef DEBUG
- freelog(LOG_DEBUG, "first:%d, last:%d, length:%d",
- pgr->first_index, pgr->last_index, pgr->length);
- for (i = pgr->first_index; i < pgr->last_index; i++) {
- freelog(LOG_NORMAL, " %d,%d", pgr->pos[i].x, pgr->pos[i].y);
+ if (packet->length == 0) {
+ assert(!unit_has_orders(punit));
+ send_unit_info(NULL, punit);
+ return;
}
-#endif
- if (punit->activity == ACTIVITY_GOTO) {
- set_goto_dest(punit, pgr->pos[pgr->last_index-1].x,
- pgr->pos[pgr->last_index-1].y);
- send_unit_info(pplayer, punit);
+ punit->has_orders = TRUE;
+ punit->orders.length = packet->length;
+ punit->orders.index = 0;
+ punit->orders.repeat = packet->repeat;
+ punit->orders.vigilant = packet->vigilant;
+ punit->orders.list
+ = fc_malloc(packet->length * sizeof(*(punit->orders.list)));
+ for (i = 0; i < packet->length; i++) {
+ punit->orders.list[i].order = packet->orders[i];
+ punit->orders.list[i].dir = packet->dir[i];
}
-
- assign_units_to_transporter(punit, TRUE);
- (void) goto_route_execute(punit);
-}
-/**************************************************************************
-Receives route packages.
-**************************************************************************/
-void handle_unit_route(struct player *pplayer, int unit_id,
- enum unit_activity activity, int length, int *x,
- int *y)
-{
- struct unit *punit = player_find_unit_by_id(pplayer, unit_id);
+ if (!packet->repeat) {
+ set_goto_dest(punit, packet->dest_x, packet->dest_y);
+ }
- if (!punit || length < 1
- || !(activity == ACTIVITY_GOTO || activity == ACTIVITY_PATROL)) {
- return;
+#ifdef DEBUG
+ freelog(LOG_DEBUG, "Orders for unit %d: length:%d",
+ packet->unit_id, packet->length);
+ for (i = 0; i < packet->length; i++) {
+ freelog(LOG_NORMAL, " %d,%s", packet->orders[i],
+ dir_get_name(packet->dir[i]));
}
+#endif
- handle_unit_activity_request(punit, activity);
- handle_route(pplayer, punit, length, x, y);
+ assign_units_to_transporter(punit, TRUE);
+ if (execute_orders(punit) != GR_DIED) {
+ send_unit_info(NULL, punit);
+ }
}
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.270
diff -u -r1.270 unittools.c
--- server/unittools.c 2004/01/11 17:45:06 1.270
+++ server/unittools.c 2004/01/19 08:36:23
@@ -653,8 +653,7 @@
struct tile *ptile = map_get_tile(punit->x, punit->y);
if (activity != ACTIVITY_IDLE && activity != ACTIVITY_FORTIFIED
- && activity != ACTIVITY_GOTO && activity != ACTIVITY_EXPLORE
- && activity != ACTIVITY_PATROL) {
+ && activity != ACTIVITY_GOTO && activity != ACTIVITY_EXPLORE) {
/* We don't need the activity_count for the above */
if (punit->moves_left > 0) {
/*
@@ -900,8 +899,8 @@
return;
}
- if (punit->activity == ACTIVITY_PATROL) {
- if (goto_route_execute(punit) == GR_DIED) {
+ if (unit_has_orders(punit)) {
+ if (execute_orders(punit) == GR_DIED) {
return;
}
}
@@ -1894,6 +1893,13 @@
packet->done_moving = punit->done_moving;
packet->carried = carried;
packet->occupy = get_transporter_occupancy(punit);
+ packet->has_orders = punit->has_orders;
+ if (punit->has_orders) {
+ packet->repeat = punit->orders.repeat;
+ packet->vigilant = punit->orders.vigilant;
+ } else {
+ packet->repeat = packet->vigilant = FALSE;
+ }
}
/**************************************************************************
@@ -1926,9 +1932,8 @@
packet->type = punit->type;
packet->hp = punit->hp;
packet->occupied = (get_transporter_occupancy(punit) > 0);
- if (punit->activity == ACTIVITY_GOTO
- || punit->activity == ACTIVITY_EXPLORE
- || punit->activity == ACTIVITY_PATROL) {
+ if (punit->activity == ACTIVITY_EXPLORE
+ || punit->activity == ACTIVITY_GOTO) {
packet->activity = ACTIVITY_IDLE;
} else {
packet->activity = punit->activity;
@@ -2744,7 +2749,8 @@
square_iterate(punit->x, punit->y, 3, x, y) {
unit_list_iterate(map_get_tile(x, y)->units, ppatrol) {
if (punit != ppatrol
- && ppatrol->activity == ACTIVITY_PATROL) {
+ && unit_has_orders(ppatrol)
+ && ppatrol->orders.vigilant) {
(void) maybe_cancel_patrol_due_to_enemy(ppatrol);
}
} unit_list_iterate_end;
@@ -2859,10 +2865,9 @@
static void check_unit_activity(struct unit *punit)
{
if (punit->activity != ACTIVITY_IDLE
- && punit->activity != ACTIVITY_GOTO
&& punit->activity != ACTIVITY_SENTRY
&& punit->activity != ACTIVITY_EXPLORE
- && punit->activity != ACTIVITY_PATROL
+ && punit->activity != ACTIVITY_GOTO
&& !punit->connecting) {
set_unit_activity(punit, ACTIVITY_IDLE);
}
@@ -2905,7 +2910,8 @@
}
/* A transporter should not take units with it on an attack goto. */
- if (punit->activity == ACTIVITY_GOTO
+ if ((unit_has_orders(punit)
+ || punit->activity == ACTIVITY_GOTO)
&& (is_non_allied_unit_tile(pdesttile, pplayer)
|| is_non_allied_city_tile(pdesttile, pplayer))
&& !is_ocean(psrctile->terrain)) {
@@ -2948,13 +2954,6 @@
pcargo->x = dest_x;
pcargo->y = dest_y;
- if ((pcargo->activity == ACTIVITY_GOTO
- || pcargo->activity == ACTIVITY_PATROL)
- && !pcargo->ai.control) {
- /* Cancel any _client_ gotos for these units. */
- handle_unit_activity_request(pcargo, ACTIVITY_IDLE);
- }
-
unit_list_insert(&pdesttile->units, pcargo);
check_unit_activity(pcargo);
send_unit_info_to_onlookers(NULL, pcargo, src_x, src_y, FALSE);
@@ -3031,14 +3030,8 @@
} unit_list_iterate_end;
assert(punit->transported_by != -1);
- /* set activity to sentry if boarding a ship unless the unit is just
- * passing through the ship on its way somewhere else. If the unit is
- * GOTOing and the ship isn't the final destination, then don't go
- * to sleep. */
- if (!(pplayer->ai.control)
- && !(punit->activity == ACTIVITY_GOTO
- && !same_pos(goto_dest_x(punit), goto_dest_y(punit),
- dest_x, dest_y))) {
+ /* Set activity to sentry if boarding a ship. */
+ if (!pplayer->ai.control && !unit_has_orders(punit)) {
set_unit_activity(punit, ACTIVITY_SENTRY);
}
@@ -3165,115 +3158,126 @@
return cancel;
}
-/**************************************************************************
-Moves a unit according to its pgr (goto or patrol order). If two consequetive
-positions in the route is not adjacent it is assumed to be a goto. The unit
-is put on idle if a move fails.
-If the activity is ACTIVITY_PATROL the map positions are put back in the
-route (at the end). To avoid infinite loops on railroad we stop for this
-turn when the unit is back where it started, eben if it have moves left.
-
-If a patrolling unit came across an enemy we could make the patrolling unit
-autoattack or just stop and wait for the owner to attack. It is also
-debateable if units on goto should stop when they encountered an enemy
-unit. Currently the unit continues if it can, or if it is blocked it stops.
-**************************************************************************/
-enum goto_result goto_route_execute(struct unit *punit)
-{
- struct goto_route *pgr = punit->pgr;
- int index, x, y;
- bool res, last_tile, moved;
- int patrol_stop_index = pgr->last_index;
+/****************************************************************************
+ Executes a unit's orders stored in punit->orders. The unit is put on idle
+ if an action fails or if "patrol" is set and an enemy unit is encountered.
+
+ If the orders are repeating the loop starts over at the beginning once it
+ completes. To avoid infinite loops on railroad we stop for this
+ turn when the unit is back where it started, even if it have moves left.
+
+ A unit will attack under orders only on its final action.
+****************************************************************************/
+enum goto_result execute_orders(struct unit *punit)
+{
+ int dest_x, dest_y;
+ bool res, last_order;
int unitid = punit->id;
struct player *pplayer = unit_owner(punit);
+ int moves_made = 0;
- assert(pgr != NULL);
- while (TRUE) {
- freelog(LOG_DEBUG, "running a round\n");
+ assert(unit_has_orders(punit));
- index = pgr->first_index;
- if (index == pgr->last_index) {
- free_unit_goto_route(punit);
- if (punit->activity == ACTIVITY_GOTO)
- /* the activity could already be SENTRY (if boarded a ship)
- -- leave it as it is then */
- handle_unit_activity_request(punit, ACTIVITY_IDLE);
- return GR_ARRIVED;
- }
- x = pgr->pos[index].x; y = pgr->pos[index].y;
- freelog(LOG_DEBUG, "%i,%i -> %i,%i\n", punit->x, punit->y, x, y);
+ freelog(LOG_DEBUG, "Executing orders for %s %d",
+ unit_name(punit->type), punit->id);
+ while (TRUE) {
if (punit->moves_left == 0) {
+ /* FIXME: this check won't work when actions take 0 MP. */
+ freelog(LOG_DEBUG, " stopping because of no more move points");
return GR_OUT_OF_MOVEPOINTS;
}
- if (punit->activity == ACTIVITY_PATROL
- && maybe_cancel_patrol_due_to_enemy(punit)) {
- return GR_FAILED;
+ if (punit->done_moving) {
+ freelog(LOG_DEBUG, " stopping because we're done this turn");
+ return GR_WAITING;
}
-
- last_tile = (((index + 1) % pgr->length) == (pgr->last_index));
- if (punit->activity == ACTIVITY_GOTO && !last_tile
- && maybe_cancel_goto_due_to_enemy(punit, x, y)) {
+ if (punit->orders.vigilant && maybe_cancel_patrol_due_to_enemy(punit)) {
+ /* "Patrol" orders are stopped if an enemy is near. */
+ freelog(LOG_DEBUG, " stopping because of nearby enemy");
return GR_FAILED;
}
-
- /* Move unit */
- moved = !same_pos(punit->x, punit->y, x, y);
- if (moved) {
- res = handle_unit_move_request(punit, x, y, FALSE, !last_tile);
- } else {
- res = TRUE;
- }
- if (!player_find_unit_by_id(pplayer, unitid)) {
- return GR_DIED;
+ if (moves_made == punit->orders.length) {
+ /* For repeating orders, don't repeat more than once per turn. */
+ freelog(LOG_DEBUG, " stopping because we ran a round");
+ return GR_ARRIVED;
}
- if (same_pos(punit->x, punit->y, x, y)) {
- /* We succeeded in moving one step forward */
- pgr->first_index = (pgr->first_index + 1) % pgr->length;
- if (punit->activity == ACTIVITY_PATROL) {
- /* When patroling we go in little circles;
- * done by reinserting points */
- pgr->pos[pgr->last_index].x = x;
- pgr->pos[pgr->last_index].y = y;
- pgr->last_index = (pgr->last_index + 1) % pgr->length;
-
- if (patrol_stop_index == pgr->first_index) {
- freelog(LOG_DEBUG, "stopping because we ran a round\n");
- return GR_ARRIVED; /* don't patrol more than one round */
- }
- if (maybe_cancel_patrol_due_to_enemy(punit)) {
- return GR_FAILED;
- }
- }
+ last_order = (!punit->orders.repeat
+ && punit->orders.index + 1 == punit->orders.length);
- if (!moved) {
- /* Sometimes the goto route will have us sit still for a moment -
- * for instance a trireme will do this to have enough MP to
- * cross the ocean in one turn. */
- punit->done_moving = TRUE;
- send_unit_info(unit_owner(punit), punit);
- return GR_WAITING;
- }
+ switch (punit->orders.list[punit->orders.index].order) {
+ case ORDER_FINISH_TURN:
+ punit->done_moving = TRUE;
+ freelog(LOG_DEBUG, " waiting this turn");
+ send_unit_info(unit_owner(punit), punit);
+ break;
+ case ORDER_MOVE:
+ /* Move unit */
+ if (!MAPSTEP(dest_x, dest_y, punit->x, punit->y,
+ punit->orders.list[punit->orders.index].dir)) {
+ freelog(LOG_DEBUG, " move order sent us to invalid location");
+ return GR_FAILED;
+ }
+
+ if (!last_order
+ && maybe_cancel_goto_due_to_enemy(punit, dest_x, dest_y)) {
+ freelog(LOG_DEBUG, " orders canceled because of enemy");
+ return GR_FAILED;
+ }
+
+ freelog(LOG_DEBUG, " moving to %d,%d", dest_x, dest_y);
+ res = handle_unit_move_request(punit, dest_x, dest_y,
+ FALSE, !last_order);
+ if (!player_find_unit_by_id(pplayer, unitid)) {
+ freelog(LOG_DEBUG, " unit died while moving.");
+ return GR_DIED;
+ }
+
+ if (res && !same_pos(dest_x, dest_y, punit->x, punit->y)) {
+ /* Movement succeeded but unit didn't move. */
+ freelog(LOG_DEBUG, " orders resulted in combat.");
+ return GR_FOUGHT;
+ }
+
+ if (!res && punit->moves_left > 0) {
+ /* Movement failed (ZOC, etc.) */
+ freelog(LOG_DEBUG, " attempt to move failed.");
+ return GR_FAILED;
+ }
+
+ if (last_order && punit->transported_by != -1) {
+ /* Set activity to sentry if boarding a ship. This is done in
+ * move_unit, but that function doesn't handle the orders case. */
+ set_unit_activity(punit, ACTIVITY_SENTRY);
+ }
+ break;
+ case ORDER_LAST:
+ freelog(LOG_DEBUG, " client sent invalid order!");
+ notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
+ _("Game: Your %s has invalid orders."),
+ unit_name(punit->type));
+ return GR_FAILED;
}
- if (res && !same_pos(x, y, punit->x, punit->y)) {
- /*
- * unit is alive, moved alright, didn't arrive, has moves_left
- * --- what else can it be
- */
- return GR_FOUGHT;
- }
+ /* We succeeded in moving one step forward */
+ punit->orders.index++;
- if (!res && punit->moves_left > 0) {
- freelog(LOG_DEBUG, "move idling\n");
- handle_unit_activity_request(punit, ACTIVITY_IDLE);
- return GR_FAILED;
+ if (punit->orders.index == punit->orders.length) {
+ if (!punit->orders.repeat) {
+ free_unit_orders(punit);
+ assert(punit->has_orders == FALSE);
+ freelog(LOG_DEBUG, " stopping because orders are complete");
+ return GR_ARRIVED;
+ } else {
+ /* Start over. */
+ freelog(LOG_DEBUG, " repeating orders.");
+ punit->orders.index = 0;
+ }
}
- } /* end while*/
+ } /* end while */
}
/**************************************************************************
Index: server/unittools.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.h,v
retrieving revision 1.60
diff -u -r1.60 unittools.h
--- server/unittools.h 2004/01/11 17:45:06 1.60
+++ server/unittools.h 2004/01/19 08:36:23
@@ -82,6 +82,6 @@
void assign_units_to_transporter(struct unit *ptrans, bool take_from_land);
bool move_unit(struct unit *punit, int dest_x, int dest_y,
bool transport_units, bool take_from_land, int move_cost);
-enum goto_result goto_route_execute(struct unit *punit);
+enum goto_result execute_orders(struct unit *punit);
#endif /* FC__UNITTOOLS_H */
- [Freeciv-Dev] Re: (PR#7131) client orders to replace client goto, (continued)
- [Freeciv-Dev] Re: (PR#7131) client orders to replace client goto, Arnstein Lindgard, 2004/01/09
- [Freeciv-Dev] Re: (PR#7131) client orders to replace client goto, Jason Short, 2004/01/09
- [Freeciv-Dev] Re: (PR#7131) client orders to replace client goto, Raimar Falke, 2004/01/10
- [Freeciv-Dev] (PR#7131) client orders to replace client goto, Jason Short, 2004/01/11
- [Freeciv-Dev] Re: (PR#7131) client orders to replace client goto, Raimar Falke, 2004/01/13
- [Freeciv-Dev] Re: (PR#7131) client orders to replace client goto, Jason Short, 2004/01/15
- [Freeciv-Dev] Re: (PR#7131) client orders to replace client goto, Raimar Falke, 2004/01/17
- [Freeciv-Dev] (PR#7131) client orders to replace client goto, Jason Short, 2004/01/17
- [Freeciv-Dev] (PR#7131) client orders to replace client goto, Jason Short, 2004/01/17
- [Freeciv-Dev] Re: (PR#7131) client orders to replace client goto, Raimar Falke, 2004/01/18
- [Freeciv-Dev] Re: (PR#7131) client orders to replace client goto,
Jason Short <=
- [Freeciv-Dev] Re: (PR#7131) client orders to replace client goto, Raimar Falke, 2004/01/19
- [Freeciv-Dev] Re: (PR#7131) client orders to replace client goto, Jason Short, 2004/01/19
- [Freeciv-Dev] Re: (PR#7131) client orders to replace client goto, Jason Short, 2004/01/19
|
|