Skip to content

Commit

Permalink
Copy RNG from Glulxe, add support for native RNG too
Browse files Browse the repository at this point in the history
  • Loading branch information
David Kinder committed Oct 12, 2023
1 parent fc4da34 commit 71f94ec
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 37 deletions.
3 changes: 3 additions & 0 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
// Define this if we can use the "inline" keyword.
// #define USE_INLINE

// Define this to use a function native_random() to get random numbers.
// #define USE_NATIVE_RANDOM

// Define this to memory-map the game file to speed up loading. (Unix-specific)
// #define USE_MMAP

Expand Down
3 changes: 1 addition & 2 deletions git.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,7 @@ extern git_sint32* gStackPointer;

extern enum IOMode gIoMode;

extern glui32 lo_random ();
extern void lo_seed_random (glui32 seed);
extern glui32 native_random ();

extern void startProgram (size_t cacheSize);

Expand Down
9 changes: 9 additions & 0 deletions git_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,12 @@ void glk_main ()
}

#endif // USE_MMAP

#ifdef USE_NATIVE_RANDOM

glui32 native_random()
{
return arc4random();

This comment has been minimized.

Copy link
@curiousdannii

curiousdannii Oct 14, 2023

arc4random is a BSDism and isn't present in some *nixes, such as Emscripten. Any chance you could add support for getrandom like Glulxe has?

This comment has been minimized.

Copy link
@curiousdannii

curiousdannii Oct 14, 2023

Oh, never mind. I see that getrandom is really for filling buffers, and Glulxe only uses it to seed the xoshiro128** RNG.

}

#endif // USE_NATIVE_RANDOM
14 changes: 14 additions & 0 deletions git_windows.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// Startup code for Windows Git

#ifdef _MSC_VER // For Visual C++, get rand_s()
#define _CRT_RAND_S
#endif

#include "glk.h"
#include "WinGlk.h"
#include "git.h"
Expand Down Expand Up @@ -101,3 +105,13 @@ void glk_main()
CloseHandle(file);
}

glui32 native_random()
{
#ifdef _MSC_VER
unsigned int value;
rand_s(&value);
return value;
#else
return xo_random();
#endif
}
8 changes: 5 additions & 3 deletions glkop.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@

#define glulx_malloc malloc
#define glulx_free free
#define glulx_random lo_random

#ifndef TRUE
#define TRUE 1
Expand All @@ -109,6 +108,7 @@
#define FALSE 0
#endif

