Activity: Build an adventure game!

By Alison Cichowlas. Do this on pencilcode.net

In this activity we'll build an adventure game, where you can choose your own path through a story.

Here's an example of the type of game we'll build: The Cave of Time .

1. Writing

We'll need to write to the screen to tell our story and play our game. Try this:
write "Everyone loves turtles."
Put what you want to say in quotes.

When you're writing words instead of drawing, you might want to hide the turtle -- do ht for "hide turtle".

Sometimes you might also want to clear all the text you've written from the screen -- do cs for "clear screen" -- like when you go to a new page or place in your adventure.

You might also want to write a note to yourself that you can see when you look at your code... but that doesn't show up when you run the program. This is useful for writing down what you're doing, to remind yourself later! You can do this by putting a # at the beginning of the line -- that will make the computer ignore the rest of the line.
do ht
# Well... everyone *secretly* loves turtles.

2. Functions

When I want to remember how to do something, I might write myself a checklist. Like:

How to get ready for school:
  1. Get dressed
  2. Eat breakfast
  3. Brush teeth
Then every time I need to remember how to do that thing, I can go back and do all the steps on my list, and be sure I don't forget anything.

A function is a list of things for the computer to do. Once you've written the list, you can easily tell the computer to do the same thing again later. Use an arrow -> to say that you're going to write a function. (Type the arrow by using a minus sign and then an angle.) Then, put two spaces at the beginning of all the lines that will be in your function -- this groups the lines together inside the function.
get_ready_for_school = ->
  # indent two spaces to put the next lines on
  # the to-do list for this function
  write "Get dressed"
  write "Eat breakfast"
  write "Brush teeth"
# now stop indenting!
If you run that by itself (try it!) nothing will happen yet. Here's why: you've only written down what should be on the checklist -- and in order to actually do those things, you can:
do get_ready_for_school
Or to do it 5 times, once for each day of the week:
do get_ready_for_school
do get_ready_for_school
do get_ready_for_school
do get_ready_for_school
do get_ready_for_school

3. Menus

In order to play a game, we need a way for the computer to ask you what to do next and listen to the answer. We'll use menu so that you can pick from a list of options.

Just like for the function, we'll indent two spaces to show the group of lines that should be part of the menu.

If you want to learn about some other ways to do this, like clicking buttons or typing text, you can read about them here.
# Ask a question and print a response.
write "Is it a weekday?"
menu
  "Yes, it is!": -> write "time to get ready for school!"
  "No, it's not!": -> write "time to sleep in!"
    
We can even use this choice to decide which function to do:
# Write checklists for weekdays and weekends
get_ready_for_school = ->
  write "Get dressed"
  write "Eat breakfast"
  write "Brush teeth"
sleep_in = ->
  write "zzzzz"

# Ask which it is, and follow the right checklist
write "Is it a weekday?"
menu
  "Yes, it is!": get_ready_for_school
  "No, it's not!": sleep_in 

4. Where's my turtle?

Now you're ready to make an adventure game!

If you want, you can peek at the code for the game we looked at at the beginning of this activity. You now know enough to understand all of it!

Here's a very short game about turtles.
page1 = ->
  write "Help, I've lost my pet turtle! Can you help me find it?"
  menu
    "Go look inside the house": page2
    "Go look in the backyard": page3

page2 = ->
  do cs
  write "No turtles here! I guess they don't hang out inside."
  menu
    "Look outside instead": page3

page3 = ->
  do cs
  do st # Show turtle!
  write "Hey, it's my turtle! Thanks!"
  write "You win! Hurrah!"

do page1
All right! Go make a game!





Advanced adventures!

If you'd like to write a more complicated game, here are some ideas and tools you can use!

1. Picking things up

You're on a quest to find the long-lost Crown of the Elf Queen so that you can reunite the kingdom! The legend says that the Crown was hidden in the treasury of the Crystal Castle, but the treasury has been locked for years and nobody can enter without the key...

In an adventure, a player might need to find a special item to win, or to take the next step towards winning. How can you keep track of whether or not the player has found the Key and the Crown, and change what the game does then?

We'll make a variable to keep track of each special item. This just means that we'll give a name to something so that we can remember it later -- like when you save something you made on a computer, and then open it again later.
# magic_word is a variable.
# The magic word is abracadabra!
magic_word = "abracadabra"
write "What's the magic word?"
write magic_word
# A variable can vary (which means "change") --
# that's where the word variable comes from!
# Let's change it to something else!
magic_word = "freckles"
write "What's the magic word?"
write magic_word 
You can save whatever you like in a variable. We saved a word here, but next we'll use some special values, true and false. Because they're special, you don't need to put true and false in quotes like you do for regular words.

