Lua Script: “Highest (Lowest) Number” (easy)


#1

I would like to link this second script to the first one, posted here. The initial script could be used to cause one of the workers to hug / greet someone else. This time I would like to find out which of workers is the most happiest, i.e. was hugged most.

Again a “translation” of the script into German is available.

Taking a look into Lua, tables are something you cannot avoid. They are powerful structures, which could potentially be used in Stonehearth to hold the data for each worker (tables cannot only include values, but also functions). The code presented in this post is based on the assumption, that there will be one table (actually a matrix) which holds all the information for each settler. Once a new settler enters the world, the table could be simply extended. If one is passing away, he can be removed from the table (or flagged).

Let’s jump into the code first:

(at the bottom you will find a version to copy & paste)

image

We start in the middle of the code (easier to explain)…

Lines 18 to 24: Last time I have checked, Stonehearth was still not released ^^. So, as we want to check a value for each worker, we need to have some workers / dummy data. In this block of code we define the structure of the table which holds all information about our little fellows.

We call the table “worker_matrix” and while you might remember that “()” relates to a function, “{}” relates to a table.

You might also remember loops from the first code (we also used “for”). We enter a loop here and want to go through it for 3 times… assuming we will create only 3 workers (enough for our purpose). The loop is slilghtly different than last time and only has 2 parameters. The third one was defining the step. If we do not include it, Lua assumes 1 as a step, which is perfectly fine with us.

The table should become a matrix, so we need another loop for each settler, which creates values. Let us give each worker 5 values and run another loop.

At the end we have a matrix which consists of 3 rows (1 row = 1 worker) and 5 columns (1 column = 1 value).

Lines 26 to 42:

The table (matrix) is filled with “0” so far, which is hard to compare. So here we are going to fill them with some dummy data. You can see the matrix-like structure of the table as we have two indices in brackets, e.g. worker_matrix with the index “2” is filling the value tracking life of “Curly Howard” (the name of worker 2) with “100”. This one is pretty healthy at the moment (assuming 100 is 100%).

You will see that a table can contain numbers as strings. Even more (as mentioned above) even functions.

Line 44: Pretty easy so far, no? All the “magic” will happen in a function which we will investigate in a second. The function is called “find_maximum” and we just call it in line 44. The function has some specialities.

  1. We define it and what it does by ourselves.
  2. It will expect a value / parameter which you can hand over once you call the function.
  3. It will return 2 values, once it is done.

Regarding bullet 1… this we do in lines 3 to 16… just one second more.

Regarding bullet 2… that is the reason we call the function and hand over our “woker_matrix”-table as input for our function. Good thing here is, the function can be re-used if you want to hand over another table

Regarding bullet 3… that is why we write “found_number, found_name=”. This way we define 2 variables and call the function. The results is that the function will be executed and each of the return values will be allocated to one of the variables. for this we need to know that 2 values are returned and in which order. But as we define it by ourselves, we know ;-).

Lines 45 and 46: This lines we use to print the outcome of our code. While line 46 shows the content of our two return-values, line 45 shows the “amount of existing workers” (i.e. length of the table). The length of a table can be shown by putting the sign “#” in front of the table-name/-identifier.

Line 3: We are defining a function here called “find_maximum”. We also define (in brackets) that a variable can be handed over and we give it the name “input_table”, which is the name how we can address it in the function.

Lines 5 and 6: The function should identify which worker is hugged most. So we need a variable holding his / her name (“found_name”) and the amount of hugs he / she received (“found_maximum”). To have a starting point, we fill this variables with the data of our first settler.

Line 8: The loop which we start her, will allow us to compare all workers, i.e. the amount of hugs they have received. We start with 1 and run the loop for “#input_table” which is the length of the variable which was been handed over to the function, i.e. lenght of “worker_matrix”, i.e. 3.

Line 9: Here we compare the value which is filled in the variable “found_maximum” with the “hug-value” of each worker (in the first run woker 1 will be compared, in the second run it will be worker 2, etc.). It is not that difficult to change the logic and to not search for the highest but e.g. lowest value. So you can easily adjust the function and outcome.

Lines 10 and 11: If a new Maximum is found, we will fill the new data into the variables.

