/*============================================================================= Name : Randy.c Purpose : Generic random-number generators with multiple streams Created 11/11/1997 by lmoloney Copyright Relic Entertainment, Inc. All rights reserved. =============================================================================*/ // unfortunately need this for system time #define WIN32_LEAN_AND_MEAN #include #include "types.h" #include "debug.h" #include "randy.h" #include "SaveGame.h" #if RAN_DEBUG_CALLER #include "universe.h" #include "file.h" #include #endif /*============================================================================= Data: =============================================================================*/ ranstream ranStream[RAN_NumberStreams]; #if RAN_DEBUG_CALLER #define RAN_LogFile "Randylog.txt" #define RAN_LogBufferLength 512 #define RAN_LogStringLength 24 bool ranCallerDebug = FALSE; bool ranLogCleared = FALSE; typedef struct { char file[RAN_LogStringLength]; sdword line; udword univCounter; } ranlogentry; ranlogentry *ranLogBuffer = NULL; sdword ranLogIndex = 0; #endif /*============================================================================= Functions: =============================================================================*/ /*----------------------------------------------------------------------------- Name : ranRandom Description : Get a random number from a random number sequence. Inputs : ranIndex - index of random number sequence. file, line - where it was called from Outputs : Return : New random number. ----------------------------------------------------------------------------*/ #if RAN_DEBUG_CALLER udword ranRandomFn(sdword ranIndex, char *file, sdword line) #else udword ranRandomFn(sdword ranIndex) #endif { long int s; ranstream *stream; #if RAN_DEBUG_CALLER char *truncatedFile; FILE *fp; if ((ranCallerDebug || logEnable == LOG_ON || logEnable == LOG_VERBOSE) && ranIndex == RAN_Game && file != NULL) { if (ranLogBuffer == NULL) { ranLogBuffer = memAlloc(sizeof(ranlogentry) * RAN_LogBufferLength, "ranLogBuffer", NonVolatile); } if (ranLogIndex >= RAN_LogBufferLength) { fp = fopen(RAN_LogFile, ranLogCleared ? "at" : "wt"); if (fp != NULL) { ranLogCleared = TRUE; for (ranLogIndex = 0; ranLogIndex < RAN_LogBufferLength; ranLogIndex++) { fprintf(fp, "%s(%d): %d\n", ranLogBuffer[ranLogIndex].file, ranLogBuffer[ranLogIndex].line, ranLogBuffer[ranLogIndex].univCounter); } fclose(fp); } ranLogIndex = 0; } truncatedFile = file + strlen(file) - (RAN_LogStringLength - 1); strcpy(ranLogBuffer[ranLogIndex].file, max(file, truncatedFile)); ranLogBuffer[ranLogIndex].line = line; ranLogBuffer[ranLogIndex].univCounter = universe.univUpdateCounter; ranLogIndex++; } #endif dbgAssert(ranIndex < RAN_NumberStreams); stream = &ranStream[ranIndex]; if(stream->y>stream->x+stream->c){s=stream->y-(stream->x+stream->c);stream->c=0;} else {s=(stream->x+stream->c)-stream->y-18;stream->c=1;} stream->x=stream->y; stream->y=stream->z; return ((stream->z=s) + (stream->n=69069*stream->n+1013904243)); } /*----------------------------------------------------------------------------- Name : ranRandomFnSimple Description : A special version of the random number generator with no file or line parmeters Inputs :ranIndex - index of random number sequence. Outputs : Return : ----------------------------------------------------------------------------*/ #if RAN_DEBUG_CALLER udword ranRandomFnSimple(sdword ranIndex) { return(ranRandomFn(ranIndex, NULL, 0)); } #endif /*----------------------------------------------------------------------------- Name : ranNumberGet Description : Get position in random-number sequence. Inputs : ranIndex - index of random number sequence. Outputs : Return : Current random stream position for this stream. ----------------------------------------------------------------------------*/ udword ranNumberGet(sdword ranIndex) { dbgAssert(ranIndex < RAN_NumberStreams); return(ranStream[ranIndex].n); } /*----------------------------------------------------------------------------- Name : ranNumberSet Description : Set position in random-number sequence. Inputs : ranIndex - index of random number sequence. nn - random number to start at. Outputs : Return : ----------------------------------------------------------------------------*/ void ranNumberSet(sdword ranIndex, udword nn) { dbgAssert(ranIndex < RAN_NumberStreams); ranStream[ranIndex].n=nn; } /*----------------------------------------------------------------------------- Name : ranParametersSet Description : Set the parameters used to define a random-number sequence. These will have defaults. Inputs : ranIndex - index of random number sequence. xx, yy, zz, cc, nn - parameters for the random stream Outputs : stores parameters for later usage Return : void ----------------------------------------------------------------------------*/ void ranParametersSet(sdword ranIndex, udword xx,udword yy,udword zz,udword cc,udword nn) { dbgAssert(ranIndex < RAN_NumberStreams); ranStream[ranIndex].x=xx; ranStream[ranIndex].y=yy; ranStream[ranIndex].z=zz; ranStream[ranIndex].c=cc; ranStream[ranIndex].n=nn; } /*----------------------------------------------------------------------------- Name : ranParametersGet Description : Get the parameters used to define a random-number sequence. Inputs : ranIndex - index of random number sequence. Outputs : xx, yy, zz, cc, nn - parameters for the random stream Return : void ----------------------------------------------------------------------------*/ void ranParametersGet(sdword ranIndex, udword *xx,udword *yy,udword *zz,udword *cc,udword *nn) { dbgAssert(ranIndex < RAN_NumberStreams); *xx = ranStream[ranIndex].x; *yy = ranStream[ranIndex].y; *zz = ranStream[ranIndex].z; *cc = ranStream[ranIndex].c; *nn = ranStream[ranIndex].n; } /*----------------------------------------------------------------------------- Name : ranParametersReset Description : Reset a stream's parameters to default values. Inputs : ranIndex - index of random number sequence. Outputs : Return : ----------------------------------------------------------------------------*/ void ranParametersReset(sdword ranIndex) { dbgAssert(ranIndex < RAN_NumberStreams); ranStream[ranIndex].x=521288629; ranStream[ranIndex].y=362436069; ranStream[ranIndex].z=1613801; ranStream[ranIndex].c=1; ranStream[ranIndex].n=1131199209; } /*----------------------------------------------------------------------------- Name : ranRandomize Description : randomizes the number stream based on system time Inputs : ranIndex - index of random number sequence. Outputs : Return : ----------------------------------------------------------------------------*/ void ranRandomize(sdword ranIndex) { SYSTEMTIME systime; udword iter; udword i; GetSystemTime(&systime); iter = systime.wSecond & 255; for (i=0;i