Part II · Growing the Project
Chapter 7: Words and Text
Go back and try something with your chapter 3 riddle: answer with "Piano"
instead of "piano", capital P. It fails. Try "piano " with a trailing
space, maybe left over from how you typed it. It fails too. Your player
knew the right answer both times, and the game told them they were wrong.
That's not a puzzle being clever, that's a bug. This chapter gives you the
tools to fix it, and to start actually understanding what the player
typed instead of just checking it letter for letter.
The Problem With ==
You already know == compares strings exactly, case and all. That's
correct behavior, it's just not always the behavior you want. A human
typing "Piano" means the same thing as "piano." Your program needs to be
told that on purpose.
upper and lower
upper() and lower() convert a string's case:
writeln(upper("piano")) // PIANO
writeln(lower("PIANO")) // pianoThe fix for the riddle check is to force both sides to the same case before comparing:
if lower(answer) == "piano" then
writeln("The door swings open.")
end ifNow "Piano", "PIANO", and "piano" all match.
trim
trim() removes whitespace from the start and end of a string, but
leaves anything in the middle alone.
writeln(trim(" piano ")) // "piano"Combine it with lower(), and the riddle check stops caring about
capitalization or stray spaces from typing:
if lower(trim(answer)) == "piano" then
writeln("The door swings open.")
end ifThat single line is the fix for both bugs you found a minute ago.
contains, startswith, and endswith
These three let you check for a piece of text without needing an exact, whole-string match:
contains("The rusty key", "key") // TRUE
startswith("take candle", "take") // TRUE
endswith("half-burned candle", "candle") // TRUEAll three are case-sensitive, so pair them with lower() the same way
you just did for the riddle, whenever the player's exact capitalization
shouldn't matter.
split
split() breaks a string into an array of pieces, wherever a delimiter
you choose shows up.
var words = split("take candle", " ")
writeln(words[0]) // take
writeln(words[1]) // candleThis is exactly what turns a typed sentence into something your code can actually reason about, a verb and a target, instead of one long string.
substring and replace
Two more worth knowing, used less often but useful when you need them.
substring() pulls out part of a string by position:
writeln(substring("cottage", 0, 3)) // cotreplace() swaps out every occurrence of one piece of text for another:
writeln(replace("the old door", "old", "new")) // the new doorGrowing the Adventure
Time to give the player real commands instead of yes/no answers.
// The Hollow Cottage
// Chapter 7
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 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("The cottage is dusty but intact.")
var inventory = array()
append(inventory, "rusty key")
append(inventory, "half-burned candle")
writeln("On the floor, you notice a rusty key and a half-burned candle.")
var command = input("What do you do? ")
var words = split(lower(trim(command)), " ")
var verb = words[0]
if verb == "take" then
showInventory(inventory)
else if verb == "look" then
writeln("A small cottage, one room, one door out.")
else
writeln("Nothing happens.")
end if
end ifMake It Yours. Add a third command your parser understands, "inventory",
"help", whatever fits your game, and give it its own else if branch.
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 7 starting checkpoint.
Continue from here
Chapter 7 completed checkpoint.
Starting code: the Chapter 6 checkpoint.
Completed code (Chapter 7):
// The Hollow Cottage
// Chapter 7
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 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("The cottage is dusty but intact.")
var inventory = array()
append(inventory, "rusty key")
append(inventory, "half-burned candle")
writeln("On the floor, you notice a rusty key and a half-burned candle.")
var command = input("What do you do? ")
var words = split(lower(trim(command)), " ")
var verb = words[0]
if verb == "take" then
showInventory(inventory)
else if verb == "look" then
writeln("A small cottage, one room, one door out.")
else
writeln("Nothing happens.")
end if
end ifCopyright © 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.