July 25, 2020

👭 Knight Challenge #11 👬

Want to try your hand at these challenges? There's a couple of things you can do!
From writing, to research, to images, find your preferred way to contribute with our eleventh theme: Couples!

Latest Announcements


From Zelda Wiki, the Zelda encyclopedia
Jump to: navigation, search
ZW Logo White.png
Getting Involved Getting Involved.png
Getting Involved
[1] Discord Logo.svg
Knight Challenges Knight Challenges Icon.png
Knight Challenges
Image edit request and support center Gimp Logo.svg
Image Requests
[2] Trello Logo.png
Guidelines:Main Guidelines Icon.png

This article or section is under construction.
This article or section is currently under construction.

Its finished form will be up momentarily. Zelda Wiki apologizes for any informational setback.

The following exercises are designed to help editors learn to make contributions in the Module namespace. The only prerequisite is an understanding of how templates are used.

The exercises have assigned readings from Programming in Lua. The readings explain the concepts covered in the exercise. Read them once before starting the exercise and refer back to them if you get stuck.

If you have any questions or feedback about these exercises, please bring them to the #modules channel on Discord.

Getting Started



  1. Create the page User: with the following contents:
    {{Sandbox/|Hello world!}}
  2. Create the page Template:Sandbox/ with the following contents:
  3. Create the page Module:Sandbox/ with the following contents, but don't save the page yet. (If you did accidentally, just go back to edit mode afterward.)
    local p = {}
    function p.Main(frame)
        return p.main(frame:getParent().args)
    function p.main(args)
        local msg = args[1]
        return msg
    return p
  4. In the Preview page with this form beneath the main text area, input User: in the Page title field and click Show preview. This displays the page as it would appear if you were to save the module changes. You should see the following text on the previewed page:
    Hello world!
  5. Scroll past the edit form to the black and green Debug console. In the text field, type the following, then press the Enter key.
    p.main({"Kooloo Limpah"})
    You should see the text Kooloo Limpah appear in the console.
  6. Save the module page.


This exercise covered:

  • How articles use modules.
Your sandbox page uses a template but has no notion of modules per se. The template uses the #invoke parser function to invoke the function Main on your module. The process is the same for real modules. The Link page uses Template:Term which invokes a function on Module:Term.
  • How modules use template arguments.
Your sandbox page passes the argument Hello world to the template. The module retrieves that argument from the frame object. (More on that later.)
  • How to make sure your module works before saving.
The preview form and the debug console are the two main tools for debugging modules. Never submit code blindly.

Game Links 1

The goal of this exercise is to recreate the functionality of game link templates using Lua.



  1. Replace the content of your user sandbox with five invocations, each time with a different canon Zelda game of your choosing. Like so:
    {{Sandbox/|Breath of the Wild}}
    {{Sandbox/|The Wind Waker}}
    {{Sandbox/|Majora's Mask}}
    {{Sandbox/|Spirit Tracks}}
    {{Sandbox/|Oracle of Ages}}
    The page should now display, for example,
    Breath of the Wild The Wind Waker Majora's Mask Spirit Tracks Oracle of Ages
  2. In your module, put mw.logObject(msg) on line 9. Your main function should look like this:
    function p.main(args)
    	local msg = args[1]
    	return msg

    Preview your user sandbox with these changes. Scroll past the edit box to the very bottom of the page until you see the section Parser profiling data (it may be collapsed by default). At the bottom of that table, uncollapse the the Lua logs section. You should see the following:

    "Breath of the Wild"
    "The Wind Waker"
    "Majora's Mask"
    "Spirit Tracks"
    "Oracle of Ages"
    mw.logObject allows you to inspect the value assigned to a variable for a given invocation. In this case, each of the five times your module was invoked when loading the preview, the value assigned to the variable msg was printed in the logs. They are shown in quotes because they are values of type string.
  3. Move the mw.logObject(msg) call to just before the return p line, outside of the main block, and preview the page again:
    function p.main(args)
    return p

    You should the following logs:

    nil represents the absence of a value. Because msg is declared as a local variable in the main function, it is lexically scoped to that function and has no value outside it. In other words, only the main function "knows" that the variable exists. Main could declare its own msg variable and it would be considered completely different. Likewise, the variable p in our module is unrelated to the p in any other module.
  4. Leave the edit form without saving. mw.logObject is meant for debugging only and should not be left on a module.


  1. Using concatenation, change the return value to a string like "* game" so that your user sandbox looks like so:
    • Breath of the Wild
    • The Wind Waker
    • Majora's Mask
    • Spirit Tracks
    • Oracle of Ages
  2. Change the return value to a string like * ''game'', so that your user sandbox looks like so:
    • Breath of the Wild
    • The Wind Waker
    • Majora's Mask
    • Spirit Tracks
    • Oracle of Ages
  3. Change the return value to a string like * [[The Legend of Zelda: game|''game'']]. The output should be like:
  4. Add The Adventure of Link (if you haven't already) or some other game whose full title doesn't start with The Legend of Zelda:. Use an if statement to ensure the proper link is returned for that game:
  5. Bonus: Rewrite the function to use string.format instead of concatenation.


This exercise covered:

  • Variables and lexical scope.
Local variables only have meaning in the block (function, if statement, for loop, etc.) or chunk (module) in which they are declared. Attempting to use one outside its scope produces nil. This is a good thing, as it prevents other parts of the code from changing data unintentionally.
Global variables are almost always a bad idea.
  • Data types.
The data types relevant to Scribunto are nil, boolean, string, number, table, and function. At a given point in time, a variable will have any one of these types. A variable's type can change when it it is re-assigned—Lua is a dynamically typed language like JavaScript or Python, as opposed to a statically typed one like C or Java.
  • String manipulation
Most modules boil down to being string manipulators. They take as input some string(s) and output some other string (usually wikitext).
  • Control flow
This exercise involved using if statements with the relational operator ==. There are other relational operators such as ~= and <, as well as the logical operators and, or, and not.


Main article: Module:Exercises

There are many ways to arrive at solutions that work, but some are better than others in terms of programming style. When writing real modules, take the time to think about what you can do to make the code easier to understand for the next person who has to read it or change it.

Quote1.png Programs must be written for people to read, and only incidentally for machines to execute. Quote2.png
— Gerald Jay Sussman and Hal Abelson, Structure and Interpretation of Computer Programs