瀏覽代碼

Edit random_numbers.rst

Remove parens, passive voice -> direct voice, fix some typos, simplify some of the language, and add a short intro listing what the reader will learn
Nathan Lovato 4 年之前
父節點
當前提交
5546ec3f90
共有 1 個文件被更改,包括 76 次插入73 次删除
  1. 76 73
      tutorials/math/random_number_generation.rst

+ 76 - 73
tutorials/math/random_number_generation.rst

@@ -3,70 +3,75 @@
 Random number generation
 Random number generation
 ========================
 ========================
 
 
-Many games rely on randomness to implement core game mechanics. This tutorial
+Many games rely on randomness to implement core game mechanics. This page
 guides you through common types of randomness and how to implement them in
 guides you through common types of randomness and how to implement them in
 Godot.
 Godot.
 
 
+After giving you a brief overview of useful functions that generate random
+numbers, you will learn how to get random elements from arrays, dictionaries,
+and how to use a noise generator in GDScript.
+
 .. note::
 .. note::
 
 
     Computers cannot generate "true" random numbers. Instead, they rely on
     Computers cannot generate "true" random numbers. Instead, they rely on
-    `psuedorandom number generators <https://en.wikipedia.org/wiki/Pseudorandom_number_generator>`__
-    (PRNGs).
+    `pseudorandom number generators
+    <https://en.wikipedia.org/wiki/Pseudorandom_number_generator>`__ (PRNGs).
 
 
 Global scope versus RandomNumberGenerator class
 Global scope versus RandomNumberGenerator class
 -----------------------------------------------
 -----------------------------------------------
 
 
-Godot exposes two ways to generate random numbers: via *global scope* methods
-or using the :ref:`class_RandomNumberGenerator` class.
+Godot exposes two ways to generate random numbers: via *global scope* methods or
+using the :ref:`class_RandomNumberGenerator` class.
 
 
 Global scope methods are easier to set up, but they don't offer as much control.
 Global scope methods are easier to set up, but they don't offer as much control.
 
 
 RandomNumberGenerator requires more code to use, but exposes many methods not
 RandomNumberGenerator requires more code to use, but exposes many methods not
-found in global scope such as
-:ref:`randi_range() <class_RandomNumberGenerator_method_randi_range>` and
-:ref:`randfn() <class_RandomNumberGenerator_method_randfn>`. On top of that,
-it allows creating multiple instances each with their own seed.
+found in global scope such as :ref:`randi_range()
+<class_RandomNumberGenerator_method_randi_range>` and :ref:`randfn()
+<class_RandomNumberGenerator_method_randfn>`. On top of that, it allows creating
+multiple instances each with their own seed.
 
 
-This tutorial uses global scope methods, except when the method is only found in
+This tutorial uses global scope methods, except when the method only exists in
 the RandomNumberGenerator class.
 the RandomNumberGenerator class.
 
 
 The randomize() method
 The randomize() method
 ----------------------
 ----------------------
 
 
-In global scope, you can find a :ref:`randomize() <class_@GDScript_method_randomize>`
-method.
-**This method should be called only once when your project starts to initialize
-the random seed.** Calling it multiple times is unnecessary and may impact
-performance negatively.
+In global scope, you can find a :ref:`randomize()
+<class_@GDScript_method_randomize>` method. **This method should be called only
+once when your project starts to initialize the random seed.** Calling it
+multiple times is unnecessary and may impact performance negatively.
 
 
 Putting it in your main scene script's ``_ready()`` method is a good choice::
 Putting it in your main scene script's ``_ready()`` method is a good choice::
 
 
     func _ready():
     func _ready():
         randomize()
         randomize()
 
 
-You can also set a fixed random seed instead using
-:ref:`seed() <class_@GDScript_method_seed>`. This will give you *deterministic*
-results across runs::
+You can also set a fixed random seed instead using :ref:`seed()
+<class_@GDScript_method_seed>`. Doing so will give you *deterministic* results
+across runs::
 
 
     func _ready():
     func _ready():
         seed(12345)
         seed(12345)
         # To use a string as a seed, you can hash it to a number.
         # To use a string as a seed, you can hash it to a number.
         seed("Hello world".hash())
         seed("Hello world".hash())
 
 
