<URL: http://bugs.freeciv.org/Ticket/Display.html?id=39365 >

I ended up with even more random debugging (attached patch), and solved
the problems, or at least several of them.

Also found an uninitialized founder_boat along the way.

My solution to the problems is entirely in savegame.c, saving enough
information to handle various turn counters and such that continue
throughout the game.  I presume these were just oversights by the
original coder(s).

The ai_manage_buildings initialization routine seems to need to be run
after loading the cities, I'm not sure exactly where in the restore it
belongs, so added it at the end.

Finally, (as I posted before) restoring the random pool a second time
at the very end of the load, as there are several initialization
routines that inexplicably randomize some variables -- just before the
actual values are restored from the file.  Eventually, it probably
would be better to rethink them, or how those tasks are organized.


--- ../rand.h   Sun Feb 18 23:01:44 2007
+++ utility/rand.h      Sun May 13 07:54:52 2007
@@ -26,7 +26,11 @@
   bool is_init;                        /* initially 0 for static storage */
 } RANDOM_STATE;
 
-RANDOM_TYPE myrand(RANDOM_TYPE size);
+#define myrand(vsize)      myrand_debug((vsize), "myrand", \
+                                        __LINE__, __FILE__)
+     
+RANDOM_TYPE myrand_debug(RANDOM_TYPE size, 
+                   const char *called_as, int line, const char *file);
 void mysrand(RANDOM_TYPE seed);
 
 bool myrand_is_init(void);
--- ../rand.c   Sun Feb 18 23:01:44 2007
+++ utility/rand.c      Sun May 13 08:56:56 2007
@@ -77,13 +77,14 @@
   directly representable in type RANDOM_TYPE, so we do instead:
          divisor = MAX_UINT32/size
 *************************************************************************/
-RANDOM_TYPE myrand(RANDOM_TYPE size) 
+RANDOM_TYPE myrand_debug(RANDOM_TYPE size,
+                    const char *called_as, int line, const char *file) 
 {
   RANDOM_TYPE new_rand, divisor, max;
   int bailout = 0;
 
   assert(rand_state.is_init);
-    
+
   if (size > 1) {
     divisor = MAX_UINT32 / size;
     max = size * divisor - 1;
@@ -108,7 +109,8 @@
     rand_state.v[rand_state.x] = new_rand;
 
     if (++bailout > 10000) {
-      freelog(LOG_ERROR, "Bailout in myrand(%u)", size);
+      freelog(LOG_ERROR, "%s(%lu) = %lu bailout at line %d of %s", 
+           called_as, (unsigned long)size, (unsigned long)new_rand, line, 
file);
       new_rand = 0;
       break;
     }
@@ -122,6 +124,8 @@
   }
 
   /* freelog(LOG_DEBUG, "rand(%u) = %u", size, new_rand); */
+  freelog(LOG_VERBOSE, "%s(%lu) = %lu at line %d of %s",
+           called_as, (unsigned long)size, (unsigned long)new_rand, line, 
file);
 
   return new_rand;
 } 
@@ -170,6 +174,16 @@
 *************************************************************************/
 RANDOM_STATE get_myrand_state(void)
 {
+  int i;
+  freelog(LOG_VERBOSE, "get_myrand_state J=%d K=%d X=%d",
+    rand_state.j, rand_state.k, rand_state.x);
+  for (i  = 0; i < 8; i++) {
+    freelog(LOG_VERBOSE, "get_myrand_state %d, %08x %08x %08x %08x %08x %08x 
%08x",
+      i, rand_state.v[7 * i],
+      rand_state.v[7 * i + 1], rand_state.v[7 * i + 2],
+      rand_state.v[7 * i + 3], rand_state.v[7 * i + 4],
+      rand_state.v[7 * i + 5], rand_state.v[7 * i + 6]);
+  }
   return rand_state;
 }
 
@@ -179,7 +193,17 @@
 *************************************************************************/
 void set_myrand_state(RANDOM_STATE state)
 {
+  int i;
   rand_state = state;
+  freelog(LOG_VERBOSE, "set_myrand_state J=%d K=%d X=%d",
+    rand_state.j, rand_state.k, rand_state.x);
+  for (i  = 0; i < 8; i++) {
+    freelog(LOG_VERBOSE, "set_myrand_state %d, %08x %08x %08x %08x %08x %08x 
%08x",
+      i, rand_state.v[7 * i],
+      rand_state.v[7 * i + 1], rand_state.v[7 * i + 2],
+      rand_state.v[7 * i + 3], rand_state.v[7 * i + 4],
+      rand_state.v[7 * i + 5], rand_state.v[7 * i + 6]);
+  }
 }
 
 /*************************************************************************
--- ../city.c   Tue Mar 20 22:23:07 2007
+++ common/city.c       Sun May 13 15:11:33 2007
@@ -2451,6 +2451,7 @@
   pcity->server.needs_arrange = FALSE;
   pcity->server.vision = NULL; /* No vision. */
 
+  pcity->ai.founder_boat = FALSE;
   pcity->ai.founder_want = 0; /* calculating this is really expensive */
   pcity->ai.next_founder_want_recalc = 0; /* turns to recalc found_want */
   pcity->ai.trade_want = 1; /* we always want some */
--- ../savegame.c       Tue Mar 20 22:22:54 2007
+++ server/savegame.c   Sun May 13 14:07:18 2007
@@ -2464,6 +2464,19 @@
     pcity->ai.urgency = secfile_lookup_int_default(file, 0, 
                                "player%d.c%d.ai.urgency", plrno, i);
 
+    /* avoid myrand recalculations on subsequent reload. */
+    pcity->ai.next_recalc = secfile_lookup_int_default(file, 0, 
+                               "player%d.c%d.ai.building_turn", plrno, i);
+
+    /* avoid myrand and expensive recalculations on subsequent reload. */
+    pcity->ai.next_founder_want_recalc = secfile_lookup_int_default(file, 0, 
+                               "player%d.c%d.ai.founder_turn", plrno, i);
+    pcity->ai.founder_want = secfile_lookup_int_default(file, 0, 
+                               "player%d.c%d.ai.founder_want", plrno, i);
+    pcity->ai.founder_boat = secfile_lookup_bool_default(file,
+                       (pcity->ai.founder_want < 0), 
+                               "player%d.c%d.ai.founder_boat", plrno, i);
+
     tile_set_city(pcity->tile, pcity);
 
     city_list_append(plr->cities, pcity);
@@ -3172,6 +3185,18 @@
     /* FIXME: remove this when the urgency is properly recalculated. */
     secfile_insert_int(file, pcity->ai.urgency,
                       "player%d.c%d.ai.urgency", plrno, i);
+
+    /* avoid myrand recalculations on subsequent reload. */
+    secfile_insert_int(file, pcity->ai.next_recalc,
+                      "player%d.c%d.ai.building_turn", plrno, i);
+
+    /* avoid myrand and expensive recalculations on subsequent reload. */
+    secfile_insert_int(file, pcity->ai.next_founder_want_recalc,
+                      "player%d.c%d.ai.founder_turn", plrno, i);
+    secfile_insert_int(file, pcity->ai.founder_want,
+                      "player%d.c%d.ai.founder_want", plrno, i);
+    secfile_insert_bool(file, pcity->ai.founder_boat,
+                      "player%d.c%d.ai.founder_boat", plrno, i);
   }
   city_list_iterate_end;
 
@@ -3398,6 +3423,7 @@
 {
   int i, k, id;
   enum server_states tmp_server_state;
+  RANDOM_STATE rstate;
   char *savefile_options;
   const char *string;
   char** improvement_order = NULL;
@@ -3799,7 +3825,6 @@
      2) if it is saved. */
   if (section_file_lookup(file, "random.index_J")
       && secfile_lookup_bool_default(file, TRUE, "game.save_random")) {
-    RANDOM_STATE rstate;
     rstate.j = secfile_lookup_int(file,"random.index_J");
     rstate.k = secfile_lookup_int(file,"random.index_K");
     rstate.x = secfile_lookup_int(file,"random.index_X");
@@ -3822,6 +3847,7 @@
      * be needed later during the load. */
     if (tmp_server_state == RUN_GAME_STATE) {
       init_game_seed();
+      rstate = get_myrand_state();
     }
   }
 
@@ -4010,6 +4036,24 @@
   players_iterate(pplayer) {
     calc_civ_score(pplayer);
   } players_iterate_end;
+
+  /* Recalculate the potential buildings for each city.  
+   * Has caused some problems with game random state. */
+  players_iterate(pplayer) {
+    bool saved_ai_control = pplayer->ai.control;
+
+   /* Recalculate for all players. */
+    pplayer->ai.control = FALSE;
+    ai_manage_buildings(pplayer);
+
+    pplayer->ai.control = saved_ai_control;
+  } players_iterate_end;
+  
+  /* Restore game random state, just in case various initialization code
+   * inexplicably altered the previously existing state. */
+  if (!game.info.is_new_game) {
+    set_myrand_state(rstate);
+  }
 }
 
 /***************************************************************
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to