mirror of https://github.com/OpenTTD/OpenTTD
(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 #ifdefrelease/0.4.5
parent
c964809d37
commit
71f9078bdd
27
functions.h
27
functions.h
|
@ -93,6 +93,21 @@ void NORETURN CDECL error(const char *str, ...);
|
||||||
|
|
||||||
//#define RANDOM_DEBUG
|
//#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
|
#ifdef RANDOM_DEBUG
|
||||||
#define Random() DoRandom(__LINE__, __FILE__)
|
#define Random() DoRandom(__LINE__, __FILE__)
|
||||||
uint32 DoRandom(int line, const char *file);
|
uint32 DoRandom(int line, const char *file);
|
||||||
|
@ -101,12 +116,18 @@ void NORETURN CDECL error(const char *str, ...);
|
||||||
#else
|
#else
|
||||||
uint32 Random(void);
|
uint32 Random(void);
|
||||||
uint RandomRange(uint max);
|
uint RandomRange(uint max);
|
||||||
|
#endif
|
||||||
|
#endif // MERSENNE_TWISTER
|
||||||
|
|
||||||
static inline TileIndex RandomTileSeed(uint32 r) { return TILE_MASK(r); }
|
static inline TileIndex RandomTileSeed(uint32 r) { return TILE_MASK(r); }
|
||||||
static inline TileIndex RandomTile(void) { return TILE_MASK(Random()); }
|
static inline TileIndex RandomTile(void) { return TILE_MASK(Random()); }
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PLAYER_SEED_RANDOM
|
||||||
|
void InitPlayerRandoms(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void InitPlayerRandoms(void);
|
|
||||||
|
|
||||||
uint32 InteractiveRandom(void); /* Used for random sequences that are not the same on the other end of the multiplayer link */
|
uint32 InteractiveRandom(void); /* Used for random sequences that are not the same on the other end of the multiplayer link */
|
||||||
uint InteractiveRandomRange(uint max);
|
uint InteractiveRandomRange(uint max);
|
||||||
|
|
|
@ -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
63
misc.c
|
@ -29,13 +29,14 @@ static inline uint32 ROR(uint32 x, int n)
|
||||||
it completely! -- TrueLight */
|
it completely! -- TrueLight */
|
||||||
#undef PLAYER_SEED_RANDOM
|
#undef PLAYER_SEED_RANDOM
|
||||||
|
|
||||||
|
#ifndef MERSENNE_TWISTER
|
||||||
|
|
||||||
#ifdef RANDOM_DEBUG
|
#ifdef RANDOM_DEBUG
|
||||||
#include "network_data.h"
|
#include "network_data.h"
|
||||||
|
|
||||||
uint32 DoRandom(int line, const char *file)
|
uint32 DoRandom(int line, const char *file)
|
||||||
#else
|
#else // RANDOM_DEBUG
|
||||||
uint32 Random(void)
|
uint32 Random(void)
|
||||||
#endif
|
#endif // RANDOM_DEBUG
|
||||||
{
|
{
|
||||||
|
|
||||||
uint32 s;
|
uint32 s;
|
||||||
|
@ -66,8 +67,9 @@ uint32 t;
|
||||||
return _random_seeds[0][1] = ROR(s, 3) - 1;
|
return _random_seeds[0][1] = ROR(s, 3) - 1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif // MERSENNE_TWISTER
|
||||||
|
|
||||||
#ifdef RANDOM_DEBUG
|
#if defined(RANDOM_DEBUG) && !defined(MERSENNE_TWISTER)
|
||||||
uint DoRandomRange(uint max, int line, const char *file)
|
uint DoRandomRange(uint max, int line, const char *file)
|
||||||
{
|
{
|
||||||
return (uint16)DoRandom(line, file) * max >> 16;
|
return (uint16)DoRandom(line, file) * max >> 16;
|
||||||
|
@ -79,6 +81,7 @@ uint RandomRange(uint max)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
uint32 InteractiveRandom(void)
|
uint32 InteractiveRandom(void)
|
||||||
{
|
{
|
||||||
uint32 t = _random_seeds[1][1];
|
uint32 t = _random_seeds[1][1];
|
||||||
|
@ -92,6 +95,8 @@ uint InteractiveRandomRange(uint max)
|
||||||
return (uint16)InteractiveRandom() * max >> 16;
|
return (uint16)InteractiveRandom() * max >> 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PLAYER_SEED_RANDOM
|
||||||
void InitPlayerRandoms(void)
|
void InitPlayerRandoms(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -100,6 +105,7 @@ void InitPlayerRandoms(void)
|
||||||
_player_seeds[i][1]=InteractiveRandom();
|
_player_seeds[i][1]=InteractiveRandom();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void SetDate(uint date)
|
void SetDate(uint date)
|
||||||
{
|
{
|
||||||
|
@ -112,55 +118,6 @@ void SetDate(uint date)
|
||||||
#endif /* ENABLE_NETWORK */
|
#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 InitializeVehicles(void);
|
||||||
void InitializeWaypoints(void);
|
void InitializeWaypoints(void);
|
||||||
void InitializeDepot(void);
|
void InitializeDepot(void);
|
||||||
|
|
|
@ -773,7 +773,9 @@ static void NetworkInitialize(void)
|
||||||
|
|
||||||
_network_reconnect = 0;
|
_network_reconnect = 0;
|
||||||
|
|
||||||
|
#ifdef PLAYER_SEED_RANDOM
|
||||||
InitPlayerRandoms();
|
InitPlayerRandoms();
|
||||||
|
#endif
|
||||||
|
|
||||||
NetworkUDPInitialize();
|
NetworkUDPInitialize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -488,11 +488,13 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP)
|
||||||
// Check if this was the last packet
|
// Check if this was the last packet
|
||||||
if (maptype == MAP_PACKET_END) {
|
if (maptype == MAP_PACKET_END) {
|
||||||
// We also get, very nice, the player_seeds in this packet
|
// We also get, very nice, the player_seeds in this packet
|
||||||
|
#ifdef PLAYER_SEED_RANDOM
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < MAX_PLAYERS; i++) {
|
for (i = 0; i < MAX_PLAYERS; i++) {
|
||||||
_player_seeds[i][0] = NetworkRecv_uint32(MY_CLIENT, p);
|
_player_seeds[i][0] = NetworkRecv_uint32(MY_CLIENT, p);
|
||||||
_player_seeds[i][1] = NetworkRecv_uint32(MY_CLIENT, p);
|
_player_seeds[i][1] = NetworkRecv_uint32(MY_CLIENT, p);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
fclose(file_pointer);
|
fclose(file_pointer);
|
||||||
|
|
||||||
|
|
|
@ -323,7 +323,9 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP)
|
||||||
NetworkSend_Packet(p, cs);
|
NetworkSend_Packet(p, cs);
|
||||||
if (feof(file_pointer)) {
|
if (feof(file_pointer)) {
|
||||||
// Done reading!
|
// Done reading!
|
||||||
|
#ifdef PLAYER_SEED_RANDOM
|
||||||
int i;
|
int i;
|
||||||
|
#endif
|
||||||
Packet *p;
|
Packet *p;
|
||||||
|
|
||||||
// XXX - Delete this when patch-settings are saved in-game
|
// 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);
|
p = NetworkSend_Init(PACKET_SERVER_MAP);
|
||||||
NetworkSend_uint8(p, MAP_PACKET_END);
|
NetworkSend_uint8(p, MAP_PACKET_END);
|
||||||
|
#ifdef PLAYER_SEED_RANDOM
|
||||||
// Send the player_seeds in this packet
|
// Send the player_seeds in this packet
|
||||||
for (i = 0; i < MAX_PLAYERS; i++) {
|
for (i = 0; i < MAX_PLAYERS; i++) {
|
||||||
NetworkSend_uint32(p, _player_seeds[i][0]);
|
NetworkSend_uint32(p, _player_seeds[i][0]);
|
||||||
NetworkSend_uint32(p, _player_seeds[i][1]);
|
NetworkSend_uint32(p, _player_seeds[i][1]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
NetworkSend_Packet(p, cs);
|
NetworkSend_Packet(p, cs);
|
||||||
|
|
||||||
// Set the status to DONE_MAP, no we will wait for the client
|
// 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();
|
InitializeGUI();
|
||||||
IConsoleCmdExec("exec scripts/autoexec.scr 0");
|
IConsoleCmdExec("exec scripts/autoexec.scr 0");
|
||||||
|
|
||||||
|
#ifdef PLAYER_SEED_RANDOM
|
||||||
InitPlayerRandoms();
|
InitPlayerRandoms();
|
||||||
|
#endif
|
||||||
|
|
||||||
GenerateWorld(1, 64, 64); // Make the viewport initialization happy
|
GenerateWorld(1, 64, 64); // Make the viewport initialization happy
|
||||||
|
|
||||||
|
|
47
unix.c
47
unix.c
|
@ -474,6 +474,7 @@ int CDECL main(int argc, char* argv[])
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_random_seeds[0][1] = _random_seeds[0][0] = time(NULL);
|
_random_seeds[0][1] = _random_seeds[0][0] = time(NULL);
|
||||||
|
SeedMT(_random_seeds[0][1]);
|
||||||
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
|
@ -581,3 +582,49 @@ void JoinOTTDThread(void)
|
||||||
|
|
||||||
pthread_join(thread1, NULL);
|
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 */
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,10 @@ VARDEF uint16 _disaster_delay;
|
||||||
VARDEF uint16 _station_tick_ctr;
|
VARDEF uint16 _station_tick_ctr;
|
||||||
|
|
||||||
VARDEF uint32 _random_seeds[2][2];
|
VARDEF uint32 _random_seeds[2][2];
|
||||||
|
|
||||||
|
#ifdef PLAYER_SEED_RANDOM
|
||||||
VARDEF uint32 _player_seeds[MAX_PLAYERS][2];
|
VARDEF uint32 _player_seeds[MAX_PLAYERS][2];
|
||||||
|
#endif
|
||||||
|
|
||||||
// Iterator through all towns in OnTick_Town
|
// Iterator through all towns in OnTick_Town
|
||||||
VARDEF uint32 _cur_town_ctr;
|
VARDEF uint32 _cur_town_ctr;
|
||||||
|
|
7
win32.c
7
win32.c
|
@ -2124,6 +2124,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||||
_random_seeds[0][0] = GetTickCount();
|
_random_seeds[0][0] = GetTickCount();
|
||||||
_random_seeds[0][1] = _random_seeds[0][0] * 0x1234567;
|
_random_seeds[0][1] = _random_seeds[0][0] * 0x1234567;
|
||||||
#endif
|
#endif
|
||||||
|
SeedMT(_random_seeds[0][0]);
|
||||||
|
|
||||||
argc = ParseCommandLine(GetCommandLine(), argv, lengthof(argv));
|
argc = ParseCommandLine(GetCommandLine(), argv, lengthof(argv));
|
||||||
|
|
||||||
|
@ -2263,3 +2264,9 @@ void JoinOTTDThread(void)
|
||||||
|
|
||||||
WaitForSingleObject(hThread, INFINITE);
|
WaitForSingleObject(hThread, INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CSleep(int milliseconds)
|
||||||
|
{
|
||||||
|
Sleep(milliseconds);
|
||||||
|
}
|
Loading…
Reference in New Issue