-When using the RandomNumberGenerator class, you should call ``randomize()``
-on the instance since it has its own seed::
+When using the RandomNumberGenerator class, you should call ``randomize()`` on
+the instance since it has its own seed::
 
 
     var rng = RandomNumberGenerator.new()
     var rng = RandomNumberGenerator.new()
     rng.randomize()
     rng.randomize()
 
 
-Get a random number
--------------------
+Getting a random number
+-----------------------
 
 
-Godot provides several methods to get random numbers.
+Let's look at some of the most commonly used functions and methods to generate
+random numbers in Godot.
 
 
-:ref:`randi() <class_@GDScript_method_randi>` returns a random number between 0
-and 2^32-1. Since the maximum value is really high, you most likely want to use
-the modulo operator (``%``) to bound the result between 0 and the denominator::
+The function :ref:`randi() <class_@GDScript_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::
 
 
     # Prints a random integer between 0 and 49.
     # Prints a random integer between 0 and 49.
     print(randi() % 50)
     print(randi() % 50)
@@ -74,32 +79,33 @@ the modulo operator (``%``) to bound the result between 0 and the denominator::
     # Prints a random integer between 10 and 60.
     # Prints a random integer between 10 and 60.
     print(randi() % 51 + 10)
     print(randi() % 51 + 10)
 
 
-:ref:`randf() <class_@GDScript_method_randf>` returns a random floating-point number
-between 0 and 1. This is useful to implement a
+:ref:`randf() <class_@GDScript_method_randf>` returns a random floating-point
+number between 0 and 1. This is useful to implement a
 :ref:`doc_random_number_generation_weighted_random_probability` system, among
 :ref:`doc_random_number_generation_weighted_random_probability` system, among
 other things.
 other things.
 
 
-:ref:`randfn() <class_RandomNumberGenerator_method_randfn>` returns a random floating-point
-number between 0 and 1. Unlike :ref:`randf() <class_@GDScript_method_randf>` which follows
-an uniform distribution, the returned number follows a
-`normal distribution <https://en.wikipedia.org/wiki/Normal_distribution>`__.
-This means the returned value is more likely to be around 0.5 compared to the
-extreme bounds (0 and 1)::
+:ref:`randfn() <class_RandomNumberGenerator_method_randfn>` returns a random
+floating-point number between 0 and 1. Unlike :ref:`randf()
+<class_@GDScript_method_randf>` which follows an uniform distribution, the
+returned number follows a `normal distribution
+<https://en.wikipedia.org/wiki/Normal_distribution>`__. This means the returned
+value is more likely to be around 0.5 compared to the extreme bounds (0 and 1)::
 
 
     # Prints a normally distributed floating-point number between 0.0 and 1.0.
     # Prints a normally distributed floating-point number between 0.0 and 1.0.
     var rng = RandomNumberGenerator.new()
     var rng = RandomNumberGenerator.new()
     rng.randomize()
     rng.randomize()
     print(rng.randfn())
     print(rng.randfn())
 
 
-:ref:`rand_range() <class_@GDScript_method_rand_range>` takes two arguments ``from`` and
-``to``, and returns a random floating-point number between ``from`` and ``to``::
+:ref:`rand_range() <class_@GDScript_method_rand_range>` takes two arguments
+``from`` and ``to``, and returns a random floating-point number between ``from``
+and ``to``::
 
 
     # Prints a random floating-point number between -4 and 6.5.
     # Prints a random floating-point number between -4 and 6.5.
     print(rand_range(-4, 6.5))
     print(rand_range(-4, 6.5))
 
 
-:ref:`RandomNumberGenerator.randi_range() <class_RandomNumberGenerator_method_randi_range>`
-takes two arguments ``from`` and ``to``, and returns a random integer between
-``from`` and ``to``::
+:ref:`RandomNumberGenerator.randi_range()
+<class_RandomNumberGenerator_method_randi_range>` takes two arguments ``from``
+and ``to``, and returns a random integer between ``from`` and ``to``::
 
 
     # Prints a random floating-point number between -10 and 10.
     # Prints a random floating-point number between -10 and 10.
     var rng = RandomNumberGenerator.new()
     var rng = RandomNumberGenerator.new()
