From: Daniel Karbach Date: Fri, 28 Aug 2015 09:15:13 +0000 (+0200) Subject: avoid library rand() X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=41652fb3d73f12e6ae4ce7380244a75a4f5c6797;p=blank.git avoid library rand() --- diff --git a/src/ai/RandomWalk.hpp b/src/ai/RandomWalk.hpp index a25d4db..4d00f0b 100644 --- a/src/ai/RandomWalk.hpp +++ b/src/ai/RandomWalk.hpp @@ -3,6 +3,8 @@ #include "Controller.hpp" +#include "../rand/GaloisLFSR.hpp" + namespace blank { @@ -11,12 +13,13 @@ class RandomWalk : public Controller { public: - explicit RandomWalk(Entity &) noexcept; + RandomWalk(Entity &, std::uint64_t seed) noexcept; ~RandomWalk(); void Update(int dt) override; private: + GaloisLFSR random; int time_left; }; diff --git a/src/ai/Spawner.cpp b/src/ai/Spawner.cpp index 1120b5b..fb2a1ea 100644 --- a/src/ai/Spawner.cpp +++ b/src/ai/Spawner.cpp @@ -11,9 +11,10 @@ namespace blank { -Spawner::Spawner(World &world) +Spawner::Spawner(World &world, std::uint64_t seed) : world(world) , controllers() +, random(seed) , timer(64) , despawn_range(128 * 128) , spawn_distance(16 * 16) @@ -97,15 +98,15 @@ void Spawner::TrySpawn() { if (controllers.size() >= max_entities) return; glm::ivec3 chunk( - (rand() % (chunk_range * 2 + 1)) - chunk_range, - (rand() % (chunk_range * 2 + 1)) - chunk_range, - (rand() % (chunk_range * 2 + 1)) - chunk_range + (random.Next() % (chunk_range * 2 + 1)) - chunk_range, + (random.Next() % (chunk_range * 2 + 1)) - chunk_range, + (random.Next() % (chunk_range * 2 + 1)) - chunk_range ); glm::ivec3 pos( - rand() % Chunk::width, - rand() % Chunk::height, - rand() % Chunk::depth + random.Next() % Chunk::width, + random.Next() % Chunk::height, + random.Next() % Chunk::depth ); @@ -132,20 +133,20 @@ void Spawner::TrySpawn() { void Spawner::Spawn(const glm::ivec3 &chunk, const glm::vec3 &pos) { glm::vec3 rot(0.000001f); - rot.x *= (rand() % 1024); - rot.y *= (rand() % 1024); - rot.z *= (rand() % 1024); + rot.x *= (random.Next() % 1024); + rot.y *= (random.Next() % 1024); + rot.z *= (random.Next() % 1024); Entity &e = world.AddEntity(); e.Name("spawned"); e.Position(chunk, pos); e.Bounds({ { -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f } }); e.WorldCollidable(true); - skeletons[rand() % 3].Instantiate(e.GetModel()); + skeletons[random.Next() % 3].Instantiate(e.GetModel()); e.AngularVelocity(rot); Controller *ctrl; - if (rand() % 2) { - ctrl = new RandomWalk(e); + if (random()) { + ctrl = new RandomWalk(e, random.Next()); } else { ctrl = new Chaser(world, e, world.Player()); } diff --git a/src/ai/Spawner.hpp b/src/ai/Spawner.hpp index 7b56130..9fb3d36 100644 --- a/src/ai/Spawner.hpp +++ b/src/ai/Spawner.hpp @@ -4,6 +4,7 @@ #include "../app/IntervalTimer.hpp" #include "../model/CompositeModel.hpp" #include "../model/EntityModel.hpp" +#include "../rand/GaloisLFSR.hpp" #include #include @@ -17,7 +18,7 @@ class World; class Spawner { public: - explicit Spawner(World &); + Spawner(World &, std::uint64_t seed); ~Spawner(); void Update(int dt); @@ -34,6 +35,8 @@ private: EntityModel models[3]; CompositeModel skeletons[3]; + GaloisLFSR random; + IntervalTimer timer; float despawn_range; float spawn_distance; diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp index e0fb955..4a2e310 100644 --- a/src/ai/ai.cpp +++ b/src/ai/ai.cpp @@ -61,8 +61,9 @@ Controller::~Controller() { } -RandomWalk::RandomWalk(Entity &e) noexcept +RandomWalk::RandomWalk(Entity &e, std::uint64_t seed) noexcept : Controller(e) +, random(seed) , time_left(0) { } @@ -74,13 +75,13 @@ RandomWalk::~RandomWalk() { void RandomWalk::Update(int dt) { time_left -= dt; if (time_left > 0) return; - time_left += 2500 + (rand() % 5000); + time_left += 2500 + (random.Next() % 5000); constexpr float move_vel = 0.0005f; glm::vec3 new_vel = Controlled().Velocity(); - switch (rand() % 9) { + switch (random.Next() % 9) { case 0: new_vel.x = -move_vel; break; diff --git a/src/app/WorldState.cpp b/src/app/WorldState.cpp index ed711bf..243b0a1 100644 --- a/src/app/WorldState.cpp +++ b/src/app/WorldState.cpp @@ -18,7 +18,7 @@ WorldState::WorldState( , block_types() , world(block_types, wc, save) , chunk_renderer(world, wc.load.load_dist) -, spawner(world) +, spawner(world, wc.gen.seed) , interface(ic, env, world) , preload(env, world.Loader(), chunk_renderer) , unload(env, world.Loader()) { diff --git a/src/rand/GaloisLFSR.hpp b/src/rand/GaloisLFSR.hpp index 88a1d37..395ff8f 100644 --- a/src/rand/GaloisLFSR.hpp +++ b/src/rand/GaloisLFSR.hpp @@ -11,10 +11,21 @@ class GaloisLFSR { public: // seed should be non-zero - explicit GaloisLFSR(std::uint64_t seed) noexcept; + explicit GaloisLFSR(std::uint64_t seed) noexcept + : state(seed) { } // get the next bit - bool operator ()() noexcept; + bool operator ()() noexcept { + bool result = state & 1; + state >>= 1; + if (result) { + state |= 0x8000000000000000; + state ^= mask; + } else { + state &= 0x7FFFFFFFFFFFFFFF; + } + return result; + } template T operator ()(T &out) noexcept { @@ -27,12 +38,19 @@ public: return out = static_cast(state); } + template + T Next() noexcept { + T next; + return (*this)(next); + } + private: std::uint64_t state; // bits 64, 63, 61, and 60 set to 1 (counting from 1 lo to hi) static constexpr std::uint64_t mask = 0xD800000000000000; }; + } #endif diff --git a/src/rand/noise.cpp b/src/rand/noise.cpp index de037ef..664096d 100644 --- a/src/rand/noise.cpp +++ b/src/rand/noise.cpp @@ -14,24 +14,6 @@ constexpr float one_sixth = 1.0f/6.0f; namespace blank { -GaloisLFSR::GaloisLFSR(std::uint64_t seed) noexcept -: state(seed) { - -} - -bool GaloisLFSR::operator ()() noexcept { - bool result = state & 1; - state >>= 1; - if (result) { - state |= 0x8000000000000000; - state ^= mask; - } else { - state &= 0x7FFFFFFFFFFFFFFF; - } - return result; -} - - SimplexNoise::SimplexNoise(unsigned int seed) noexcept : grad({ { 1.0f, 1.0f, 0.0f },