diff options
-rw-r--r-- | functions.h | 27 | ||||
-rw-r--r-- | mersenne.c | 72 | ||||
-rw-r--r-- | misc.c | 63 | ||||
-rw-r--r-- | network.c | 2 | ||||
-rw-r--r-- | network_client.c | 2 | ||||
-rw-r--r-- | network_server.c | 4 | ||||
-rw-r--r-- | openttd.c | 2 | ||||
-rw-r--r-- | unix.c | 47 | ||||
-rw-r--r-- | variables.h | 3 | ||||
-rw-r--r-- | win32.c | 7 |
10 files changed, 173 insertions, 56 deletions
diff --git a/functions.h b/functions.h index 4960eb338..1ea2c9a8e 100644 --- a/functions.h +++ b/functions.h @@ -93,6 +93,21 @@ void NORETURN CDECL error(const char *str, ...); //#define RANDOM_DEBUG + +// Enable this to produce higher quality random numbers. +// Doesn't work with network yet. +//#define MERSENNE_TWISTER + +// Mersenne twister functions +void SeedMT(uint32 seed); +uint32 RandomMT(void); + + +#ifdef MERSENNE_TWISTER + static inline uint32 Random(void) { return RandomMT(); } + uint RandomRange(uint max); +#else + #ifdef RANDOM_DEBUG #define Random() DoRandom(__LINE__, __FILE__) uint32 DoRandom(int line, const char *file); @@ -101,12 +116,18 @@ void NORETURN CDECL error(const char *str, ...); #else uint32 Random(void); uint RandomRange(uint max); - - static inline TileIndex RandomTileSeed(uint32 r) { return TILE_MASK(r); } - static inline TileIndex RandomTile(void) { return TILE_MASK(Random()); } #endif +#endif // MERSENNE_TWISTER + +static inline TileIndex RandomTileSeed(uint32 r) { return TILE_MASK(r); } +static inline TileIndex RandomTile(void) { return TILE_MASK(Random()); } + +#ifdef PLAYER_SEED_RANDOM void InitPlayerRandoms(void); +#endif + + uint32 InteractiveRandom(void); /* Used for random sequences that are not the same on the other end of the multiplayer link */ uint InteractiveRandomRange(uint max); diff --git a/mersenne.c b/mersenne.c new file mode 100644 index 000000000..98170084f --- /dev/null +++ b/mersenne.c @@ -0,0 +1,72 @@ +#include "stdafx.h"
+#include "openttd.h"
+
+#ifdef MERSENNE_TWISTER
+
+// Source code for Mersenne Twister.
+// A Random number generator with much higher quality random numbers.
+
+#define N (624) // length of _mt_state vector
+#define M (397) // a period parameter
+#define K (0x9908B0DFU) // a magic constant
+#define hiBit(u) ((u) & 0x80000000U) // mask all but highest bit of u
+#define loBit(u) ((u) & 0x00000001U) // mask all but lowest bit of u
+#define loBits(u) ((u) & 0x7FFFFFFFU) // mask the highest bit of u
+#define mixBits(u, v) (hiBit(u)|loBits(v)) // move hi bit of u to hi bit of v
+
+static uint32 _mt_state[N+1]; // _mt_state vector + 1 extra to not violate ANSI C
+static uint32 *_mt_next; // _mt_next random value is computed from here
+static int _mt_left = -1; // can *_mt_next++ this many times before reloading
+
+void SeedMT(uint32 seed)
+{
+ register uint32 x = (seed | 1U) & 0xFFFFFFFFU, *s = _mt_state;
+ register int j;
+
+ for(_mt_left=0, *s++=x, j=N; --j;
+ *s++ = (x*=69069U) & 0xFFFFFFFFU);
+ }
+
+
+static uint32 ReloadMT(void)
+ {
+ register uint32 *p0=_mt_state, *p2=_mt_state+2, *pM=_mt_state+M, s0, s1;
+ register int j;
+
+ if(_mt_left < -1)
+ SeedMT(4357U);
+
+ _mt_left=N-1, _mt_next=_mt_state+1;
+
+ for(s0=_mt_state[0], s1=_mt_state[1], j=N-M+1; --j; s0=s1, s1=*p2++)
+ *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
+
+ for(pM=_mt_state, j=M; --j; s0=s1, s1=*p2++)
+ *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
+
+ s1=_mt_state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
+ s1 ^= (s1 >> 11);
+ s1 ^= (s1 << 7) & 0x9D2C5680U;
+ s1 ^= (s1 << 15) & 0xEFC60000U;
+ return(s1 ^ (s1 >> 18));
+ }
+
+
+uint32 RandomMT(void)
+{
+ uint32 y;
+
+ if(--_mt_left < 0)
+ return ReloadMT();
+
+ y = *_mt_next++;
+ y ^= (y >> 11);
+ y ^= (y << 7) & 0x9D2C5680U;
+ y ^= (y << 15) & 0xEFC60000U;
+ return y ^ (y >> 18);
+}
+#else
+
+void SeedMT(uint32 seed) {}
+
+#endif
\ No newline at end of file @@ -29,13 +29,14 @@ static inline uint32 ROR(uint32 x, int n) it completely! -- TrueLight */ #undef PLAYER_SEED_RANDOM +#ifndef MERSENNE_TWISTER + #ifdef RANDOM_DEBUG #include "network_data.h" - uint32 DoRandom(int line, const char *file) -#else +#else // RANDOM_DEBUG uint32 Random(void) -#endif +#endif // RANDOM_DEBUG { uint32 s; @@ -66,8 +67,9 @@ uint32 t; return _random_seeds[0][1] = ROR(s, 3) - 1; #endif } +#endif // MERSENNE_TWISTER -#ifdef RANDOM_DEBUG +#if defined(RANDOM_DEBUG) && !defined(MERSENNE_TWISTER) uint DoRandomRange(uint max, int line, const char *file) { return (uint16)DoRandom(line, file) * max >> 16; @@ -79,6 +81,7 @@ uint RandomRange(uint max) } #endif + uint32 InteractiveRandom(void) { uint32 t = _random_seeds[1][1]; @@ -92,6 +95,8 @@ uint InteractiveRandomRange(uint max) return (uint16)InteractiveRandom() * max >> 16; } + +#ifdef PLAYER_SEED_RANDOM void InitPlayerRandoms(void) { int i; @@ -100,6 +105,7 @@ void InitPlayerRandoms(void) _player_seeds[i][1]=InteractiveRandom(); } } +#endif void SetDate(uint date) { @@ -112,55 +118,6 @@ void SetDate(uint date) #endif /* ENABLE_NETWORK */ } - -#ifdef ENABLE_NETWORK - -// multi os compatible sleep function - -#ifdef __AMIGA__ -// usleep() implementation -# include <devices/timer.h> -# include <dos/dos.h> - - extern struct Device *TimerBase = NULL; - extern struct MsgPort *TimerPort = NULL; - extern struct timerequest *TimerRequest = NULL; -#endif // __AMIGA__ - -void CSleep(int milliseconds) -{ - #if defined(WIN32) - Sleep(milliseconds); - #endif - #if defined(UNIX) - #if !defined(__BEOS__) && !defined(__AMIGA__) - usleep(milliseconds * 1000); - #endif - #ifdef __BEOS__ - snooze(milliseconds * 1000); - #endif - #if defined(__AMIGA__) - { - ULONG signals; - ULONG TimerSigBit = 1 << TimerPort->mp_SigBit; - - // send IORequest - TimerRequest->tr_node.io_Command = TR_ADDREQUEST; - TimerRequest->tr_time.tv_secs = (milliseconds * 1000) / 1000000; - TimerRequest->tr_time.tv_micro = (milliseconds * 1000) % 1000000; - SendIO((struct IORequest *)TimerRequest); - - if (!((signals = Wait(TimerSigBit | SIGBREAKF_CTRL_C)) & TimerSigBit) ) { - AbortIO((struct IORequest *)TimerRequest); - } - WaitIO((struct IORequest *)TimerRequest); - } - #endif // __AMIGA__ - #endif -} - -#endif /* ENABLE_NETWORK */ - void InitializeVehicles(void); void InitializeWaypoints(void); void InitializeDepot(void); @@ -773,7 +773,9 @@ static void NetworkInitialize(void) _network_reconnect = 0; +#ifdef PLAYER_SEED_RANDOM InitPlayerRandoms(); +#endif NetworkUDPInitialize(); } diff --git a/network_client.c b/network_client.c index aad7e57ad..5b6a8bf27 100644 --- a/network_client.c +++ b/network_client.c @@ -488,11 +488,13 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP) // Check if this was the last packet if (maptype == MAP_PACKET_END) { // We also get, very nice, the player_seeds in this packet +#ifdef PLAYER_SEED_RANDOM int i; for (i = 0; i < MAX_PLAYERS; i++) { _player_seeds[i][0] = NetworkRecv_uint32(MY_CLIENT, p); _player_seeds[i][1] = NetworkRecv_uint32(MY_CLIENT, p); } +#endif fclose(file_pointer); diff --git a/network_server.c b/network_server.c index 99150aa8a..76223dfd2 100644 --- a/network_server.c +++ b/network_server.c @@ -323,7 +323,9 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP) NetworkSend_Packet(p, cs); if (feof(file_pointer)) { // Done reading! +#ifdef PLAYER_SEED_RANDOM int i; +#endif Packet *p; // XXX - Delete this when patch-settings are saved in-game @@ -331,11 +333,13 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP) p = NetworkSend_Init(PACKET_SERVER_MAP); NetworkSend_uint8(p, MAP_PACKET_END); +#ifdef PLAYER_SEED_RANDOM // Send the player_seeds in this packet for (i = 0; i < MAX_PLAYERS; i++) { NetworkSend_uint32(p, _player_seeds[i][0]); NetworkSend_uint32(p, _player_seeds[i][1]); } +#endif NetworkSend_Packet(p, cs); // Set the status to DONE_MAP, no we will wait for the client @@ -676,7 +676,9 @@ int ttd_main(int argc, char* argv[]) InitializeGUI(); IConsoleCmdExec("exec scripts/autoexec.scr 0"); +#ifdef PLAYER_SEED_RANDOM InitPlayerRandoms(); +#endif GenerateWorld(1, 64, 64); // Make the viewport initialization happy @@ -474,6 +474,7 @@ int CDECL main(int argc, char* argv[]) #endif _random_seeds[0][1] = _random_seeds[0][0] = time(NULL); + SeedMT(_random_seeds[0][1]); signal(SIGPIPE, SIG_IGN); @@ -581,3 +582,49 @@ void JoinOTTDThread(void) pthread_join(thread1, NULL); } + + + +#ifdef ENABLE_NETWORK + +// multi os compatible sleep function + +#ifdef __AMIGA__ +// usleep() implementation +# include <devices/timer.h> +# include <dos/dos.h> + + extern struct Device *TimerBase = NULL; + extern struct MsgPort *TimerPort = NULL; + extern struct timerequest *TimerRequest = NULL; +#endif // __AMIGA__ + +void CSleep(int milliseconds) +{ + #if !defined(__BEOS__) && !defined(__AMIGA__) + usleep(milliseconds * 1000); + #endif + #ifdef __BEOS__ + snooze(milliseconds * 1000); + #endif + #if defined(__AMIGA__) + { + ULONG signals; + ULONG TimerSigBit = 1 << TimerPort->mp_SigBit; + + // send IORequest + TimerRequest->tr_node.io_Command = TR_ADDREQUEST; + TimerRequest->tr_time.tv_secs = (milliseconds * 1000) / 1000000; + TimerRequest->tr_time.tv_micro = (milliseconds * 1000) % 1000000; + SendIO((struct IORequest *)TimerRequest); + + if (!((signals = Wait(TimerSigBit | SIGBREAKF_CTRL_C)) & TimerSigBit) ) { + AbortIO((struct IORequest *)TimerRequest); + } + WaitIO((struct IORequest *)TimerRequest); + } + #endif // __AMIGA__ +} + +#endif /* ENABLE_NETWORK */ + diff --git a/variables.h b/variables.h index 985390095..011627fe2 100644 --- a/variables.h +++ b/variables.h @@ -82,7 +82,10 @@ VARDEF uint16 _disaster_delay; VARDEF uint16 _station_tick_ctr; VARDEF uint32 _random_seeds[2][2]; + +#ifdef PLAYER_SEED_RANDOM VARDEF uint32 _player_seeds[MAX_PLAYERS][2]; +#endif // Iterator through all towns in OnTick_Town VARDEF uint32 _cur_town_ctr; @@ -2124,6 +2124,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, _random_seeds[0][0] = GetTickCount(); _random_seeds[0][1] = _random_seeds[0][0] * 0x1234567; #endif + SeedMT(_random_seeds[0][0]); argc = ParseCommandLine(GetCommandLine(), argv, lengthof(argv)); @@ -2263,3 +2264,9 @@ void JoinOTTDThread(void) WaitForSingleObject(hThread, INFINITE); } + + +void CSleep(int milliseconds) +{ + Sleep(milliseconds); +}
\ No newline at end of file |