#include <time.h>
#include "glk.h"
#include "git.h"
#include "gi_dispa.h"
Expand Down Expand Up @@ -270,7 +270,8 @@ static maybe_unused char *get_game_id(void);
int git_init_dispatch()
{
int ix;

int randish;

/* What with one thing and another, this *could* be called more than
once. We only need to allocate the tables once. */
if (git_classes)
Expand All @@ -289,8 +290,9 @@ int git_init_dispatch()
if (!git_classes)
return FALSE;

randish = time(NULL) % 101;
for (ix=0; ix<num_classes; ix++) {
git_classes[ix] = new_classtable((glulx_random() % (glui32)(101)) + 1);
git_classes[ix] = new_classtable(1+120*ix+randish);
if (!git_classes[ix])
return FALSE;
}
Expand Down
105 changes: 76 additions & 29 deletions terp.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,38 +35,85 @@ enum IOMode gIoMode = IO_NULL;
// -------------------------------------------------------------
// Random number generator, from Glulxe

static glui32 rand_table[55]; /* State for the RNG. */
static int rand_index1, rand_index2;
static glui32 xo_random(void);
static void xo_seed_random(glui32 seed);

glui32 lo_random()
static int rand_use_native = 1;

/* Set the random-number seed, and also select which RNG to use.
*/
void git_seed_random(glui32 seed)
{
rand_index1 = (rand_index1 + 1) % 55;
rand_index2 = (rand_index2 + 1) % 55;
rand_table[rand_index1] = rand_table[rand_index1] - rand_table[rand_index2];
return rand_table[rand_index1];
if (seed == 0)
{
rand_use_native = 1;
xo_seed_random(time(NULL));
}
else
{
rand_use_native = 0;
xo_seed_random(seed);
}
}

void lo_seed_random(glui32 seed)
/* Return a random number in the range 0 to 2^32-1. */
glui32 git_random()
{
glui32 k = 1;
int i, loop;

rand_table[54] = seed;
rand_index1 = 0;
rand_index2 = 31;

for (i = 0; i < 55; i++) {
int ii = (21 * i) % 55;
rand_table[ii] = k;
k = seed - k;
seed = rand_table[ii];
}
for (loop = 0; loop < 4; loop++) {
for (i = 0; i < 55; i++)
rand_table[i] = rand_table[i] - rand_table[ (1 + i + 30) % 55];
#ifdef USE_NATIVE_RANDOM
if (rand_use_native)
return native_random();
#endif
return xo_random();
}

/* This is the "xoshiro128**" random-number generator and seed function.
Adapted from: https://prng.di.unimi.it/xoshiro128starstar.c
About this algorithm: https://prng.di.unimi.it/
*/
static uint32_t xo_table[4];

static void xo_seed_random(glui32 seed)
{
int ix;
/* Set up the 128-bit state from a single 32-bit integer. We rely
on a different RNG, SplitMix32. This isn't high-quality, but we
just need to get a bunch of bits into xo_table. */
for (ix=0; ix<4; ix++) {
seed += 0x9E3779B9;
glui32 s = seed;
s ^= s >> 15;
s *= 0x85EBCA6B;
s ^= s >> 13;
s *= 0xC2B2AE35;
s ^= s >> 16;
xo_table[ix] = s;
}
}

static glui32 xo_random(void)
{
/* I've inlined the utility function:
rotl(x, k) => (x << k) | (x >> (32 - k))
*/

const uint32_t t1x5 = xo_table[1] * 5;
const uint32_t result = ((t1x5 << 7) | (t1x5 >> (32-7))) * 9;

const uint32_t t1s9 = xo_table[1] << 9;

xo_table[2] ^= xo_table[0];
xo_table[3] ^= xo_table[1];
xo_table[1] ^= xo_table[2];
xo_table[0] ^= xo_table[3];

xo_table[2] ^= t1s9;

const uint32_t t3 = xo_table[3];
xo_table[3] = ((t3 << 11) | (t3 >> (32-11)));

return result;
}

// -------------------------------------------------------------
// Floating point support

Expand Down Expand Up @@ -202,7 +249,7 @@ void startProgram (size_t cacheSize)
initCompiler (cacheSize);

// Initialise the random number generator.
lo_seed_random (time(NULL));
git_seed_random (0);

// Set up the stack.

Expand Down Expand Up @@ -1271,17 +1318,17 @@ do_S1_addr8: memWrite8 (READ_PC, S1); NEXT;

do_random:
if (L1 > 0)
S1 = lo_random () % L1;
S1 = git_random () % L1;
else if (L1 < 0)
S1 = -(lo_random () % -L1);
S1 = -(git_random () % -L1);
else
{
S1 = lo_random ();
S1 = git_random ();
}
NEXT;

do_setrandom:
lo_seed_random (L1 ? L1 : time(NULL));
git_seed_random (L1);
NEXT;

do_glk:
Expand Down
6 changes: 3 additions & 3 deletions win/Git.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>WindowsGlk/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>USE_INLINE;USE_DIRECT_THREADING;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>USE_NATIVE_RANDOM;USE_INLINE;USE_DIRECT_THREADING;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>Disabled</Optimization>
Expand All @@ -74,7 +74,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>WindowsGlk/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>USE_INLINE;USE_DIRECT_THREADING;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>USE_NATIVE_RANDOM;USE_INLINE;USE_DIRECT_THREADING;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<AdditionalOptions>-Wno-unused-function %(AdditionalOptions)</AdditionalOptions>
Expand Down Expand Up @@ -147,4 +147,4 @@ copy help\Git.chm $(OutDir)</Command>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

0 comments on commit 71f94ec

Please sign in to comment.