Random.range return weird values(SOLVED)

Hello everyone,
Getting ahead with my almost complete game. One more thing though, when I call random.range, in a way similar to this:

function init(self)
   local random = math.random(10, 99)
end

or

function init(self)
  self.random = math.random(1,4)
end

It keeps on returning the same value each time i run the game.
This has been troubling me ever since I began the game, and after being unable to find a solution,
I decide to finally ask it.

You need to change the seed to be based on os.time()

math.randomseed(os.time())

Then you need to dispose of the initial few random values as they are not actually random.

math.random();math.random();math.random();math.random();math.random();

You only have to do this once in your main entrypoint.

I prefer MT for RNG https://github.com/subsoap/defrng/blob/master/defrng/mt.lua

1 Like

It’s usually enough to throw away the first value only, at least from what I’ve seen.

I do it entirely out of paranoia, but using something else like MT instead avoids the issue entirely.

1 Like

What is the importance of this?

On computers, random numbers are not actually random because of the way machines work. If you set the same seed each time you will get the same “random” numbers generated in order every time you reset that seed. By setting the seed to the current time, you are generating “random” numbers based on that seed value, which should always be different as time goes up.

Mersenne Twister is a pretty good PRNG for games. There are still better ones out there such as ones listed here http://www.pcg-random.org/ someone could make a PCG extension…

Thanks man!! :wink:
This works just as it was expected to. However this code :

function init(self)
	math.randomseed(os.time())
	math.random();
	math.random();
	local random = math.random(10, 99)
	msg.post("#sprite", "play_animation", {id = hash("ships_asteroids_"..self.random)})
	self.dir = vmath.vector3(math.random()*math.random(-1,1), math.random()*math.random(-1,1), 0)
	print(self.random)
	self.speed = 100
end

still returns the same value of random for all asteroids on the screen.
I know that I am missing something, but what?

Can you please explain why is it needed?

Are you doing math.random(-1,1) to try to multiply by 1 or -1 randomly? Because you’ll also get some multiplies by 0 which will mess up what you probably want. Try (math.random(1,2)*2)-3 for randomly 1 or -1 instead.

You should only seed once in a single script!

1 Like

Yes it is done on a purpose so that the direction of the asteroid Amounts between -ve x/y axis too or can be 0, so that the asteroid remains stationary on X or y axis(or both?). But the problem is that all the asteroids on the screen have the same value of random as well as self.dir .

Yes. You set a local ”random” and then prints ”self.random”. They are two different variables.

Change the line:

local random = math.random(10, 99)

to

self.random = math.random(10, 99)

Sorry, local random was actually self.random. but when I was posting, I thought let’s try and change to local random, and then in a hurry I forgot to change the print value,. Nonetheless self. random also returned the same problem.

Ok. This code runs for all your asteroids. The line “math.randomseed(…)” is run for each asteroid as well. So you reseed the randomizer for each asteroid with the current time, which is the same value (seconds resolution). This means that you restart the randomizer for each asteroid, with the same initial value.

You should not reseed the randomizer more than once, as @britzl said above.

1 Like

So probably this should work

local A = 0
function init(self)
if A == 0 then 
math.randomseed(os.time())
A=A+1
end 

No. The local is local to the script. (Edit: sorry that would work if the local is declared at the top level, but it’s unnecessarily complex)

You should add a script to a single object somewhere and use that to seed. You probably have such an object somewhere already?

3 Likes

Tried this today, it works for now. But just as @sicher pointed, it is not as good.

I still not understand this. You mean to add it to an object (a gameobject??) and use that (the question is what??). This seeding part is confusing me, so maybe I will need some guidance.

The general idea is that you seed the random number generator once. This is typically done in a startup/loader/setup script. If you don’t have one yet you’ll probably need one down the road so create a script and attach to a game object once.

Once for each go or once globally??

Once globally.