(svn r2583) Move OS specific code out of misc.c

Added support for Mersenne Twister random number generator (not implemented in network yet)
Wrap player randoms around #ifdef
This commit is contained in:
ludde 2005-07-15 20:29:06 +00:00
parent c964809d37
commit 71f9078bdd
10 changed files with 173 additions and 56 deletions

View File

@ -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);
#endif
#endif // MERSENNE_TWISTER
static inline TileIndex RandomTileSeed(uint32 r) { return TILE_MASK(r); }
static inline TileIndex RandomTile(void) { return TILE_MASK(Random()); }
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
void InitPlayerRandoms(void);
uint32 InteractiveRandom(void); /* Used for random sequences that are not the same on the other end of the multiplayer link */
uint InteractiveRandomRange(uint max);

72
mersenne.c Normal file
View File

@ -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

63
misc.c
View 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);

View File

@ -773,7 +773,9 @@ static void NetworkInitialize(void)
_network_reconnect = 0;
#ifdef PLAYER_SEED_RANDOM
InitPlayerRandoms();
#endif
NetworkUDPInitialize();
}

View File

@ -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);

View File

@ -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

View File

@ -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

47
unix.c
View File

@ -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 */

View File

@ -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;

View File

@ -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);
}