We'll use if to figure out what to do about the things we're remembering with variables. if does the next group of code when the variable next to it is true. It skips that group if the variable next to it is false.
# say_hello is a variable, set to the special value "false"
say_hello = false
if say_hello
  # Indent 2 spaces, just like for functions and menus.
  # The next line won't happen because write_hello is set
  # to "false" (which means "no")
  write "hello, world!"
# write_something is a variable, set to the special value "false"
say_goodbye = true
if say_goodbye
  # This one will happen, because say_goodbye is set
  # to "true" (which means "yes")
  write "goodbye!" 
Using these two things, we can remember when you find the Key -- then later, we can check whether you already found the key, and then let you open the door.
# This is a variable! You can name variables whatever you like.
found_the_key = false
under_the_hidden_tree = ->
  do cs
  write "Finally, after a long walk in the forest, you "
  write "find yourself under an old, mossy oak tree."
  write "The sunlight glimmers against something "
  write "hidden in its gnarled roots..."
  menu
    "Look closer at the roots": tree_roots
    "Return to the castle": castle

tree_roots = ->
  do cs
  write "You dig among the roots with your fingers and find an old key."
  write "It's dirty and rusty, but it looks like it would still work."
  # Here's where we make sure to remember you found the key!
  found_the_key = true
  menu
    "Go back to the castle": castle

castle = ->
  do cs
  write "You walk to the castle and go inside to "
  write "look at the treasury door."
  # If you found the key, then you get to unlock the door.
  if found_the_key
    menu
      "Unlock the door": treasure_room
  # If you haven't found it yet...
  if not found_the_key
    write "If only you had the key, you might be able to save the kingdom..."
    menu "Search for the key": under_the_hidden_tree

treasure_room = ->
  write "The key fits! You open the door, and among "
  write "the treasure you see a Crown..."

# Start the game
do castle

2. People

You've arrived at the city in the desert! But in order to pass the guardian at the gate, you must first answer her riddle...

What if you want to talk to people in your game? Well, the choices in a menu don't need to be just places. You can use them to move through a conversation, too.

If you want to put a quotation mark inside your text, you need to "escape" the quotation mark. Do this by putting a backslash, \, in front of the quote -- that tells the computer to write out the quote instead of treating it like it means the end of the text. Be careful to use a backslash and not a slash (/), which goes the other direction.
sphinx_start = ->
  do cs
  write "You've found the Sphinx! "
  write "A huge lion with the head of a person, she looks at you and growls:"
  write "\"You can only pass if you can answer my riddle. Do you want to hear it?\""
  menu
    "Say \"Yes, tell me!\"": sphinx_riddle
    "Run away!": run_away

sphinx_riddle = ->
  write "She asks: \"What creature has one voice, but first walks on four feet, then"
  write "on two feet, and finally on three feet?\""
  write "Hmmm....."
  menu
    "Say \"The answer is a caterpillar!\"": sphinx_wrong
    "Say \"The answer is the Nile River!\"": sphinx_wrong
    "Say \"The answer is a person!\"": sphinx_right
    "Say \"The answer is nothing!\"": sphinx_wrong

sphinx_right = ->
  write "The sphinx frowns and replies: "
  write "\"Yes. A person walks on four feet when they crawl as a baby, "
  write "then on two as an adult,"
  write "and finally on three when they are old and walk with a cane. "
  write "But how did you know...? "
  write "Very well, you may enter.\" "

sphinx_wrong = ->
  write "The sphinx frowns and replies:"
  write "\"No, that is wrong. You may not enter the city.\""
  menu
    "Say \"Wait, wait, let me try again!\"": sphinx_riddle
    "Run away": run_away

run_away = ->
  write "You flee!"

# Start the game
do sphinx_start

3. Mazes and maps

You are in a maze of twisty little passages, all alike...

If you've added a lot of places to your game, then you might want to come up with a way to keep track of them all. That way, you can check to make sure people won't get stuck -- unless you want them to! (Putting in a maze is a good way to make your game harder on purpose!)

Just like in real life, a good way to plan out your game is to draw a map. You might want to start with pictures that show the idea in your head, and then figure out how that corresponds to functions and menus for your game. For example, here's a picture for the turtle game:



Thinking about that picture, I decided that I needed to write three functions -- one for inside, one for outside, and one for when you start (even though that's not really a place). Then in each place, I thought about where you should be able to go to, and that helped me decide what should go in each menu.

Here's the map of all my functions and menus for the turtle game. In this picture, every circle stands for a function, and every arrow stands for a choice in a menu. (Following the arrows is like choosing a menu option!)



For the turtle game, we would be okay without a map since it isn't very complicated. But if the game were more complex -- say, you had more rooms inside the house, and a backyard and a front yard -- then a map is useful! Here's how we might plan out a bigger turtle hunt:



You can see by the "???" that I haven't decided yet what happens when you go upstairs!

How many different places are there in the diagram? Which places are hardest to get to?