-
-
Notifications
You must be signed in to change notification settings - Fork 21.5k
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
Random Number Generation class #7199
Comments
What I'm really missing is this: |
Yes, something like that is needed and it should be able to accept an optional seed: |
Related to #5852, (maybe) #6235 and (maybe) #1268. (to sum up the first two of those issues, plus the rest of the thread, plus the python docs), we might have the following functions in the Random class:
|
Poisson is not continuous distribution, so I would omit |
@lukaskotik I think we should design the class not for people well versed in the terminology of statistics, but for normal people that are just getting into gamedev with godot. Still, I agree that naming the functions var world_random
func _ready():
world_random = Random.new()
world_random.set_algorithm(Random.ALGO_MT) # for example
world_random.set_seed(123)
generate_world(4, 200)
func generate_world(level, size):
# rand_*
for i in range(world_random.rand_int_range(100 + 10 * level, 150 + 20 * level)):
var obstacle = generate_obstacle()
obstacle.set_pos(Vector2(
world_random.rand_float_range(-size, +size),
world_random.rand_float_range(-size, +size)
))
if world_random.rand_float() < 0.1 + 0.01 * level:
obstacle.set_type(OBSTACLE_LAVA)
add_child(obstacle)
# get_*
for i in range(world_random.get_int_range(3 + 6 * level, 4 + 7 * level)):
var enemy = generate_enemy()
enemy.set_pos(Vector2(
world_random.get_float_range(-size, +size),
world_random.get_float_range(-size, +size)
))
if world_random.get_float() < 0.01 * (level-3):
enemy.set_boss(true)
add_child(enemy) |
@bojidar-bg You are right. It can be misleading for a gamedev. |
Then... should it be |
Uniform distribution is defined on an interval, so I assume that the term What about the following? Continuous distributions:
Discrete distributions:
And maybe
It is a question whether All these distributions are quite common and quite natural (have nice interpretations) so having them in Godot would be nice! I don't know if someone could feel desire to have some other probabilistic distributions (Pareto, gamma, hypergeometric, ...?) |
@lukaskotik I think that's a nice selection of probability functions! (my terminology is off probably) About the About the parameter names, I don't know if we should keep the "official" names, or would it be better to call most of them just Finally, about the range, I wondered really, really much about it, but, consider the following case: var my_0_1_float = random.get_uniform_float()
# Yay, works
var my_0_100_float = random.get_uniform_float(100)
# Uh, why does it error here? OR Why does it never return numbers between 0 and 1?
var my_0_100_float = random.get_unform_float() * 100
# Eureka, that works!
var my_2_100_float = random.get_unform_float(2, 100)
# Nice, this also works! I.e. some people might/would/won't mistake the first parameter for But, on the opposite side of the coin, |
I was thinking about completely omit About the names of parameters. Maybe we can use the same naming conventions as Python.numpy.random? I see your point with the |
SUMMARY Initializing
Setter
Getter (return depending on algorithm/seed/size set)
Range (same arguments like in for iterating)
Do we need to randomize()? I don't like this function, it should do it automatically after initializing. |
Great ideas/discussion. I'm fine with any naming convention .. just make sure the class/methods have good documentation |
@puppetmaster- Ok, but... there is a slight problem -- we cannot pass arguments to constructors from GDScript, due to the nature of the GDNativeClass class (since its |
I updated my comment, what do you think? |
I think it would be nice to have |
Does anyone know if this feature would be well received by the Godot devs? I actually started to sketch an implementation, but I think I will not spend much more time in it unless it has a good chance of being merged. If you are curious, the code is in the random_number_generators branch of my Godot fork. There are some points I'd like to change, and, of course, I need to add more random number generators and distributions (which would be basically a port from code I previously wrote in other languages. |
I have no idea, but just wanted to add that this random number generator might be interesting: |
That's already what Godot 3.0 uses, implemented by @tagcup. |
I'm totally for this. The only PRNG had only one variable as the state (called seed), but the current minimal PCG has two: seed and inc. Due to retrofitting to the old API, we're currently using the default inc. A class can encapsulate both variables and would be future-proof in that regard. |
@lmbarros Our current PRNG is already a very good one (see there also for comparisons with LCG, which has poor statistical quality). All core the implementation is already there, I'd say we just need a wrapper for GDScript for existing functions for basic things. Others (normal etc) can be built on top of PCG. |
Hi @tagcup,
Yes, PCG is good, sure. I personally have three concerns I would like to
solve:
1) Add a few more distributions beyond uniform (this would be the most
important point for me).
2) Let the user create separate instances of the RNG algorithm, in order to
generate different independent sequences.
3) Allow users to be sure that they can create reproducible pseudorandom
sequences even between Godot releases.
Maybe point 3 deserves some explanation. Imagine I implemented a
world-generation algorithm in Godot 2.1. My players are happy exchanging
nice "world seeds" they have found. Then I upgrade to Godot 3.0, which has
a different (arguably better, but different) RNG algorithm. This breaks all
the world seeds my players have been sharing among each other. (This gets
worse for games like the old Elite, in which the world is generated
procedurally generated, but always using the same seed.)
So, my idea to solve point 3 is to be explicit about what algorithm is
being used. Do I want to use PCG? Instantaite the RandPCG32 class. Wanna
Xoroshiro128+? Instantiate RandXoroshiro128Plus. Different RNGs have
different trade offs, so I wanted to leave this choice up to the users.
Yes, we can say that PCG will be our RNG of choice forever. I don't think
I'd vote for this, but I'd agree to follow this path if this is the choice
of the devs. (I can see merits in having one single RNG -- simplicity, to
begin with).
(BTW, I was not suggesting to replace PCG with an LCG, I just used an LCG
in my "proof of concept" because it was the simplest one I had at hand. The
LCG would be just one of the RNGs available to the user.)
Oh, my, I am verbose :-)
Anyway, my main point at the moment is: I want to help to improve the
random number generation in Godot, but I'd like to align the approach to
follow with the devs (because I want it merged).
What do you think?
…On Thu, Mar 2, 2017 at 1:18 PM, Ferenc Arn ***@***.***> wrote:
@lmbarros <https://github.com/lmbarros> Our current PCG is already a very
good one <http://www.pcg-random.org/pdf/toms-oneill-pcg-family-v1.02.pdf>
(see there also for comparisons with LCG, which has poor statistical
quality). All the implementation is already there, I'd say we just need a
wrapper for GDScript for existing functions.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#7199 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA-DaZWlqO8EsVQIPuS1BcWEB3LWaAeDks5rhuvAgaJpZM4K9Lhd>
.
|
These can be built on top of a basic PRNG class, so I'd suggest leaving those out from the PRNG class, and make additional functions/classes that accept the basic PRNG as parameters. This also solves the 2nd point you made.
This isn't up to me, but I don't think Godot makes such promises in general. If you want that level of guarantees, then I guess you should be using your own (basic) PRNG module. So overall, I'd recommend splitting this into two parts: base PRNG class which can be called "source", and a generic API for stuff like returning numbers in intervals, or from different probability distributions, which makes use of source. Something similar to Go's rand API would be nice. |
My design already separates the distributions/utlities from the RNG
algorithms themselves, albeit in a slightly different manner.
Well, I guess I'll work a little further on this and I'll ping you again
when I have something more complete.
Thanks!
PS: You said "this isn't up to me". This would be up to whom, then? :-) I
just started to look at Godot more seriously, so I am still trying to
figure out who is who :-)
…On Thu, Mar 2, 2017 at 3:33 PM, Ferenc Arn ***@***.***> wrote:
1. Add a few more distributions beyond uniform (this would be the most
important point for me).
These can be built on top of a basic PRNG class, so I'd suggest leaving
those out from the PRNG class, and make additional functions/classes that
accept the basic PRNG as parameters. This also solves the 2nd point you
made.
1. Allow users to be sure that they can create reproducible
pseudorandom sequences even between Godot releases.
This isn't up to me, but I don't think Godot makes such promises in
general. If you want that level of guarantees, then I guess you should be
using your own (basic) PRNG module.
So overall, I'd recommend splitting this into two parts: base PRNG class
which can be called "source", and a generic API for stuff like returning
numbers in intervals, or from different probability distributions, which
makes use of source. Something similar to Go's rand API
<https://golang.org/pkg/math/rand/> would be nice.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#7199 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA-DadAuZBdVRFVm1-DAQ235ff3g6LrHks5rhwuDgaJpZM4K9Lhd>
.
|
Sure, sound good. About such big decisions (like compatibility promises across versions), you should talk to @reduz or @akien-mga. |
So, I have added a pull request with the RNG stuff I wrote so far. I don't think it really really ready to be merged, but maybe we can discuss the merits and flaws of my design and implementation in the pull request itself. |
+1 for a sample or shuffle function. Edit: Looks like shuffle is in there already |
Please refrain from bumping issues without contributing new information; use the 👍 reaction button on the first post instead. |
Begin to address godotengine#7199 and godotengine#7989, among others. Add a Random class implementing the existing interface for random number generation, acting as a thin wrapper around the current functionality. The random functions in the Math namespace operate on a global instance of this class, keeping backwards-compatibility and simple use cases. The code had to be split into two classes, RandomBase and Random, as it seems like reference.h relies on math_funcs.h, and thus math_funcs cannot itself instance a reference.
We have randi() and randf() already, why is this not closed? |
@Zireael07 |
Fixed by #22314. |
I find Godot's random number generation methods to be somewhat lacking.
I think for a game engine, there should be more random number generation methods built-in.
It would be nice if Godot implemented something like this:
https://docs.python.org/2/library/random.html
I've never written Python but since GDScript is based on it, I looked up what rng features Python had, and it looks a lot better than what GDScript has.
What is needed is a class like that that can encapsulate random number generation from a specified seed. Right now what we have are methods that use a shared global seed - but in game dev, you need separate RNGs with separate seeds for things such as an RNG for randomly generating procedural worlds with a 'world seed', another RNG for particles and non-important stuff - etc.
I have tried using
rand_seed
... but there is no documentation on what type it returns (it looks like an int) and no documentation on the possible range.So again, it would be great if Godot could provide an easy to use and optimized RNG class in GDScript encapsulating a seed and exposing methods such as
_init(seed = -1) - allows initializing the seed upon construction, default value means random seed
rand() - returns float 0-1
randi(max)
randf(max)
randf_range(from, to)
randi_range(from, to)
and even other methods like Python provides such as
(using Python's names)
choice(array) - returns a random element in the array
sample(n, array) - returns new array with n elements randomed from input array
shuffle(array) - shuffle the array in place
etc.
I was about to build a class like this built on
rand_seed
, but as noted, I don't even know what range the values can be. Also I'm not sure what algorithm is being used for it and how good it is.The text was updated successfully, but these errors were encountered: