Lua math.random problem

Hi guys, the game that I working on is creating blocks with position of x in some range. But I realized that on the start of the game it always pick the same value like every time it picks 320. What is the problem or how can I fix it?

You have to use math.randomseed before math.random
More info here

4 Likes

Also should always discard first few random values as the first few will always be the same due to some C thing

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

I prefer to use https://github.com/subsoap/defrng/blob/master/defrng/mt.lua for random numbers

4 Likes

Is that a lua or a defold thing, because that is really annoying. :confused:

If you’re talking about needing to clear the first few bad RNG it’s a Lua thing. Using MT avoids the issue.

1 Like

It’s not really a defold or a lua thing, it is a computer thing. You should read more about it, because it’s really interesting*

*well i think it’s quite interesting

7 Likes

Thanks for reference, I am currently using it. However there is another problem

function init(self)
	self.last_pos = 100
	create(self, "#diamond-factory")
end

function create(self, fac)
	local pos = vmath.vector3()
	pos.y = 480
	local random_x = m.random(50, 590)
	while self.last_pos >= random_x - 100 or self.last_pos <= random_x + 100 do
		random_x = m.random(50, 590)
	end
	self.last_pos = random_x
	local pos_of_ball = go.get_position("/ball")
	pos.x = random_x
	factory.create(fac, pos)
end

I am using this script to pick values of long distance. If the position of the last one is between “prev_x - 100 and prev_x + 100” then it should pick new value until it is OK. But the game crashes because of infinite loop. What is the problem ? Or how can I fix it? Any idea?

So, we start with self.last_pos == 100, so let’s figure out what values of random_x get us out of the loop.

  • self.last_pos >= random_x - 100 is false when random_x >= 201
  • self.last_pos <= random_x + 100 is false when random_x < 0

Since random_x can’t be less than 50, it will never be less than 0, so your while loop will never exit.

2 Likes

Why loop like that? Can’t you pass in the correct min and max values to math.random()?

1 Like

There is a ball which is moving from left to right and right to left all the game time, so when the ball reaches a block, then the next block must be far away from ball’s position on the reach point. I don’t know if it is clear :frowning:

I gave different values to self.last_pos but same result :frowning:

Sorry for flood but I solved the problem, It was my mistake…

	while random_x >= self.last_pos - 200 and random_x <= self.last_pos + 200 do
		random_x = m.random(50, 590)
	end

This worked fine while self.last_pos is initially 320. Then the random_x value should be between 120 and 520. So thanks for ideas :slight_smile:

1 Like

Since you’re trying to ensure the delta (difference) between two objects is “large enough” you should rewrite the conditional to make that clear, like:

repeat
    random_x = math.random(50, 590)
until math.abs(self.last_pos - random_x) >= 200

That’s far easier to understand: keep generating a random number until the delta between the random and the self.last_pos is more than 200.

3 Likes

I am going to remember that bit of code. it is handy!

@Pkeod thanks for the link! this module should really be included in Defold, the default math.random is very annoying due to this math.randomseed(os.clock()*100000000000) and even with that from my test the module from your link works a lot better out of box!

1 Like

What are you doing to that poor seed?

Use math.randomseed(socket.gettime()) and optionally throw away the first random value.

1 Like

@britzl maybe “math.randomseed(socket.gettime())” works fine when I need to pick a number from the big range, but for my example, I just tested it, when I have 3 elements array (table) and I need to pick 1 random element from this array 3 times - one after another (my case is I just instantiate 3 objects but the object can have 3 different sprites and in init() of the object I assign one of the spites randomly) - “math.randomseed(socket.gettime())” works really bad unfortunately, basically almost always picking the same value for all 3 object (calls). When I use math.randomseed(os.clock()*100000000000) - this works better but the linked library - works perfectly out of box without any additional lines…

I noticed that the default math.random works really bad when I need to pick a random element from some small array (small range of numbers math.random(1,3) for example) without this “os.clock()*100000000000” madness , so basically analogue to https://docs.yoyogames.com/source/dadiospice/002_reference/maths/real%20valued%20functions/choose.html which works excellent in GMS 2…

Ah, I see. Well, hmm, if you throw away the first one or two random numbers you start to get the kind of variation that is to be expected:

-- os.time() seems to work equally well
math.randomseed(socket.gettime()) math.random() math.random()
print(math.random(1,3))

Not optimal. Perhaps we can deal with this better internally in the engine…

1 Like

exactly, it is a bit hacky, and given the number of questions on the forum about “Random does not work” I believe this is the problem which must be addressed given the fact how often random functionality needed in game development.

Here are some illustrations of “bad rng” drawing 4 colors randomly on a canvas I made a few years ago. I think the method was pick a random x,y and pick a random one of the 4 colors based on the RNG methods. So after a few seconds the patterns would emerge.

2018-10-27%2002_20_38-exp 2018-10-27%2002_19_50-exp

And “better rng”

2018-10-27%2002_21_45-exp 2018-10-27%2002_21_32-exp

8 Likes