Part III · Making It Solid
Chapter 14: Finishing the Project
Thirteen chapters ago, this program was one line: writeln("You are standing outside a locked cottage."). Everything since then, every
variable, every loop, every function, has been added because the story
needed it, not because it was next on a checklist. This chapter closes it
out, and takes stock of everything that got you here.
One Last Polish Pass
Two small touches, nothing new to learn, just tying off loose ends with
tools you already have. A short title banner at the very top, using
write() the way you first met it back in chapter 1:
write("=")
for i = 1 to 30
write("=")
end for
writeln("")
writeln("THE HOLLOW COTTAGE")
write("=")
for i = 1 to 30
write("=")
end for
writeln("")
writeln("")And a short farewell at the very end, after the final score:
writeln("")
writeln("Thanks for playing.")Small touches, but they're the difference between a program that just stops and a program that feels like it has a beginning and an end on purpose.
The Complete Program
// The Hollow Cottage
// Complete
write("=")
for i = 1 to 30
write("=")
end for
writeln("")
writeln("THE HOLLOW COTTAGE")
write("=")
for i = 1 to 30
write("=")
end for
writeln("")
writeln("")
const cottageName = "The Hollow Cottage"
var score = 0
function addScore(amount)
score = score + amount
writeln("(+" + amount + " points)")
end function
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 lower(trim(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("You step inside. In the corner sits a locked chest with a dial numbered 1 to 100.")
var secret = randomint(1, 100)
var guessesLeft = 6
var found = false
while guessesLeft > 0 and not found
var guess = empty
var validInput = false
while not validInput
attempt
guess = num(input("Turn the dial to a number (1-100): "))
validInput = true
error
writeln("That doesn't look like a number. Try again.")
end attempt
end while
guessesLeft = guessesLeft - 1
if guess == secret then
writeln("The chest clicks open!")
found = true
addScore(10)
sound("C4", 150)
sound("E4", 150)
sound("G4", 150)
else
sound("A3", 200)
var distance = abs(guess - secret)
match distance
when 0 to 5
writeln("Very warm. " + guessesLeft + " turns left.")
when 6 to 20
writeln("Warm. " + guessesLeft + " turns left.")
when else
writeln("Cold. " + guessesLeft + " turns left.")
end match
end if
end while
var inventory = array()
append(inventory, "rusty key")
append(inventory, "half-burned candle")
if not found then
writeln("The dial jams. The chest stays locked, for now.")
bell()
else
append(inventory, "small silver coin")
writeln("Inside, you find a small silver coin.")
showInventory(inventory)
end if
var command = input("What do you do? ")
var words = split(lower(trim(command)), " ")
var verb = words[0]
match verb
when "take"
showInventory(inventory)
when "look"
writeln("A small cottage, one room, one door out.")
when "quit"
when "exit"
writeln("You step back out into the cold.")
when else
writeln("Nothing happens.")
end match
end if
writeln("")
writeln("Final score: " + score)
writeln("")
writeln("Thanks for playing.")One change from the running checkpoints worth noticing: the riddle at the
door now uses lower(trim(answer)), the chapter 7 fix, instead of the
plain == it started with back in chapter 3. That's not an accident,
it's this book's whole approach in miniature, nothing gets left as it was
first written if a later chapter taught you a better way to write it.
A Tour of Everything You Used
Every chapter you worked through is sitting somewhere in that program:
- Chapter 1:
write(),writeln(), comments - Chapter 2:
var,const,input(), concatenation,num() - Chapter 3:
if,else, comparison operators - Chapter 4:
while, the riddle's attempt counter - Chapter 5:
array(),append(), indexing - Chapter 6:
showInventory()andaddScore(), both functions - Chapter 7:
lower(),trim(),split(), the command parser - Chapter 8:
randomint(),abs(), the chest puzzle - Chapter 9:
match, both in the hints and the command dispatch - Chapter 10:
attempt/error, guarding the dial input - Chapter 11: the global
score, updated from inside a function - Chapter 12:
sound()andbell(), the chest's chime and thud - Chapter 13: nothing here, and that was always fine
That's not a small list for something that started as one line of output.
What You Could Add Next
This book is finished, but your game doesn't have to be. A few directions worth trying entirely on your own, with tools you already have:
- A second room, reached after the chest, with its own description and its own commands
- An
if inventorycheck that changes an ending depending on what the player is carrying - A difficulty setting the player picks at the start, changing the number of riddle attempts or chest guesses
- A proper
helpcommand that lists everything the parser understands
Make It Yours, for the last time in this book, in the biggest sense of that phrase. Everything past this point is entirely your own game now.
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.
Start this chapter
Chapter 14 starting checkpoint.
Continue from here
Chapter 14 completed checkpoint.
Starting code: the Chapter 13 checkpoint.
Completed code (Chapter 14): the complete program above.
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.