# What does "function () return" and "math.random" actually mean?

## Recommended Posts

In this exact code what does it mean?

countprefabs= {
pighouse = function () return 5 + math.random(4) end,

-----

Does it mean that its 5 guaranteed spawned pighouses and 4 that can randomly spawn?
OR
Does it mean that its 40% chance for them all to spawn?
OR
Does 5 and 4 both mean percentage?
---------

I assumed 5 meant possitive spawns, and math.random would be 4 possible spawns, but when I tried the same thing on "countstaticlayouts" weird things started to happen. Was I wrong?

-----------------------------

And then this is where things didnt add upp for me...

countstaticlayouts=
{
["CropCircle"]=function() return math.random(0,1) end,

----------

I assumed the above meant 10% chance to spawn 1 crop circle. And I wanted it to spawn one on random and one always so I changed the code to this.

["CropCircle"]=function() return 1 + math.random(1) end,

BUT then it instead ALWAYS spawns 2 cropcircles OR ALWAYS none... Never just ONE. Why?

EDIT: Does function () return 1 + math.random(1) end have a different meaning if its under "countstaticlayouts" instead of "countprefabs"???? What in the world does "math.random(1)" and "return 1" actually do??

Edited by NamelessName
##### Share on other sites

1 hour ago, NamelessName said:

In this exact code what does it mean?

function () return 5 + math.random(4) end,

function() return math.random(0,1) end,

function () return 1 + math.random(1) end

In LUA you can have anonymous functions.  These are those.

The function may have any number of return values, so in this case all of the functions are returning one value which is a number type.

The math.random function has different meanings when the number of arguments passed changes.

math.random() will return a uniformly distributed number from the interval [0,1).

math.random(N) will return a uniformly distributed integer from the interval [1, N].

math.random(A, B) will return a uniformly distributed integer from the interval [A, B].

So:

`5 + math.random(4)` will return an integer in the range of [5+1, 5+4] == [6, 9].

`math.random(0,1)` will return an integer in the range of [0, 1].

`1 + math.random(1)` will return an integer in the range of [1+1, 1+1] == 2.

Edited by CarlZalph
1+1 == 2, not 1.
• 3
##### Share on other sites

Ok thank you man for those details. My brain is not used to these lua maths just yet. So what would i change if I wanted to always spawn 1 cropcircle and randomly spawn 1 crop circle (2 spawns possible, but only 1 guaranteed)?

Would I have to actually add two different lines for that, so something like this:

["CropCircle"]=function() return math.random(0,1) end,
["CropCircle"]=function() return math.random(1) end,

PS: Every time I try to change something with just one line I seem to gain 2 guaranteed spawns or 2 random spawns... I want one of both (1 guaranteed, 1 random).

EDIT: None of these below achieves what I want it seems.

["CropCircle"]=function() return 1+ math.random(0,1) end,

["CropCircle"]=function() return 2+ math.random(0,1) end,

["CropCircle"]=function() return 1+ math.random(1) end,

Edited by NamelessName
##### Share on other sites

2 hours ago, NamelessName said:

So what would i change if I wanted to always spawn 1 cropcircle and randomly spawn 1 crop circle (2 spawns possible, but only 1 guaranteed)?

Assuming you have the worldgen room/piece/etc setup properly and you're having it function, then:

["CropCircle"] = function() return 1 + math.random(0,1) end,

It may take a few worldgens to see the deviation since the 50% roll for double is independent of prior rolls.

• 1
##### Share on other sites

28 minutes ago, CarlZalph said:

Assuming you have the worldgen room/piece/etc setup properly and you're having it function, then:

["CropCircle"] = function() return 1 + math.random(0,1) end,

It may take a few worldgens to see the deviation since the 50% roll for double is independent of prior rolls.

I thought that exact line would work properly but when I added that theres like 1 out of 3 times where circlecrop does not spawn at all. Is this something hardcoded or maybe the object shares with other object and can be "removed" if too many objects? I think this is what partly makes me confused. If I add that exact line it should always spawn at least one circlecrop, but it doesnt... Its very strange.

I was trying to make a mod where 5 extra pighouses always spawn and 1 circlecrop always spawn (with one circlecrop being random).

Edited by NamelessName
##### Share on other sites

15 minutes ago, NamelessName said:

I thought that exact line would work properly but when I added that theres like 1 out of 3 times where circlecrop does not spawn at all. Is this something hardcoded or maybe the object shares with other object and can be "removed" if too many objects?

I don't know the specifics, but I do know that if things aren't marked in a certain way like the dragonfly or pig king, then worldgen will optionally remove things that didn't fit the worldgen.

Something about reservation spots and not having enough space.

• 1
##### Share on other sites

28 minutes ago, CarlZalph said:

I don't know the specifics, but I do know that if things aren't marked in a certain way like the dragonfly or pig king, then worldgen will optionally remove things that didn't fit the worldgen.

Something about reservation spots and not having enough space.

Thank you man. My last question is, why does "math.random(0,2)" appear to do the exact same thing as "math.random(2)" (0,2-0,9 and 2-9)???

Anyway if you dont want to answer anymore thats cool. You helped me tons man, and I feel I am one step closer to understanding some lua code. Thank you!

Edited by NamelessName
##### Share on other sites

6 hours ago, NamelessName said:

Thank you man. My last question is, why does "math.random(0,2)" appear to do the exact same thing as "math.random(2)" (0,2-0,9 and 2-9)???

Ah, well they shouldn't.  When you have the 0 for the first parameter it allows the value of 0 to be returned.  One argument excludes it and it the same as using (1,N) for the argument list.

Here's a simple trial run to record 10k rolls for each of these and print them out:

Spoiler
```
outputs = {{},{},{},{},}
trials = 10000
for i=1,trials
do
local r1 = math.random(0,2)
local r2 = math.random(2)
local r3 = math.random(0,9)
local r4 = math.random(9)
outputs[1][r1] = (outputs[1][r1] or 0) + 1
outputs[2][r2] = (outputs[2][r2] or 0) + 1
outputs[3][r3] = (outputs[3][r3] or 0) + 1
outputs[4][r4] = (outputs[4][r4] or 0) + 1
end
for k,v in pairs(outputs[1])
do
print("r1", k,v, v/trials)
end
print("")
for k,v in pairs(outputs[2])
do
print("r2", k,v, v/trials)
end
print("")
for k,v in pairs(outputs[3])
do
print("r3", k,v, v/trials)
end
print("")
for k,v in pairs(outputs[4])
do
print("r4", k,v, v/trials)
end```

Example output:

Spoiler
```
r1	1	3331	0.3331
r1	2	3295	0.3295
r1	0	3374	0.3374

r2	1	4996	0.4996
r2	2	5004	0.5004

r3	1	971	0.0971
r3	2	1061	0.1061
r3	3	1007	0.1007
r3	4	998	0.0998
r3	5	993	0.0993
r3	6	1012	0.1012
r3	7	975	0.0975
r3	8	996	0.0996
r3	9	956	0.0956
r3	0	1031	0.1031

r4	1	1108	0.1108
r4	2	1149	0.1149
r4	3	1135	0.1135
r4	4	1084	0.1084
r4	5	1123	0.1123
r4	6	1107	0.1107
r4	7	1086	0.1086
r4	8	1099	0.1099
r4	9	1109	0.1109

```

The ones where the 0 was for the first parameter had an additional value output and subsequently 1/(N+1) odds of rolling it versus the 1/N with one argument.

• 1
• 1
##### Share on other sites

5 hours ago, CarlZalph said:

Ah, well they shouldn't.  When you have the 0 for the first parameter it allows the value of 0 to be returned.  One argument excludes it and it the same as using (1,N) for the argument list.

Here's a simple trial run to record 10k rolls for each of these and print them out:

Reveal hidden contents
```

outputs = {{},{},{},{},}
trials = 10000
for i=1,trials
do
local r1 = math.random(0,2)
local r2 = math.random(2)
local r3 = math.random(0,9)
local r4 = math.random(9)
outputs[1][r1] = (outputs[1][r1] or 0) + 1
outputs[2][r2] = (outputs[2][r2] or 0) + 1
outputs[3][r3] = (outputs[3][r3] or 0) + 1
outputs[4][r4] = (outputs[4][r4] or 0) + 1
end
for k,v in pairs(outputs[1])
do
print("r1", k,v, v/trials)
end
print("")
for k,v in pairs(outputs[2])
do
print("r2", k,v, v/trials)
end
print("")
for k,v in pairs(outputs[3])
do
print("r3", k,v, v/trials)
end
print("")
for k,v in pairs(outputs[4])
do
print("r4", k,v, v/trials)
end```

Example output:

Reveal hidden contents
```

r1	1	3331	0.3331
r1	2	3295	0.3295
r1	0	3374	0.3374

r2	1	4996	0.4996
r2	2	5004	0.5004

r3	1	971	0.0971
r3	2	1061	0.1061
r3	3	1007	0.1007
r3	4	998	0.0998
r3	5	993	0.0993
r3	6	1012	0.1012
r3	7	975	0.0975
r3	8	996	0.0996
r3	9	956	0.0956
r3	0	1031	0.1031

r4	1	1108	0.1108
r4	2	1149	0.1149
r4	3	1135	0.1135
r4	4	1084	0.1084
r4	5	1123	0.1123
r4	6	1107	0.1107
r4	7	1086	0.1086
r4	8	1099	0.1099
r4	9	1109	0.1109

```

The ones where the 0 was for the first parameter had an additional value output and subsequently 1/(N+1) odds of rolling it versus the 1/N with one argument.

I see. So I think I understand it. Its a higher percentage on lets say "math.random(2)" compared to "math.random(0,2)".

Thank you man for all the great explanations. This will be a great thread for anyone asking about "math.random" in the future.

• 1