A Beginner's Guide to TPT Lua

  • FeynmanLogomaker
    12th Oct 2013 Member 10 Permalink

                                                           Lua Logo
    You may be familiar with the Lua Console - press the tilde key (~) and it pops up.
    However, the Powder Toy implementation of Lua goes far beyond that; you can modify practically all the behavior of The Powder Toy with Lua.

    The first thing you need to know about Lua, though, is the syntax.


    The basic math operators are the same as any language:
    '+' to add, '-' to subtract, '*' to multiply, and '/' to divide.

    Assigning a Variable

    Assigning to a variable is also similar to most other mainstream languages:

    variable name = value

    Lua also allows you to give a variable local scope:

    local variable name = value

    Or, if you want to create a local variable but not assign a value to it, you can just type this:

    local variable name

    One minor feature of Lua is that it allows you to assign to multiple variables at the same time:

    var1, var2 = 1, 2

    That assigns the value 1 to var1 and the value 2 to var2.
    This isn't much use except for one thing: when you need to switch two variables. You can do that like so:

    var1, var2 = var2, var1

    Defining a function

    Functions allow you to remotely perform an operation in many different places of a program. They are especially useful if you need to perform a complex operation many times throughout a program.

    For example, compare the following instructions:

    Lay out bread
    Get out peanut butter
    Get out grape jelly
    Put peanut butter on one slice of bread
    Put grape jelly on the other slice

    to this:

    Make a peanut butter and jelly sandwich

    That is obviously not what an actual Lua function would look like, but it gets the point across: functions are good for making a complex task less complex.

    In Lua, you would define a function like so:

    function function name(argument, another_argument, etc)

    The arguments the function is called with can be accessed within the function, but not outside of it. For example, the following code:

    function printArg(num)

    would print the following:


    (In Lua, nil signifies a variable that has no value defined to it. You can also assign nil to a variable)

    You can also have a function return a value; that is, the function can be used to assign to any variable.

    For example this code:

    function returnArg(arg1, arg2)
        return arg1, arg2
    var1, var2 = returnArgs(1, 2)
    print(var1, var2)

    would print this:

    1    2

    Of course, that function itself isn't very useful, but you can use return to write much more useful functions.

    Working with Strings

    Lua has a fairly large string library, with just about everything you need to work with text. It goes far beyond simple creation of strings; you can edit them in almost every way imaginable.

    For starters, you can create a string just like in most other languages, by surrounding it with either single (') or double (") quotes, like so:

    string = 'Hello world'
    otherString = "Hello world"

    If you need to include any quotes inside your string, you can just use the other type of quotes, like so:

    string = 'a "quoted" string'
    otherString = "a 'quoted' string"

    Or, you can use backslash-escaped characters, which you may be familiar with if you use c or c++.
    To escape a quotation mark, you can use \' or \", like so:

    string = 'a \'quoted\' string'
    otherString = "a \"quoted\" string"

    Backslash-escaping can also be used to make other characters:

    \a: Makes the computer beep! Alas, it doesn't work in TPT.
    \b: Backspace*
    \f: Formfeed
    \n: New Line
    \r: Carriage Return (I have no clue what it does)
    \t: Tab, you can use this to format things into columns
    \v: Vertical tab*
    \\: Backslash
    \99: The character whose code is 99 (works for any number really)

    The ones marked by a * aren't useful or just don't do anything, you can ignore them.

    Fun fact: Strings that only contain a number can be treated as numbers - for example:

    print(1 + '2')

    displays this:


    String formatting is perhaps one of the most powerful features of Lua, allowing you to display data clearly, easily and fluently, and with more precision than a simple 'print'.

    The main way of formatting strings is through the aptly-named function string.format.
    To use string.format, you call it with the format string and the source string. For example, to surround a string with brackets and right-align it in  a 15-character-wide box, you would use this:

    print(string.format('[%15s]', 'Test string'))

    This would print the following:


    [    Test string]

    The most important format string is %s, which matches all of a string. There are others, such as %d (matches a number), but they won't be discussed here. You can find more information about format strings at http://www.lua.org/manual/5.1/manual.html, along with many other things.


    Except for file operations, this section does not apply to the TPT implementation of Lua, if you aren't planning to use Lua outside
    of TPT, skip this section!
    This part can, howe
    ver, be done with the Lua Standalone Interpreter - you can download the whole package at www.lua.org.

    NOTE: When you first open the Lua Interpreter, you will be presented with something like this:

    Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio

    Finally, you can control your programs from the outside!

    In Lua, input and output is done with the aptly-named 'io' library.


    The simplest user interaction can be done with io.read().

    When you type io.read() into the console, it gives you a blank line to type something in.
    When you press enter, it just goes back to the regular interpreter; it doesn't do anything really.

    However, you can also do something like this:

    var1 = io.read()

    It behaves exactly the same on the outside, but it also assigns whatever you typed to the variable var1.

    However, whatever you type in will be treated as a string: if you type in the number 1 when you do the previous example, var1 will not be 1, it actually will be '1'.

    However, you can do things with files themselves from the io library.

    File Operations

    The first step to working with a file is opening it, you do that with the io.open function.

    To use said function, you simply do this:

    file handle = io.open(file name, mode)

        The modes:

            'r': Read from the file
            'w': Write to the file and overwrite the previous version
            'a': Append to the file (add data on to the end of the file)

    For some reason, programmers traditionally use 'f' or 'file' as the file handle, but anything works.

    To write to a file once you've opened it, you can use the file handle:write function.
    You call it like so:

    f:write(numbers or strings)

    It works exactly the same as io.write, except that instead of writing to the screen, you can write to a file.


    You can also do output with the io library - it gives you much more fine-grained control of output than print does.

    The most basic output function (besides print) is io.write - it works exactly the same as f:write, except to stdin instead of to any specific file.
    Using io.write is simple; you just have to call it with whatever you want it to print as arguments. For example, this code:

    io.write('Hello world!')
    will display this:


    Hello world!

    However, there is one major feature that gives io.write an advantage over print - it doesn't force any formatting upon its arguments.
    For example, the command:

    print('Hello ' , 'world', '\n')

    would display this:

    Hello    world   

    whereas this command:

    io.write('Hello ', 'world', '\n')
    would display this:


    Hello world

    This can be useful when you are writing a prompt with io.read(), such as this:

    SomeVar = io.read()

    which would display 'Input>' without a newline.

    Working with Tables

     Tables are one of Lua's most flexible types of variable, and also one of the most useful. They are very commonly used for storing large amounts of data, but there are countless other uses.

    First though, you have to be able to create a table. To do so, you just use something like this:

    tblA = {}

    If you want a table to contain data in it on creation, there are several ways to do so.

    First - and simplest - is numerical indexing. With numerical indexing, all you need to do is have the values contained in the table. For example:

    tblA = {'string', 42, true, {1, 2}, function(k) print k end}

    The other type of indexing is explicit indexing, in which you assign values to a specific index. You would do that like this:

    tblA = {['string'] = 'Hello world!', [42] = 12345, [true] = false}

    To access any of the values in a table, you do something like this:

    val = tblA[1]

    An extra feature of explicit indexing is that you can access a string index of a table like so:

    val = tblA.string

    A table can actually contain any value, even a small table, as shown by the numerical indexing example. A common use of a table in a table is construction of 2-dimensional matrices, like this:

    matrixA = {
    {1, 2, 3, 4, 5}
    {2, 4, 6, 8, 10}
    {3, 6, 9, 12, 18}
    {4, 8, 16, 20, 24}
    {5, 10, 15, 20, 25}

    You can read such a table like this:

    val = matrixA[y][x]

    Also helpful is to get the length of a table; you would do that with the length operand, like this:

    tblA = {1, 2, 3, 4, 5}
    val = #tblA

    In that example, val would be 5 - the number of items in tblA.

    Also, Lua provides a way to loop through a table, called a generic for loop.
    The structure of a generic for loop is like so:

    for index, value in [pairs or ipairs](TableName) do

    In such a loop, the first value, here referred to as index, is assigned the current index in the table you are looping through, and the second value - value - is assigned the value at that index in TableName.

    The two types of iterators are ipairsand pairs - they are both similar, but ipairs only loops through integer indexes of the table, and pairs loops through all of them.

    As an example, take this code:

    tbl = {'one', 'two', 'three', 'four', 'five'}
    for i, v in ipairs(tbl) do
        print(i, v)

    This prints the following:

    1    one
    2    two
    3    three
    4    four
    5    five

    This is especially useful for when you need to loop through a table, but you don't know what all is in the table.

    Edited 16 times by FeynmanLogomaker. Last: 14th Oct 2013
  • Iridium616
    12th Oct 2013 Member 0 Permalink

    Neat. The huge logo is a bit too big.

  • edza101
    12th Oct 2013 Member 0 Permalink

    @FeynmanLogomaker (View Post)

     Huge logo is huge, but other than that nice tutorial. Maybe consider making a wiki article, or expanding current one?

  • FeynmanLogomaker
    12th Oct 2013 Member 0 Permalink

    Lol, I just looked at the logo compared to the rest of the text, it's HUGE! I'll have to fix that :)

  • Iridium616
    12th Oct 2013 Member 0 Permalink

    :-P told ya'

  • FeynmanLogomaker
    12th Oct 2013 Member 0 Permalink

    Yeah, now it's stuck with a crappy fuzzy image until I can get ahold of a better one :)

  • Iridium616
    12th Oct 2013 Member 0 Permalink

    Googling lua could find some good images. Or you could resize it manually

    EDIT: also I've commented on all first page topics, lol. Im that bored

    Edited once by Iridium616. Last: 12th Oct 2013
  • FeynmanLogomaker
    12th Oct 2013 Member 0 Permalink

    I actually used a Lua script to generate a better logo :D


    (Although somehow it's a bit blurred-ish)


    Edit: Yeah, I do that a lot too, when I'm bored I just go through the forum until I get sick of that, and then I go to xkcd - I've read every single xkcd comic there is)

    Edited once by FeynmanLogomaker. Last: 12th Oct 2013
  • MiningMarsh
    12th Oct 2013 Member 0 Permalink

    For people who don't feel like installing an interpreter (it can be kind of annoying outside of linux):


  • boxmein
    12th Oct 2013 Moderator 0 Permalink
    And please don't use spaces inside placeholder names if they're not surrounded with brackets of some sort.