Lua Script: "Random Numbers" (easy)

As one or the other of you, I have also started to play a bit around with Lua (you might know why ^^). Actually I do have some background in coding… but that’s an awfully long time ago. So maybe I can share a bit what I learn, if that is interesting at all ;-).

Under this link you will find a translation into German.

For the beginning I had this scenario in my mind:

I want to control the behaviour of a setter. Based on a random value
(which I want to influence), the settler should have a tendency to do
something. This could be simply greeting or hugging another settler,
or something more complex.

As it is not yet known, how observing, actions, etc. will work, I have decided to focus on pure Lua and leave it open, how this could be connected to the game.

So the following code askes the user for 2 inputs. On one side, you have to tell the script with which probability you want an event to be executed. On the other side, you can tell the script how often it should run (this should simulate for me how often the settler meets someone else). After that, a random number is generated for each time “your settler is meeting someone else” (or simply for each time the responsible code is executed). Finally I count the times where we have a positive response (e.g. the settler greets or hugs someone)… just to see if the script is working correctly and the probability is met, kind of.

Here goes the code:

image

Here goes a short explanation of the lines.

Line 3: “print()” is a function which shows on the screen what is included in the brackets. Here it is used to tell the user to enter a number (probability of the event).

Line 4: “io.read()” is another function, which will wait for input from the user. Line 3 only prints the text, we need to use io.read() to get the input. The parameter “*n” allows that only numbers are entered. Finally the result of the input should be stored in a variable called “probability_plan”.

Line 6: Same as line 3, but other message to the user ^^. Here we ask for the time this event should happen.

Line 7: Same as line 4, but saved in another variable.

Line 9: A variable “probability_yes” is initialized with the value 0. We will later increase this value for each time the event happens.

Line 11: Another function… “math.randomseed()”. This one needs a bit explanation. There are things which do not belong together and one of them are computers and “randomness”. Simply, a computer cannot generate a random number. Instead, it is using some mathematical formulas and functions to simulate one. The problem with this is, that somewhere all this “algorithm” has to start and if the starting point is always the same, the “random” numbers you will get, will be always the same. Here the function “math.randomseed()” comes into play. It allows the programmer to decide what the starting point is. Clever as coders are, they feed this little creature with the system time, available in Lua via another function “os.time()”. So, as long as you do not have a machine to travel back in time, the chances are high, that this starting point is different every time you start the code, i.e. different random numbers will be generated.

Line 13: Now we enter into a loop. “for” is one of the ways how you can repeat a part of your code based on conditions. Here we have a counter (i), a maximum of how often the loop should be executed (amount_runs, which was filled by the user). The “1” at the end simply controls the steps by which the counter (i) will increase until he reaches the value stored in “amount_runs”).

Line 14: Simply starts the block of code which belongs to the for-loop.

Line 16: “math.random()” is now the function which generates random numbers. Remember, the starting point was defined in line 11. The function accepts some parameters, of which you see here two… “1” and “100”. This tells the function to generate a number which is between 1 and 100 (including both). The result is saved in a variable “random_number”.

This variable is a bit special as it is defined as “local”. Local variables are “deleted” again once you leave the “area” in which they are defined. In this case, the variable will no longer exist, once we leave the for-loop (which is after line 24).

Line 17: Now we know the random number and we know the probability with which we wanted the event to occur. This line should decide if the condition is met or not. Depending on the result, either one part of the code (could control one kind of behaviour of the settler) or another part (could control the other kind of behaviour of the settler) is executed.

We actually compare here simply the random number with the probability we would like to see. If the number is smaller than the probability, we consider this as a trigger of the behaviour we want to see.

Line 18: Here we land only if the condition is met, i.e. the event will be triggered. If the user has selected a probability of 33%, in average we will end up every third time in this part of the code.

The function “print()” is already known from the beginning of the code. What is different here are two things. We print not only a text, but also a varaible (you remember the counter called “i”). The two dots “…” are merging the variable with the text afterwards… and the variable “random_number” and the text again.

Line 19: The event was triggered, so we want to increase now the count of the variable we defined in line 9. This is for tracking reasons. We will use it a bit later. Pay attention that this variable is not defined as local… because “use it later” means outside the for-loop. So it cannot be defined local.

Line 20: Here starts the second block of code which will be executed if the condition in line 17 is not met.

Line 21: More or less the same as line 18.

Line 22: We end the “if” here.

Line 24: We end the “for” here.

Line 26: By applying some math, we calculate the percentage telling us how often the event happened.

Line 27: … and we show it on the screen.

So far a first look into Lua by myself. I hope this is kind of interesting / useful.

Update: Sorry, the initial link to the picture was wrong and did not show up :-/.

Update: Here the “copy & paste”-version of the code:

-- Random Numbers

print("enter probability as a number (0-100%):")
probability_plan=io.read("*n")

print("enter amount of runs a number:")
amount_runs=io.read("*n")

probability_yes=0

math.randomseed(os.time())

