1

I'm wrapping my head around procedural generation, and the difference between it and random generation. I get that the difference is that it's deterministic, which is based off a specific seed value, like all random engines are.

So in C++11, I understand that to get the 'best' random sequences, an std::seed_seq should be used, and it doesn't need to be cryptographically secure, so an std::mt19937 is fine.

In this scenario, I want a bunch of positions for objects in the world so I can generate a level, and then I want to text my friend the seed of this brand new level because it was really cool. But as it is, typing 189151022 140947902 1454660100 853918093 3243866855 is really annoying. So what can I do as a dev to make sure the randomness is preserved with a bit more type-ability?

I thought hash the values as a string and then reverse it, (but then I remembered the point of hashes) or just use the hash itself, but would that be worse as a seed? Or does it even matter, and can I just use "lol" as my seed and have that be just as good as a megabyte-long perfectly random number?

Here's the quick example I made to help me understand it a bit better.

#include <iostream>
#include <random>
#include <array>

using std::cout;
using std::endl;
using std::array;

struct pos
{
    float x, y;
    pos(float x, float y) : x(x), y(y) {}

    void print()
    {
        cout << "(" << x << " " << y << ")" << endl;
    }
};

int main()
{
    //Get seed
    std::random_device rd;
    array<unsigned long, 5> seed = { rd(), rd(), rd(), rd(), rd() };

    //Seed generator
    std::mt19937 generator;
    generator.seed(std::seed_seq(seed.begin(), seed.end()));

    //Setup distribution
    std::uniform_real_distribution<float> distribution(0, 100);

    //Generate the world (or whatever)
    pos a = pos(distribution(generator), distribution(generator));
    pos b = pos(distribution(generator), distribution(generator));
    pos c = pos(distribution(generator), distribution(generator));
    //And many, many more calls to get values from the generator

    a.print();
    b.print();
    c.print();

    //For when I want the same world back
    cout << "Seed: ";
    for (unsigned long s : seed)
    {
        cout << s << " ";
    }
    cout << endl;
}

To be clear, the question I'm asking is:

What should I use for a seed in a procedural generator in a game context, and what are the upsides and downsides of doing it in that fashion?

Yann
  • 978
  • 2
  • 12
  • 31
  • 1
    It's usually not necessary to use "fancy" random numbers in games. Have you tried using a plain 32-bit seed (four hexadecimal digits, very textable) and concluded that it wasn't good enough? (The "best" RNG for your game is the one that works best for you, and that isn't necessarily the one with "best randomness".) – molbdnilo Jul 05 '16 at 11:08
  • @molbdnilo I don't know, basically. Hence the question. I continue to be hazy on how random number generation works, and if I'd run into issues like the pool running out just using a short seed. – Yann Jul 05 '16 at 11:11
  • 1
    On a side note: your two calls to `distribution` occur in an unspecified order, so the positions may vary between compilers and even with compiler settings. If you want reliable positions, compute their values before passing them to `pos`. – molbdnilo Jul 05 '16 at 11:11
  • @molbdnilo Fair enough, I'll keep that in mind, but the code was more as an example than a thing that I'd use. But barring anything else, I'd be happy to accept a cited version of your first comment as an answer. – Yann Jul 05 '16 at 11:17
  • If you don't know, "the simplest thing that could possibly work" is a good starting point. Just abstract out the RNG details so you can swap the actual generator easily. Esthetics and enjoyment are more important than mathematical rigour. (I'm not posting any answer because I don't think there is one beyond "start simple, try some stuff, see what happens, and take it from there".) – molbdnilo Jul 05 '16 at 11:42

2 Answers2

1

Start with a sufficiently long generated string (like 'gorgeous house').

Convert it to a number (enough for random seed), by hashing it. A hash can be obtained by using the string characters and their position.

If you use the same hash function on the other side your friend should be able to use the same text and get the same number (same seed !).

Community
  • 1
  • 1
Christophe Roussy
  • 16,299
  • 4
  • 85
  • 85
-1

make the seed a string value. to get the number to use from the string, take a hash f it, like sha256

aa257
  • 1