diff --git a/tutorials/math/random_number_generation.rst b/tutorials/math/random_number_generation.rst index b9abb724979..a12f43eb3a1 100644 --- a/tutorials/math/random_number_generation.rst +++ b/tutorials/math/random_number_generation.rst @@ -33,6 +33,9 @@ Global scope methods are easier to set up, but they don't offer as much control. RandomNumberGenerator requires more code to use, but allows creating multiple instances, each with their own seed and state. +This tutorial uses global scope methods, except when the method only exists in +the RandomNumberGenerator class. + The randomize() method ---------------------- @@ -81,6 +84,7 @@ across runs: public override void _Ready() { GD.Seed(12345); + // To use a string as a seed, you can hash it to a number. GD.Seed("Hello world".Hash()); } @@ -105,9 +109,9 @@ Let's look at some of the most commonly used functions and methods to generate random numbers in Godot. The function :ref:`randi() ` returns a random -number between 0 and 2^32-1. Since the maximum value is huge, you most likely -want to use the modulo operator (``%``) to bound the result between 0 and the -denominator: +number between ``0`` and ``2^32 - 1``. Since the maximum value is huge, you most +likely want to use the modulo operator (``%``) to bound the result between 0 and +the denominator: .. tabs:: .. code-tab:: gdscript GDScript @@ -145,7 +149,7 @@ varying by the deviation (1.0 by default): .. code-tab:: csharp - // Prints a normally distributed floating-point number between 0.0 and 1.0. + // Prints a random floating-point number from a normal distribution with a mean of 0.0 and deviation of 1.0. GD.Print(GD.Randfn()); :ref:`randf_range() ` takes two arguments @@ -174,7 +178,7 @@ and ``to``, and returns a random integer between ``from`` and ``to``: .. code-tab:: csharp - // Prints a random integer number between -10 and 10. + // Prints a random integer between -10 and 10. GD.Print(GD.RandiRange(-10, 10)); Get a random array element @@ -255,7 +259,7 @@ prevent repetition: func get_fruit(): var random_fruit = _fruits[randi() % _fruits.size()] while random_fruit == _last_fruit: - # The last fruit was picked, try again until we get a different fruit. + # The last fruit was picked. Try again until we get a different fruit. random_fruit = _fruits[randi() % _fruits.size()] # Note: if the random element to pick is passed by reference, @@ -286,7 +290,7 @@ prevent repetition: string randomFruit = _fruits[GD.Randi() % _fruits.Length]; while (randomFruit == _lastFruit) { - // The last fruit was picked, try again until we get a different fruit. + // The last fruit was picked. Try again until we get a different fruit. randomFruit = _fruits[GD.Randi() % _fruits.Length]; } @@ -379,7 +383,7 @@ floating-point number between 0.0 and 1.0. We can use this to create a } else if (randomFloat < 0.95f) { - // 15% chance of being returned + // 15% chance of being returned. return "Uncommon"; } else @@ -389,6 +393,44 @@ floating-point number between 0.0 and 1.0. We can use this to create a } } +You can also get a weighted random *index* using the +:ref:`rand_weighted() ` method +on a RandomNumberGenerator instance. This returns a random integer +between 0 and the size of the array that is passed as a parameter. Each value in the +array is a floating-point number that represents the *relative* likelihood that it +will be returned as an index. A higher value means the value is more likely to be +returned as an index, while a value of ``0`` means it will never be returned as an index. + +For example, if ``[0.5, 1, 1, 2]`` is passed as a parameter, then the method is twice +as likely to return ``3`` (the index of the value ``2``) and twice as unlikely to return +``0`` (the index of the value ``0.5``) compared to the indices ``1`` and ``2``. + +Since the returned value matches the array's size, it can be used as an index to +get a value from another array as follows: + +.. tabs:: + .. code-tab:: gdscript GDScript + + # Prints a random element using the weighted index that is returned by `rand_weighted()`. + # Here, "apple" will be returned twice as rarely as "orange" and "pear". + # "banana" is twice as common as "orange" and "pear", and four times as common as "apple". + var fruits = ["apple", "orange", "pear", "banana"] + var probabilities = [0.5, 1, 1, 2]; + + var random = RandomNumberGenerator.new() + print(fruits[random.rand_weighted(probabilities)]) + + .. code-tab:: csharp + + // Prints a random element using the weighted index that is returned by `RandWeighted()`. + // Here, "apple" will be returned twice as rarely as "orange" and "pear". + // "banana" is twice as common as "orange" and "pear", and four times as common as "apple". + string[] fruits = { "apple", "orange", "pear", "banana" }; + float[] probabilities = { 0.5, 1, 1, 2 }; + + var random = new RandomNumberGenerator(); + GD.Print(fruits[random.RandWeighted(probabilities)]); + .. _doc_random_number_generation_shuffle_bags: "Better" randomness using shuffle bags