Author: sveinung
Date: Tue Sep 22 11:04:33 2015
New Revision: 29950

URL: http://svn.gna.org/viewcvs/freeciv?rev=29950&view=rev
Log:
Save unit order targets as a vector

so its value can be outside what char2num can represent.

This makes it possible to store non extra targets in it.

The filler values are added avoid breaking the tabular format of the unit
table in the save games.

See patch #6363

Modified:
    trunk/common/fc_types.h
    trunk/server/savecompat.c
    trunk/server/savegame3.c

Modified: trunk/common/fc_types.h
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/fc_types.h?rev=29950&r1=29949&r2=29950&view=diff
==============================================================================
--- trunk/common/fc_types.h     (original)
+++ trunk/common/fc_types.h     Tue Sep 22 11:04:33 2015
@@ -43,8 +43,6 @@
 #define MAX_LEN_VET_SHORT_NAME 8
 /* Used in the network protocol. See diplomat_success_vs_defender() */
 #define MAX_VET_LEVELS 20
-/* Limited by what values num2char() can store in unit orders in
- * savegames. */
 #define MAX_EXTRA_TYPES 64 /* Used in the network protocol. */
 #define MAX_BASE_TYPES MAX_EXTRA_TYPES /* Used in the network protocol. */
 #define MAX_ROAD_TYPES MAX_EXTRA_TYPES /* Used in the network protocol. */

Modified: trunk/server/savecompat.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/savecompat.c?rev=29950&r1=29949&r2=29950&view=diff
==============================================================================
--- trunk/server/savecompat.c   (original)
+++ trunk/server/savecompat.c   Tue Sep 22 11:04:33 2015
@@ -1036,11 +1036,35 @@
   }
 }
 
+#ifdef FREECIV_DEV_SAVE_COMPAT
+static const char num_chars[] =
+  "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+";
+
+/**************************************************************************
+  Converts single character into numerical value. This is not hex
+  conversion.
+**************************************************************************/
+static int char2num(char ch)
+{
+  const char *pch;
+
+  if (ch == '?') {
+    /* Not specified. */
+    return -1;
+  }
+
+  pch = strchr(num_chars, ch);
+
+  sg_failure_ret_val(NULL != pch, 0,
+                     "Unknown ascii value for num: '%c' %d", ch, ch);
+
+  return pch - num_chars;
+}
+
 /****************************************************************************
   Translate savegame secfile data from earlier development version format
   to current one.
 ****************************************************************************/
-#ifdef FREECIV_DEV_SAVE_COMPAT
 static void compat_load_dev(struct loaddata *loading)
 {
   bool randsaved;
@@ -1075,6 +1099,51 @@
       name = secfile_lookup_str_default(loading->file, "", 
"player%d.ranked_username", plrno);
       secfile_insert_bool(loading->file, (!strcmp(name, ANON_USER_NAME)),
                           "player%d.unassigned_ranked", plrno);
+    }
+  }
+
+  /* Units orders. */
+  for (plrno = 0; plrno < nplayers; plrno++) {
+    int units_num = secfile_lookup_int_default(loading->file, 0,
+                                               "player%d.nunits",
+                                               plrno);
+    int unit;
+    int tgt_vec[MAX_LEN_ROUTE + 1];
+
+    for (unit = 0; unit < units_num; unit++) {
+      int ord_num;
+
+      /* Load the old target list string. */
+      const char *tgt_str =
+          secfile_lookup_str_default(loading->file, NULL,
+                                     "player%d.u%d.tgt_list",
+                                     plrno, unit);
+
+      /* Load the order length */
+      const int len =
+          secfile_lookup_int_default(loading->file, 0,
+                                     "player%d.u%d.orders_length",
+                                     plrno, unit);
+
+      if (tgt_str == NULL) {
+        /* Already upgraded */
+        continue;
+      }
+
+      if (len <= 0) {
+        /* No orders. */
+        continue;
+      }
+
+      /* Convert the target of each order. */
+      for (ord_num = 0; ord_num < len; ord_num++) {
+        tgt_vec[ord_num] = char2num(tgt_str[ord_num]);
+      }
+
+      /* Store the order target vector. */
+      secfile_insert_int_vec(loading->file, tgt_vec, len,
+                             "player%d.u%d.tgt_vec",
+                             plrno, unit);
     }
   }
 }