Lines 12 and 13: … are closing the for-loop and the if-condition.

Line 15: “return” defines the value(s) which a function will send back to whomever was calling it. We want to send back two values, the name and the maximum number of hugs. So we define simply two return values. What is important though is the order of the variables which are sent back, to not confuse them later on.

Line 16: … ends the function, which can be called from anywhere now in the code below.

Again, this is a not so difficult example but gives hopefully a first introduction into functions, tables and how values can be compared.

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

-- Functions and find highest number in a Table

function find_maximum(input_table)

	local found_maximum=input_table[1][5]
  local found_name=input_table[1][1]

	for i=1, #input_table do
		if input_table[i][5] > found_maximum then
			found_maximum = input_table[i][5]
      found_name = input_table[i][1]
		end
	end

  return found_maximum, found_name
end

worker_matrix={}
for i=1,3 do
    worker_matrix[i]={}
  for j=1,5 do
    worker_matrix[i][j]=0
  end
end

worker_matrix[1][1]="Moe"             -- Name of worker
worker_matrix[1][2]="male"            -- Gender
worker_matrix[1][3]=100               -- Life in %
worker_matrix[1][4]=11                -- Hunger
worker_matrix[1][5]=2                 -- Hugs

worker_matrix[2][1]="Curly Howard"
worker_matrix[2][2]="femal"
worker_matrix[2][3]=100
worker_matrix[2][4]=9
worker_matrix[2][5]=15

worker_matrix[3][1]="Larry Fine"
worker_matrix[3][2]="male"
worker_matrix[3][3]=90
worker_matrix[3][4]=7
worker_matrix[3][5]=3

found_number, found_name = find_maximum(worker_matrix)
print("Number of workers: " .. #worker_matrix)
print("Most hugged: " .. found_name .. " (" .. found_number .. " times)")

Welcome to the Bitcave! Nerdiness, Jokes, Mods, Ideas, and coding!
Welcome to the Bitcave! Nerdiness, Jokes, Mods, Ideas, and coding!
Learning how to mod Stonehearth
Learning how to mod Stonehearth
#2

I don’t know a gosh gollied thing about coding aside how to make a chat room. So… most of this means nothing to me. But I like it anyway. I’ve been meaning to learn how to code.


#3

That’s actually what I am doing right now. I am also not the greatest coder on earth (probably not even the greatest coder in my flat ^^), but it’s interesting to dig a bit into how Lua works. All of the samples I post here can be achieved with much less code and in a much nicer way, I am very convinced of that. But the idea is more to share some basics and give an overview on one or the other aspect, not to provide ready to use code.

So feel free to join me learning ;-). I have posted here the sources I am using.


#4

i havent read the entire snippet, or the accompanying breakdown… but any code that has hugs stored as an array value, gets a :+1: in my book… :smiley:


#5

I noticed in the copy paste that the numbers for the Name of worker is wrong for each worker. Shouldn’t it be [1][1] , [2][1], [3][1] ?

Also I noticed that it’s returning the value of 9 for variable “found_name” in the print function. Shouldn’t this be displaying “Curly Howard”? I barely grasp the idea of this program and matrices though, so I could be wrong. :sweat_smile:


#6

@Avairian Thanks for making me aware. Don’t know where this happened… but sure, the numbering for the names is not right. Will just adjust it. For the other part I need to run the code and take another look.

Update: Seems like there have been some other numbers tossed around while I was pasting this code in. In case of doubt, take the screenshot, which shows the right code (and should work). I have adjusted the code now. Thanks once more.


#7

No problem. :smiley: Thank you for the little tutorial! Got a little debugging practice out of it too. :stuck_out_tongue:


#8

Exactly that was the reason for the errors and you did it! :wink:


#9

Hi.

If you need to retrieve an extermum several time, I suggest you use a sorted data structure.

Also, instead of returning the found_maximum and the name, you could return the index, allowing to retrieve any information. And handling the case where the table is empty:

function find_maximum(table)
    local m = nil
    for key, item in pairs(table) do
        if (m==nil or item[5]>table[m][5]) then
            m = key
        end
    end
    return m
end

Notable Forum Posts by Likes