1 /** 2 A class for generating pseudo-random numbers. 3 4 Copyright: 5 Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. 6 Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) 7 Copyright (c) 2017-2018 Godot-D contributors 8 9 License: $(LINK2 https://opensource.org/licenses/MIT, MIT License) 10 11 12 */ 13 module godot.randomnumbergenerator; 14 import std.meta : AliasSeq, staticIndexOf; 15 import std.traits : Unqual; 16 import godot.d.traits; 17 import godot.core; 18 import godot.c; 19 import godot.d.bind; 20 import godot.d.reference; 21 import godot.globalenums; 22 import godot.object; 23 import godot.classdb; 24 import godot.reference; 25 /** 26 A class for generating pseudo-random numbers. 27 28 RandomNumberGenerator is a class for generating pseudo-random numbers. It currently uses $(D url=http://www.pcg-random.org/)PCG32$(D /url). 29 $(B Note:) The underlying algorithm is an implementation detail. As a result, it should not be depended upon for reproducible random streams across Godot versions. 30 To generate a random float number (within a given range) based on a time-dependant seed: 31 32 33 var rng = RandomNumberGenerator.new() 34 func _ready(): 35 rng.randomize() 36 var my_random_number = rng.randf_range(-10.0, 10.0) 37 38 39 $(B Note:) The default values of $(D seed) and $(D state) properties are pseudo-random, and changes when calling $(D randomize). The `0` value documented here is a placeholder, and not the actual default seed. 40 */ 41 @GodotBaseClass struct RandomNumberGenerator 42 { 43 package(godot) enum string _GODOT_internal_name = "RandomNumberGenerator"; 44 public: 45 @nogc nothrow: 46 union { /** */ godot_object _godot_object; /** */ Reference _GODOT_base; } 47 alias _GODOT_base this; 48 alias BaseClasses = AliasSeq!(typeof(_GODOT_base), typeof(_GODOT_base).BaseClasses); 49 package(godot) __gshared bool _classBindingInitialized = false; 50 package(godot) static struct GDNativeClassBinding 51 { 52 __gshared: 53 @GodotName("get_seed") GodotMethod!(long) getSeed; 54 @GodotName("get_state") GodotMethod!(long) getState; 55 @GodotName("randf") GodotMethod!(double) randf; 56 @GodotName("randf_range") GodotMethod!(double, double, double) randfRange; 57 @GodotName("randfn") GodotMethod!(double, double, double) randfn; 58 @GodotName("randi") GodotMethod!(long) randi; 59 @GodotName("randi_range") GodotMethod!(long, long, long) randiRange; 60 @GodotName("randomize") GodotMethod!(void) randomize; 61 @GodotName("set_seed") GodotMethod!(void, long) setSeed; 62 @GodotName("set_state") GodotMethod!(void, long) setState; 63 } 64 /// 65 pragma(inline, true) bool opEquals(in RandomNumberGenerator other) const 66 { return _godot_object.ptr is other._godot_object.ptr; } 67 /// 68 pragma(inline, true) typeof(null) opAssign(typeof(null) n) 69 { _godot_object.ptr = n; return null; } 70 /// 71 pragma(inline, true) bool opEquals(typeof(null) n) const 72 { return _godot_object.ptr is n; } 73 /// 74 size_t toHash() const @trusted { return cast(size_t)_godot_object.ptr; } 75 mixin baseCasts; 76 /// Construct a new instance of RandomNumberGenerator. 77 /// Note: use `memnew!RandomNumberGenerator` instead. 78 static RandomNumberGenerator _new() 79 { 80 static godot_class_constructor constructor; 81 if(constructor is null) constructor = _godot_api.godot_get_class_constructor("RandomNumberGenerator"); 82 if(constructor is null) return typeof(this).init; 83 return cast(RandomNumberGenerator)(constructor()); 84 } 85 @disable new(size_t s); 86 /** 87 88 */ 89 long getSeed() 90 { 91 checkClassBinding!(typeof(this))(); 92 return ptrcall!(long)(GDNativeClassBinding.getSeed, _godot_object); 93 } 94 /** 95 96 */ 97 long getState() const 98 { 99 checkClassBinding!(typeof(this))(); 100 return ptrcall!(long)(GDNativeClassBinding.getState, _godot_object); 101 } 102 /** 103 Generates a pseudo-random float between `0.0` and `1.0` (inclusive). 104 */ 105 double randf() 106 { 107 checkClassBinding!(typeof(this))(); 108 return ptrcall!(double)(GDNativeClassBinding.randf, _godot_object); 109 } 110 /** 111 Generates a pseudo-random float between `from` and `to` (inclusive). 112 */ 113 double randfRange(in double from, in double to) 114 { 115 checkClassBinding!(typeof(this))(); 116 return ptrcall!(double)(GDNativeClassBinding.randfRange, _godot_object, from, to); 117 } 118 /** 119 Generates a $(D url=https://en.wikipedia.org/wiki/Normal_distribution)normally-distributed$(D /url) pseudo-random number, using Box-Muller transform with the specified `mean` and a standard `deviation`. This is also called Gaussian distribution. 120 */ 121 double randfn(in double mean = 0, in double deviation = 1) 122 { 123 checkClassBinding!(typeof(this))(); 124 return ptrcall!(double)(GDNativeClassBinding.randfn, _godot_object, mean, deviation); 125 } 126 /** 127 Generates a pseudo-random 32-bit unsigned integer between `0` and `4294967295` (inclusive). 128 */ 129 long randi() 130 { 131 checkClassBinding!(typeof(this))(); 132 return ptrcall!(long)(GDNativeClassBinding.randi, _godot_object); 133 } 134 /** 135 Generates a pseudo-random 32-bit signed integer between `from` and `to` (inclusive). 136 */ 137 long randiRange(in long from, in long to) 138 { 139 checkClassBinding!(typeof(this))(); 140 return ptrcall!(long)(GDNativeClassBinding.randiRange, _godot_object, from, to); 141 } 142 /** 143 Setups a time-based seed to generator. 144 */ 145 void randomize() 146 { 147 checkClassBinding!(typeof(this))(); 148 ptrcall!(void)(GDNativeClassBinding.randomize, _godot_object); 149 } 150 /** 151 152 */ 153 void setSeed(in long seed) 154 { 155 checkClassBinding!(typeof(this))(); 156 ptrcall!(void)(GDNativeClassBinding.setSeed, _godot_object, seed); 157 } 158 /** 159 160 */ 161 void setState(in long state) 162 { 163 checkClassBinding!(typeof(this))(); 164 ptrcall!(void)(GDNativeClassBinding.setState, _godot_object, state); 165 } 166 /** 167 Initializes the random number generator state based on the given seed value. A given seed will give a reproducible sequence of pseudo-random numbers. 168 $(B Note:) The RNG does not have an avalanche effect, and can output similar random streams given similar seeds. Consider using a hash function to improve your seed quality if they're sourced externally. 169 $(B Note:) Setting this property produces a side effect of changing the internal $(D state), so make sure to initialize the seed $(I before) modifying the $(D state): 170 171 172 var rng = RandomNumberGenerator.new() 173 rng.seed = hash("Godot") 174 rng.state = 100 # Restore to some previously saved state. 175 176 177 $(B Warning:) the getter of this property returns the previous $(D state), and not the initial seed value, which is going to be fixed in Godot 4.0. 178 */ 179 @property long seed() 180 { 181 return getSeed(); 182 } 183 /// ditto 184 @property void seed(long v) 185 { 186 setSeed(v); 187 } 188 /** 189 The current state of the random number generator. Save and restore this property to restore the generator to a previous state: 190 191 192 var rng = RandomNumberGenerator.new() 193 print(rng.randf()) 194 var saved_state = rng.state # Store current state. 195 print(rng.randf()) # Advance internal state. 196 rng.state = saved_state # Restore the state. 197 print(rng.randf()) # Prints the same value as in previous. 198 199 200 $(B Note:) Do not set state to arbitrary values, since the random number generator requires the state to have certain qualities to behave properly. It should only be set to values that came from the state property itself. To initialize the random number generator with arbitrary input, use $(D seed) instead. 201 */ 202 @property long state() 203 { 204 return getState(); 205 } 206 /// ditto 207 @property void state(long v) 208 { 209 setState(v); 210 } 211 }