URL: http://bugs.freeciv.org/Ticket/Display.html?id=40073
There's a problem with reproducing reports for 2.2 savegames. Over the past
9 months, I've spent considerable time improving the reproducibility of 2.1
(PR#39365, PR#39572, etc.)
Searching for myrand() differences between 2.1 and 2.2, found only 1 more
variable, added by PR#12682. It is used as both an interval *and* a weight
multiplier for calculating AI wants.
Renamed it to ai.building_wait, and save/restore it. (Yes, that's punny.)
Renamed the related AI recalc variables to have the same prefix_* as the
corresponding *_want counterparts (matching the names in the savegames).
Moved the pseudo-random equation from tilespec into rand, making it easier
to find, trace, and use elsewhere.
Other trivial cleanup.
Index: utility/rand.c
===
--- utility/rand.c (revision 14377)
+++ utility/rand.c (working copy)
@@ -78,8 +78,8 @@
directly representable in type RANDOM_TYPE, so we do instead:
divisor = MAX_UINT32/size
*/
-RANDOM_TYPE myrand_debug(RANDOM_TYPE size, const char *called_as, int line,
- const char *file)
+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;
@@ -110,8 +110,8 @@
rand_state.v[rand_state.x] = new_rand;
if (++bailout 1) {
- freelog(LOG_ERROR, %s(%lu) = %lu bailout at line %d of %s,
- called_as, (unsigned long)size, (unsigned long)new_rand, line,
file);
+ freelog(LOG_ERROR, %s(%lu) = %lu bailout at %s:%d,
+ called_as, (unsigned long)size, (unsigned long)new_rand, file,
line);
new_rand = 0;
break;
}
@@ -124,8 +124,8 @@
new_rand = 0;
}
- freelog(LOG_RAND, %s(%lu) = %lu at line %d of %s,
- called_as, (unsigned long)size, (unsigned long)new_rand, line,
file);
+ freelog(LOG_RAND, %s(%lu) = %lu at %s:%d,
+ called_as, (unsigned long)size, (unsigned long)new_rand, file,
line);
return new_rand;
}
@@ -248,3 +248,31 @@
/* restore state: */
set_myrand_state(saved_state);
}
+
+/*
+ Local pseudo-random function for repeatedly reaching the same result,
+ instead of myrand(). Primarily needed for tiles.
+
+ Use an invariant equation for seed.
+ Result is 0 to (size - 1).
+*/
+RANDOM_TYPE myrandomly_debug(RANDOM_TYPE seed, RANDOM_TYPE size,
+const char *called_as, int line, const char *file)
+{
+ RANDOM_TYPE result;
+
+#define LARGE_PRIME (10007)
+#define SMALL_PRIME (1009)
+
+ /* Check for overflow and underflow */
+ assert((int)(seed * LARGE_PRIME) 0);
+ assert(size SMALL_PRIME);
+ assert(size 0);
+ result = ((seed * LARGE_PRIME) % SMALL_PRIME) % size;
+
+ freelog(LOG_RAND, %s(%lu,%lu) = %lu at %s:%d,
+ called_as, (unsigned long)seed, (unsigned long)size,
+ (unsigned long)result, file, line);
+
+ return result;
+}
Index: utility/rand.h
===
--- utility/rand.h (revision 14377)
+++ utility/rand.h (working copy)
@@ -26,8 +26,8 @@
bool is_init;/* initially 0 for static storage */
} RANDOM_STATE;
-#define myrand(vsize) myrand_debug((vsize), myrand, \
-__LINE__, __FILE__)
+#define myrand(_size) \
+ myrand_debug((_size), myrand, __LINE__, __FILE__)
RANDOM_TYPE myrand_debug(RANDOM_TYPE size, const char *called_as,
int line, const char *file);
@@ -40,4 +40,12 @@
void test_random1(int n);
+/*===*/
+
+#define myrandomly(_seed, _size) \
+ myrandomly_debug((_seed), (_size), myrandomly, __LINE__, __FILE__)
+
+RANDOM_TYPE myrandomly_debug(RANDOM_TYPE seed, RANDOM_TYPE size,
+const char *called_as, int line, const char *file);
+
#endif /* FC__RAND_H */
Index: server/stdinhand.c
===
--- server/stdinhand.c (revision 14377)
+++ server/stdinhand.c (working copy)
@@ -2357,7 +2357,6 @@
} else {
pcity-debug = TRUE;
CITY_LOG(LOG_TEST, pcity, debugged);
- pcity-ai.next_recalc = 0; /* force recalc of city next turn */
}
} else if (ntokens 0 strcmp(arg[0], units) == 0) {
int x, y;
Index: server/savegame.c
===
--- server/savegame.c (revision 14377)
+++ server/savegame.c (working copy)
@@ -2533,21 +2533,30 @@
worklist_load(file, pcity-worklist, player%d.c%d, plrno, i);
/* FIXME: remove this when the urgency is properly recalculated. */
-