Я обволакиваю вокруг процессуального поколения, а также разницу между ним и случайным поколением. Я понимаю, что разница в том, что она детерминирована, которая основана на определенном начальном значении, как и все случайные двигатели.Как типичное семя, генерируемое для процедурной генерации?
Итак, в C++ 11, я понимаю, что для получения «лучших» случайных последовательностей следует использовать std::seed_seq
, и он не нуждается в криптографической защите, поэтому std::mt19937
в порядке.
В этом случае я хочу иметь кучу позиций для объектов в мире, чтобы я мог генерировать уровень, а затем хочу, чтобы текст моего друга стал семенем этого совершенно нового уровня, потому что это было действительно круто. Но как это, печатать 189151022 140947902 1454660100 853918093 3243866855
действительно раздражает. Итак, что я могу сделать в качестве разработчика, чтобы убедиться, что случайность сохранена с немного большей способностью к типу?
Я думал, что хэширует значения как строку, а затем меняет ее (но потом я вспомнил точку хэшей) или просто использовал сам хеш, но будет ли это хуже, чем семя? Или это даже имеет значение, и могу ли я просто использовать «lol» в качестве моего семени, и это будет так же хорошо, как мегабайт-длинный совершенно случайный номер?
Вот быстрый пример, который я сделал, чтобы помочь мне понять его немного лучше.
#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;
}
Чтобы было ясно, вопрос я спрашиваю:
Что я должен использовать для семян в процедурный генератор в контексте игры, и каковы плюсы и минусы ведения его в эта мода?
Обычно нет необходимости использовать «причудливые» случайные числа в играх. Вы пробовали использовать обычное 32-битное семя (четыре шестнадцатеричных цифры, очень текстовое) и пришли к выводу, что это недостаточно хорошо? («Лучший» RNG для вашей игры - тот, который лучше всего подходит для вас, и это не обязательно тот, у кого «лучшая случайность».) – molbdnilo
@molbdnilo Я не знаю, в принципе. Отсюда вопрос. Я по-прежнему неясен в отношении того, как работает случайное числовое число, и если у меня возникнут проблемы, такие как пул, заканчивающийся только использованием короткого семени. – Yann
На стороне примечания: ваши два вызова 'distribution' происходят в неуказанном порядке, поэтому позиции могут различаться между компиляторами и даже с настройками компилятора. Если вам нужны надежные позиции, вычислите их значения, прежде чем передавать их в 'pos'. – molbdnilo