while wait() do
print(Random.new():NextInteger(1,6))
end
Prints the exact same number on mobile every time, this is game breaking for me as I have a recursive function in my game which I use to get a different number every time so there can’t be two numbers in a row, but because Random() always produces the same number the game hangs as it’s on an infinite loop.
My code which causes the game to freeze on mobile:
local previousNum = 1
function getNum()
local Num = Random.new():NextInteger(1,6)
if Num == previousNum then
return getNum()
else
previousNum = Num
return Num
end
end
I tried this on a OnePlus5T and was unable to reproduce your observed behaviour.
As a general point, you should probably define Random.new() once at the start of a script rather than creating a new Random object each time.
You should also see if initialising it with tick() makes any difference in case the way Random generates a seed on its own is somehow broken on mobile.
local rand = Random.new(tick())
while wait() do
print(rand:NextInteger(1,6))
end
Right, so my friend tested the original code with his iPhone 6s+ and Samsung Galaxy S6 Edge and it worked fine on his iPhone 6+, but it did not work on his Samsung Galaxy S6 Edge.
I have also tried your code on my own Galaxy S9+ and it worked fine, so it seems like this has something to do with the way Random() generates a seed on its own on Samsung devices.
math.randomseed had the same issue across all platforms I believe.
Either way, Random isn’t designed to be using a new object every time.
Setting it to a variable outside of the repeating-code’s scope is both more performant, and it allows for NextInteger to do its work properly (because it has a frame of reference).
You’re spawning a new random number generator with each call, and you’re not seeding it, and it looks like it’s using the same default seed. It’s only meant to be used the way @MasterDaniel shows. That said, the documentation indicates that, when not seeded explicitly, Random.new() should use a seed “pulled from an internal entropy source.” Clearly that’s not happening on the platform returning all 4.
Also, just for readability’s sake, consider converting your function to a while or repeat loop. A tail-recursive function like this can be converted to a loop that doesn’t even need a stack, just something like:
local prev = 0
local RNG = Random.new(tick())
local function GetNum()
local num
repeat
num = RNG:NextInteger(1,6)
until num~=prev
prev = num
return num
end
Once converted to a loop, the original bug you posted about would still be a problem without the manual seeding of Random using tick(). It would just have caused an infinite loop instead of a call stack overflow. You can really easily safeguard against hanging your game with a cap on how many times you loop. Consider your example of needing numbers from 1 to 6. If you cap the loop at say, 15 tries, the chance of hitting that cap and returning a duplicate value with no bug is math.pow(1/6, 15), which is 2 in 1 trillion. You’re more likely to win a tri-state lottery than hit 15 iterations under normal operation, yet 15 calls to NextInteger takes a few microseconds, so you’d catch something like the original bug as near instantly as makes no difference. If those odds aren’t long enough, just cap it at 100; the sun will have engulfed the earth and Mars pigs will have evolved wings before it returns a duplicate under normal operation of NextInteger. The code would just have something like this:
local function GetNum()
local count = 0
local num
repeat
count = count + 1
num = RNG:NextInteger(1,6)
until num~=prev or count > 14
if count > 14 then
warn("GetNum exceeded allowed loop count, possibly returning a duplicate value")
end
prev = num
return num
end
Clearly, this is the source code for the mobile entropy source:
More seriously…,
The thread is marked as solved by @AllYourBlox’s post, which is absolutely right that you should not instantiate a Random every time you want one random number, but there is still a bug if Random.new() provides the exact same seed every time when the doc says it pulls from entropy. A developer should be able to call Random.new() and not get the same sequence every time (in a tight loop maybe, but across multiple frames?)