#include "Controller.hpp"
 
+#include "../rand/GaloisLFSR.hpp"
+
 
 namespace blank {
 
 : 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;
 
 };
 
 
 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)
        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<unsigned char>() % (chunk_range * 2 + 1)) - chunk_range,
+               (random.Next<unsigned char>() % (chunk_range * 2 + 1)) - chunk_range,
+               (random.Next<unsigned char>() % (chunk_range * 2 + 1)) - chunk_range
        );
 
        glm::ivec3 pos(
-               rand() % Chunk::width,
-               rand() % Chunk::height,
-               rand() % Chunk::depth
+               random.Next<unsigned char>() % Chunk::width,
+               random.Next<unsigned char>() % Chunk::height,
+               random.Next<unsigned char>() % Chunk::depth
        );
 
 
 
 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<unsigned short>() % 1024);
+       rot.y *= (random.Next<unsigned short>() % 1024);
+       rot.z *= (random.Next<unsigned short>() % 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<unsigned char>() % 3].Instantiate(e.GetModel());
        e.AngularVelocity(rot);
        Controller *ctrl;
-       if (rand() % 2) {
-               ctrl = new RandomWalk(e);
+       if (random()) {
+               ctrl = new RandomWalk(e, random.Next<std::uint64_t>());
        } else {
                ctrl = new Chaser(world, e, world.Player());
        }
 
 #include "../app/IntervalTimer.hpp"
 #include "../model/CompositeModel.hpp"
 #include "../model/EntityModel.hpp"
+#include "../rand/GaloisLFSR.hpp"
 
 #include <vector>
 #include <glm/glm.hpp>
 class Spawner {
 
 public:
-       explicit Spawner(World &);
+       Spawner(World &, std::uint64_t seed);
        ~Spawner();
 
        void Update(int dt);
        EntityModel models[3];
        CompositeModel skeletons[3];
 
+       GaloisLFSR random;
+
        IntervalTimer timer;
        float despawn_range;
        float spawn_distance;
 
 }
 
 
-RandomWalk::RandomWalk(Entity &e) noexcept
+RandomWalk::RandomWalk(Entity &e, std::uint64_t seed) noexcept
 : Controller(e)
+, random(seed)
 , time_left(0) {
 
 }
 void RandomWalk::Update(int dt) {
        time_left -= dt;
        if (time_left > 0) return;
-       time_left += 2500 + (rand() % 5000);
+       time_left += 2500 + (random.Next<unsigned short>() % 5000);
 
        constexpr float move_vel = 0.0005f;
 
        glm::vec3 new_vel = Controlled().Velocity();
 
-       switch (rand() % 9) {
+       switch (random.Next<unsigned char>() % 9) {
                case 0:
                        new_vel.x = -move_vel;
                        break;
 
 , 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()) {
 
 
 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<class T>
        T operator ()(T &out) noexcept {
                return out = static_cast<T>(state);
        }
 
+       template<class T>
+       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
 
 
 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 },