Best protocol for randomization?

I am working on a game in Unreal Engine 4, it doesnt use any C++, just Blueprints, its visual node based programming language, but it utilizes randomization in it and I am trying to come up with a good solution for a randomization protocol that will work. So far we have tried 2 or 3 solutions that dont seem to work well, so I came up with this:

Taken from my design document:

For deciding randomness in the game, anything that needs to be randomized and uses rarity can use this number generator technique:

Numbers will be generated from 0 to a defined number and a randomized item will pick a defined number between a number within the defined number range. So if i have 4 random crates, a common, uncommon, rare, and ultra rare crate the common crate can have a number range from 0 to 10. And choose a number or number range between that, and since its such a small range the chance of getting a common crate is very high, for an ultra rare crate a range of 0 to 500 could be picked and a range between that would be chosen.

Randomization Blueprint

Note:

The values below should be set and used by anything that uses randomization. These values should be part of the crates blueprint since each crate will need to have its own randomization numbers, it should be under a new category called “Randomization Protocol”. The old randomization code should be deprecated.
If i wanted to have a single digit number instead of a range of numbers for BetweenFirstNumber and BetweenSecondNumber I would just enter that number in both of those fields.

NumberRangeStart[Int] - The minimum and maximum values that the random number will be chosen from(0-100 etc.)
NumberRangeEnd[Int]
BetweenFirstNumber[Int] - the number between the first and second value where if landed on a number between these two values will choose the item.
BetweenSecondNumber[Int]


Is this a good way or is there a better one? Lets say I have 4 items that need to be picked, each with an increasing level of difficulty to obtain, so the first is a very common item, the second is uncommon, then rare, and ultra rare, would this way be best?
Compute the cumulative distribution function - something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <initializer_list>
#include <iostream>
#include <map>
#include <random>
template <typename T, typename Weight = double> struct weighted_grab_bag {
  weighted_grab_bag(std::initializer_list<std::pair<T, Weight>> il) : acc{} {
    for (auto pair : il) {
      auto const &weight = pair.second;
      auto const &x = pair.first;

      acc += weight;
      cdf[acc] = x;
    }
  }

  T sample() const {
    if (!empty()) {
      static std::mt19937 gen{std::random_device{}()};
      std::uniform_real_distribution<Weight> dist(0., acc);

      auto it = cdf.lower_bound(dist(gen));
      if (it != cdf.end())
        return it->second;
    }
    return {};
  }

  auto size() const { return cdf.size(); };
  bool empty() const { return cdf.empty(); }

private:
  std::map<Weight, T> cdf;
  Weight acc{};
};

int main() {
  weighted_grab_bag<std::string> bag{{"common", 0.80},
                                     {"uncommon", 0.15},
                                     {"rare", 0.045},
                                     {"ultra-rare", 0.005}};
  for (int i = 0; i < 10; ++i)
    std::cout << bag.sample() << '\n';
}
I dont really understand any of that code, could you please explain it in text instead of code? similar to my example?
Last edited on
How about discrete_distribution

Good idea! That would be much better.

Seeding a generator might not be trivial:

The way I did it is wrong, but it works in a pinch.
http://www.pcg-random.org/posts/cpp-seeding-surprises.html

Someone needs to come up with a short way to properly seed mt19937 that can be used in little throwaway examples. The shortcut I used propagates bad practice.
Topic archived. No new replies allowed.