Skip to content

Commit

Permalink
Additional changes based on code review
Browse files Browse the repository at this point in the history
  • Loading branch information
StephenCWills committed Mar 19, 2024
1 parent f79a8fb commit 28a7a4e
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 39 deletions.
22 changes: 20 additions & 2 deletions Source/engine/random.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "engine/random.hpp"

#include <bit>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <limits>
Expand All @@ -16,9 +18,25 @@ std::linear_congruential_engine<uint32_t, 0x015A4E35, 1, 0> diabloGenerator;
/** Xoshiro pseudo-random number generator to provide less predictable seeds */
xoshiro128plusplus seedGenerator;

void ResetSeedGenerator(uint64_t seed)
uint32_t xoshiro128plusplus::rotl(const uint32_t x, int k)
{
seedGenerator.seed(seed);
return std::rotl(x, k);
}

uint64_t xoshiro128plusplus::timeSeed()
{
auto now = std::chrono::system_clock::now();
auto nano = std::chrono::nanoseconds(now.time_since_epoch());
long long time = nano.count();
SplitMix64 seedSequence { static_cast<uint64_t>(time) };
return seedSequence.next();
}

xoshiro128plusplus ReserveSeedSequence()
{
xoshiro128plusplus reserved = seedGenerator;
seedGenerator.jump();
return reserved;
}

uint32_t GenerateSeed()
Expand Down
97 changes: 73 additions & 24 deletions Source/engine/random.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#pragma once

#include <algorithm>
#include <bit>
#include <cstdint>
#include <initializer_list>
#include <random>
Expand Down Expand Up @@ -205,13 +204,67 @@ class SplitMix64 {

/** Adapted from https://prng.di.unimi.it/xoshiro128plusplus.c written in 2019 by David Blackman and Sebastiano Vigna */
class xoshiro128plusplus {
private:
uint32_t s[4];

public:
xoshiro128plusplus() { seed(static_cast<uint64_t>(1)); }
xoshiro128plusplus(uint32_t initialSeed) { seed(initialSeed); }
typedef uint32_t state[4];

xoshiro128plusplus() { seed(); }
xoshiro128plusplus(const state &s) { memcpy(this->s, s, sizeof(this->s)); }
xoshiro128plusplus(uint64_t initialSeed) { seed(initialSeed); }
xoshiro128plusplus(uint32_t initialSeed) { seed(initialSeed); }

uint32_t next()
{
const uint32_t result = rotl(s[0] + s[3], 7) + s[0];

const uint32_t t = s[1] << 9;

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

s[2] ^= t;

s[3] = rotl(s[3], 11);

return result;
}

/* This is the jump function for the generator. It is equivalent
to 2^64 calls to next(); it can be used to generate 2^64
non-overlapping subsequences for parallel computations. */
void jump()
{
static const uint32_t JUMP[] = { 0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b };

uint32_t s0 = 0;
uint32_t s1 = 0;
uint32_t s2 = 0;
uint32_t s3 = 0;
for (int i = 0; i < sizeof JUMP / sizeof *JUMP; i++)
for (int b = 0; b < 32; b++) {
if (JUMP[i] & UINT32_C(1) << b) {
s0 ^= s[0];
s1 ^= s[1];
s2 ^= s[2];
s3 ^= s[3];
}
next();
}

s[0] = s0;
s[1] = s1;
s[2] = s2;
s[3] = s3;
}

void save(state &s) const
{
memcpy(s, this->s, sizeof(s));
}

private:
state s;

void seed(uint64_t value)
{
Expand All @@ -231,30 +284,26 @@ class xoshiro128plusplus {
seedSequence.generate(s, s + 4);
}

uint32_t next()
void seed()
{
const uint32_t result = std::rotl(s[0] + s[3], 7) + s[0];

const uint32_t t = s[1] << 9;

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

s[2] ^= t;

s[3] = std::rotl(s[3], 11);

return result;
uint64_t ts = timeSeed();
s[0] = static_cast<uint32_t>(ts >> 32);
s[1] = static_cast<uint32_t>(ts);

static std::random_device rd;
std::uniform_int_distribution<uint32_t> dist;
s[2] = dist(rd);
s[3] = dist(rd);
}

static uint32_t rotl(const uint32_t x, int k);
static uint64_t timeSeed();
};

/**
* @brief Overwrite the state of the global seed generator with state derived from the given seed
* @param seed Seed from which to derive the new state
* @brief Returns a copy of the global seed generator and fast-forwards the global seed generator to avoid collisions
*/
void ResetSeedGenerator(uint64_t seed);
xoshiro128plusplus ReserveSeedSequence();

/**
* @brief Advances the global seed generator state and returns the new value
Expand Down
15 changes: 5 additions & 10 deletions Source/multi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,19 +481,14 @@ bool InitMulti(GameData *gameData)
return true;
}

uint64_t GenerateGameSeed()
{
auto now = std::chrono::high_resolution_clock::now();
auto duration = now.time_since_epoch();
return static_cast<uint64_t>(duration.count());
}

} // namespace

void InitGameInfo()
{
xoshiro128plusplus gameGenerator = ReserveSeedSequence();
gameGenerator.save(sgGameInitInfo.gameSeed);

sgGameInitInfo.size = sizeof(sgGameInitInfo);
sgGameInitInfo.gameSeed = GenerateGameSeed();
sgGameInitInfo.programid = GAME_ID;
sgGameInitInfo.versionMajor = PROJECT_VERSION_MAJOR;
sgGameInitInfo.versionMinor = PROJECT_VERSION_MINOR;
Expand Down Expand Up @@ -794,11 +789,11 @@ bool NetInit(bool bSinglePlayer)
NetClose();
gbSelectProvider = false;
}
ResetSeedGenerator(sgGameInitInfo.gameSeed);
xoshiro128plusplus gameGenerator(sgGameInitInfo.gameSeed);
gnTickDelay = 1000 / sgGameInitInfo.nTickRate;

for (int i = 0; i < NUMLEVELS; i++) {
DungeonSeeds[i] = GenerateSeed();
DungeonSeeds[i] = gameGenerator.next();
LevelSeeds[i] = std::nullopt;
}
PublicGame = DvlNet_IsPublicGame();
Expand Down
2 changes: 1 addition & 1 deletion Source/multi.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct Player;
struct GameData {
int32_t size;
/** Used to initialise the seed table for dungeon levels so players in multiplayer games generate the same layout */
uint64_t gameSeed;
uint32_t gameSeed[4];
uint32_t programid;
uint8_t versionMajor;
uint8_t versionMinor;
Expand Down
2 changes: 0 additions & 2 deletions Source/stores.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2134,8 +2134,6 @@ void SetupTownStores()
if (myPlayer._pLvlVisited[i])
l = i;
}
} else {
SetRndSeed(DungeonSeeds[currlevel] * SDL_GetTicks());
}

l = std::clamp(l + 2, 6, 16);
Expand Down

0 comments on commit 28a7a4e

Please sign in to comment.