Skip to content

Commit

Permalink
Document rand_weighted() in Random number generation (#10283)
Browse files Browse the repository at this point in the history
* Document `rand_weighted()` in Random number generation

---------

Co-authored-by: Max Hilbrunner <[email protected]>
  • Loading branch information
Calinou and mhilbrunner committed Nov 30, 2024
1 parent fec6259 commit e163152
Showing 1 changed file with 50 additions and 8 deletions.
58 changes: 50 additions & 8 deletions tutorials/math/random_number_generation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
----------------------

Expand Down Expand Up @@ -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());
}

Expand All @@ -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() <class_@GlobalScope_method_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
Expand Down Expand Up @@ -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() <class_@GlobalScope_method_randf_range>` takes two arguments
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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];
}

Expand Down Expand Up @@ -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
Expand All @@ -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() <class_RandomNumberGenerator_method_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
Expand Down

0 comments on commit e163152

Please sign in to comment.