@@ -125,12 +131,12 @@ We can use random integer generation to get a random element from an array::
 
 
     func get_fruit():
     func get_fruit():
         var random_fruit = fruits[randi() % fruits.size()]
         var random_fruit = fruits[randi() % fruits.size()]
-        # Returns "apple", "orange", "pear", or "banana" every time the code is run.
-        # The same fruit may be selected multiple times in succession.
+        # Returns "apple", "orange", "pear", or "banana" every time the code runs.
+        # We may get the same fruit multiple times in a row.
         return random_fruit
         return random_fruit
 
 
-To prevent the same fruit from being picked more than once in a row, we can add more
-logic to this method::
+To prevent the same fruit from being picked more than once in a row, we can add
+more logic to this method::
 
 
     var fruits = ["apple", "orange", "pear", "banana"]
     var fruits = ["apple", "orange", "pear", "banana"]
     var last_fruit = ""
     var last_fruit = ""
@@ -139,9 +145,9 @@ logic to this method::
     func _ready():
     func _ready():
         randomize()
         randomize()
 
 
+        # Pick 100 fruits randomly.
+        # Note: ``for i in 100`` is a shorthand for ``for i in range(100)``.
         for i in 100:
         for i in 100:
-            # Pick 100 fruits randomly.
-            # (``for i in 100`` is a faster shorthand for ``for i in range(100)``.)
             print(get_fruit())
             print(get_fruit())
 
 
 
 
@@ -151,19 +157,19 @@ logic to this method::
             # 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()]
             random_fruit = fruits[randi() % fruits.size()]
 
 
-        # Note: If the random element to pick is passed by reference
-        # (such as an array or dictionary),
+        # Note: if the random element to pick is passed by reference,
+        # such as an array or dictionary,
         # use `last_fruit = random_fruit.duplicate()` instead.
         # use `last_fruit = random_fruit.duplicate()` instead.
         last_fruit = random_fruit
         last_fruit = random_fruit
 
 
-        # Returns "apple", "orange", "pear", or "banana" every time the code is run.
-        # The same fruit will never be returned more than once in a row.
+        # Returns "apple", "orange", "pear", or "banana" every time the code runs.
+        # The function will never return the same fruit more than once in a row.
         return random_fruit
         return random_fruit
 
 
 This approach can be useful to make random number generation feel less
 This approach can be useful to make random number generation feel less
-repetitive, but it doesn't prevent results from "ping-ponging" between a limited
-set of values. To prevent this, use the
-:ref:`shuffle bag <doc_random_number_generation_shuffle_bags>` pattern instead.
+repetitive. Still, it doesn't prevent results from "ping-ponging" between a
+limited set of values. To prevent this, use the :ref:`shuffle bag
+<doc_random_number_generation_shuffle_bags>` pattern instead.
 
 
 Get a random dictionary value
 Get a random dictionary value
 -----------------------------
 -----------------------------
@@ -186,7 +192,7 @@ We can apply similar logic from arrays to dictionaries as well::
 
 
     func get_metal():
     func get_metal():
         var random_metal = metals.values()[randi() % metals.size()]
         var random_metal = metals.values()[randi() % metals.size()]
-        # Returns a random metal value dictionary every time the code is run.
+        # Returns a random metal value dictionary every time the code runs.
         # The same metal may be selected multiple times in succession.
         # The same metal may be selected multiple times in succession.
         return random_metal
         return random_metal
 
 
@@ -196,9 +202,9 @@ We can apply similar logic from arrays to dictionaries as well::
 Weighted random probability
 Weighted random probability
 ---------------------------
 ---------------------------
 
 
