Part II · Growing the Project

Chapter 6: Organizing Your Code

Your program is five chapters long now, and it's all still one long list of statements running top to bottom. That's worked fine so far, but imagine adding a second room, then a third. Printing an inventory list is already something you'd want to do more than once, and copying that same for each block everywhere it's needed is exactly the kind of thing that gets messy fast. Functions are how you give a piece of code a name and reuse it wherever you need it.

Declaring a Function

A function is a named, reusable block of code.

QF Code example 1
function showHeader()
    writeln("=== The Hollow Cottage ===")
end function

Once it's declared, you call it by name, with parentheses, every time:

QF Code example 2
showHeader()

Parentheses are required even when a function takes nothing, an empty () is how QF Code knows you mean "call this" rather than just mentioning its name.

Parameters and Arguments

Most useful functions take input. Parameters are the names a function expects, arguments are the actual values you hand it when you call it.

QF Code example 3
function greet(name)
    writeln("Welcome, " + name + ".")
end function

greet("Alice")
greet(playerName)

The number of arguments you pass must exactly match the number of parameters the function declares, no more, no fewer. Inside the function, a parameter behaves just like a regular local variable, you can read it, and you can reassign it, without affecting whatever was passed in from outside.

Returning a Value

Some functions don't just do something, they hand something back. That's what return is for.

QF Code example 4
function double(value)
    return value * 2
end function

var result = double(21)
writeln(result)   // 42

If a function reaches end function without ever hitting a return, it hands back empty automatically, not an error, just nothing useful. If you're expecting a value from a function and getting empty instead, the first thing to check is whether every path through that function actually returns something.

A Note on Scope

A function can read global variables, the ones declared at the top level of your program, but it cannot see local variables belonging to whoever called it. Each call gets its own private workspace.

QF Code example 5
var cottageName = "The Hollow Cottage"

function announce()
    writeln("Welcome to " + cottageName + ".")   // fine, cottageName is global
end function

One honest limitation worth knowing now, not discovering the hard way later: QF Code 1.1 doesn't support closures. A function can't reach back into another function's local variables just because it happens to be defined nearby. If a function needs a value, the cleanest way to give it one is to pass it as a parameter.

Hoisting: Calling Before Declaring

QF Code registers every top-level function before your program actually starts running. That means you're free to call a function above the point where it's declared in the file:

QF Code example 6
greet("Alice")

function greet(name)
    writeln("Welcome, " + name + ".")
end function

That runs just fine. It's worth knowing this exists, but it's also fine to just declare functions before you use them, the way this book will, since that's usually easier to follow when you're reading your own code later.

Growing the Adventure

Time to pull the repeated inventory-printing logic out into its own function.

QF Code example 7
// The Hollow Cottage
// Chapter 6


const cottageName = "The Hollow Cottage"

function showInventory(items)
    writeln("You are carrying:")
    for each item in items
        writeln("- " + item)
    end for
end function

writeln("You are standing outside " + cottageName + ".")

var playerName = input("What is your name, traveler? ")
writeln("Welcome, " + playerName + ".")

var tries = 0
var solved = false

while tries < 3 and not solved
    tries = tries + 1
    var answer = input("There is a riddle carved into the door. It asks: what has keys but no locks? ")

    if answer == "piano" then
        writeln("The door swings open. You step inside.")
        solved = true
    else
        writeln("Nothing happens.")
    end if
end while

if not solved then
    writeln("The door refuses to budge. You'll have to find another way in.")
else
    writeln("The cottage is dusty but intact.")

    var inventory = array()
    append(inventory, "rusty key")
    append(inventory, "half-burned candle")

    writeln("On the floor, you notice:")
    showInventory(inventory)

    writeln("You pick up both items.")
end if

Nothing about what the player sees has changed. What's changed is that showInventory can now be called again, anywhere, anytime you want to show the player what they're carrying, without retyping the loop.

Make It Yours. Write one more function of your own, something that takes a parameter and does something with it, a function that describes a room, announces a sound effect, or checks whether an item is in the inventory. It doesn't need a return value yet if you don't want one.

Chapter Checkpoint

Open either known-good checkpoint directly in QF Code, or download the .qfc file to keep locally. The IDE opens in a new tab and does not run the program automatically.

Starting code: the Chapter 5 checkpoint.

Completed code (Chapter 6):

QF Code example 8Open in QF Code
// The Hollow Cottage
// Chapter 6


const cottageName = "The Hollow Cottage"

function showInventory(items)
    writeln("You are carrying:")
    for each item in items
        writeln("- " + item)
    end for
end function

writeln("You are standing outside " + cottageName + ".")

var playerName = input("What is your name, traveler? ")
writeln("Welcome, " + playerName + ".")

var tries = 0
var solved = false

while tries < 3 and not solved
    tries = tries + 1
    var answer = input("There is a riddle carved into the door. It asks: what has keys but no locks? ")

    if answer == "piano" then
        writeln("The door swings open. You step inside.")
        solved = true
    else
        writeln("Nothing happens.")
    end if
end while

if not solved then
    writeln("The door refuses to budge. You'll have to find another way in.")
else
    writeln("The cottage is dusty but intact.")

    var inventory = array()
    append(inventory, "rusty key")
    append(inventory, "half-burned candle")

    writeln("On the floor, you notice:")
    showInventory(inventory)

    writeln("You pick up both items.")
end if

Next: your candle and key are just strings right now. Chapter 7 teaches you to work with the text itself, so your game can actually understand what the player types instead of just checking it word for word.


Copyright © 2026 Edison Mooers. Published by Gibidda Press. Free for personal learning and qualifying noncommercial educational use. Commercial training, organizational use, redistribution, and adaptation require written permission. Full use terms.