Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document rand_weighted() in Random number generation #10283

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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