 # Lua math.random problem

#1

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?

0 Likes

#2

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

4 Likes

#3

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

#4

Is that a lua or a defold thing, because that is really annoying. 0 Likes

#5

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

#6

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

5 Likes

#7

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?

0 Likes

#8

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

#9

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

1 Like

#10

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 0 Likes

#11

I gave different values to self.last_pos but same result 0 Likes

#12

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 1 Like

#13

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

#14

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

0 Likes

#15

@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

#16

What are you doing to that poor seed?

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

1 Like

#17

@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…

0 Likes

#18

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

#19

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.

0 Likes

#20

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.  And “better rng”  6 Likes