Page 1 of 2

Math.Random question

Posted: Tue Feb 05, 2013 3:53 am
by Luska72
I understand that math.random's seed in based on the os.clock. I am having a small problem with many random numbers declared many times in a row. Here is an example:

Code: Select all

for a=1, #objectsToMove do
local rand = math.random(-5,5)
objectsToMove[a].x = objectsToMove[a].x + rand * dt
end
This is an example of what I am talking about, in this instance all of the objects will move randomly, but in the same pattern. I want all the objects to move independently based on their own random number.

Any tips would be great, I'm pretty stumped!

Re: Math.Random question

Posted: Tue Feb 05, 2013 4:29 am
by Inny
It's your imagination.

Alright, the long answer is that math.random doesn't actually provide random numbers, it provides pseudorandom numbers. The distinction is that regular random numbers are generated from sources like you moving your mouse, or cosmic radiation, where as pseudorandom numbers start with a number, (like the current time) and keep adding and multiplying to them in some algorithm. HOWEVER, the "period" for PRNGs, or how many times it can generate a number before it loops back and starts over is immensely huge.

Anyway, a good tip, use math.random without any parameters. When you give it numbers, it returns integers. Without, it returns a real number between [0 and 1). That can increase the amount of diversity in their movement.

Another tip, you're moving them randomly every frame, which means you're going to get wiggling at best. Instead, pick a direction, speed, and time randomly, and try moving them in a straight line for that period before picking a new way to go.

Re: Math.Random question

Posted: Tue Feb 05, 2013 7:14 am
by Robin
Yes, the real problem here is statistics: over a long period of time, on average all these enemies just keep bouncing back to the middle. Like Inny said: pick a direction/speed for them at the beginning and use that:

(Also, I use ipairs here instead of a numeric for.)

Code: Select all

-- in love.load
for i, obj in ipairs(objectsToMove) do
    obj.speed = math.random(-5,5)
end

-- in love.update
for i, obj in ipairs(objectsToMove) do
    obj.x = obj.x + obj.speed * dt
end

Re: Math.Random question

Posted: Tue Feb 05, 2013 3:12 pm
by Luska72
Thank you very much for the replies, I still a little stumped though.

While I do (now) understand how random numbers are generated, I still don't know the best way to get different random numbers at the same os.time. How would I implement something like mouse movement or cosmic radiation to my random number?

Thank you very much again, Love2d has an awesome community!

Re: Math.Random question

Posted: Tue Feb 05, 2013 3:20 pm
by Luska72
In other words: How can I get a random number that is NOT based on os.time, because I generate multiple random numbers at the EXACT SAME TIME which causes them to all be the same.

Re: Math.Random question

Posted: Tue Feb 05, 2013 3:33 pm
by Nixola
Calling math.random even one thousand times in the same second still returns different numbers

Re: Math.Random question

Posted: Tue Feb 05, 2013 3:34 pm
by Robin
If you're calling math.randomseed(), remove all those calls.

If not, could you upload your code (bundle it all together in a .love, please)?

Also, please don't double post.

Re: Math.Random question

Posted: Tue Feb 05, 2013 3:56 pm
by Luska72
First of all, sorry about the double post. It will not happen again.

The computer I am on isn't working properly for making .love files (not admin on this comp). I will upload the .love file later when I get access to my home computer.

For now here is all the code I am using for the random:

rand.lua:

Code: Select all

rand = { }

function rand:init()
math.randomseed (os.time())
end

function rand:seed()
math.randomseed (os.time())
end

function rand:newInteger(low,high)
local randomNum
randomNum = math.random(low,high)
randomNum = math.random(low,high)
randomNum = math.random(low,high)
randomNum = math.random(low,high)
return randomNum
end

In love.load:

Code: Select all

rand:init()
In my npc.lua

Code: Select all

function npc:update(dt)
for i,v in ipairs(self.currentNPCs) do
	local direction = rand:newInteger(-5,5)
		v["x"] = v["x"] - direction * dt * 100
	end
end
end
I know the NPC code is bad right now, I plan on making NPCs move more smoothly after I get this random thing worked out.

Thank you again, I do appreciate you taking the time to help me out.

Re: Math.Random question

Posted: Tue Feb 05, 2013 4:40 pm
by micha
Ok, here is how random number generation on a computer works:

The code for generation random numbers has an internal state. Depending on that and on some complicated calculations, the next number is generated and then the state is updated. So next time you call the math.random function, you get a new random number.
These numbers are not truly random in the sense that in a certain state the algorithm will always generate the same random number. However the state is not visible to the user and the sequence that comes out of the generator looks random (unless you understand all the details of the algorithm, which I dont).

When you start your program, the state of the generator cannot be random, because the computer is deterministic. So if you set the state (seed) to a fixed number, then every time you start your program, you get the same sequence of random number. You don't want that. So in most implementations the random seed is set according to the system time. This has only to be done once. After that the sequence you get is as random as it can.

Now in löve, the setting of the random seed is done anyway at start up (guys correct me, when I'm wrong here). So you don't even need to ever call the randomseed function yourself. Never.

The only application I see, where you need to set the randomseed, is when you do scientific applications and want reproducible results. In that case you can set the seed to a number you know and get the same random sequence every time.

Edit: Also, if you need one random number, there is no point in calling the math.random function multiple times. There is no visible correlation between to consecutive function calls.

Re: Math.Random question

Posted: Tue Feb 05, 2013 5:26 pm
by Roland_Yonaba
micha wrote: When you start your program, the state of the generator cannot be random, because the computer is deterministic. So if you set the state (seed) to a fixed number, then every time you start your program, you get the same sequence of random number. You don't want that. So in most implementations the random seed is set according to the system time. This has only to be done once. After that the sequence you get is as random as it can.
Totally. Actually, you use math.randomseed for that.
Pil covers the topic, take a quick peek here. Lua-users have a dedicated topic about that, aswell.
micha wrote: Now in löve, the setting of the random seed is done anyway at start up (guys correct me, when I'm wrong here). So you don't even need to ever call the randomseed function yourself. Never.
You're quite right, Micha. Well, it seems that this was introduced in love 0.8.0. See love.run default implementation.