-The :ref:`randf() <class_@GDScript_method_randf>` method returns a floating-point number
-between 0.0 and 1.0. We can use this to create a "weighted" probability where
-different outcomes have different likelihoods::
+The :ref:`randf() <class_@GDScript_method_randf>` method returns a
+floating-point number between 0.0 and 1.0. We can use this to create a
+"weighted" probability where different outcomes have different likelihoods::
 
 
     func _ready():
     func _ready():
         randomize()
         randomize()
@@ -225,15 +231,14 @@ different outcomes have different likelihoods::
 "Better" randomness using shuffle bags
 "Better" randomness using shuffle bags
 --------------------------------------
 --------------------------------------
 
 
-Taking the same exemple as above, we would like to pick fruits at random.
+Taking the same example as above, we would like to pick fruits at random.
 However, relying on random number generation every time a fruit is selected can
 However, relying on random number generation every time a fruit is selected can
 lead to a less *uniform* distribution. If the player is lucky (or unlucky), they
 lead to a less *uniform* distribution. If the player is lucky (or unlucky), they
-could get the same fruit 3 or more times in a row.
+could get the same fruit three or more times in a row.
 
 
-This can be accomplished by using the *shuffle bag* pattern. It works by
-removing the element from the array once it has been chosen. If this is done
-multiple times, the array might end up being empty. In this case, its value is
-reinitialized to its default state where it's full::
+You can accomplish this using the *shuffle bag* pattern. It works by removing an
+element from the array after choosing it. After multiple selections, the array
+ends up empty. When that happens, you reinitialize it to its default value::
 
 
     var fruits = ["apple", "orange", "pear", "banana"]
     var fruits = ["apple", "orange", "pear", "banana"]
     # A copy of the fruits array so we can restore the original value into `fruits`.
     # A copy of the fruits array so we can restore the original value into `fruits`.
@@ -255,33 +260,31 @@ reinitialized to its default state where it's full::
             fruits = fruits_full.duplicate()
             fruits = fruits_full.duplicate()
             fruits.shuffle()
             fruits.shuffle()
 
 
-        # Get a random fruit (since the array has been suffled)
+        # Get a random fruit, since we shuffled the array,
         # and remove it from the `fruits` array.
         # and remove it from the `fruits` array.
         var random_fruit = fruits.pop_front()
         var random_fruit = fruits.pop_front()
-        # Prints "apple", "orange", "pear", or "banana" every time the code is run.
+        # Prints "apple", "orange", "pear", or "banana" every time the code runs.
         return random_fruit
         return random_fruit
 
 
-When running the above code, the same fruit will *never* be picked more than
-twice in a row. This is because once a fruit has been picked, it will no longer
-be a possible return value unless the array is now empty. When the array is
-empty, we reset it back to its full state, which makes it possible to have the
-same fruit again (but only once).
+When running the above code, there is a chance to get the same fruit twice in a
+row. Once we picked a fruit, it will no longer be a possible return value unless
+the array is now empty. When the array is empty, we reset it back to its default
+value, making it possible to have the same fruit again, but only once.
 
 
 Random noise
 Random noise
 ------------
 ------------
 
 
 The random number generation shown above can show its limits when you need a
 The random number generation shown above can show its limits when you need a
-value that *slowly* changes depending on the input. (The input can be a
-position, time, or anything else.)
+value that *slowly* changes depending on the input. The input can be a position,
+time, or anything else.
 
 
 To achieve this, you can use random *noise* functions. Noise functions are
 To achieve this, you can use random *noise* functions. Noise functions are
-especially poopular in producedural generation to generate realistic-looking
+especially popular in procedural generation to generate realistic-looking
 terrain. Godot provides :ref:`class_opensimplexnoise` for this, which supports
 terrain. Godot provides :ref:`class_opensimplexnoise` for this, which supports
 1D, 2D, 3D, and 4D noise. Here's an example with 1D noise::
 1D, 2D, 3D, and 4D noise. Here's an example with 1D noise::
 
 
     var noise = OpenSimplexNoise.new()
     var noise = OpenSimplexNoise.new()
 
 
-
     func _ready():
     func _ready():
         randomize()
         randomize()
         # Configure the OpenSimplexNoise instance.
         # Configure the OpenSimplexNoise instance.