for i=1, amount_runs, 1
do
  
  local random_number=math.random(0,100)
  if (random_number<probability_plan) then
    print(i .. " " .. random_number .. " Yes")
    probability_yes=probability_yes + 1
  else
    print(i .. " " .. random_number .. " No")
  end

end

probability_actual=100/amount_runs*probability_yes
print("probability: " .. probability_actual)
3 Likes

as a fellow code monkey, i find this extremely interesting, so, thanks! unfortunately, your code block didnt seem to come through (at least for me)… :frowning:

looking forward to pouring over your code in a bit… :slight_smile:

@steveadamo Thanks for the hint. I need to get used to link to picutes instead of uploading them. Works now.

Now that is very interesting! I’m fairly new to programming, only taken intro classes to both C++ and Python in college, but I’ve always loved the “putting together a puzzle” like feeling you get while writing code. =) Very good job on your descriptions of the code, I learned quite a lot. Looking forward to anything else you might feel like posting on the subject. =P

Thanks or this post it was verry informative I haven’t used lua before but i would like to learn

now that ive had a chance to take a look at the code, i have to offer you a hearty piece o :cake: … primarily because you took the time to explain in great detail each of the lines… kudos…

i wrote a quick python equivalent while in the seminar this afternoon, but it got lost in transit… :smile:

import random

print 'Enter probability as number (0-100%):'
probability_plan=input()

print 'Enter mount of runs a number:'
amount_runs=input()

probability_yes = 0

for i in xrange(amount_runs):
random_number = random.randint(0,100)
if random_number < probability_plan:
print i, ’ ', random_number, 'Yes’
probability_yes += 1
else:
print i, ’ ‘, random_number, ’ No’

probability_actual = 100/amount_runs*probability_yes
print 'Probability: ', probability_actual
There’s your python code, functionally identical with the sole exception of random_number not being local to the block. And I’d prefer putting the code in the actual post voxel_pirate for ease but it would remove highlighting so idk.

1 Like

i see someone is still using 2.7? :slight_smile:

i’ve forced myself to 3.3, and still cant wrap my brain around the print()… :angry:

I’m pretty sure the only difference is the print in that code, I still use 2.7 though for pygame as only windows supports python 3.

Python is dead, long live Lua :wink: … well almost. Actually Blender is allowing Export-Functions to be written in Python. So who of you @SteveAdamo and @Xavion is volunteering to write a routine to export animations from Blender to Stonehearth? ^^

@Xavion Good point! Makes more sense as you can easily copy & paste it. Did not think about it, to be honest. However, it takes a bit of the readability. I think I will simply add it at the end of the post.

Well I have a bit of experience with Blender, I’m not sure how stonehearth handles animations though or how you’d animate them in blender. If I knew that I could take a crack at it but I’m not sure how well I’d succeed.

hahha… im not married to python, i just love how simple and human readable the language is… attributes it shares with its “kissing cousin” lua… :wink:

as for writing an export routine, im not familiar with blender (from this aspect), but would be happy to stumble through something… :smiley:

I am sure we will figure it out, latest during the beta. I have downloaded Blender just now and put it on my list of things to sort out. Seems like it is not that complicated (the export routine). However, never worked with Python and would prefer to focus on Lua ;-).

oh, i’ll definitely be spending more time with Lua (havent touched it in ages though)… but if anyone is interested, we’ll just offer other language export options… :smiley:

Slight error there. The probability is slightly incorrect; you’d need the user input of probability to be > 100 in order to truly achieve a 100% probability. Right now the random number goes from 0 - 100, so it possible to get a random value that is not < 100 probability.

Also, it’s pretty easy to manage an infinite loop here. You don’t have any error checking to ensure that the user enters an amount of runs of 1 or more. Even entering 0 will cause an infinite loop.

True, changing to a <= should fix it though so no problems there.

What version of lua are you using because for me a value of <= 0 causes it to never run the internal code because it finishes instantly.

Thanks for the remarks. I did not want to cover validation of user input more than allowing only for numeric-input. That might be another stand-alone post, going into some details.

@Causeless Can you post a “corrected” version of the code which you see wrong (regarding probability)? Makes it easier to read.

As not per my post the probability can be fixed by changing this

   local random_number=math.random(0,100)

for this

  local random_number=math.random(0,99)

and I’m pretty sure only *number validates, and *n just strips whitespace.

Wouldn’t it be more:

if (random_number<=probability_plan) then

as you suggested?

No, the reason why is due to the fact that the random number generates a number from 0 to 100 inclusive. So given an input of n you should be getting n/100 chance of getting it right, however <= you have (n+1)/101 chance as a<=b can be thought of as a<b+1 so that n is effectively guessing from 1-101 not 0-100. With the 0,99 and the < it makes it so that it balances by having each choice of n correspond to all choices below them, eg. 0 gets nothing as there isn’t anything below 0 while 50 gets 0-49 which is 50 out of the 100 options.

I could try explaining better if that didn’t make sense but it’s kinda hard to explain.