Modified: trunk/server/savegame3.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/savegame3.c?rev=29950&r1=29949&r2=29950&view=diff
==============================================================================
--- trunk/server/savegame3.c    (original)
+++ trunk/server/savegame3.c    Tue Sep 22 11:04:33 2015
@@ -5133,7 +5133,6 @@
                                          "%s.orders_length", unitstr);
     if (len > 0) {
       const char *orders_unitstr, *dir_unitstr, *act_unitstr;
-      const char *tgt_unitstr;
       const char *action_unitstr;
 
       punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
@@ -5157,15 +5156,14 @@
       act_unitstr
         = secfile_lookup_str_default(loading->file, "",
                                      "%s.activity_list", unitstr);
-      tgt_unitstr
-        = secfile_lookup_str_default(loading->file, NULL, "%s.tgt_list", 
unitstr);
-
       action_unitstr
         = secfile_lookup_str_default(loading->file, "",
                                      "%s.action_list", unitstr);
+
       punit->has_orders = TRUE;
       for (j = 0; j < len; j++) {
         struct unit_order *order = &punit->orders.list[j];
+        int order_tgt;
 
         if (orders_unitstr[j] == '\0' || dir_unitstr[j] == '\0'
 #ifndef FREECIV_DEV_SAVE_COMPAT
@@ -5219,19 +5217,26 @@
           break;
         }
 
-        if (tgt_unitstr) {
-          if (tgt_unitstr[j] != '?') {
-            extra_id = char2num(tgt_unitstr[j]);
-
-            if (extra_id < 0 || extra_id >= loading->extra.size) {
+        order_tgt = secfile_lookup_int_default(loading->file, -1,
+                                               "%s.tgt_vec,%d",
+                                               unitstr, j);
+
+        if (order->order == ORDER_PERFORM_ACTION) {
+          /* TODO: Validate action target */
+          order->target = order_tgt;
+        } else {
+          /* Assume that this is an extra */
+          extra_id = order_tgt;
+
+          if (extra_id < 0 || extra_id >= loading->extra.size) {
+            if (order_tgt != EXTRA_NONE) {
               log_sg("Cannot find extra %d for %s to build",
                      extra_id, unit_rule_name(punit));
-              order->target = EXTRA_NONE;
-            } else {
-              order->target = extra_id;
             }
+
+            order->target = EXTRA_NONE;
           } else {
-            order->target = EXTRA_NONE;
+            order->target = extra_id;
           }
         }
       }
@@ -5302,17 +5307,29 @@
                                  struct player *plr)
 {
   int i = 0;
+  int longest_order = 0;
 
   /* Check status and return if not OK (sg_success != TRUE). */
   sg_check_ret();
 
   secfile_insert_int(saving->file, unit_list_size(plr->units),
                      "player%d.nunits", player_number(plr));
+
+  /* Find the longest unit order so different order length won't break
+   * storing units in the tabular format. */
+  unit_list_iterate(plr->units, punit) {
+    if (punit->has_orders) {
+      if (longest_order < punit->orders.length) {
+        longest_order = punit->orders.length;
+      }
+    }
+  } unit_list_iterate_end;
 
   unit_list_iterate(plr->units, punit) {
     char buf[32];
     char dirbuf[2] = " ";
     int nat_x, nat_y;
+    int last_order, j;
 
     fc_snprintf(buf, sizeof(buf), "player%d.u%d", player_number(plr), i);
     dirbuf[0] = dir2char(punit->facing);
@@ -5393,10 +5410,13 @@
                        "%s.transported_by", buf);
 
     if (punit->has_orders) {
-      int len = punit->orders.length, j;
+      int len = punit->orders.length;
       char orders_buf[len + 1], dir_buf[len + 1];
-      char act_buf[len + 1], tgt_buf[len + 1];
+      char act_buf[len + 1];
       char action_buf[len + 1];
+      int tgt_vec[len];
+
+      last_order = len;
 
       secfile_insert_int(saving->file, len, "%s.orders_length", buf);
       secfile_insert_int(saving->file, punit->orders.index,
@@ -5410,14 +5430,14 @@
         orders_buf[j] = order2char(punit->orders.list[j].order);
         dir_buf[j] = '?';
         act_buf[j] = '?';
-        tgt_buf[j] = '?';
+        tgt_vec[j] = -1;
         action_buf[j] = '?';
         switch (punit->orders.list[j].order) {
         case ORDER_MOVE:
           dir_buf[j] = dir2char(punit->orders.list[j].dir);
           break;
         case ORDER_ACTIVITY:
-          tgt_buf[j] = num2char(punit->orders.list[j].target);
+          tgt_vec[j] = punit->orders.list[j].target;
           act_buf[j] = activity2char(punit->orders.list[j].activity);
           break;
         case ORDER_PERFORM_ACTION:
@@ -5438,15 +5458,17 @@
           break;
         }
       }
-      orders_buf[len] = dir_buf[len] = act_buf[len] = tgt_buf[len] = '\0';
+      orders_buf[len] = dir_buf[len] = act_buf[len] = '\0';
       action_buf[len] = '\0';
 
       secfile_insert_str(saving->file, orders_buf, "%s.orders_list", buf);
       secfile_insert_str(saving->file, dir_buf, "%s.dir_list", buf);
       secfile_insert_str(saving->file, act_buf, "%s.activity_list", buf);
-      secfile_insert_str(saving->file, tgt_buf, "%s.tgt_list", buf);
       secfile_insert_str(saving->file, action_buf, "%s.action_list", buf);
+      secfile_insert_int_vec(saving->file, tgt_vec, len,
+                             "%s.tgt_vec", buf);
     } else {
+
       /* Put all the same fields into the savegame - otherwise the
        * registry code can't correctly use a tabular format and the
        * savegame will be bigger. */
@@ -5457,8 +5479,18 @@
       secfile_insert_str(saving->file, "-", "%s.orders_list", buf);
       secfile_insert_str(saving->file, "-", "%s.dir_list", buf);
       secfile_insert_str(saving->file, "-", "%s.activity_list", buf);
-      secfile_insert_str(saving->file, "-", "%s.tgt_list", buf);
       secfile_insert_str(saving->file, "-", "%s.action_list", buf);
+
+      /* The start of a vector has no number. */
+      secfile_insert_int(saving->file, -1, "%s.tgt_vec", buf);
+      last_order = 1;
+    }
+
+    for (j = last_order; j < longest_order; j++) {
+      /* Fill in dummy values for order targets so the registry will save
+       * the unit table in a tabular format. */
+
+      secfile_insert_int(saving->file, -1, "%s.tgt_vec,%d", buf, j);
     }
 
     i++;


_______________________________________________
Freeciv-commits mailing list
Freeciv-commits@gna.org
https://mail.gna.org/listinfo/freeciv-commits

Reply via email to