Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2004:
[Freeciv-Dev] (PR#7344) Expanded Orders
Home

[Freeciv-Dev] (PR#7344) Expanded Orders

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#7344) Expanded Orders
From: "Arnstein Lindgard" <a-l@xxxxxxx>
Date: Thu, 29 Jan 2004 06:05:30 -0800
Reply-to: rt@xxxxxxxxxxx

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

Expanded Orders is Mission Orders minus client interface.

Now expanding the struct unit_orders, not using unions or
chained enums.


Arnstein

diff -pruN -Xdiff_ignore clean-E1/common/capstr.c E1/common/capstr.c
--- clean-E1/common/capstr.c    Sun Jan 25 11:18:53 2004
+++ E1/common/capstr.c  Thu Jan 29 14:55:26 2004
@@ -75,7 +75,7 @@ const char * const our_capability = our_
  */
 
 #define CAPABILITY "+1.14.delta +last_turns_shield_surplus veteran +orders " \
-                   "+starter"
+                   "+starter +expanded_orders"
 
 /* "+1.14.delta" is the new delta protocol for 1.14.0-dev.
  *
@@ -88,6 +88,9 @@ const char * const our_capability = our_
  * "veteran" means the extended veteran system.
  *
  * "starter" means the Starter terrain flag is supported.
+ *
+ * "expanded_orders" is a preparation for mission orders, with no client
+ * interface.
  */
 
 void init_our_capability(void)
diff -pruN -Xdiff_ignore clean-E1/common/packets.def E1/common/packets.def
--- clean-E1/common/packets.def Tue Jan 20 23:08:40 2004
+++ E1/common/packets.def       Thu Jan 29 14:55:26 2004
@@ -176,6 +176,7 @@ type AUTH_TYPE              = uint8(enum authenticat
 type IMPR_RANGE                = uint8(enum impr_range)
 type DIRECTION         = uint8(enum direction8)
 type ORDERS            = uint8(enum unit_orders)
+type MOVEMENT_TYPE     = uint8(enum movement_type)
 
 # typedefs for IDs
 type PLAYER            = UINT8
@@ -599,6 +600,8 @@ PACKET_UNIT_INFO=49; is-info,sc
   BOOL veteran_old; remove-cap(veteran)
   BOOL ai, paradropped, connecting, carried, done_moving;
   BOOL has_orders, repeat, vigilant;
+  ORDERS mission;
+  MOVEMENT_TYPE move_type;
 
   UNIT_TYPE type;
   UINT8 movesleft, hp, fuel, activity_count;
diff -pruN -Xdiff_ignore clean-E1/common/unit.c E1/common/unit.c
--- clean-E1/common/unit.c      Sun Jan 25 11:18:54 2004
+++ E1/common/unit.c    Thu Jan 29 14:55:26 2004
@@ -222,6 +222,18 @@ bool unit_has_orders(struct unit *punit)
   return punit->has_orders;
 }
 
+/****************************************************************************
+  TRUE if the order is an action or activity, other than move. Determines
+  sprites in the client and helpful for server to examine the orders list.
+****************************************************************************/
+bool order_is_action(enum unit_orders order)
+{
+  return (order != ORDER_LAST &&
+         order != ORDER_MOVE &&
+         order != ORDER_NONE &&
+         order != ORDER_FINISH_TURN);
+}
+
 /**************************************************************************
 ...
 **************************************************************************/
diff -pruN -Xdiff_ignore clean-E1/common/unit.h E1/common/unit.h
--- clean-E1/common/unit.h      Sun Jan 25 11:18:54 2004
+++ E1/common/unit.h    Thu Jan 29 14:55:26 2004
@@ -37,10 +37,24 @@ enum unit_activity {
 
 /* Changing this enum will break savegame and network compatability. */
 enum unit_orders {
-  ORDER_MOVE, ORDER_FINISH_TURN,
+  ORDER_MOVE, ORDER_FINISH_TURN, ORDER_NONE,
+  /* "Actions" not technically "activities". */
+  ORDER_AUTO_ATTACK, ORDER_AUTO_SETTLE, ORDER_BUILD_CITY,
+  ORDER_BUILD_WONDER, ORDER_DISBAND, ORDER_HOMECITY,
+  ORDER_TRADEROUTE, ORDER_UNLOAD,
+  /* These duplicate items from "enum unit_activity". */
+  ORDER_AIRBASE, ORDER_EXPLORE, ORDER_FALLOUT, ORDER_FORTIFYING,
+  ORDER_FORTRESS, ORDER_IRRIGATE, ORDER_MINE, ORDER_PILLAGE,
+  ORDER_POLLUTION, ORDER_ROAD, ORDER_RAILROAD, ORDER_SENTRY,
+  ORDER_TRANSFORM,
   ORDER_LAST
 };
 
+/* For client to determine which sprite to display. */
+enum movement_type {
+  GOTO_ORDERS, PATROL_ORDERS, STATIONARY_ORDERS
+};
+
 enum unit_focus_status {
   FOCUS_AVAIL, FOCUS_WAIT, FOCUS_DONE  
 };
@@ -65,10 +79,6 @@ enum goto_move_restriction {
   GOTO_MOVE_STRAIGHTEST
 };
 
-enum goto_route_type {
-  ROUTE_GOTO, ROUTE_PATROL
-};
-
 enum unit_move_result {
   MR_OK, MR_BAD_TYPE_FOR_CITY_TAKE_OVER, MR_NO_WAR, MR_ZOC,
   MR_BAD_ACTIVITY, MR_BAD_DESTINATION, MR_BAD_MAP_POSITION,
@@ -168,6 +178,9 @@ struct unit {
     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 */
+    /* Information for client to display sprites correctly. */
+    enum unit_orders mission;       /* The last order in the list. */
+    enum movement_type move_type;   /* Goto, Patrol, Stationary.   */
   } orders;
 };
 
@@ -238,6 +251,7 @@ bool unit_can_est_traderoute_here(struct
 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 order_is_action(enum unit_orders order);
 
 bool can_unit_paradrop(struct unit *punit);
 bool can_unit_change_homecity(struct unit *punit);
diff -pruN -Xdiff_ignore clean-E1/server/savegame.c E1/server/savegame.c
--- clean-E1/server/savegame.c  Tue Jan 20 23:08:47 2004
+++ E1/server/savegame.c        Thu Jan 29 14:55:26 2004
@@ -1131,6 +1131,10 @@ static void player_load(struct player *p
          punit->orders.list[j].order = orders_buf[j] - 'a';
          punit->orders.list[j].dir = dir_buf[j] - 'a';
        }
+       punit->orders.mission = secfile_lookup_int_default(file,
+           (int) ORDER_NONE, "player%d.u%d.orders_mission", plrno, i);
+       punit->orders.move_type = secfile_lookup_int_default(file,
+           (int) STATIONARY_ORDERS, "player%d.u%d.move_type", plrno, i);
        punit->has_orders = TRUE;
       } else {
        punit->has_orders = FALSE;
@@ -1561,6 +1565,11 @@ static void player_save(struct player *p
                         "player%d.u%d.orders_list", plrno, i);
       secfile_insert_str(file, dir_buf,
                         "player%d.u%d.dir_list", plrno, i);
+
+      secfile_insert_int(file, punit->orders.mission,
+                        "player%d.u%d.orders_mission", plrno, i);
+      secfile_insert_int(file, punit->orders.move_type,
+                        "player%d.u%d.move_type", plrno, i);
     } else {
       secfile_insert_int(file, 0, "player%d.u%d.orders_length", plrno, i);
     }
diff -pruN -Xdiff_ignore clean-E1/server/unithand.c E1/server/unithand.c
--- clean-E1/server/unithand.c  Wed Jan 28 08:42:38 2004
+++ E1/server/unithand.c        Thu Jan 29 14:55:26 2004
@@ -1509,6 +1509,26 @@ void handle_unit_orders(struct player *p
       }
       break;
     case ORDER_FINISH_TURN:
+    case ORDER_AUTO_ATTACK:
+    case ORDER_AUTO_SETTLE:
+    case ORDER_BUILD_CITY:
+    case ORDER_BUILD_WONDER:
+    case ORDER_DISBAND:
+    case ORDER_HOMECITY:
+    case ORDER_TRADEROUTE:
+    case ORDER_UNLOAD:
+    case ORDER_AIRBASE:
+    case ORDER_EXPLORE:
+    case ORDER_FALLOUT:
+    case ORDER_FORTIFYING:
+    case ORDER_FORTRESS:
+    case ORDER_IRRIGATE:
+    case ORDER_MINE:
+    case ORDER_PILLAGE:
+    case ORDER_POLLUTION:
+    case ORDER_ROAD:
+    case ORDER_SENTRY:
+    case ORDER_TRANSFORM:
       break;
     default:
       /* An invalid order.  This is handled in execute_orders. */
@@ -1536,6 +1556,9 @@ void handle_unit_orders(struct player *p
     punit->orders.list[i].order = packet->orders[i];
     punit->orders.list[i].dir = packet->dir[i];
   }
+  /* For client to display correct sprites. */
+  punit->orders.mission = packet->orders[packet->length - 1];
+  punit->orders.move_type = packet->repeat ? PATROL_ORDERS : GOTO_ORDERS;
 
   if (!packet->repeat) {
     set_goto_dest(punit, packet->dest_x, packet->dest_y);
diff -pruN -Xdiff_ignore clean-E1/server/unittools.c E1/server/unittools.c
--- clean-E1/server/unittools.c Thu Jan 29 12:01:18 2004
+++ E1/server/unittools.c       Thu Jan 29 14:55:26 2004
@@ -1898,8 +1898,12 @@ void package_unit(struct unit *punit, st
   if (punit->has_orders) {
     packet->repeat = punit->orders.repeat;
     packet->vigilant = punit->orders.vigilant;
+    packet->mission = punit->orders.mission;
+    packet->move_type = punit->orders.move_type;
   } else {
     packet->repeat = packet->vigilant = FALSE;
+    packet->mission = ORDER_NONE;
+    packet->move_type = STATIONARY_ORDERS;
   }
 }
 
@@ -3167,10 +3171,12 @@ static bool maybe_cancel_patrol_due_to_e
 bool 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;
+  bool res, is_last_order;
+  enum unit_activity activity;
+  struct player *pplayer = unit_owner(punit);
+  struct city *pcity;
 
   assert(unit_has_orders(punit));
 
@@ -3182,18 +3188,34 @@ bool execute_orders(struct unit *punit)
   while (TRUE) {
     struct unit_order order;
 
-    if (punit->moves_left == 0) {
-      /* FIXME: this check won't work when actions take 0 MP. */
+    order = punit->orders.list[punit->orders.index];
+
+    is_last_order = (!punit->orders.repeat &&
+                    punit->orders.index + 1 == punit->orders.length);
+
+    if (is_last_order && order_is_action(order.order)) {
+      /* Don't display goto/patrol sprite any more. In practice, this is
+       * only for exhausted settlers with Mission Order: Build city. */
+      punit->orders.move_type = STATIONARY_ORDERS;
+
+      if (punit->moves_left == 0 && order.order == ORDER_BUILD_CITY) {
+       freelog(LOG_DEBUG, "  ran out of MPs and will build city later.");
+       return TRUE;
+      }
+    }
+
+    else if (punit->moves_left == 0) {
       freelog(LOG_DEBUG, "  stopping because of no more move points");
       return TRUE;
     }
 
-    if (punit->done_moving) {
+    else if (punit->done_moving) {
       freelog(LOG_DEBUG, "  stopping because we're done this turn");
       return TRUE;
     }
 
-    if (punit->orders.vigilant && maybe_cancel_patrol_due_to_enemy(punit)) {
+    else 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");               
       free_unit_orders(punit);
@@ -3204,17 +3226,13 @@ bool execute_orders(struct unit *punit)
       return TRUE;
     }
 
-    if (moves_made == punit->orders.length) {
+    else 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 TRUE;
     }
 
-    last_order = (!punit->orders.repeat
-                 && punit->orders.index + 1 == punit->orders.length);
-
-    order = punit->orders.list[punit->orders.index];
-    if (last_order) {
+    if (is_last_order) {
       /* Clear the orders before we engage in the move.  That way any
        * has_orders checks will yield FALSE and this will be treated as
        * a normal move.  This is important: for instance a caravan goto
@@ -3222,6 +3240,7 @@ bool execute_orders(struct unit *punit)
       free_unit_orders(punit);
     }
 
+    activity = ACTIVITY_LAST;
     switch (order.order) {
     case ORDER_FINISH_TURN:
       punit->done_moving = TRUE;
@@ -3240,7 +3259,7 @@ bool execute_orders(struct unit *punit)
        return TRUE;
       }
 
-      if (!last_order
+      if (!is_last_order
          && maybe_cancel_goto_due_to_enemy(punit, dest_x, dest_y)) {
        freelog(LOG_DEBUG, "  orders canceled because of enemy");
        free_unit_orders(punit);
@@ -3253,7 +3272,7 @@ bool execute_orders(struct unit *punit)
 
       freelog(LOG_DEBUG, "  moving to %d,%d", dest_x, dest_y);
       res = handle_unit_move_request(punit, dest_x, dest_y,
-                                    FALSE, !last_order);
+                                    FALSE, !is_last_order);
       if (!player_find_unit_by_id(pplayer, unitid)) {
        freelog(LOG_DEBUG, "  unit died while moving.");
        /* A player notification should already have been sent. */
@@ -3276,9 +3295,81 @@ bool execute_orders(struct unit *punit)
                         unit_name(punit->type));
        return TRUE;
       }
-
       break;
-    case ORDER_LAST:
+    case ORDER_AUTO_ATTACK:
+    case ORDER_AUTO_SETTLE:
+      freelog(LOG_DEBUG, "  entering auto mode.");
+      handle_unit_auto(pplayer, unitid);
+      break;
+    case ORDER_BUILD_CITY:
+      /* We don't need extra 2-way communication about city names,
+       * since this function may be called when sniff_packets() is
+       * not active. Player will just have to accept that
+       * Build Missions take default city name. */
+      freelog(LOG_DEBUG, "  founding new city.");
+      handle_unit_build_city(pplayer, unitid,
+        city_name_suggestion(pplayer, punit->x, punit->y));
+      break;
+    case ORDER_BUILD_WONDER:
+      freelog(LOG_DEBUG, "  building wonder.");
+      handle_unit_help_build_wonder(pplayer, unitid);
+      break;
+    case ORDER_DISBAND:
+      freelog(LOG_DEBUG, "  disbanding unit.");
+      handle_unit_disband(pplayer, unitid);
+      break;
+    case ORDER_HOMECITY:
+      freelog(LOG_DEBUG, "  changing homecity.");
+      pcity = map_get_city(punit->x, punit->y);
+      handle_unit_change_homecity(pplayer, unitid, pcity ? pcity->id : -1);
+      break;
+    case ORDER_TRADEROUTE:
+      freelog(LOG_DEBUG, "  establishing a trade route.");
+      handle_unit_establish_trade(pplayer, unitid);
+      break;
+    case ORDER_UNLOAD:
+      freelog(LOG_DEBUG, "  unloading.");
+      handle_unit_unload(pplayer, unitid);
+      break;
+    case ORDER_AIRBASE:
+      activity = ACTIVITY_AIRBASE;
+      break;
+    case ORDER_EXPLORE:
+      activity = ACTIVITY_EXPLORE;
+      break;
+    case ORDER_FALLOUT:
+      activity = ACTIVITY_FALLOUT;
+      break;
+    case ORDER_FORTIFYING:
+      activity = ACTIVITY_FORTIFYING;
+      break;
+    case ORDER_FORTRESS:
+      activity = ACTIVITY_FORTRESS;
+      break;
+    case ORDER_IRRIGATE:
+      activity = ACTIVITY_IRRIGATE;
+      break;
+    case ORDER_MINE:
+      activity = ACTIVITY_MINE;
+      break;
+    case ORDER_PILLAGE:
+      activity = ACTIVITY_PILLAGE;
+      break;
+    case ORDER_POLLUTION:
+      activity = ACTIVITY_POLLUTION;
+      break;
+    case ORDER_SENTRY:
+      activity = ACTIVITY_SENTRY;
+      break;
+    case ORDER_TRANSFORM:
+      activity = ACTIVITY_TRANSFORM;
+      break;
+    case ORDER_ROAD:
+    case ORDER_RAILROAD:
+      activity = map_has_special(punit->x, punit->y, S_ROAD)
+                 ? ACTIVITY_RAILROAD : ACTIVITY_ROAD;
+      break;
+    default:
       freelog(LOG_DEBUG, "  client sent invalid order!");
       free_unit_orders(punit);
       notify_player_ex(pplayer, punit->x, punit->y, E_UNIT_ORDERS,
@@ -3287,7 +3378,25 @@ bool execute_orders(struct unit *punit)
       return TRUE;
     }
 
-    if (last_order) {
+    if (activity == ACTIVITY_EXPLORE) {
+      /* This generates new orders. */
+      free_unit_orders(punit);
+      freelog(LOG_DEBUG, "  entering explore mode.");
+      handle_unit_change_activity(pplayer, unitid, activity, S_NO_SPECIAL);
+      return player_find_unit_by_id(pplayer, unitid) ? TRUE : FALSE;
+    }
+
+    if (activity != ACTIVITY_LAST) {
+      freelog(LOG_DEBUG, "  setting new activity.");
+      handle_unit_change_activity(pplayer, unitid, activity, S_NO_SPECIAL);
+    }
+
+    if (!player_find_unit_by_id(pplayer, unitid)) {
+      freelog(LOG_DEBUG, "  unit died from executing order.");
+      return FALSE;
+    }
+
+    if (is_last_order) {
       assert(punit->has_orders == FALSE);
       freelog(LOG_DEBUG, "  stopping because orders are complete");
       return TRUE;

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#7344) Expanded Orders, Arnstein Lindgard <=