A Guide To Adventuron PDF
A Guide To Adventuron PDF
A Guide To Adventuron
Chris Ainsley
Table of Contents
1. Introduction
1.1. Adventuron
1.2. Lesson Structure
1.3. About Text Adventures
1.4. About Excalibur
2. Tutorial
2.1. The Game Design
2.2. Story
2.3. Locations
2.4. Map
2.5. Part 1 (Outside The Castle)
2.6. Part 2 (Inside The Castle)
2.7. Reading The Maps
2.8. Up and Down
2.9. Puzzles
2.10. Objects
2.11. Objects & Scenery
3. Using The Keyboard
3.1. Coding And The Keyboard
3.2. Moving The Cursor
3.3. Selecting Text
3.4. Selecting text with the cursor keys, holding the SHIFT key
3.5. Selecting text, by holding left mouse button then moving mouse
3.6. Deleting Text
3.7. Deleting Text
3.8. Select All, Cut,Copy & Paste
3.9. The Control / Command Button
3.10. Information For Apple Computer Users
3.11. Select All
3.12. Copy Paste
3.13. Cut Paste
3.14. Undo
3.15. Saving
3.16. Saving
3.17. Privacy Modes & Save Files
3.18. Other Keys
3.19. Page Up & Page Down
3.20. Redo (Control + Y)
3.21. Finding Text (Control + F)
3.22. Underscore (_)
3.23. Colon (:)
3.24. Double Quote (")
1. Introduction
Adventuron Classroom a fun way to learn to code for kids aged 8 - 12, working with a trusted adult.
1.1. Adventuron
Classroom first introduces "adventure" games then demonstrates how to build such a game.
Games made with Classroom are playable on PCs, tablets, mobile phones, and more.
A text adventure game is a type of game in which the player types (or speaks) commands to the computer and
the computer tells you the result of your command.
Text adventures can be pure text, or they might have graphics too to show the player where they are in the
fantasy world.
The adventure game we will use as the focus of the coding portion of the lessons is "Excalibur: Sword of Kings".
Excalibur: Sword of Kings, was written in 1987, by Ian Smith & Shaun McClure.
Excalibur, Sword of Kings is copyright of Adventuron Software Limited, all rights reserved.
2. Tutorial
2.1. The Game Design
There are five things to think about when creating a simple text adventure game.
2.1.1. 1 - Story
Most adventure games revolve around a goal, and some reason for trying to achieve the goal.
The story may be very complicated, almost like a book, or it could be very simple, such as in Excalibur.
2.1.2. 2 - Locations
Locations are places that the player can be inside the game.
Each location has its own sentences to describe itself, and in Excalibur, every location has a picture (graphic).
2.1.3. 3 - Map
The map of a game that describes how the locations are connected together.
2.1.4. 4 - Objects
A game usually has a series of things in it (or objects). A thing can be an object like an apple, or a thing might
even be a person. Adventuron calls all these things "objects".
The player can take objects, drop object, and use objects. The game remembers what the player has, and where
every object is, even if the player doesn’t have it yet.
2.1.5. 5 - Puzzles
The puzzles of a game describe things that must be solved to make progress in a game.
Usually a part of the game is blocked until a puzzle is solved, then after the player is allowed in the new part of
the game, new puzzles are revealed.
2.2. Story
The story of Excalibur: Sword of Kings, is that Arthur has been taken prisoner by the evil sorceress Crania and
it’s up to you, a knight of the round table, to find Excalibur, defeat the sorceress, and rescue King Arthur.
2.3. Locations
3. Camelot Castle.
Excalibur also shows the player a simple picture (like the one at the top of this section) when describing the
location to the player.
We will learn how to add graphics in this course, but not how to draw them.
You can double click in the documentation panel to make the documentation full screen, you can double
click again to minimise back to just showing in the left hand column.
Here is a list of all the locations (and the graphics we will add to the game later):
(Locations with two images are places where the contents of the location can change due to solving a puzzle)
salt mine 3 You are at the end of the mine. You can
hear the drip of water.
2.4. Map
A map is a drawing that shows locations in the game, and how they are connected together.
A map can be drawn as one big drawing, or may be split up into different pieces.
Here is how to read the map, using the compass directions as our guide:
2.9. Puzzles
2.9.1. Puzzles
Excalibur is a short game with just 13 puzzles, most easy to solve. The fun of the adventure is exploring, seeing
new graphics, and working out how to solve puzzles.
Not all the answers are obvious. Each object will give a clue if the player types "examine xxxxx" where xxxxx is
the name of something.
This adventure is simple for the purpose of the tutorial, and usually (puzzle type) text adventure games have
many more puzzles than this one.
It is strongly recommended that you play the game before you read onwards, as spoilers for all the puzzles will
follow. The link below has a built in tutorial to help you understand how to play the game.
Puzzle Description
Climbing The Tree The player will encounter a tree that has no branches and cannot be climbed.
The player needs to collect the ladder from the start location, and type lean
ladder or stand ladder at the base of the tree, and then the player can navigate
"up" to reach the stone room inside the top of the tree.
Crossing The Chasm The player encounters a gorge. The gorge has a tightrope, but it looks dangerous.
If the player types "cross gorge" then they will fall and the game will end.
To solve the puzzle the player must break ladder to make a pole, and then once
the player is holding the pole, type cross chasm, and the game will inform the
player that they use the pole to balance, and they can make their way across the
gorge and into the forest.
If the player breaks the ladder before climbing the tree, then the game is not
winnable.
Treasure In The Forest In the forest, the player must examine (or search) two items in the forest. e
xamine logs will find an axe, and examine bush will find the stone key.
Crossing The Chasm Making sure they are still holding the pole (from the broken ladder), the player
Again must type cross chasm again to return to the road network.
Getting Past the Demon The player must type attack knight (or similar), when holding the short sword
Knight in order to defeat the knight in battle.
The knight was blocking the road to camelot, so if the player didn’t solve the tree
puzzle, and the knight puzzle, then the player cannot reach the entrance of
Camelot.
Opening The Gate At the front gate of camelot, whilst holding the stone key, the player must type
unlock door, then open door. This will allow the player to enter camelot.
Buying The Lamp Inside the castle there is a coin, and the coin must be picked up, and the player
must go back outside the castle to buy lamp from the old woman that is selling
lamps.
Whilst holding the axe, the player should type smash trapdoor or break
trapdoor and the trapdoor will be replaced with a broken trapdoor message,
and the player should be able to type "down" to enter the salt mines (beneath
the castle).
The Rockworm Inside the salt mines, there is a creature called a rockworm, which is blocking
the way further into the mines. If the player tries to go past the room, the player
will be attacked and the game will end.
To remove the rockworm, light lamp. Once past the rockworm, go further into
the mines and take the salt. Some string is also in the mines, but it serves no
purpose.
Getting Past The Ice In another part of the castle, there is an ice creature, blocking a doorway. throw
Creature salt at ice creature to melt it.
Once past the rock creature, get oil, and get excalibur (the legendary sword)
from the armoury room.
Opening The Portcullis There is one part of the castle that is blocked now, it is a room with a closed
portcullis (gate). We should now be holding the oil and excalibur. Inside the
winch room, there is a winch but it is rusty.
Type oil winch, then type turn winch, doing so will raise the portcullis (open
the gate).
The Sorceress In the room on the other side of the portcullis we see the sorceress Crania, and
she has cast a spell at the player.
If the player is holding excalibur, they should type reflect spell or deflect spell
and it will bounce the spell using excalibur and make the sorceress vanish.
King Arthur Now we have access to one more room of the castle, and in this room, King
Arthur is prisoner, and is asleep. Type wake arthur, and the game is won.
2.10. Objects
Any items of interest in the game is referred to as an "object", even people. Usually, players can pick up objects,
but some "objects" are marked as immovable, and cannot be collected.
ladder a ladder hut Used to climb tree (by leaning it), then
must be broken to create a pole with
which to cross the chasm.
oil can of oil cold_room Used to oil the winch, so it can be turned
to open the portcullis.
old_woman an old woman lamp_seller_on_road Disappears after buying lamp with coin.
selling lamps
rockworm a Rockworm, worm_room Blocks the path further into the salt
guarding the south mines. Must be scared away by lighting
tunnel lamp.
ice_creature an Ice Creature, cold_room Blocks the entrance to the winch room
guarding the north and armoury, must be melted by
exit throwing ice at it. When melted, ice
creature is removed from the game.
asleep_arthur King Arthur arthur (arthur is the Arthur must be woken to win the game.
(asleep) room identifier)
You can skip the chapter by clicking the up arrow above this text, and then just scroll down to the next chapter
in the lesson list.
Adventuron is a code based system and requires that game-makers are able to use a keyboard and mouse /
touchpad.
If it’s your first time to type a large document on a keyboard, don’t worry - practise makes perfect
Step 1 - Select "Keyboard Practise" from the menu at the bottom right of the middle panel (the editor window).
Make sure there is a tick next to the "Keyboard Practise" menu option.
Step 2 - Click inside the text editor window you the left mouse button.
Step 3 - After selected the keyboard practise mode, type in the following text:
If you have never used a keyboard before this might be hard at first, so ask an adult for help in finding the
right buttons to press if you get lost.
3.4. Selecting text with the cursor keys, holding the SHIFT key
Holding the SHIFT button whist tapping a cursor will "select" text (light it up).
The SHIFT key is the key to the left of the "Z" key on the keyboard.
3.5. Selecting text, by holding left mouse button then moving mouse
We can also select text by moving the mouse to the start of an area, holding the left mouse button, moving it
until the text is selected then letting go.
The backspace button is usually above the ENTER button and next to the + and - buttons. The image above
shows the key on a typical keyboard.
If we press the BACKSPACE button when text is selected, all the text we selected will disappear.
Then press CONTROL and V to place the copy of the deleted text that was copied where the cursor is. Cut and
paste is extremely useful for moving text around quickly.
3.14. Undo
Hold the CONTROL button and then tap the Z button to undo the last action you performed, this can work
more than once. This is very handy if you press something wrong, or type something wrong. Remember, it’s
very normal to get things wrong, in fact, that’s the reason that undo is there.
3.15. Saving
3.16. Saving
There are two ways to save in Adventuron.
2. Or you can click the play icon (picture) on the top bar. It looks like a triangle pointing right.
If you can’t remember all of these it’s OK. You will reminded when and how you can save.
If you use Adventuron Classroom in 'incognito' or private browsing mode, then your work will be lost when
you close the Window as nothing is currently stored on the Adventuron website server.
We can use the PAGE UP and PAGE DOWN buttons to move the cursor up and down the screen, very quickly.
The mouse wheel can also be used to page up and page down.
The underscore character is used a lot in Adventuron. To type it, you need to press the button to the right of the
'0' key on the keyboard, whilst pressing SHIFT.
The colon character is used a lot in adventuron. To type it, you need to press the button to the right of the 'L'
key on the keyboard, whilst pressing SHIFT.
"
The double quote character is used a lot in adventuron. To type it, you need look at your keyboard for where it
is, and press it whilst pressing SHIFT. (this key in a different place depening on your keyboard type).
There are more advanced things you can do with the keyboard, and they are all very fun, but that’s enough for
now.
Here are the characters that require the shift button on a British keyboard.
4. Starting To Code
4.1. Getting Started With Autocompletion
Before we can start to code, we need to clear the editor window of all text and switch off keyboard practise
mode (if it is enabled).
To do this, click the "Menu" button, and select "Start Coding (Clear All Text)" option.
In Adventuron the ID is the part of a line of code BEFORE the : letter. The DESCRIPTION is surrounded by the
double-quote " characters.
We will change the first location to have an ID of hut, type in the description of the first location, and set the
start location of the game to the id of the hut location.
It doesn’t do much yet, but Adventuron is at least describing our first location.
Code so far …
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the north." ;
########################################
# Connections #
########################################
connections {
from, direction, to = [
########################################
# Objects #
########################################
objects {
Adventuron automatically knows that if road 1 is north of the hut, that the hut is south of road 1, so you don’t
need to create connections in each direction.
Placing your cursor on a blank line in the middle the connections block, and press CONTROL + SPACE.
The first item to be suggested will be a location identifier. This is the from location.
Select "hut" as the from location, by using the cursor (arrow) keys on the keyboard, then press the ENTER
button. You can move up or down the selected options with the CURSOR KEYS, or you can use the mouse to
click the option you want.
After you select hut, Adventuron will write "hut," (hut followed by comma).
The middle section header colour will be red and read "Attention required on line xx" (xx is a number),
because connections require 3 items per line.
Until we add all three items on a line, Adventuron will not be very happy. It likes everything to be very tidy.
Next, press CONTROL + SPACE again. This is now the direction column, again use the cursor (arrow) keys to
select NORTH, then press the ENTER button.
The line should now read "hut, north, " and your cursor (the flashy part) should be at the end of the line.
The window should be reporting there is a validation problem. This is because it is waiting for the 3rd entry on
the line. The third entry should be the "road_1".
Press "r" then press CONTROL + SPACE, and we will be presented with an option for road_1 and road_2.
Typing the first few letters of something you are looking for before pressing CONTROL + SPACE will only show
options containing the letters you typed. Typing the first few letters of things you know about can really speed
up AUTOCOMPLETION.
Now use the right hand side of the screen to explore these three locations. Adventuron will display the
connections between our locations.
South is the opposite direction as north, so we can type "n" (short for north) to move up the map, and "s" (short
for south) to move down the map.
If we try to go in a direction without a connection, Adventuron will tell inform us that we cannot go that way.
We can also click on the directions with a mouse click to go in that direction.
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the north." ;
road_1 : location "You are standing on a track. The hut is south." ;
road_2 : location "You are where the road turns eastwards. You see small hills in the distance." ;
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
]
########################################
# Objects #
########################################
objects {
In Adventuron, objects are a type of things that exists in the game world.
The first object in the game, in the first location (the hut) in fact, is the ladder.
Adventuron supports different types of objects, but the ladder is just a normal type of object (can be picked up
and put down), so we create it as an object.
To create the ladder object, we move the cursor (using the mouse or the cursor keys) to an empty line inside
the objects {} code block.
We then press CONTROL + SPACE, and just like creating a new location, we type the name of the object id (or
nickname), then we press the TAB button (usually left of the letter Q) to move to the area between the " letters,
then type the description of the object.
Articles
The part between the '"' characters, is usually prefixed by the "article" which is a word like "the" or "some" or
"a" or "an".
If you don’t know what an article is, or which one to use, ask a teacher or a trusted grown up.
If you don’t know what to do, just write the name of the object by itself.
Now we have defined what a ladder is, but we need to place the ladder in the hut.
We want to put the ladder in the hut, so we need to find a bit of space in the objects line. The place where you
find space is usually before the ";" character.
Move your cursor just before the ";" character, and press CONTROL + SPACE:
Once there, now type "sta", this will narrow down the set of options to options that contain "sta".
After selecting "start_at" from the list, now we have to choose the start location for the ladder.
When your cursor is between the "" characters, press CONTROL + SPACE again !
Now we can choose which location in which we wish to create the ladder.
Select "hut" (using the cursor keys then pressing ENTER, or clicking with your mouse pointer). Adventuron will
type hut automatically.
Now let’s press the PLAY ICON and play the game for a little while ….
If you feel tired, or get stuck, then take a break, or ask a trusted grown up for help.
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the north." ;
road_1 : location "You are standing on a track. The hut is south." ;
road_2 : location "You are where the road turns eastwards. You see small hills in the distance." ;
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
]
########################################
# Objects #
########################################
objects {
ladder : object "a ladder" start_at = "hut" ;
}
We will now type in all the remaining locations of Excalibur into the game.
It’s much easier if you do this in a pair, with one person reading the ids and descriptions, and the other person
typing.
Remember, you always need to start on an EMPTY LINE then press CONTROL + SPACE and Adventuron will
give you a new location template. After that, type the name of the identifier, then press the TAB button (left of
the Q button), then type the description of the location.
The underscore '_' looks like a minus symbol, but lower. To type it you have to hold the SHIFT button and press
the minus '-' button.
You can copy and paste this text if you wish, but this is good typing practise if you have the time to type all
these locations yourself.
(If the following text is too cramped, remember you can double click the documentation to go into full screen
mode, then double click to go back)
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
########################################
# Objects #
########################################
objects {
ladder : object "a ladder" start_at = "hut" ;
}
Map - Part 1
Map - Part 2
This table (which was prepared from the map earlier in the tutorial) shows how all the locations are
connected.
from direction to
Now, we have to enter this information into the connections block of code.
Now, you must repeat the lesson from earlier for each entry in this table. See the animation at the bottom of
this section to show how this works, but you have to use CONTROL + SPACE - a lot.
It might help if you do this in a pair, and one person reads out each line, as the other person creates a new line
in the navigation table. After you type each line, check it to make sure you have not made any mistakes.
The video below is sped up, but the it shows how you should be able to edit the connections easily, using
CONTROL + SPACE.
After entering this information into Adventuron, you now have a map you can completely explore.
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
chasm, south, edge_of_birwood,
edge_of_birwood, south, deep_inside_birwood,
deep_inside_birwood, west, birwood_bush,
demon_knight_road, east, castle_approach_1,
castle_approach_1, east, castle_approach_2,
castle_approach_2, east, castle_porch,
castle_porch, east, banquet_hall,
banquet_hall, north, portcullis,
banquet_hall, south, drafty_room,
portcullis, north, most_splendid_room,
most_splendid_room, west, arthur,
drafty_room, east, ornate_antechamber,
drafty_room, down, salt_mine_1,
ornate_antechamber, east, cold_room,
cold_room, north, winch_room,
winch_room, east, armoury,
salt_mine_1, west, salt_mine_2,
salt_mine_1, south, worm_room,
worm_room, south, salt_mine_3,
]
########################################
# Objects #
########################################
objects {
ladder : object "a ladder" start_at = "hut" ;
}
lamp a lamp -
Remember that we create an object by pressing CONTROL + SPACE on an empty line in the objects {} code
block, select 'object', then type in the identifier, then press the TAB button to type in the description.
To create a new line, press ENTER at the end of the line (after the ';').
Non moveable things are known as 'scenery' and scenery is something that is shown by the game, but cannot
be put in your pocket.
It’s important that you tell the computer if something is an object (you can take it), or scenery (you can not take
it).
objects {
We have the location descriptions, connections between locations, and objects that the game contains.
Even though we have not yet created the puzzles, we should now be able to explore the world, and all the
objects / scenery in the world, without the game stopping us from going anywhere.
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
chasm, south, edge_of_birwood,
edge_of_birwood, south, deep_inside_birwood,
deep_inside_birwood, west, birwood_bush,
demon_knight_road, east, castle_approach_1,
castle_approach_1, east, castle_approach_2,
castle_approach_2, east, castle_porch,
########################################
# Objects #
########################################
objects {
5. Adding Logic
5.1. Responding to commands
If the player types something the game doesn’t know about, the game try its best to give the player some
feedback.
If a reply is not programmed, then Adventuron will use one of its standard replies.
There are different ways of writing command handlers, but the way we will use in the tutorial is the "manual"
method.
This method involves, manually looking at the verb (the doing word) and the noun (the thing, person, object,
or scenery).
The response we want when examine the ladder (when it is held or in the same location) is "A LONG POLE
WITH RUNGS ATTACHED."
Well, the response is there to give the player a clue about how the ladder might be used. Later on, there is a
tightrope across a chasm.
Normally a pole is used by people balancing on a tightrope, so this message gives a clue to the player that the
ladder could be converted into a pole, somehow.
The location can be anywhere you like (outside of the other code blocks), but we will place it UNDERNEATH the
objects block.
To create the "on_command {}" block, press CONTROL + SPACE, next start typing the first few letters of
on_command (such as "on"), when you see the "on_command" item, select it using the "enter" button on the
keyboard.
The "on_command {}" block is used to process commands that the player submitted (could be via keyboard or
joypad or hyperlink or voice) … and respond to those user entered command with a reaction.
If nothing is matched, the Adventuron will either do something with the command itself (if it knows what to
do), or tell the player that it doesn’t something about what they typed.
Now we need to match "examine ladder", so lets go to an empty line inside on_command {} and press …
CONTROL + SPACE. There are a couple of options here, so let’s select "match", and then press enter.
After pressing enter, we should see the following block of code appear. The "get lamp" text is already
highlighted by the editor, this means if we start typing, it will automatically wipe over the text.
The "get lamp" text is just there to demonstrate how to use match items, and will appear as a default every time
you create a new match using this technique. You don’t need to delete it, you just start typing and it will
disappear.
Now lets save our text by pressing CONTROL + S, and press the PLAY icon to try out the adventure.
That’s because we didn’t tell Adventuron what to do if ladder is matched, so Adventuron didn’t do anything,
and therefore just gave its normal response.
Start typing the letters "pri" (the first 3 letters of print), and now we will be able to pick the command we are
interested in, which is "print".
The text we want to display is "A LONG POLE WITH RUNGS ATTACHED.", so after selecting the "print"
command, type "A LONG POLE WITH RUNGS ATTACHED." in the area between the quotes (").
In the original Excalibur: Sword of Kings game, all messages are in capital letters, but this is optional, and if
you prefer not to use capital letters, that is fine.
Now, lets save the document with CONTROL + S, and run the game with the play icon. Actually, it’s not
necessary to press the PLAY icon, as CONTROL + S will reset the game every time.
Now when we type "EXAMINE LADDER" we see the response "A LONG POLE WITH RUNGS ATTACHED."
appear. Success !
The problem is that if you type "EXAMINE LADDER" anywhere, even if you are in a different location, you still
get the same response.
The response to the command should only be made when the ladder is present - and to do that we need to
make the ": print {}" command CONDITIONAL.
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
########################################
# Objects #
########################################
objects {
########################################
# On Command #
########################################
on_command {
We use conditions every day when we speak to each other. We might say something like, "if the weather is
good, let’s go to the park". The right time to go to the park is when the weather is good.
On Saturday, I go to the cinema, is also kind of a condition too. It can be rephrased "if it’s saturday, I go to the
cinema."
We tell computers the right time to do something using the word "if".
We wish to only display "A LONG POLE WITH RUNGS ATTACHED." when we examine the ladder if we are in
the same location or if we are holding the ladder.
: if → This is an if command
{} → This is what we should do, only if it’s the right time to do it.
To make our "if" command, we make a line ABOVE the print command, then press CONTROL + SPACE, then
type "if" then select the if with the CURSOR KEYS, then press ENTER.
We can see in the video above how to make an if statement using the autocomplete (CONTROL + SPACE)
method.
Go to the end of the match code block (using a mouse or the cursor keys), and then once at the end of the line,
hold the SHIFT button on the keyboard (ask a grown up or friend if you can’t find the button), and then keep
tapping the cursor key left and up until the whole of the match code block is selected (starting from the ":"
character next to match).
If you select too much, use the right and down cursor keys to go back.
Once you select the print line, let go of the shift key, and the cursor keys, then press CONTROL + X, on the
keyboard. This will cut the text. Cutting text is like deleting text temporarily, but the computer remembers the
deleted text so it can move it somewhere else.
Now move the cursor to the empty line inside main part of the if statement and press CONTROL + V. This will
paste the cut text into the new space.
You can see from the video about that we add new spaces to the start of the "match" block when it is inside of
the "if" block. This makes the code easier to see the start and end of blocks.
Cutting and pasting is extremely useful, and it really benefits you to practise cutting and pasting a lot of text. If
you have a mouse, you can also select the text by dragging the mouse across the text you want to cut.
If you want to copy text, rather than move text, use CONTROL + C, instead of CONTROL + X at the beginning….
If you have cut and paste correctly, the header bar should not be red, and we should save the document
(CONTROL + S), and move forward.
We now have an if statement with the thing to do if it’s a good time part (the print command), but we still don’t
know when it is the right time to perform the print command…
So, when is the right time to be able to examine the ladder? Well, you can’t examine (look) at a ladder if it’s not
in the same location can you? So, it either has to be in the same location, or if you are holding it. That’s the right
time that you can examine (look) at a ladder.
Adventuron has lots of different recipes for getting a yes or a no answer. One of these recipes is called the
"is_present" recipe.
"present" has two meanings. The first meaning is the type of thing you might get on your birthday.
The second mean is if something is with you. You could say, "my friend is here', or "my friend is present", and
they both mean the same thing.
We can use "is_present" to check to see if the ladder is in the same location or if the person playing the game is
holding the ladder.
Adventuron will only perform the middle part (the part between the {} bracey brackets) only if the ladder is in
the same location, or we are holding the ladder.
Now we can see that we can only look at the ladder if it is in the same location as us. If we go north from the
hut, and try to examine the ladder, we see the usual message that is shown when adventuron doesn’t know
what to do.
Press CONTROL + S to save your progress, and try out examining the ladder when you are in the hut, and
when you are not in the hut.
Remember that navigating requires you to know the directions of the compass. North is up on the map, south
is down.
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
chasm, south, edge_of_birwood,
########################################
# Things #
########################################
objects {
########################################
# On Command #
########################################
on_command {
: if ( is_present "ladder" ) {
: match "examine ladder" {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
5.11. Examine
In text adventure games, objects are able to be examined.
examine sword
It’s a way of delivering clues to the player, and sometimes to discover something hidden.
Here are the some messages that we wish to display when examining certain objects.
examine sword is_present INSCRIBED UPON IT ARE THE WORDS 'GOOD LUCK!' ~~
"short_sword" MERLIN.
The following code should be added to the bottom of the on_command{} section:
We will also modify the existing ladder handler to place the command matcher on the outside.
So far the only thing that we have done in response to a player entering some text (such as examine ladder or
examine lamp), is to display some text to the player.
examine bush is_present YOU FIND SOMETHING! Create the stone_key , wait for the
"bush" user to press something, then
redescribe the scene. * NOTE: This
examine logs is_present YOU FIND AN AXE! Create the axe in the current
"logs" location, wait for the user to press
something, then redescribe the
scene. * NOTE: This is slightly
different behaviour to the
original game.
Both the logs and the bush create a new object in the scene that the player is in when they are examined.
They also redescribe (refresh) the description of the scene so that the player can see the created objects. Hiding
objects within a scene is quite normal in this type of adventure.
To be able to program this, we require 3 new commands, in addition to the ': print' command, which we have
already used.
Command Description
: press_any_key Tells the game to wait until the player either presses a key on the keyboard, or
clicks the mouse, or touches the touchscreen. (NEW)
: redescribe Tells the game to clear the screen, then to redescribe the current scene,
including the contents of the scene. (NEW)
Command Description
An AND statement what we use to put together statements that must ALL BE TRUE in order to execute the part
between the { } statements.
We use AND statements in English all the time to describe some requirements. Things like "if the weather is
good and I have time this weekend, I will go to the park."
"We will go to the park only if the weather is good, AND we have time."
In Adventuron, an and is written using the && letters. Let’s see how this is used below by building our logic for
"examine logs" and "examine bushes".
In the animation shown above, the bush code block is created, and after checking the "is_present" condition,
the && operator is used to connect the two expressions that must be true.
The purpose behind this condition is to make sure that we won’t KEEP generating keys every time the bush is
examined.
Without this, every time we examine the bush, the message is displayed, and the key is regenerated.
Next in the animation, we create the message to display when the bush is examined (for the first time), then we
add the "create" command to create the key (in the scene that the player is in), then we add the "press_any_key"
command, and finally, the "redescribe" command.
We copy this block of code using copy and paste (as described earlier), and then modify the differences we
need the logs.
We swap the stone_key for the axe, and the logs for the bush, and we have a different message to print, but the
structure of the block is the same, so that’s why we copied and pasted.
It’s important not to type more than you need to type, so learning to copy and paste is a time saver.
There is actually a more elegant (easier) way to give objects examine messages and to check for existence of
something, but we are sticking to the basic method in this tutorial.
Let’s Play
So, let’s play the game again to see what happens when we examine the bush and the logs.
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
########################################
# Things #
########################################
objects {
########################################
# On Command #
########################################
on_command {
: match "examine ladder" {
: if ( is_present "ladder" ) {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
: match "examine woman" {
: if (is_present "old_woman") {
: print "SHE LOOKS AT YOU WITH AN INTENSE GLARE." ;
}
}
: match "examine lamp" {
: if (is_present "lamp") {
: print "IT'S OLD AND TARNISHED." ;
}
}
: match "examine fish" {
: if (is_present "red_fish") {
: print "IT STINKS!" ;
}
}
: match "examine sword" {
: if (is_present "short_sword") {
: print "INSCRIBED UPON IT ARE THE WORDS 'GOOD LUCK' ~~ MERLIN." ;
}
}
: match "examine bush" {
: if (is_present "bush" && has_not_created "stone_key") {
: print "YOU FIND SOMETHING!" ;
: create "stone_key" ;
: press_any_key ;
: redescribe ;
}
}
: match "examine logs" {
: if (is_present "logs" && has_not_created "axe") {
: print "YOU FIND AN AXE!" ;
: create "axe" ;
: press_any_key ;
: redescribe ;
}
}
}
These pictures are called graphics, and you can use graphics to make your adventure more fun and colourful.
Adventuron lets you add (also known as import) fun blocky graphics from files.
A file is a named thing on your computer, that you can access inside a folder. Files can contain all sorts of
things, like words, or web pages, or music, or videos, or … graphics.
There are lots of different types of graphic files, but the type that Adventuron likes best is PNG.
A PNG file is a type of file that can hold old-style blocky graphics very nicely, but it can also store other types of
picture too.
The most common type of graphic file type is JPEG, but this type of file can sometimes make blocky graphics
blurry, so let’s use PNG instead.
But, for the time being, on Windows, you might use Microsoft Paint, and when you save the file, make sure to
select PNG.
On OSX, there are many applications that will produce PNG files. Ask a parent or teacher to recommend one.
This file is made available for the purpose of following this tutorial only, and must not be redistributed.
These graphics should ONLY be used for following this tutorial and MUST NOT be used in any personal
adventures you make yourself. Better to make your own graphics.
After clicking that, find the zip file you downloaded (it should be in the downloads folder on your computer),
and then click "Open".
Getting the graphics from the zip "file" into the Adventuron is called importing. It can also be sometimes
referred to as loading.
The graphics we just imported (or loaded) share the same identifiers as the scenes we have already entered.
Adventuron will automatically associate the graphics with the scenes, if they share the same identifiers, so now
all the initial scene graphics are set up already.
When the import takes place, Adventuron converts the graphics into text. It’s not readable to human beings but
the computer knows how to read this strange text.
assets base64
If it looks impossible to read, then don’t worry, it’s impossible to read for everyone.
This type of text is called base64 text, and it’s not important for humans to be able to read it - just understand
that it makes sense to the computer.
All that’s important is the identifier part, and that the computer knows how to read it.
Now that we importing the graphics, we should be able to take a walk around the game world, but this time,
with graphics.
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
chasm, south, edge_of_birwood,
edge_of_birwood, south, deep_inside_birwood,
deep_inside_birwood, west, birwood_bush,
demon_knight_road, east, castle_approach_1,
castle_approach_1, east, castle_approach_2,
castle_approach_2, east, castle_porch,
castle_porch, east, banquet_hall,
banquet_hall, north, portcullis,
banquet_hall, south, drafty_room,
portcullis, north, most_splendid_room,
most_splendid_room, west, arthur,
drafty_room, east, ornate_antechamber,
drafty_room, down, salt_mine_1,
ornate_antechamber, east, cold_room,
cold_room, north, winch_room,
winch_room, east, armoury,
salt_mine_1, west, salt_mine_2,
salt_mine_1, south, worm_room,
worm_room, south, salt_mine_3,
]
########################################
# Objects #
########################################
objects {
########################################
# On Command #
########################################
on_command {
: match "examine ladder" {
: if ( is_present "ladder" ) {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
: match "examine woman" {
: if (is_present "old_woman") {
: print "SHE LOOKS AT YOU WITH AN INTENSE GLARE." ;
}
}
: match "examine lamp" {
: if (is_present "lamp") {
: print "IT'S OLD AND TARNISHED." ;
}
}
: match "examine fish" {
: if (is_present "red_fish") {
: print "IT STINKS!" ;
}
}
: match "examine sword" {
: if (is_present "short_sword") {
: print "INSCRIBED UPON IT ARE THE WORDS 'GOOD LUCK' ~~ MERLIN." ;
}
}
: match "examine bush" {
: if (is_present "bush" && has_not_created "stone_key") {
: print "YOU FIND SOMETHING!" ;
: create "stone_key" ;
: press_any_key ;
: redescribe ;
}
}
: match "examine logs" {
: if (is_present "logs" && has_not_created "axe") {
: print "YOU FIND AN AXE!" ;
: create "axe" ;
: press_any_key ;
: redescribe ;
}
}
}
// Placeholders used for documentation purposes only as graphic data is too large to place in document.
assets {
graphics {
armoury : placeholder ;
arthur : placeholder ;
banquet_hall : placeholder ;
birwood_bush : placeholder ;
castle_approach_1 : placeholder ;
castle_approach_2 : placeholder ;
castle_approach_2a : placeholder ;
castle_porch : placeholder ;
chasm : placeholder ;
cold_room : placeholder ;
cold_room_2 : placeholder ;
deep_inside_birwood : placeholder ;
demon_knight_road : placeholder ;
demon_knight_road_2 : placeholder ;
drafty_room : placeholder ;
drafty_room_2 : placeholder ;
edge_of_birwood : placeholder ;
ending_screen : placeholder ;
excalibur_loading : placeholder ;
foot_of_tree : placeholder ;
foot_of_tree_2 : placeholder ;
game_over : placeholder ;
hut : placeholder ;
lamp_seller_on_road : placeholder ;
lamp_seller_on_road_2 : placeholder ;
most_splendid_room : placeholder ;
most_splendid_room_2 : placeholder ;
ornate_antechamber : placeholder ;
portcullis : placeholder ;
portcullis_2 : placeholder ;
road_1 : placeholder ;
road_2 : placeholder ;
road_3 : placeholder ;
road_4 : placeholder ;
salt_mine_1 : placeholder ;
salt_mine_2 : placeholder ;
salt_mine_3 : placeholder ;
top_of_tree : placeholder ;
winch_room : placeholder ;
worm_room : placeholder ;
worm_room_2 : placeholder ;
}
}
6. Adding Puzzles
6.1. Blocking The Top Of The Tree
At this point in the tutorial, the player has complete freedom to go everywhere, and there are no puzzles.
Blocking means restricting access to a location or an area of the map (until a puzzle is solved or action is
performed).
The first block we will create is blocking access to the top of the tree.
Currently, there is no barrier to going from the bottom of the tree to the top of the tree.
The first puzzle in the game is climbing the stone tree. There are no branches on the tree, so it cannot be
climbed.
Even though we have created an entry in the connections section, describing that the bottom of the tree leads
up to the top of the tree, after creating the BLOCK, typing up should not allow the player to go UP to the location
"top of tree" unless the ladder is rested against the tree.
Imagine it like an envelope, and inside the envelope there can only be written "yes" or "no".
In most computer languages, YES is the same as TRUE, and NO is the same as FALSE.
YES = TRUE
NO = FALSE
So, now, we will create an envelope that contains the answer to the question:
The ladder starts in the hut, so the answer to the question at the start of the game is no (or false).
We will store this fact inside the boolean variable 'is_ladder_standing'. We could call the variable
'is_the_ladder_standing_against_the_tree' but keeping variable names as short as possible makes it faster to
code.
Variables are convenient because it lets the game author keep track of when the player has done things in the
game.
Never be tempted to make variable names TOO SHORT, because you need to understand what they mean.
We can create the boolean variable like this by pressing CONTROL + SPACE, on a blank line when not in
another section (just above on_command {} is good), then typing the name
booleans {
is_ladder_standing : boolean "false";
}
Remember, 'is_ladder_standing', now contains a false (no) answer, but if the player goes to the tree, holding the
ladder, and type LEAN LADDER or STAND LADDER or REST LADDER or DROP LADDER then we should put
a true (or yes) value in this variable (or envelope).
on_command {}
1. It checks that the player typed stand ladder or lean ladder or rest ladder or drop ladder. If the player
didn’t type one of these things, then we don’t execute any further step.
2. Next it checks that the player is carrying the ladder, and that the player is currently at the foot of the tree
location. If the players isn’t carrying the ladder or isn’t at the foot of the tree, then we don’t execute any
further step.
3. It drops the object currently being reference (in this case ladder).
5. It changes the graphic for the current scene to the 2nd version (a version showing the ladder).
6. It redescribes the current location (forcing the graphic and text to be refreshed).
1. It checks that the player typed "get ladder". If the player didn’t type it, then we don’t execute any further
step.
2. Next it checks that the player is beside (but not carrying) the ladder, and that the player is currently at the
foot of the tree location. If the players isn’t beside the ladder or isn’t at the foot of the tree, then we don’t
execute any further step.
3. It gets the object currently being reference (in this case ladder).
5. It changes the graphic for the current scene to the 1st version (a version not showing the stood ladder).
6. It redescribes the current location (forcing the graphic and text to be refreshed).
Although we have code now to record if the ladder is standing or not, it doesn’t prevent us from going UP the
tree when the ladder is not stood against the tree. Also, the UP direction is still listed even when the ladder is
not standing against the tree.
For real immersion, we want to remove the UP direction from the exit lists if the ladder is not standing against
the tree.
We can achieve both of these goals (remove up exit, and block access up) by using a barrier.
There are many types of barrier, but the one we will use for the tree puzzle is a block.
A block prevents acess to a location via regular direction commands (north, south, east, west, up, down, …).
As standard, if the block is active then the block will also remove the direction from list of available directions.
This lets the player know that the direction is not available. Sometimes we do want to list the location of a
blocked exit anyway, and we will explore this option later.
An activation condition.
The activation condition which tells the block when it should be active, or inactive.
barriers{}
tree : block {
location = top_of_tree
message = YOU CAN'T FIND YOUR GRIP
block_when_not = is_ladder_standing
}
The code shown above tells Adventuron to block the top_of_tree location, but only when is_ladder_standing
contains a false (no) value/answer.
Adventuron takes care of removing the listing of an exit when a block is encountered, so if the ladder is not
stood at the bottom of the tree, the "UP" exit will not be shown.
If the player types UP by themselves, they see the message "YOU CAN’T FIND YOUR GRIP" but they do not travel
to the top of the tree.
If we click the PLAY icon at the top of the screen, and play the game now. We can navigate to the bottom of the
tree (N, N, E, E, N), and we can now see that UP is not listed as an exit.
If we type UP, we are show the message "YOU CAN’T FIND YOUR GRIP".
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
chasm, south, edge_of_birwood,
edge_of_birwood, south, deep_inside_birwood,
deep_inside_birwood, west, birwood_bush,
demon_knight_road, east, castle_approach_1,
########################################
# Objects #
########################################
objects {
########################################
# Booleans #
########################################
booleans {
is_ladder_standing : boolean "false";
}
########################################
# Blocks #
########################################
barriers {
tree : block {
location = top_of_tree
message = YOU CAN'T FIND YOUR GRIP
block_when_not = is_ladder_standing
}
}
########################################
# On Command #
########################################
on_command {
: match "examine ladder" {
: if ( is_present "ladder" ) {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
: match "examine woman" {
: if (is_present "old_woman") {
: print "SHE LOOKS AT YOU WITH AN INTENSE GLARE." ;
}
}
: match "examine lamp" {
: if (is_present "lamp") {
: print "IT'S OLD AND TARNISHED." ;
}
}
: match "examine fish" {
: if (is_present "red_fish") {
: print "IT STINKS!" ;
}
}
: match "examine sword" {
: if (is_present "short_sword") {
: print "INSCRIBED UPON IT ARE THE WORDS 'GOOD LUCK' ~~ MERLIN." ;
}
}
: match "examine bush" {
: if (is_present "bush" && has_not_created "stone_key") {
: print "YOU FIND SOMETHING!" ;
: create "stone_key" ;
: press_any_key ;
: redescribe ;
}
}
: match "examine logs" {
: if (is_present "logs" && has_not_created "axe") {
: print "YOU FIND AN AXE!" ;
: create "axe" ;
: press_any_key ;
: redescribe ;
}
}
}
}
// Placeholders used for documentation purposes only as graphic data is too large to place in document.
assets {
graphics {
armoury : placeholder ;
arthur : placeholder ;
banquet_hall : placeholder ;
birwood_bush : placeholder ;
castle_approach_1 : placeholder ;
castle_approach_2 : placeholder ;
castle_approach_2a : placeholder ;
castle_porch : placeholder ;
chasm : placeholder ;
cold_room : placeholder ;
cold_room_2 : placeholder ;
deep_inside_birwood : placeholder ;
demon_knight_road : placeholder ;
demon_knight_road_2 : placeholder ;
drafty_room : placeholder ;
drafty_room_2 : placeholder ;
edge_of_birwood : placeholder ;
ending_screen : placeholder ;
excalibur_loading : placeholder ;
foot_of_tree : placeholder ;
foot_of_tree_2 : placeholder ;
game_over : placeholder ;
hut : placeholder ;
lamp_seller_on_road : placeholder ;
lamp_seller_on_road_2 : placeholder ;
most_splendid_room : placeholder ;
most_splendid_room_2 : placeholder ;
ornate_antechamber : placeholder ;
portcullis : placeholder ;
portcullis_2 : placeholder ;
road_1 : placeholder ;
road_2 : placeholder ;
road_3 : placeholder ;
road_4 : placeholder ;
salt_mine_1 : placeholder ;
salt_mine_2 : placeholder ;
salt_mine_3 : placeholder ;
top_of_tree : placeholder ;
winch_room : placeholder ;
worm_room : placeholder ;
worm_room_2 : placeholder ;
}
}
The Demon Knight stands in the path on the way to Camelot. Currently, we can just walk past the knight,
because we haven’t added any logic.
If we try to attack the knight without a weapon, then the knight will defeat us in battle, and the game will end.
If we try to walk past the knight, then the knight will strike us, and the game will end.
The way to defeat the knight is to attack the knight whilst carrying the short sword (which was obtained from
the room at the top of the tree, which itself required the ladder puzzle to be solved).
1. If in same location as knight, and issuing the 'east' command, then describe defeat, and end game.
2. If in the same location as the knight, and typing 'attack knight', or 'fight knight', and not holding short
sword, then describe defeat, and end game.
3. If in the same location as the knight, and typing 'attack knight', or 'fight knight', and holding short sword,
then describe victory, and remove the knight from the game.
A subroutine block is a block that executes a subroutine instead of moving to the blocked location.
knight : block {
location = castle_approach_1
gosub = lose_fight
block_when_exists = demon_knight
show_blocked_exit = true
}
The 'show_blocked_exit' option is something that can be added to a block to tell adventuron to show the
blocked exit in the exits list.
In this puzzle, we want to show the exit 'east' even though moving in that direction will end the game.
As standard, if there is an active block, then the exit will not be listed until the block is removed or made
inactive.
6.8.1. Subroutines
A subroutine is section of code that can be referenced from some other part of the code.
The advantage of using subroutines is that sometimes the same functionality needs to be used multiple times,
and it makes it easy to write code that does one thing, in one place, rather than copying and pasting it in
multiple places.
The code inside a subroutine can be referenced in various parts of Adventuron, and once the code is finished
executing, it returns to the place in the code from where it was referenced (unless the subroutine ends the
game).
lose_fight The subroutine will print the message "THE KNIGHT If we try to move into the blocked
WIELDS HIS SWORD DEFTLY AND ATTACKS YOU…." location beyond the knight or if we
then it will execute the "end_game" subroutine. attempt to attack the knight without
the short sword, then the lose_fight
subroutine is executed.
win_fight This subroutine prints the message "A GREAT This subroutine is executed if we
BATTLE ENSUES IN WHICH YOU ARE VICTORIOUS. fight the knight whilst holding the
BEFORE YOUR EYES THE KNIGHT TURNS TO DUST short sword.
ALONG WITH YOUR SWORD!", then the short sword
is removed from the game, the knight is removed
from the game, the graphic for the location with the
knight is changed to remove the knight, and the
block of the castle_approach_1 location is removed.
end_game Waits for the user to press a button, then clears the The subroutine is executed when the
current screen, then shows the "game_over" graphic, game is lost. It is referenced from
then prints the message, "Your quest is over ……….", the "lose_fight" subroutine, but it
then prints the number of turns, and signals to will also be referenced by other
Adventuron to end the game (game over). parts of the game later on.
Subroutines
########################################
# Subroutines #
########################################
subroutines {
end_game : subroutine {
: press_any_key ;
: clear_screen;
: print_graphic "game_over" ;
: print "Your quest is over .........." ;
: turns ;
: end_game ;
}
}
To initiate fighting the knight, then the command "fight knight" or "attack knight" or "challenge knight" should
be typed.
on_command {} code
An else statement can only be used after an 'if' statement or an 'else_if' statement (described later).
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
chasm, south, edge_of_birwood,
edge_of_birwood, south, deep_inside_birwood,
deep_inside_birwood, west, birwood_bush,
demon_knight_road, east, castle_approach_1,
castle_approach_1, east, castle_approach_2,
castle_approach_2, east, castle_porch,
castle_porch, east, banquet_hall,
banquet_hall, north, portcullis,
banquet_hall, south, drafty_room,
portcullis, north, most_splendid_room,
most_splendid_room, west, arthur,
drafty_room, east, ornate_antechamber,
drafty_room, down, salt_mine_1,
ornate_antechamber, east, cold_room,
cold_room, north, winch_room,
winch_room, east, armoury,
salt_mine_1, west, salt_mine_2,
salt_mine_1, south, worm_room,
worm_room, south, salt_mine_3,
]
########################################
# Objects #
########################################
objects {
########################################
# Booleans #
########################################
booleans {
is_ladder_standing : boolean "false";
}
########################################
# Blocks #
########################################
barriers {
tree : block {
location = top_of_tree
message = YOU CAN'T FIND YOUR GRIP
block_when_not = is_ladder_standing
}
knight : block {
location = castle_approach_1
gosub = lose_fight
block_when_exists = demon_knight
show_blocked_exit = true
}
}
########################################
# On Command #
########################################
on_command {
: match "examine ladder" {
: if ( is_present "ladder" ) {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
: match "examine woman" {
: if (is_present "old_woman") {
: print "SHE LOOKS AT YOU WITH AN INTENSE GLARE." ;
}
}
: match "examine lamp" {
: if (is_present "lamp") {
: print "IT'S OLD AND TARNISHED." ;
}
}
: match "examine fish" {
: if (is_present "red_fish") {
: print "IT STINKS!" ;
}
}
: match "examine sword" {
: if (is_present "short_sword") {
: print "INSCRIBED UPON IT ARE THE WORDS 'GOOD LUCK' ~~ MERLIN." ;
}
}
: match "examine bush" {
: if (is_present "bush" && has_not_created "stone_key") {
: print "YOU FIND SOMETHING!" ;
: create "stone_key" ;
: press_any_key ;
: redescribe ;
}
}
: match "examine logs" {
: if (is_present "logs" && has_not_created "axe") {
: print "YOU FIND AN AXE!" ;
: create "axe" ;
: press_any_key ;
: redescribe ;
}
}
########################################
# Subroutines #
########################################
subroutines {
win_fight : subroutine {
: print "A GREAT BATTLE ENSUES IN WHICH YOU ARE VICTORIOUS. THE KNIGHT TURNS TO DUST BEFORE YOUR EYES
ALONG WITH YOUR SWORD!" ;
: press_any_key ;
: destroy "demon_knight" ;
: destroy "short_sword" ;
: set_graphic graphic = "demon_knight_road_2" target = "demon_knight_road" ;
: redescribe ;
}
end_game : subroutine {
: press_any_key ;
: clear_screen;
: print_graphic "game_over" ;
: print "Your quest is over .........." ;
: turns ;
: end_game ;
}
// Placeholders used for documentation purposes only as graphic data is too large to place in document.
assets {
graphics {
armoury : placeholder ;
arthur : placeholder ;
banquet_hall : placeholder ;
birwood_bush : placeholder ;
castle_approach_1 : placeholder ;
castle_approach_2 : placeholder ;
castle_approach_2a : placeholder ;
castle_porch : placeholder ;
chasm : placeholder ;
cold_room : placeholder ;
cold_room_2 : placeholder ;
deep_inside_birwood : placeholder ;
demon_knight_road : placeholder ;
demon_knight_road_2 : placeholder ;
drafty_room : placeholder ;
drafty_room_2 : placeholder ;
edge_of_birwood : placeholder ;
ending_screen : placeholder ;
excalibur_loading : placeholder ;
foot_of_tree : placeholder ;
foot_of_tree_2 : placeholder ;
game_over : placeholder ;
hut : placeholder ;
lamp_seller_on_road : placeholder ;
lamp_seller_on_road_2 : placeholder ;
most_splendid_room : placeholder ;
most_splendid_room_2 : placeholder ;
ornate_antechamber : placeholder ;
portcullis : placeholder ;
portcullis_2 : placeholder ;
road_1 : placeholder ;
road_2 : placeholder ;
road_3 : placeholder ;
road_4 : placeholder ;
salt_mine_1 : placeholder ;
salt_mine_2 : placeholder ;
salt_mine_3 : placeholder ;
top_of_tree : placeholder ;
winch_room : placeholder ;
worm_room : placeholder ;
worm_room_2 : placeholder ;
}
}
To cross the chasm you need to be holding a pole to help you balance, then type CROSS CHASM whilst holding
the pole.
Both sides of the chasm require typing CROSS CHASM to take you to the opposite side, and the holding of the
pole that assists your balance.
The pole is an object that is created if the player types BREAK LADDER, SMASH LADDER or DISASSEMBLE
LADDER whilst holding the ladder.
The clue to solve this puzzle is the use of the word "tightrope" in the "edge of a huge chasm" location.
Examining the ladder describes the ladder as "A LONG POLE WITH RUNGS ATTACHED.". Interesting !
Breaking, smashing or dismantling the ladder will create the objects "some rungs" and "a long pole". It will also
remove the ladder from the game.
The ladder can be broken at any time, including BEFORE climbing the tree. Breaking the ladder this way puts
the game into an unwinnable state, as the ladder cannot be reconstructed.
The player will probably become aware of this if they solve the chasm puzzle before the tree puzzle, but if they
don’t it may be frustrating.
QUIZ - Can you think of a way to fix the unwinnability problem here ?
The following code should be added to the bottom of the on_command{} section:
We will be using less animations going forward as you should be getting used to how to use CONTROL +
SPACE, TAB, the CURSOR KEYS, and other keyboard shortcuts.
We will use yet another form of blocking now which is simply removing the navigation item entirely.
To do this, we can "comment out" the line in the navigation table which connects the chasm location to the
edge_of_birwood location.
To comment something out, we can type the // character at the start of the line (or lines) we wish to ignore. We
could also delete the line, but in this case, we will comment out the line.
Some logic can be added for falling if the player types "CROSS CHASM" without holding the pole.
The "!" character in from of is_carried "long_pole" means NOT, and of course the && characters read as AND.
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
//chasm, south, edge_of_birwood,
edge_of_birwood, south, deep_inside_birwood,
deep_inside_birwood, west, birwood_bush,
demon_knight_road, east, castle_approach_1,
castle_approach_1, east, castle_approach_2,
castle_approach_2, east, castle_porch,
castle_porch, east, banquet_hall,
banquet_hall, north, portcullis,
banquet_hall, south, drafty_room,
portcullis, north, most_splendid_room,
most_splendid_room, west, arthur,
drafty_room, east, ornate_antechamber,
drafty_room, down, salt_mine_1,
ornate_antechamber, east, cold_room,
cold_room, north, winch_room,
winch_room, east, armoury,
salt_mine_1, west, salt_mine_2,
salt_mine_1, south, worm_room,
worm_room, south, salt_mine_3,
]
########################################
# Objects #
########################################
objects {
########################################
# Booleans #
########################################
booleans {
is_ladder_standing : boolean "false";
}
########################################
# Blocks #
########################################
barriers {
tree : block {
location = top_of_tree
message = YOU CAN'T FIND YOUR GRIP
block_when_not = is_ladder_standing
}
knight : block {
location = castle_approach_1
gosub = lose_fight
block_when_exists = demon_knight
show_blocked_exit = true
}
}
########################################
# On Command #
########################################
on_command {
: match "examine ladder" {
: if ( is_present "ladder" ) {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
: match "examine woman" {
: if (is_present "old_woman") {
: print "SHE LOOKS AT YOU WITH AN INTENSE GLARE." ;
}
}
: match "examine lamp" {
: if (is_present "lamp") {
: print "IT'S OLD AND TARNISHED." ;
}
}
: match "examine fish" {
: if (is_present "red_fish") {
: print "IT STINKS!" ;
}
}
: match "examine sword" {
: if (is_present "short_sword") {
: print "INSCRIBED UPON IT ARE THE WORDS 'GOOD LUCK' ~~ MERLIN." ;
}
}
: match "examine bush" {
: if (is_present "bush" && has_not_created "stone_key") {
: print "YOU FIND SOMETHING!" ;
: create "stone_key" ;
: press_any_key ;
: redescribe ;
}
}
: match "examine logs" {
: if (is_present "logs" && has_not_created "axe") {
: print "YOU FIND AN AXE!" ;
: create "axe" ;
: press_any_key ;
: redescribe ;
}
}
########################################
# Subroutines #
########################################
subroutines {
: press_any_key ;
: destroy "demon_knight" ;
: destroy "short_sword" ;
: set_graphic graphic = "demon_knight_road_2" target = "demon_knight_road" ;
: redescribe ;
}
end_game : subroutine {
: press_any_key ;
: clear_screen;
: print_graphic "game_over";
: print "Your quest is over .........." ;
: turns ;
: end_game ;
}
// Placeholders used for documentation purposes only as graphic data is too large to place in document.
assets {
graphics {
armoury : placeholder ;
arthur : placeholder ;
banquet_hall : placeholder ;
birwood_bush : placeholder ;
castle_approach_1 : placeholder ;
castle_approach_2 : placeholder ;
castle_approach_2a : placeholder ;
castle_porch : placeholder ;
chasm : placeholder ;
cold_room : placeholder ;
cold_room_2 : placeholder ;
deep_inside_birwood : placeholder ;
demon_knight_road : placeholder ;
demon_knight_road_2 : placeholder ;
drafty_room : placeholder ;
drafty_room_2 : placeholder ;
edge_of_birwood : placeholder ;
ending_screen : placeholder ;
excalibur_loading : placeholder ;
foot_of_tree : placeholder ;
foot_of_tree_2 : placeholder ;
game_over : placeholder ;
hut : placeholder ;
lamp_seller_on_road : placeholder ;
lamp_seller_on_road_2 : placeholder ;
most_splendid_room : placeholder ;
most_splendid_room_2 : placeholder ;
ornate_antechamber : placeholder ;
portcullis : placeholder ;
portcullis_2 : placeholder ;
road_1 : placeholder ;
road_2 : placeholder ;
road_3 : placeholder ;
road_4 : placeholder ;
salt_mine_1 : placeholder ;
salt_mine_2 : placeholder ;
salt_mine_3 : placeholder ;
top_of_tree : placeholder ;
winch_room : placeholder ;
worm_room : placeholder ;
worm_room_2 : placeholder ;
}
}
The next puzzle is opening the castle stone door. The door is either open or closed, locked or unlocked.
The door requires the stone key to unlock the door. The stone key was found in the bush in Birwood forest.
A door is a kind of barrier, and can be created in the barriers section (at the top of the document).
We create a door this way, and it will take care of all the opening / closing / and blocking logic for us.
barriers{}
castle_door : door {
key = stone_key
from = castle_approach_2
to = castle_porch
on_unlock {
: print "YOU UNLOCK IT WITH THE KEY, WHICH JAMS IN THE LOCK." ;
: destroy "stone_key" ;
}
on_open {
: set_graphic graphic = "castle_approach_2a" target = "castle_approach_2" ;
: redescribe ;
}
on_close {
: set_graphic graphic = "castle_approach_2" target = "castle_approach_2" ;
: redescribe ;
}
}
The on_unlock {} section is executed when the door is unlocked. In our section, we wish to destroy the key
(remove it from being carried by the player) after the door is locked.
The on_open {} section is executed when the door is opened. In our case, we wish to change the graphic to a
version of the graphic with an open door, then redescribe (repaint) the current location.
The on_close {} section is executed when the door is closed. In our case, we wish to change the graphic to a
version of the graphic with a closed door, then redescribe (repaint) the current location.
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
########################################
# Objects #
########################################
objects {
########################################
# Booleans #
########################################
booleans {
is_ladder_standing : boolean "false";
}
########################################
# Blocks #
########################################
barriers {
castle_door : door {
key = stone_key
from = castle_approach_2
to = castle_porch
on_unlock {
: print "YOU UNLOCK IT WITH THE KEY, WHICH JAMS IN THE LOCK." ;
: destroy "stone_key" ;
}
on_open {
: set_graphic graphic = "castle_approach_2a" target = "castle_approach_2" ;
: redescribe ;
}
on_close {
: set_graphic graphic = "castle_approach_2" target = "castle_approach_2" ;
: redescribe ;
}
}
tree : block {
location = top_of_tree
message = YOU CAN'T FIND YOUR GRIP
block_when_not = is_ladder_standing
}
knight : block {
location = castle_approach_1
gosub = lose_fight
block_when_exists = demon_knight
show_blocked_exit = true
}
########################################
# On Command #
########################################
on_command {
: match "examine ladder" {
: if ( is_present "ladder" ) {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
: match "examine woman" {
: if (is_present "old_woman") {
: print "SHE LOOKS AT YOU WITH AN INTENSE GLARE." ;
}
}
: create "long_pole" ;
: create "rungs" ;
: press_any_key ;
: redescribe ;
}
}
########################################
# Subroutines #
########################################
subroutines {
end_game : subroutine {
: press_any_key ;
: clear_screen;
: print_graphic "game_over" ;
: print "Your quest is over .........." ;
: turns ;
: end_game ;
}
// Placeholders used for documentation purposes only as graphic data is too large to place in document.
assets {
graphics {
armoury : placeholder ;
arthur : placeholder ;
banquet_hall : placeholder ;
birwood_bush : placeholder ;
castle_approach_1 : placeholder ;
castle_approach_2 : placeholder ;
castle_approach_2a : placeholder ;
castle_porch : placeholder ;
chasm : placeholder ;
cold_room : placeholder ;
cold_room_2 : placeholder ;
deep_inside_birwood : placeholder ;
demon_knight_road : placeholder ;
demon_knight_road_2 : placeholder ;
drafty_room : placeholder ;
drafty_room_2 : placeholder ;
edge_of_birwood : placeholder ;
ending_screen : placeholder ;
excalibur_loading : placeholder ;
foot_of_tree : placeholder ;
foot_of_tree_2 : placeholder ;
game_over : placeholder ;
hut : placeholder ;
lamp_seller_on_road : placeholder ;
lamp_seller_on_road_2 : placeholder ;
most_splendid_room : placeholder ;
most_splendid_room_2 : placeholder ;
ornate_antechamber : placeholder ;
portcullis : placeholder ;
portcullis_2 : placeholder ;
road_1 : placeholder ;
road_2 : placeholder ;
road_3 : placeholder ;
road_4 : placeholder ;
salt_mine_1 : placeholder ;
salt_mine_2 : placeholder ;
salt_mine_3 : placeholder ;
top_of_tree : placeholder ;
winch_room : placeholder ;
worm_room : placeholder ;
worm_room_2 : placeholder ;
}
}
Buying the lamp is a very simple piece of logic, and is an 'item swap' puzzle. You take an item to a place, type
something, and it is replaced with something else.
In this case, the "old woman selling lamps" has a lamp to "sell". When the player gains access to the castle, they
will find a coin.
If the player takes the coin, then goes to the same location as the woman, and types BUY LAMP or GIVE COIN,
then the game will print "THE OLD LADY TAKES YOUR COIN, GIVES YOU A BRASS LAMP, THEN DISAPPEARS
INTO THIN AIR.".
The following code should be added at the end (but inside) the on_command {} section of code.
on_command {}
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
########################################
# Objects #
########################################
objects {
########################################
# Booleans #
########################################
booleans {
is_ladder_standing : boolean "false";
}
########################################
# Barriers #
########################################
barriers {
castle_door : door {
key = stone_key
from = castle_approach_2
to = castle_porch
on_unlock {
: print "YOU UNLOCK IT WITH THE KEY, WHICH JAMS IN THE LOCK." ;
: destroy "stone_key" ;
}
on_open {
: set_graphic graphic = "castle_approach_2a" target = "castle_approach_2" ;
: redescribe ;
}
on_close {
: set_graphic graphic = "castle_approach_2" target = "castle_approach_2" ;
: redescribe ;
}
}
tree : block {
location = top_of_tree
message = YOU CAN'T FIND YOUR GRIP
block_when_not = is_ladder_standing
}
knight : block {
location = castle_approach_1
gosub = lose_fight
block_when_exists = demon_knight
show_blocked_exit = true
}
########################################
# On Command #
########################################
on_command {
: match "examine ladder" {
: if ( is_present "ladder" ) {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
: match "examine woman" {
: if (is_present "old_woman") {
: print "SHE LOOKS AT YOU WITH AN INTENSE GLARE." ;
}
}
: create "long_pole" ;
: create "rungs" ;
: press_any_key ;
: redescribe ;
}
}
########################################
# Subroutines #
########################################
subroutines {
win_fight : subroutine {
: print "A GREAT BATTLE ENSUES IN WHICH YOU ARE VICTORIOUS. THE KNIGHT TURNS TO DUST BEFORE YOUR EYES
ALONG WITH YOUR SWORD!" ;
: press_any_key ;
: destroy "demon_knight" ;
: destroy "short_sword" ;
: set_graphic graphic = "demon_knight_road_2" target = "demon_knight_road" ;
: redescribe ;
}
end_game : subroutine {
: press_any_key ;
: clear_screen;
: print_graphic "game_over" ;
: print "Your quest is over .........." ;
: turns ;
: end_game ;
}
// Placeholders used for documentation purposes only as graphic data is too large to place in document.
assets {
graphics {
armoury : placeholder ;
arthur : placeholder ;
banquet_hall : placeholder ;
birwood_bush : placeholder ;
castle_approach_1 : placeholder ;
castle_approach_2 : placeholder ;
castle_approach_2a : placeholder ;
castle_porch : placeholder ;
chasm : placeholder ;
cold_room : placeholder ;
cold_room_2 : placeholder ;
deep_inside_birwood : placeholder ;
demon_knight_road : placeholder ;
demon_knight_road_2 : placeholder ;
drafty_room : placeholder ;
drafty_room_2 : placeholder ;
edge_of_birwood : placeholder ;
ending_screen : placeholder ;
excalibur_loading : placeholder ;
foot_of_tree : placeholder ;
foot_of_tree_2 : placeholder ;
game_over : placeholder ;
hut : placeholder ;
lamp_seller_on_road : placeholder ;
lamp_seller_on_road_2 : placeholder ;
most_splendid_room : placeholder ;
most_splendid_room_2 : placeholder ;
ornate_antechamber : placeholder ;
portcullis : placeholder ;
portcullis_2 : placeholder ;
road_1 : placeholder ;
road_2 : placeholder ;
road_3 : placeholder ;
road_4 : placeholder ;
salt_mine_1 : placeholder ;
salt_mine_2 : placeholder ;
salt_mine_3 : placeholder ;
top_of_tree : placeholder ;
winch_room : placeholder ;
worm_room : placeholder ;
worm_room_2 : placeholder ;
}
}
Inside the castle is a trapdoor, which is locked, and cannot be opened or unlocked.
The axe is required to smash the trapdoor, and this can be found by examining the logs inside Birwood Forest.
When the player types SMASH TRAPDOOR or CHOP TRAPDOOR or BREAK TRAPDOOR we also need to
swap the scenery object of "trapdoor" with the new object "smashed trapdoor" and update the graphic in the
'drafty_room' to show the smashed trapdoor.
We add a block for the 'salt_mine_1' location (the location underneath the room with the trapdoor).
The block is only active when the original (non swapped) 'trapdoor' object exists, so when we swap the
trapdoor objects for the smashed trapdoor object, the block is switched off, and the DOWN exit is shown.
barriers {}
trapdoor : block {
location = salt_mine_1
message = THE TRAPDOOR IS JAMMED SHUT!
block_when_exists = trapdoor
}
on_command{}
Well, it’s just an identifier for the block, and used internally.
The identified should be unique, but it doesn’t correspond to anything else. It is 'arbitrary'.
Arbitrary is a word that means that 'it could be anything'. All adventuron requires is an id here, but it helps if
you name it something useful, so you can remember what the block is doing.
The ': pause' command is used to introduce a delay (or pause) in executing your code.
Usage
: pause "1600" ;
The number in the quotes represents milliseconds of time to wait. One second is the same as 1,000 milliseconds
of time, so the line shown above commands Adventuron to wait for 1.6 seconds.
The reason for this might be to give the player a change to read something before moving on, or for dramatic
effect.
Make sure that if using a pause before a clear screen or redescribe command, that you give the player a second
chance to understand what just happened.
In this case, we give two visual indicators that the trapdoor is smashed. We change the on screen graphic, and
we change the on screen text (to show a smashed trapdoor).
It is a good idea NOT to place any critical story information behind a pause followed by an instant clearing of
the screen (or redescribe). It will be frustrating for the player.
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
//chasm, south, edge_of_birwood,
edge_of_birwood, south, deep_inside_birwood,
deep_inside_birwood, west, birwood_bush,
demon_knight_road, east, castle_approach_1,
castle_approach_1, east, castle_approach_2,
castle_approach_2, east, castle_porch,
castle_porch, east, banquet_hall,
banquet_hall, north, portcullis,
banquet_hall, south, drafty_room,
portcullis, north, most_splendid_room,
most_splendid_room, west, arthur,
drafty_room, east, ornate_antechamber,
drafty_room, down, salt_mine_1,
ornate_antechamber, east, cold_room,
cold_room, north, winch_room,
winch_room, east, armoury,
salt_mine_1, west, salt_mine_2,
salt_mine_1, south, worm_room,
worm_room, south, salt_mine_3,
]
########################################
# Objects #
########################################
objects {
########################################
# Booleans #
########################################
booleans {
is_ladder_standing : boolean "false";
}
########################################
# Barriers #
########################################
barriers {
castle_door : door {
key = stone_key
from = castle_approach_2
to = castle_porch
on_unlock {
: print "YOU UNLOCK IT WITH THE KEY, WHICH JAMS IN THE LOCK." ;
: destroy "stone_key" ;
}
on_open {
: set_graphic graphic = "castle_approach_2a" target = "castle_approach_2" ;
: redescribe ;
}
on_close {
: set_graphic graphic = "castle_approach_2" target = "castle_approach_2" ;
: redescribe ;
}
}
tree : block {
location = top_of_tree
message = YOU CAN'T FIND YOUR GRIP
block_when_not = is_ladder_standing
}
knight : block {
location = castle_approach_1
gosub = lose_fight
block_when_exists = demon_knight
show_blocked_exit = true
}
trapdoor : block {
location = salt_mine_1
message = THE TRAPDOOR IS JAMMED SHUT!
block_when_exists = trapdoor
########################################
# On Command #
########################################
on_command {
: match "examine ladder" {
: if ( is_present "ladder" ) {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
: match "examine woman" {
: if (is_present "old_woman") {
: print "SHE LOOKS AT YOU WITH AN INTENSE GLARE." ;
}
}
: match "examine lamp" {
: if (is_present "lamp") {
: print "IT'S OLD AND TARNISHED." ;
}
}
: match "examine fish" {
: if (is_present "red_fish") {
: print "IT STINKS!" ;
}
}
: match "examine sword" {
: if (is_present "short_sword") {
: print "INSCRIBED UPON IT ARE THE WORDS 'GOOD LUCK' ~~ MERLIN." ;
}
}
: match "examine bush" {
: if (is_present "bush" && has_not_created "stone_key") {
: print "YOU FIND SOMETHING!" ;
: create "stone_key" ;
: press_any_key ;
: redescribe ;
}
}
: match "examine logs" {
: if (is_present "logs" && has_not_created "axe") {
: print "YOU FIND AN AXE!" ;
: create "axe" ;
: press_any_key ;
: redescribe ;
}
}
: redescribe;
}
}
}
}
########################################
# Subroutines #
########################################
subroutines {
end_game : subroutine {
: press_any_key ;
: clear_screen;
: print_graphic "game_over" ;
: print "Your quest is over .........." ;
: turns ;
: end_game ;
}
// Placeholders used for documentation purposes only as graphic data is too large to place in document.
assets {
graphics {
armoury : placeholder ;
arthur : placeholder ;
banquet_hall : placeholder ;
birwood_bush : placeholder ;
castle_approach_1 : placeholder ;
castle_approach_2 : placeholder ;
castle_approach_2a : placeholder ;
castle_porch : placeholder ;
chasm : placeholder ;
cold_room : placeholder ;
cold_room_2 : placeholder ;
deep_inside_birwood : placeholder ;
demon_knight_road : placeholder ;
demon_knight_road_2 : placeholder ;
drafty_room : placeholder ;
drafty_room_2 : placeholder ;
edge_of_birwood : placeholder ;
ending_screen : placeholder ;
excalibur_loading : placeholder ;
foot_of_tree : placeholder ;
foot_of_tree_2 : placeholder ;
game_over : placeholder ;
hut : placeholder ;
lamp_seller_on_road : placeholder ;
lamp_seller_on_road_2 : placeholder ;
most_splendid_room : placeholder ;
most_splendid_room_2 : placeholder ;
ornate_antechamber : placeholder ;
portcullis : placeholder ;
portcullis_2 : placeholder ;
road_1 : placeholder ;
road_2 : placeholder ;
road_3 : placeholder ;
road_4 : placeholder ;
salt_mine_1 : placeholder ;
salt_mine_2 : placeholder ;
salt_mine_3 : placeholder ;
top_of_tree : placeholder ;
winch_room : placeholder ;
worm_room : placeholder ;
worm_room_2 : placeholder ;
}
}
The Rockworm puzzle is the most complex puzzle to code, so please take your time to read and study this
section.
The Rockworm lives in the salt mine under the castle and is blocking the way forward.
Rockworms are sensitive to light, so lighting the lamp is all that is required to scare the worm away.
The worm is blocking further access to the salt mines, and salt is required to tackle the Ice Creature problem.
Rather than change the original logic, we will implement the mechanics here, as the game is short, and a death
will only cost the player a few minutes of time.
The game also has save slots, so if the player feels like something is dangerous they can save the game.
6.13.2. Outcomes
There are 3 different outcomes to this puzzle.
1. Solution
The solution to getting past the rockworm is the light the lamp (which was purchased from the old woman) in
the same room as the worm. The worm will make a noise, and get out of the way (the worm doesn’t like light).
2. Sudden Death 1
The first way is to linger in the worm’s location for too long. The game will warn the player before the worm
will make its fatal move, then on the next move, if the player has not moved away, the player will 'die'.
3. Sudden Death 2
The second is to try to move beyond the worm. This is a variant of the knight logic (where moving past the
demon knight would end the game).
The original logic of the game had a restriction that it was only possible to light the lamp
NOTE once, and if you did it at the wrong time, the game was unwinnable. This version of the
game removes that unwinnable state.
subroutines {}
worm_attack : subroutine {
: print "THE ROCKWORM RISES UP AND TAKES YOU IN ITS GLEAMING MANDIBLES." ;
: gosub "end_game" ;
}
This will make sure that if the player attempts to move past the worm, they will see the message "THE
ROCKWORM RISES UP AND TAKES YOU IN ITS GLEAMING MANDIBLES.", and then the game will end.
barriers {}
worm : block {
location = salt_mine_3
gosub = worm_attack
block_when_exists = rockworm
show_blocked_exit = true
}
Timed Events
Adventuron supports timed events. A timed even is something that will happen after a certain amount of turns
of the game (entering commands).
To perform a timed event, we need to put some if statements in the on_tick {} block of code. The on_tick{}
section of code is executed after the player has submitted a command.
This can be after the screen is redrawn (such as changing location), or it could be after any command is
executed (such as GET LAMP or EXAMINE BUSH).
In Excalibur, we want the worm to attack if the player stays in the same location as the worm for 4 turns. We
also want to issue a warning to the player after 3 turns that the worm is getting ready to attack.
on_tick {
: if (is_present "rockworm" ) {
: if (linger() == 3) {
: print "THE ROCKWORM STARTS MOVING TOWARDS YOU" ;
}
: if (linger() == 4) {
: gosub "worm_attack" ;
}
}
}
The next part is an if () {} statement that checks to see if the rockworm is present in the same scene / location of
the game. The inner if statements will only be executed if we are sharing a scene with the rockworm.
The first INNER IF STATEMENT tests to see if we have been 3 turns in the current location. If we have then it
prints "THE ROCKWORM STARTS MOVING TOWARDS YOU".
The second INNER IF STATEMENT tests to see if we have been 4 turns in the current location. If we have, then it
prints "THE ROCKWORM RISES UP AND TAKES YOU IN ITS GLEAMING MANDIBLES.", and it executs the
end_game subroutine. (Game over).
Numbers can be turned into a yes or no answer by comparing them against other numbers.
Boolean Variables
A boolean variable is a way of storing if something is a yes answer (true) or a no answer (false).
In Excalibur, we create the 'is_light_lit' boolean variable, which is initially set to have a 'false' value. A 'false'
value is the same as a 'no' value. So, this section of code tells the game, that at the start of the game, we should
remember that we light is not lit.
We can change the VALUE of a VARIABLE during the game, and we can ask questions about the current content
of a variable from anywhere inside our game code. So, later on in the code, we can store a TRUE value inside
'is_light_lit'…. But that comes later.
booleans {
is_light_lit : boolean "false" ;
}
The boolean variable is created at root level (not inside any other block of code).
We set the 'is_light_lit' boolean variable to a value of TRUE (we use this to inform the player that the light
has gone out if they change location).
If the player lights the lamp in the presence of the Rockworm, the following happens:
We print the message "THE ROCKWORM’S SENSITIVE EYES ARE SURPRISED BY THE STRONG LIGHT AND IT
RETREATS DOWN ITS BURROW …."
We change the graphic of 'worm_room' location to the replacement picture 'worm_room_2' (room without
the worm).
Redescribe the current location (redraw the graphic and clear previous commands from the screen).
on_command{}
on_describe{}
The on_describe{} code block is executed when a scene is described, either by moving to a new location, or by
typing (or clicking/touching/saying) "look".
It is usually used to add additional information to a scene or to trigger some event (triggering an event means
performing some code that tells the player new information or changes the game).
We will use this block to make sure that we report that the light (from the lamp) goes out when we change
location. The purpose of this is so that the player must always type LIGHT LAMP to solve the Rockworm
puzzle.
If the player could just light the lamp and carry it around indefinately, then they may solve the Rockworm
puzzle accidentally.
Putting this in the on_redescribe {} means that whatever location is travelled to after lighting the lamp, the
light is described as going out, so the player knows that lighting the lamp will still do something if they do it
again.
on_describe {
: if (is_light_lit) {
: print "THE LIGHT'S GONE OUT." ;
: set_false "is_light_lit" ;
}
}
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
//chasm, south, edge_of_birwood,
edge_of_birwood, south, deep_inside_birwood,
deep_inside_birwood, west, birwood_bush,
demon_knight_road, east, castle_approach_1,
castle_approach_1, east, castle_approach_2,
castle_approach_2, east, castle_porch,
castle_porch, east, banquet_hall,
banquet_hall, north, portcullis,
banquet_hall, south, drafty_room,
portcullis, north, most_splendid_room,
most_splendid_room, west, arthur,
drafty_room, east, ornate_antechamber,
drafty_room, down, salt_mine_1,
ornate_antechamber, east, cold_room,
cold_room, north, winch_room,
winch_room, east, armoury,
salt_mine_1, west, salt_mine_2,
salt_mine_1, south, worm_room,
worm_room, south, salt_mine_3,
]
########################################
# Object #
########################################
objects {
########################################
# Booleans #
########################################
booleans {
is_ladder_standing : boolean "false" ;
is_light_lit : boolean "false" ;
}
########################################
# Barriers #
########################################
barriers {
castle_door : door {
key = stone_key
from = castle_approach_2
to = castle_porch
on_unlock {
: print "YOU UNLOCK IT WITH THE KEY, WHICH JAMS IN THE LOCK." ;
: destroy "stone_key" ;
}
on_open {
: set_graphic graphic = "castle_approach_2a" target = "castle_approach_2" ;
: redescribe ;
}
on_close {
: set_graphic graphic = "castle_approach_2" target = "castle_approach_2" ;
: redescribe ;
}
}
tree : block {
location = top_of_tree
message = YOU CAN'T FIND YOUR GRIP
block_when_not = is_ladder_standing
}
knight : block {
location = castle_approach_1
gosub = lose_fight
block_when_exists = demon_knight
show_blocked_exit = true
trapdoor : block {
location = salt_mine_1
message = THE TRAPDOOR IS JAMMED SHUT!
block_when_exists = trapdoor
}
worm : block {
location = salt_mine_3
gosub = worm_attack
block_when_exists = rockworm
show_blocked_exit = true
}
########################################
# On Describe #
########################################
on_describe {
: if (is_light_lit) {
: print "THE LIGHT'S GONE OUT." ;
: set_false "is_light_lit" ;
}
}
########################################
# On Describe #
########################################
on_tick {
: if (is_present "rockworm" ) {
: if (linger() == 3) {
: print "THE ROCKWORM STARTS MOVING TOWARDS YOU" ;
}
: if (linger() == 4) {
: gosub "worm_attack" ;
}
}
}
########################################
# On Command #
########################################
on_command {
: match "examine ladder" {
: if ( is_present "ladder" ) {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
: match "examine woman" {
: if (is_present "old_woman") {
: print "SHE LOOKS AT YOU WITH AN INTENSE GLARE." ;
}
}
: match "examine lamp" {
: if (is_present "lamp") {
: print "IT'S OLD AND TARNISHED." ;
}
}
: match "examine fish" {
: if (is_present "red_fish") {
: print "THE ROCKWORM'S SENSITIVE EYES ARE SURPRISED BY THE STRONG LIGHT AND IT RETREATS DOWN ITS
BURROW ...." ;
: destroy "rockworm" ;
: set_graphic target = "worm_room" graphic = "worm_room_2" ;
: press_any_key ;
: redescribe ;
}
: else {
: print "IT EMITS A BRIGHT LIGHT." ;
: done ;
}
}
}
########################################
# Subroutines #
########################################
subroutines {
end_game : subroutine {
: press_any_key ;
: clear_screen;
: print_graphic "game_over";
: print "Your quest is over .........." ;
: turns ;
: end_game ;
}
worm_attack : subroutine {
: print "THE ROCKWORM RISES UP AND TAKES YOU IN ITS GLEAMING MANDIBLES." ;
: gosub "end_game" ;
}
// Placeholders used for documentation purposes only as graphic data is too large to place in document.
assets {
graphics {
armoury : placeholder ;
arthur : placeholder ;
banquet_hall : placeholder ;
birwood_bush : placeholder ;
castle_approach_1 : placeholder ;
castle_approach_2 : placeholder ;
castle_approach_2a : placeholder ;
castle_porch : placeholder ;
chasm : placeholder ;
cold_room : placeholder ;
cold_room_2 : placeholder ;
deep_inside_birwood : placeholder ;
demon_knight_road : placeholder ;
demon_knight_road_2 : placeholder ;
drafty_room : placeholder ;
drafty_room_2 : placeholder ;
edge_of_birwood : placeholder ;
ending_screen : placeholder ;
excalibur_loading : placeholder ;
foot_of_tree : placeholder ;
foot_of_tree_2 : placeholder ;
game_over : placeholder ;
hut : placeholder ;
lamp_seller_on_road : placeholder ;
lamp_seller_on_road_2 : placeholder ;
most_splendid_room : placeholder ;
most_splendid_room_2 : placeholder ;
ornate_antechamber : placeholder ;
portcullis : placeholder ;
portcullis_2 : placeholder ;
road_1 : placeholder ;
road_2 : placeholder ;
road_3 : placeholder ;
road_4 : placeholder ;
salt_mine_1 : placeholder ;
salt_mine_2 : placeholder ;
salt_mine_3 : placeholder ;
top_of_tree : placeholder ;
winch_room : placeholder ;
worm_room : placeholder ;
worm_room_2 : placeholder ;
}
}
You must throw salt at the Ice Creature, and then it dissolves into nothingness.
What did the Ice Creature ever do to anyone apart from block the path to the winch? Why was the Ice creature
guarding the winch? Did it expect that this would be its final job? Who will take care of the icicles now?
Anyway, this again is a simple blocking arrangement, then graphic swap (to a version of the graphic without
the creature) upon typing the words THROW SALT when in the same room as the ice creature, and holding the
salt.
First, let’s add the block, and the description of the block.
This block itsel is not a 'sudden death' block. It just tells the player 'THE ICE CREATURE WILL NOT ALLOW IT …
'.
barriers {}
ice_creature : block {
location = winch_room
message = THE ICE CREATURE WILL NOT ALLOW IT ...
block_when_exists = ice_creature
show_blocked_exit = true
}
Now we add the on_command{} match command to respond to "throw salt". Perhaps you can figure out what
to type now without reading the next part?
on_command {}
The Ice Creature is another "sudden death" type monster if you stay in the room more than one turn.
on_tick {}
: if (is_present "ice_creature") {
: if (linger() == 1) {
: print "THE ICE CREATURE TAKES YOU IN A FREEZING GRIP" ;
: gosub "end_game" ;
}
}
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
//chasm, south, edge_of_birwood,
edge_of_birwood, south, deep_inside_birwood,
deep_inside_birwood, west, birwood_bush,
demon_knight_road, east, castle_approach_1,
castle_approach_1, east, castle_approach_2,
castle_approach_2, east, castle_porch,
castle_porch, east, banquet_hall,
banquet_hall, north, portcullis,
banquet_hall, south, drafty_room,
portcullis, north, most_splendid_room,
most_splendid_room, west, arthur,
drafty_room, east, ornate_antechamber,
drafty_room, down, salt_mine_1,
ornate_antechamber, east, cold_room,
cold_room, north, winch_room,
winch_room, east, armoury,
salt_mine_1, west, salt_mine_2,
salt_mine_1, south, worm_room,
worm_room, south, salt_mine_3,
]
########################################
# Objects #
########################################
objects {
########################################
# Booleans #
########################################
booleans {
is_ladder_standing : boolean "false" ;
is_light_lit : boolean "false" ;
}
########################################
# Blocks #
########################################
barriers {
castle_door : door {
key = stone_key
from = castle_approach_2
to = castle_porch
on_unlock {
: print "YOU UNLOCK IT WITH THE KEY, WHICH JAMS IN THE LOCK." ;
: destroy "stone_key" ;
}
on_open {
: set_graphic graphic = "castle_approach_2a" target = "castle_approach_2" ;
: redescribe ;
}
on_close {
: set_graphic graphic = "castle_approach_2" target = "castle_approach_2" ;
: redescribe ;
}
}
tree : block {
location = top_of_tree
message = YOU CAN'T FIND YOUR GRIP
block_when_not = is_ladder_standing
}
knight : block {
location = castle_approach_1
gosub = lose_fight
block_when_exists = demon_knight
show_blocked_exit = true
trapdoor : block {
location = salt_mine_1
message = THE TRAPDOOR IS JAMMED SHUT!
block_when_exists = trapdoor
}
worm : block {
location = salt_mine_3
gosub = worm_attack
block_when_exists = rockworm
show_blocked_exit = true
}
ice_creature : block {
location = winch_room
message = THE ICE CREATURE WILL NOT ALLOW IT ...
block_when_exists = ice_creature
show_blocked_exit = true
}
########################################
# On Describe #
########################################
on_describe {
: if (is_light_lit) {
: print "THE LIGHT'S GONE OUT." ;
: set_false "is_light_lit" ;
}
}
########################################
# On Describe #
########################################
on_tick {
: if (is_present "rockworm" ) {
: if (linger() == 3) {
: print "THE ROCKWORM STARTS MOVING TOWARDS YOU" ;
}
: if (linger() == 4) {
: gosub "worm_attack" ;
}
}
: if (is_present "ice_creature") {
: if (linger() == 1) {
: print "THE ICE CREATURE TAKES YOU IN A FREEZING GRIP" ;
: gosub "end_game" ;
}
}
}
########################################
# On Command #
########################################
on_command {
: match "examine ladder" {
: if ( is_present "ladder" ) {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
: match "examine woman" {
: if (is_present "old_woman") {
: print "SHE LOOKS AT YOU WITH AN INTENSE GLARE." ;
}
}
: match "examine lamp" {
: if (is_present "lamp") {
: print "IT'S OLD AND TARNISHED." ;
}
}
: match "examine fish" {
: if (is_present "red_fish") {
: print "IT STINKS!" ;
}
}
: match "examine sword" {
: if (is_present "short_sword") {
: print "INSCRIBED UPON IT ARE THE WORDS 'GOOD LUCK' ~~ MERLIN." ;
}
}
: match "examine bush" {
: if (is_present "bush" && has_not_created "stone_key") {
: print "YOU FIND SOMETHING!" ;
: create "stone_key" ;
: press_any_key ;
: redescribe ;
}
}
: match "examine logs" {
: if (is_present "logs" && has_not_created "axe") {
: print "YOU FIND AN AXE!" ;
: create "axe" ;
: press_any_key ;
: redescribe ;
}
}
: redescribe ;
}
: else {
: print "A FRUITLESS EXERCISE!" ;
: done ;
}
}
}
########################################
# Subroutines #
########################################
subroutines {
: press_any_key ;
: destroy "demon_knight" ;
: destroy "short_sword" ;
: set_graphic graphic = "demon_knight_road_2" target = "demon_knight_road" ;
: redescribe ;
}
end_game : subroutine {
: press_any_key ;
: clear_screen;
: print_graphic "game_over";
: print "Your quest is over .........." ;
: turns ;
: end_game ;
}
worm_attack : subroutine {
: print "THE ROCKWORM RISES UP AND TAKES YOU IN ITS GLEAMING MANDIBLES." ;
: gosub "end_game" ;
}
// Placeholders used for documentation purposes only as graphic data is too large to place in document.
assets {
graphics {
armoury : placeholder ;
arthur : placeholder ;
banquet_hall : placeholder ;
birwood_bush : placeholder ;
castle_approach_1 : placeholder ;
castle_approach_2 : placeholder ;
castle_approach_2a : placeholder ;
castle_porch : placeholder ;
chasm : placeholder ;
cold_room : placeholder ;
cold_room_2 : placeholder ;
deep_inside_birwood : placeholder ;
demon_knight_road : placeholder ;
demon_knight_road_2 : placeholder ;
drafty_room : placeholder ;
drafty_room_2 : placeholder ;
edge_of_birwood : placeholder ;
ending_screen : placeholder ;
excalibur_loading : placeholder ;
foot_of_tree : placeholder ;
foot_of_tree_2 : placeholder ;
game_over : placeholder ;
hut : placeholder ;
lamp_seller_on_road : placeholder ;
lamp_seller_on_road_2 : placeholder ;
most_splendid_room : placeholder ;
most_splendid_room_2 : placeholder ;
ornate_antechamber : placeholder ;
portcullis : placeholder ;
portcullis_2 : placeholder ;
road_1 : placeholder ;
road_2 : placeholder ;
road_3 : placeholder ;
road_4 : placeholder ;
salt_mine_1 : placeholder ;
salt_mine_2 : placeholder ;
salt_mine_3 : placeholder ;
top_of_tree : placeholder ;
winch_room : placeholder ;
worm_room : placeholder ;
worm_room_2 : placeholder ;
}
}
The Winch Room contains the winch that will raise (open) the portcullis leading to Crania and Arthur.
The portcullis (a kind of gate/door that goes up and down). The portcullis is in a different room to the winch.
The first 'puzzle' is that the winch is jammed and needs some oil.
Lucky for the player that there is a can of oil in the room where the ice creature met its salty demise.
Turning the winch will remove the block on the most splendid room and change the graphic in the portcullis
room to show an open door instead of a closed portcullis.
At the start of the game we have not oiled or turned the winch, so they are both set to a value of false initially.
booleans {}
Next, let’s make a block for the most splendid room (which is north of the portcullis room). The block is a
simple block that displays the message "YOU CAN’T GO THAT WAY.".
This block uses the 'block_when_not' condition, which means, block when a boolean variable contains a 'false'
value.
It’s easy to understand if we read it like we see it (even though it is slightly strange english:
barriers {}
portcullis : block {
location = most_splendid_room
message = YOU CAN'T GO THAT WAY.
block_when_not = has_turned_winch
}
Finally, let’s wire up the command handler for OIL WINCH and TURN WINCH:
on_command {}
We can perform an conditional action based on if a boolean variable (or boolean expression) contains a true
(or yes) answer, or a false (or no) answer.
Imagine that the has_oiled_winch boolean variable was called oiled_winch. It would be difficult to know if
the identifier represented a fact (such as something is true or false), or an object.
The way we choose to name something is called a naming convention. These are are very common in
programming, and it really makes things a lot easier if you follow a pattern - even if the pattern is unique to
yourself.
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
//chasm, south, edge_of_birwood,
edge_of_birwood, south, deep_inside_birwood,
deep_inside_birwood, west, birwood_bush,
demon_knight_road, east, castle_approach_1,
castle_approach_1, east, castle_approach_2,
castle_approach_2, east, castle_porch,
castle_porch, east, banquet_hall,
banquet_hall, north, portcullis,
banquet_hall, south, drafty_room,
portcullis, north, most_splendid_room,
most_splendid_room, west, arthur,
drafty_room, east, ornate_antechamber,
drafty_room, down, salt_mine_1,
ornate_antechamber, east, cold_room,
cold_room, north, winch_room,
winch_room, east, armoury,
salt_mine_1, west, salt_mine_2,
salt_mine_1, south, worm_room,
worm_room, south, salt_mine_3,
]
########################################
# Objects #
########################################
objects {
########################################
# Booleans #
########################################
booleans {
is_ladder_standing : boolean "false" ;
is_light_lit : boolean "false" ;
has_oiled_winch : boolean "false" ;
has_turned_winch : boolean "false" ;
}
########################################
# Blocks #
########################################
barriers {
castle_door : door {
key = stone_key
from = castle_approach_2
to = castle_porch
on_unlock {
: print "YOU UNLOCK IT WITH THE KEY, WHICH JAMS IN THE LOCK." ;
: destroy "stone_key" ;
}
on_open {
: set_graphic graphic = "castle_approach_2a" target = "castle_approach_2" ;
: redescribe ;
}
on_close {
: set_graphic graphic = "castle_approach_2" target = "castle_approach_2" ;
: redescribe ;
}
}
tree : block {
location = top_of_tree
knight : block {
location = castle_approach_1
gosub = lose_fight
block_when_exists = demon_knight
show_blocked_exit = true
}
trapdoor : block {
location = salt_mine_1
message = THE TRAPDOOR IS JAMMED SHUT!
block_when_exists = trapdoor
}
worm : block {
location = salt_mine_3
gosub = worm_attack
block_when_exists = rockworm
show_blocked_exit = true
}
ice_creature : block {
location = winch_room
message = THE ICE CREATURE WILL NOT ALLOW IT ...
block_when_exists = ice_creature
show_blocked_exit = true
}
portcullis : block {
location = most_splendid_room
message = YOU CAN'T GO THAT WAY.
block_when_not = has_turned_winch
}
########################################
# On Describe #
########################################
on_describe {
: if (is_light_lit) {
: print "THE LIGHT'S GONE OUT." ;
: set_false "is_light_lit" ;
}
}
########################################
# On Describe #
########################################
on_tick {
: if (is_present "rockworm" ) {
: if (linger() == 3) {
: print "THE ROCKWORM STARTS MOVING TOWARDS YOU" ;
}
: if (linger() == 4) {
: gosub "worm_attack" ;
}
}
: if (is_present "ice_creature") {
: if (linger() == 1) {
########################################
# On Command #
########################################
on_command {
: match "examine ladder" {
: if ( is_present "ladder" ) {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
: match "examine woman" {
: if (is_present "old_woman") {
: print "SHE LOOKS AT YOU WITH AN INTENSE GLARE." ;
}
}
: match "examine lamp" {
: if (is_present "lamp") {
: print "IT'S OLD AND TARNISHED." ;
}
}
: match "examine fish" {
: if (is_present "red_fish") {
: print "IT STINKS!" ;
}
}
: match "examine sword" {
: if (is_present "short_sword") {
: print "INSCRIBED UPON IT ARE THE WORDS 'GOOD LUCK' ~~ MERLIN." ;
}
}
: match "examine bush" {
: if (is_present "bush" && has_not_created "stone_key") {
: print "YOU FIND SOMETHING!" ;
: create "stone_key" ;
: press_any_key ;
: redescribe ;
}
}
: match "examine logs" {
: if (is_present "logs" && has_not_created "axe") {
: print "YOU FIND AN AXE!" ;
: create "axe" ;
: press_any_key ;
: redescribe ;
}
}
: set_true "is_ladder_standing" ;
: set_graphic target = "foot_of_tree" graphic = "foot_of_tree_2" ;
: redescribe;
}
}
}
}
}
}
########################################
# Subroutines #
########################################
subroutines {
end_game : subroutine {
: press_any_key ;
: clear_screen;
: print_graphic "game_over" ;
: print "Your quest is over .........." ;
: turns ;
: end_game ;
}
worm_attack : subroutine {
: print "THE ROCKWORM RISES UP AND TAKES YOU IN ITS GLEAMING MANDIBLES." ;
: gosub "end_game" ;
}
// Placeholders used for documentation purposes only as graphic data is too large to place in document.
assets {
graphics {
armoury : placeholder ;
arthur : placeholder ;
banquet_hall : placeholder ;
birwood_bush : placeholder ;
castle_approach_1 : placeholder ;
castle_approach_2 : placeholder ;
castle_approach_2a : placeholder ;
castle_porch : placeholder ;
chasm : placeholder ;
cold_room : placeholder ;
cold_room_2 : placeholder ;
deep_inside_birwood : placeholder ;
demon_knight_road : placeholder ;
demon_knight_road_2 : placeholder ;
drafty_room : placeholder ;
drafty_room_2 : placeholder ;
edge_of_birwood : placeholder ;
ending_screen : placeholder ;
excalibur_loading : placeholder ;
foot_of_tree : placeholder ;
foot_of_tree_2 : placeholder ;
game_over : placeholder ;
hut : placeholder ;
lamp_seller_on_road : placeholder ;
lamp_seller_on_road_2 : placeholder ;
most_splendid_room : placeholder ;
most_splendid_room_2 : placeholder ;
ornate_antechamber : placeholder ;
portcullis : placeholder ;
portcullis_2 : placeholder ;
road_1 : placeholder ;
road_2 : placeholder ;
road_3 : placeholder ;
road_4 : placeholder ;
salt_mine_1 : placeholder ;
salt_mine_2 : placeholder ;
salt_mine_3 : placeholder ;
top_of_tree : placeholder ;
winch_room : placeholder ;
worm_room : placeholder ;
worm_room_2 : placeholder ;
}
}
Now that the portcullis is up, we have access to the MOST SPLENDID ROOM, which is a yellow version of a
regular room - but this one has CRANIA, THE EVIL SORCERESS in it, and she’s throwing a spell your way.
We deal with the spell by typing REFLECT SPELL or DEFLECT SPELL whilst holding the sword, EXCALIBUR,
which was in the armoury next to the winch room.
If you type those magic words, then the spell will be reflected back at CRANIA, and the room is then clear.
This is very easy to write the code for, it’s basically the same logic as the Ice Creature.
barriers {}
crania : block {
location = arthur
message = YOU CAN'T GET PAST
block_when_exists = spell
}
on_command{}
on_tick{}
: if (is_present "spell") {
: if (linger() == 1) {
: print "THE SPELL HITS YOU HEAD ON, PETRIFYING YOU INSTANTLY." ;
: gosub "end_game" ;
}
}
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
//chasm, south, edge_of_birwood,
edge_of_birwood, south, deep_inside_birwood,
deep_inside_birwood, west, birwood_bush,
demon_knight_road, east, castle_approach_1,
castle_approach_1, east, castle_approach_2,
castle_approach_2, east, castle_porch,
castle_porch, east, banquet_hall,
banquet_hall, north, portcullis,
banquet_hall, south, drafty_room,
portcullis, north, most_splendid_room,
most_splendid_room, west, arthur,
drafty_room, east, ornate_antechamber,
drafty_room, down, salt_mine_1,
ornate_antechamber, east, cold_room,
cold_room, north, winch_room,
winch_room, east, armoury,
salt_mine_1, west, salt_mine_2,
salt_mine_1, south, worm_room,
worm_room, south, salt_mine_3,
]
########################################
# Objects #
########################################
objects {
########################################
# Booleans #
########################################
booleans {
is_ladder_standing : boolean "false" ;
is_light_lit : boolean "false" ;
has_oiled_winch : boolean "false" ;
has_turned_winch : boolean "false" ;
}
########################################
# Blocks #
########################################
barriers {
castle_door : door {
key = stone_key
from = castle_approach_2
to = castle_porch
on_unlock {
: print "YOU UNLOCK IT WITH THE KEY, WHICH JAMS IN THE LOCK." ;
: destroy "stone_key" ;
}
on_open {
: set_graphic graphic = "castle_approach_2a" target = "castle_approach_2" ;
: redescribe ;
}
on_close {
: set_graphic graphic = "castle_approach_2" target = "castle_approach_2" ;
: redescribe ;
}
}
tree : block {
location = top_of_tree
message = YOU CAN'T FIND YOUR GRIP
block_when_not = is_ladder_standing
}
knight : block {
location = castle_approach_1
gosub = lose_fight
block_when_exists = demon_knight
show_blocked_exit = true
}
trapdoor : block {
location = salt_mine_1
message = THE TRAPDOOR IS JAMMED SHUT!
block_when_exists = trapdoor
}
worm : block {
location = salt_mine_3
gosub = worm_attack
block_when_exists = rockworm
show_blocked_exit = true
}
ice_creature : block {
location = winch_room
message = THE ICE CREATURE WILL NOT ALLOW IT ...
block_when_exists = ice_creature
show_blocked_exit = true
}
portcullis : block {
location = most_splendid_room
message = YOU CAN'T GO THAT WAY.
block_when_not = has_turned_winch
}
crania : block {
location = arthur
message = YOU CAN'T GET PAST
block_when_exists = spell
}
########################################
# On Describe #
########################################
on_describe {
: if (is_light_lit) {
: print "THE LIGHT'S GONE OUT." ;
: set_false "is_light_lit" ;
}
}
########################################
# On Describe #
########################################
on_tick {
: if (is_present "rockworm" ) {
: if (linger() == 3) {
: print "THE ROCKWORM STARTS MOVING TOWARDS YOU" ;
}
: if (linger() == 4) {
: gosub "worm_attack" ;
}
}
: if (is_present "ice_creature") {
: if (linger() == 1) {
: print "THE ICE CREATURE TAKES YOU IN A FREEZING GRIP" ;
: gosub "end_game" ;
}
}
: if (is_present "spell") {
: if (linger() == 1) {
: print "THE SPELL HITS YOU HEAD ON, PETRIFYING YOU INSTANTLY." ;
: gosub "end_game" ;
}
}
}
########################################
# On Command #
########################################
on_command {
: match "examine ladder" {
: if ( is_present "ladder" ) {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
: match "examine woman" {
: if (is_present "old_woman") {
: print "SHE LOOKS AT YOU WITH AN INTENSE GLARE." ;
}
}
: match "examine lamp" {
: if (is_present "lamp") {
: print "IT'S OLD AND TARNISHED." ;
}
}
: match "examine fish" {
: if (is_present "red_fish") {
: print "IT STINKS!" ;
}
}
: match "examine sword" {
: if (is_present "short_sword") {
: print "INSCRIBED UPON IT ARE THE WORDS 'GOOD LUCK' ~~ MERLIN." ;
}
}
: match "examine bush" {
: if (is_present "bush" && has_not_created "stone_key") {
: print "YOU FIND SOMETHING!" ;
: create "stone_key" ;
: press_any_key ;
: redescribe ;
}
}
: match "examine logs" {
: if (is_present "logs" && has_not_created "axe") {
: print "YOU FIND AN AXE!" ;
: create "axe" ;
: press_any_key ;
: redescribe ;
}
}
: redescribe ;
}
: else {
: match "buy lamp" {
: print "'CROSS MY PALM WITH SILVER!'" ;
}
}
}
}
########################################
# Subroutines #
########################################
subroutines {
end_game : subroutine {
: press_any_key ;
: clear_screen;
: print_graphic "game_over" ;
: print "Your quest is over .........." ;
: turns ;
: end_game ;
}
worm_attack : subroutine {
: print "THE ROCKWORM RISES UP AND TAKES YOU IN ITS GLEAMING MANDIBLES." ;
: gosub "end_game" ;
}
// Placeholders used for documentation purposes only as graphic data is too large to place in document.
assets {
graphics {
armoury : placeholder ;
arthur : placeholder ;
banquet_hall : placeholder ;
birwood_bush : placeholder ;
castle_approach_1 : placeholder ;
castle_approach_2 : placeholder ;
castle_approach_2a : placeholder ;
castle_porch : placeholder ;
chasm : placeholder ;
cold_room : placeholder ;
cold_room_2 : placeholder ;
deep_inside_birwood : placeholder ;
demon_knight_road : placeholder ;
demon_knight_road_2 : placeholder ;
drafty_room : placeholder ;
drafty_room_2 : placeholder ;
edge_of_birwood : placeholder ;
ending_screen : placeholder ;
excalibur_loading : placeholder ;
foot_of_tree : placeholder ;
foot_of_tree_2 : placeholder ;
game_over : placeholder ;
hut : placeholder ;
lamp_seller_on_road : placeholder ;
lamp_seller_on_road_2 : placeholder ;
most_splendid_room : placeholder ;
most_splendid_room_2 : placeholder ;
ornate_antechamber : placeholder ;
portcullis : placeholder ;
portcullis_2 : placeholder ;
road_1 : placeholder ;
road_2 : placeholder ;
road_3 : placeholder ;
road_4 : placeholder ;
salt_mine_1 : placeholder ;
salt_mine_2 : placeholder ;
salt_mine_3 : placeholder ;
top_of_tree : placeholder ;
winch_room : placeholder ;
worm_room : placeholder ;
worm_room_2 : placeholder ;
}
}
6.17.1. Wake Up !
Waking Arthur is a very simple puzzle. Arthur is asleep, the obvious action is to try to wake him. Typing WAKE
ARTHUR or WAKE KING should show the ending screen of the game (good ending), then end the game.
on_command{}
If you are building your own game, you can construct a textual message, or make your own ending graphic.
There are still some minor tasks to perform to make the experience better for the player, and to package the
game, but it’s time to take a rest and enjoy what you have achieved so far.
########################################
# Adventuron #
########################################
start_at = hut
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
road_3, east, road_4,
road_4, north, foot_of_tree,
road_4, south, lamp_seller_on_road,
lamp_seller_on_road, east, demon_knight_road,
lamp_seller_on_road, south, chasm,
foot_of_tree, up, top_of_tree,
//chasm, south, edge_of_birwood,
edge_of_birwood, south, deep_inside_birwood,
deep_inside_birwood, west, birwood_bush,
demon_knight_road, east, castle_approach_1,
castle_approach_1, east, castle_approach_2,
castle_approach_2, east, castle_porch,
castle_porch, east, banquet_hall,
banquet_hall, north, portcullis,
banquet_hall, south, drafty_room,
########################################
# Objects #
########################################
objects {
########################################
# Booleans #
########################################
booleans {
is_ladder_standing : boolean "false" ;
is_light_lit : boolean "false" ;
has_oiled_winch : boolean "false" ;
has_turned_winch : boolean "false" ;
}
########################################
# Blocks #
########################################
barriers {
castle_door : door {
key = stone_key
from = castle_approach_2
to = castle_porch
on_unlock {
: print "YOU UNLOCK IT WITH THE KEY, WHICH JAMS IN THE LOCK." ;
: destroy "stone_key" ;
}
on_open {
: set_graphic graphic = "castle_approach_2a" target = "castle_approach_2" ;
: redescribe ;
}
on_close {
: set_graphic graphic = "castle_approach_2" target = "castle_approach_2" ;
: redescribe ;
}
}
tree : block {
location = top_of_tree
message = YOU CAN'T FIND YOUR GRIP
block_when_not = is_ladder_standing
}
knight : block {
location = castle_approach_1
gosub = lose_fight
block_when_exists = demon_knight
show_blocked_exit = true
}
trapdoor : block {
location = salt_mine_1
message = THE TRAPDOOR IS JAMMED SHUT!
block_when_exists = trapdoor
}
worm : block {
location = salt_mine_3
gosub = worm_attack
block_when_exists = rockworm
show_blocked_exit = true
}
ice_creature : block {
location = winch_room
message = THE ICE CREATURE WILL NOT ALLOW IT ...
block_when_exists = ice_creature
show_blocked_exit = true
}
portcullis : block {
location = most_splendid_room
message = YOU CAN'T GO THAT WAY.
block_when_not = has_turned_winch
}
crania : block {
location = arthur
message = YOU CAN'T GET PAST
block_when_exists = spell
########################################
# On Describe #
########################################
on_describe {
: if (is_light_lit) {
: print "THE LIGHT'S GONE OUT." ;
: set_false "is_light_lit" ;
}
}
########################################
# On Describe #
########################################
on_tick {
: if (is_present "rockworm" ) {
: if (linger() == 3) {
: print "THE ROCKWORM STARTS MOVING TOWARDS YOU" ;
}
: if (linger() == 4) {
: gosub "worm_attack" ;
}
}
: if (is_present "ice_creature") {
: if (linger() == 1) {
: print "THE ICE CREATURE TAKES YOU IN A FREEZING GRIP" ;
: gosub "end_game" ;
}
}
: if (is_present "spell") {
: if (linger() == 1) {
: print "THE SPELL HITS YOU HEAD ON, PETRIFYING YOU INSTANTLY." ;
: gosub "end_game" ;
}
}
}
########################################
# On Command #
########################################
on_command {
: match "examine ladder" {
: if ( is_present "ladder" ) {
: print "A LONG POLE WITH RUNGS ATTACHED." ;
}
}
: match "examine woman" {
: if (is_present "old_woman") {
: print "SHE LOOKS AT YOU WITH AN INTENSE GLARE." ;
}
}
: match "examine lamp" {
: if (is_present "lamp") {
: print "IT'S OLD AND TARNISHED." ;
}
}
: match "examine fish" {
: if (is_present "red_fish") {
: print "IT STINKS!" ;
}
}
: match "examine sword" {
: if (is_present "short_sword") {
: print "INSCRIBED UPON IT ARE THE WORDS 'GOOD LUCK' ~~ MERLIN." ;
}
}
: match "examine bush" {
: if (is_present "bush" && has_not_created "stone_key") {
: print "YOU FIND SOMETHING!" ;
: create "stone_key" ;
: press_any_key ;
: redescribe ;
}
}
: match "examine logs" {
: if (is_present "logs" && has_not_created "axe") {
: print "YOU FIND AN AXE!" ;
: create "axe" ;
: press_any_key ;
: redescribe ;
}
}
BURROW ...." ;
: destroy "rockworm" ;
: set_graphic target = "worm_room" graphic = "worm_room_2" ;
: press_any_key ;
: redescribe ;
}
: else {
: print "IT EMITS A BRIGHT LIGHT." ;
}
}
}
: if (is_carried "excalibur") {
: print "EXCALIBUR REFLECTS THE SPELL! THE SORCERESS, PROMISING REVENGE, VANISHES!" ;
: destroy "spell" ;
: set_graphic target = "most_splendid_room" graphic = "most_splendid_room_2";
: press_any_key ;
: redescribe ;
}
: else {
: print "YOU WAVE YOUR HANDS BUT IT'S NO GOOD..." ;
}
}
: else {
: print "YOU CAN'T." ;
}
}
########################################
# Subroutines #
########################################
subroutines {
end_game : subroutine {
: press_any_key ;
: clear_screen;
: print_graphic "game_over" ;
: print "Your quest is over .........." ;
: turns ;
: end_game ;
}
worm_attack : subroutine {
: print "THE ROCKWORM RISES UP AND TAKES YOU IN ITS GLEAMING MANDIBLES." ;
: gosub "end_game" ;
}
// Placeholders used for documentation purposes only as graphic data is too large to place in document.
assets {
graphics {
armoury : placeholder ;
arthur : placeholder ;
banquet_hall : placeholder ;
birwood_bush : placeholder ;
castle_approach_1 : placeholder ;
castle_approach_2 : placeholder ;
castle_approach_2a : placeholder ;
castle_porch : placeholder ;
chasm : placeholder ;
cold_room : placeholder ;
cold_room_2 : placeholder ;
deep_inside_birwood : placeholder ;
demon_knight_road : placeholder ;
demon_knight_road_2 : placeholder ;
drafty_room : placeholder ;
drafty_room_2 : placeholder ;
edge_of_birwood : placeholder ;
ending_screen : placeholder ;
excalibur_loading : placeholder ;
foot_of_tree : placeholder ;
foot_of_tree_2 : placeholder ;
game_over : placeholder ;
hut : placeholder ;
lamp_seller_on_road : placeholder ;
lamp_seller_on_road_2 : placeholder ;
most_splendid_room : placeholder ;
most_splendid_room_2 : placeholder ;
ornate_antechamber : placeholder ;
portcullis : placeholder ;
portcullis_2 : placeholder ;
road_1 : placeholder ;
road_2 : placeholder ;
road_3 : placeholder ;
road_4 : placeholder ;
salt_mine_1 : placeholder ;
salt_mine_2 : placeholder ;
salt_mine_3 : placeholder ;
top_of_tree : placeholder ;
winch_room : placeholder ;
worm_room : placeholder ;
worm_room_2 : placeholder ;
}
}
7. Final Steps
7.1. Adding Polish
7.1.1. Some More Examine Commands
The fish is found early on in the game, and the player might naturally try to eat the fish. This response checks
to see if the fish is present (present means in the same scene or held in the players hands). If the fish is present,
and if "EAT FISH" is submitted as a comant, then it’s game over. The fish is rotten.
Note : If using sound in your game, the game will automatically ask for consent for sound after the intro screen
is shown.
on_startup {
: gosub "intro_song" ;
}
subroutines {}
intro_song : subroutine {
: beep millis = "256" pitch = "0" ;
: beep millis = "512" pitch = "3" ;
: beep millis = "256" pitch = "5" ;
: beep millis = "512" pitch = "7" ;
: beep millis = "256" pitch = "8" ;
: beep millis = "256" pitch = "7" ;
: beep millis = "512" pitch = "5" ;
: beep millis = "256" pitch = "2" ;
: beep millis = "512" pitch = "-2" ;
: beep millis = "256" pitch = "0" ;
: beep millis = "256" pitch = "2" ;
: beep millis = "256" pitch = "3" ;
: beep millis = "256" pitch = "2" ;
: beep millis = "512" pitch = "2" ;
: beep millis = "256" pitch = "7" ;
: beep millis = "256" pitch = "8" ;
: beep millis = "256" pitch = "3" ;
: beep millis = "256" pitch = "0" ;
}
How to write a song is a whole different subject, but pitch = 0 represents middle c, so you can experiment just
by doing.
Adventuron supports an image such as this - an image to be displayed, before the player clicks the screen or
touches the keyboard for the first time.
We go to a blank line at the "root" level of the source code, then press CONTROL + SPACE, then select
"loading_screen".
loading_screen = excalibur_loading
After doing this, pressing the "play" button, will display the loading screen instead of the ADVENTURON logo.
: if_examine "red_fish" {
: print "IT STINKS!" ;
}
The examine command doesn’t require a check for if the object is present, and it doesn’t require a verb. It
expects the identifier of an object.
It will automatically know which noun and verb to match from the id of the object.
on_command {
########################################
# Adventuron #
########################################
start_at = hut
loading_screen = excalibur_loading
########################################
# Locations #
########################################
locations {
hut : location "You are in an old hut. Sunlight shines in from a doorway to the
north.";
road_1 : location "You are standing on a track. The hut is south.";
road_2 : location "You are where the road turns eastwards. You see small hills in the
distance.";
road_3 : location "You are on a road surrounded by grass. Trees can be seen on a hill in
the distance.";
road_4 : location "You are on a dusty path on the edge of Birwood.";
lamp_seller_on_road : location "You are at a crossroads.";
chasm : location "You are stood on the edge of a huge chasm (a cliff). A tightrope spans
the gap, but it looks dangerous.";
edge_of_birwood : location "You are on the edge of Birwood. A rope spans the chasm northwards." ;
deep_inside_birwood : location "You are deep inside Birwood. The trees are alive with the buzzing of
tiny insects.";
birwood_bush : location "You are standing in Birwood. A gap in the trees lets a warm light
filter through.";
demon_knight_road : location "You are in a dip in the road by dark Birwood. Birds can be heard
above.";
foot_of_tree : location "You are at the bottom of a large stone tree that is bare of any
branches. The road ends here.";
top_of_tree : location "You are in a stone room set in a large stone tree.";
castle_approach_1 : location "You are now a fair distance from Birwood. You can see castle Camelot to
the east.";
castle_approach_2 : location "You are outside Camelot Castle. A great stone door is the only way
in.";
castle_porch : location "You are in the porch of Camelot.";
banquet_hall : location "You are in an abandoned banquet hall (eating area). Furniture lays
broken on the floor.";
drafty_room : location "You are in a drafty room. Wind blows through gaps in the walls creating
howling noises.";
ornate_antechamber : location "You are in an antechamber covered in thin ice that even covers the
paintings.";
portcullis : location "You are in a room which has an iron portcullis set into the northern
wall.";
salt_mine_1 : location "You are in an old salt mine. Tunnels lead to the west and south.";
salt_mine_2 : location "You are in the west part of the mine. It looks like it's been
abandoned.";
salt_mine_3 : location "You are at the end of the mine. You can hear the drip of water.";
worm_room : location "You are in the south part of the mine. There been recent movement in
the rocks near your feet.";
cold_room : location "You are in a bitterly cold room. Everything is coated in a thick layer
of ice.";
winch_room : location "You are in the winch room.";
armoury : location "You are in the armoury. Empty weapon racks line the walls.";
most_splendid_room : location "You are in the most splendid room in the castle. Rugs and paintings
adorn the floor and walls.";
arthur : location "You are in a sparse and lonely room. A cold wind enters through a high
window.";
########################################
# Connections #
########################################
connections {
from, direction, to = [
hut, north, road_1,
road_1, north, road_2,
road_2, east, road_3,
########################################
# Objects #
########################################
objects {
########################################
# Booleans #
########################################
booleans {
is_ladder_standing : boolean "false" ;
is_light_lit : boolean "false" ;
has_oiled_winch : boolean "false" ;
has_turned_winch : boolean "false" ;
}
########################################
# Blocks #
########################################
barriers {
castle_door : door {
key = stone_key
from = castle_approach_2
to = castle_porch
on_unlock {
: print "YOU UNLOCK IT WITH THE KEY, WHICH JAMS IN THE LOCK." ;
: destroy "stone_key" ;
}
on_open {
: set_graphic graphic = "castle_approach_2a" target = "castle_approach_2" ;
: redescribe ;
}
on_close {
: set_graphic graphic = "castle_approach_2" target = "castle_approach_2" ;
: redescribe ;
}
}
tree : block {
location = top_of_tree
message = YOU CAN'T FIND YOUR GRIP
block_when_not = is_ladder_standing
}
knight : block {
location = castle_approach_1
gosub = lose_fight
block_when_exists = demon_knight
show_blocked_exit = true
}
trapdoor : block {
location = salt_mine_1
message = THE TRAPDOOR IS JAMMED SHUT!
block_when_exists = trapdoor
}
worm : block {
location = salt_mine_3
gosub = worm_attack
block_when_exists = rockworm
show_blocked_exit = true
}
ice_creature : block {
location = winch_room
portcullis : block {
location = most_splendid_room
message = YOU CAN'T GO THAT WAY.
block_when_not = has_turned_winch
}
crania : block {
location = arthur
message = YOU CAN'T GET PAST
block_when_exists = spell
}
########################################
# On Startup #
########################################
on_startup {
: gosub "intro_song" ;
}
########################################
# On Describe #
########################################
on_describe {
: if (is_light_lit) {
: print "THE LIGHT'S GONE OUT." ;
: set_false "is_light_lit" ;
}
}
########################################
# On Describe #
########################################
on_tick {
: if (is_present "rockworm" ) {
: if (linger() == 3) {
: print "THE ROCKWORM STARTS MOVING TOWARDS YOU" ;
}
: if (linger() == 4) {
: gosub "worm_attack" ;
}
}
: if (is_present "ice_creature") {
: if (linger() == 1) {
: print "THE ICE CREATURE TAKES YOU IN A FREEZING GRIP" ;
: gosub "end_game" ;
}
}
: if (is_present "spell") {
: if (linger() == 1) {
: print "THE SPELL HITS YOU HEAD ON, PETRIFYING YOU INSTANTLY." ;
: gosub "end_game" ;
}
}
}
########################################
# On Command #
########################################
on_command {
#########################################
## Examine Messages
#########################################
: if_examine "bush" {
: if (has_not_created "stone_key") {
: print "YOU FIND SOMETHING!" ;
: create "stone_key" ;
: press_any_key ;
: redescribe ;
}
}
: if_examine "logs" {
: if (has_not_created "axe") {
: print "YOU FIND AN AXE!" ;
: create "axe" ;
: press_any_key ;
: redescribe ;
}
}
: else {
: gosub "lose_fight" ;
}
}
}
: create "smashed_trapdoor" ;
: destroy "axe" ;
: set_graphic target = "drafty_room" graphic = "drafty_room_2" ;
: pause "1600" ;
: redescribe ;
}
: else {
: print "A FRUITLESS EXERCISE!" ;
: done ;
}
}
}
########################################
# Subroutines #
########################################
subroutines {
end_game : subroutine {
: press_any_key ;
: clear_screen;
: print_graphic "game_over" ;
: print "Your quest is over .........." ;
: turns ;
: end_game ;
}
worm_attack : subroutine {
: print "THE ROCKWORM RISES UP AND TAKES YOU IN ITS GLEAMING MANDIBLES." ;
: gosub "end_game" ;
}
intro_song : subroutine {
: print_graphic "excalibur_loading" ;
: beep millis = "256" pitch = "0" ;
: beep millis = "512" pitch = "3" ;
: beep millis = "256" pitch = "5" ;
: beep millis = "512" pitch = "7" ;
: beep millis = "256" pitch = "8" ;
: beep millis = "256" pitch = "7" ;
: beep millis = "512" pitch = "5" ;
: beep millis = "256" pitch = "2" ;
: beep millis = "512" pitch = "-2" ;
: beep millis = "256" pitch = "0" ;
: beep millis = "256" pitch = "2" ;
: beep millis = "256" pitch = "3" ;
: beep millis = "256" pitch = "2" ;
: beep millis = "512" pitch = "2" ;
: beep millis = "256" pitch = "7" ;
: beep millis = "256" pitch = "8" ;
: beep millis = "256" pitch = "3" ;
: beep millis = "256" pitch = "0" ;
}
// Placeholders used for documentation purposes only as graphic data is too large to place in document.
assets {
graphics {
armoury : placeholder ;
arthur : placeholder ;
banquet_hall : placeholder ;
birwood_bush : placeholder ;
castle_approach_1 : placeholder ;
castle_approach_2 : placeholder ;
castle_approach_2a : placeholder ;
castle_porch : placeholder ;
chasm : placeholder ;
cold_room : placeholder ;
cold_room_2 : placeholder ;
deep_inside_birwood : placeholder ;
demon_knight_road : placeholder ;
demon_knight_road_2 : placeholder ;
drafty_room : placeholder ;
drafty_room_2 : placeholder ;
edge_of_birwood : placeholder ;
ending_screen : placeholder ;
excalibur_loading : placeholder ;
foot_of_tree : placeholder ;
foot_of_tree_2 : placeholder ;
game_over : placeholder ;
hut : placeholder ;
lamp_seller_on_road : placeholder ;
lamp_seller_on_road_2 : placeholder ;
most_splendid_room : placeholder ;
most_splendid_room_2 : placeholder ;
ornate_antechamber : placeholder ;
portcullis : placeholder ;
portcullis_2 : placeholder ;
road_1 : placeholder ;
road_2 : placeholder ;
road_3 : placeholder ;
road_4 : placeholder ;
salt_mine_1 : placeholder ;
salt_mine_2 : placeholder ;
salt_mine_3 : placeholder ;
top_of_tree : placeholder ;
winch_room : placeholder ;
worm_room : placeholder ;
worm_room_2 : placeholder ;
}
}
game_information {
game_name = Excalibur : Sword of Kings
game_shortname = Excalibur
ported_by = xxxxx
written_by = Ian Smith / Shaun McClure
copyright_message = (C) Adventuron Software Limited
year = 1987
game_version = 1.0.0
short_synopsis = Rescue King Arthur In Camelot
}
Now, click the menu button at the bottom right, then click the "Compile" option.
Adventuron will display a message, which you should read, then produce a HTML file containing the game.
Excalibur is copyright of Adventuron Software Limited for the purpose of using in this tutorial. Producing a
HTML version is to demonstrate the feature. You are not permitted to redistribute your HTML copy of
Excalibur.
Adventuron is not licensed for commercial use, and games created with Classroom embed Adventuron into the
generated HTML files.
As long as you make your own adventure that does not break the license terms, you can share HTML versions
of your own creations, providing you do not charge a fee for your game.
Your packaged game will be independent of the Adventuron website, and also available to play without an
internet connection. It is very important for archival purposes.
7.4. Congratulations
7.4.1. Congratulations
Congratulations, you have completed this tutorial.
You have now constructed an illustrated text adventure using the Adventuron game system.
The concepts used in this tutorial can be used to create all sorts of games.
Be careful about creating game featuring copyright characters. For example, games involving famous comic
book characters would not be legal to distribute.
Of course you are free to experiment with anything you like privately, but it’s more fun to make a game that
you can share with other people.
When you are more comfortable with Adventuron, there are many more features to be discovered, such as
container support, advanced parser (use full sentences rather than verb noun), gamebook mode, chiptune
support, hyperlinks, export to 8-bit machines, dynamic graphics, loops, maths, attribute support, and much
more.
These are all the commands and conditions that Excalibur uses.
Table 5. Commands
Command Description
: match Execute some commands if a verb or noun (or both) match a pattern.
: else_if Perform some commands only if a condition is satisfied (the condition evaluates
to true). Must follow an :if command.
: press_any_key Tells the game to wait until the player either presses a key on the keyboard, or
clicks the mouse, or touches the touchscreen.
: done Stop executing commands and wait for input by the player.
: clear_screen Clears the current screen. This happens automatically when the player
navigates to a different location, but sometimes we may wish to refresh the
screen when the player does not move.
: redescribe Tells the game to clear the screen, then to redescribe the current scene,
including the contents of the scene.
: increment Adds 1 to the value of the specified integer variable (an integer variable holds a
number).
: end_game Display the end_game text, then wait for the player to press or click something,
and then restart the game. Typically you would want to give the player some
specific information before using this command (like display a failure screen).
: set_graphic Change the graphic that is drawn when the player enters a scene. The game will
remember the changed graphic. This is useful for if the location should look
different in response to some event that has happened in the game.
: show_graphic Print a graphic at the current line of the display (inline). This only happens once,
and does not change any graphic that will be displayed when the player re-
enters a scene.
: set_theme Change the current theme of the game to the specified new theme. A theme is
the way that the game is configured to be drawn or laid out. This is an
ADVANCED command.
: block Blocks access to a location on the map. All entrances to the location from all
directions are blocked, and a customizable message will be displayed to the
player if they attempt to access the location.
: unblock Unblocks access to a location. The message is removed, and now the location
will be listed as an exit direction in neighbouting locations/scenes.
Condition Description
is_carried Is the player holding the specified item (in the inventory).
is_beside Is the specified item in the same location as the player, but not in the player’s
inventory?
is_just_entered Did the player just enter the current location from a different location?
Condition Description
linger() Returns the number of turns since we arrived in the current scene. This resets to
zero when the player moves to a new location.
on_startup{} This code block will be executed before any other block when a game is first
started. It will NOT be executed if loading a saved game, but it will be executed
on a new game.
on_command{} The on_command{} block is executed after the player submits a command (via
keyboard / mouse / joypad / speech / touch / etc). Typically this section contains
one or more : match {} items, which are used to check for a particular verb /
noun combination.
on_describe{} The on_describe{} block is executed when a scene is redescribed (this may not
be every turn). This may happen due to a code executed in the on_command {}
block, or due to the player moving to a new location.
on_tick{} The on_tick{} block is executed after the on_command{} block, and if the scene
has just been changed, it is executed after the on_describe{} block tooand can be
used for actions that occur in the game world, independent of what the player
just typed.
If you came here accidentally, click the up arrow icon at the top of this panel to go back to the main menu, .
8.1. Introduction
Adventuron Classroom is a web-hosted text-adventure authoring system, with a goal or replicating the magical
feel of old-school text adventures from the 1980s.
Website : https://adventuron.io
8.3. License
Created text adventures can be exported as HTML for non-commercial use.
8.4. Locations
An Adventuron text adventure game must contain one or more location.
Each location has an id, which is the id that you refer to the location by in the game code. A location must also
have a description - although the description can be empty if you want.
Locations are very configurable, but we’ll deal with the normal simple definition of a location here.
start_at = bottom_of_hill
locations {
bottom_of_hill : location "You are standing at the bottom of the hill." ;
top_of_hill : location "You are standing at the top of the hill." ;
}
locations {
bottom_of_hill : location "You are standing at the bottom of the hill." header="Bottom of Hill";
top_of_hill : location "You are standing at the top of the hill." header="Top of Hill";
}
8.5. Connections
Direction mappings are bidirectional in Adventuron, and you read from left to right.
Bidirectional Mappings
connections {
from, direction, to = [
bottom_of_hill, up, top_of_hill
]
}
Bottom of hill goes UP to the top of the hill - THEREFORE - the top of the hill goes DOWN to the bottom of the
hill.
Unidirectional Mappings
connections {
from, direction, to = [
bottom_of_hill, up_oneway, top_of_hill
]
}
Bottom of hill goes UP to the top of the hill, but the top of the hill does NOT lead down to the bottom of the hill.
8.6. Variables
8.6.1. Boolean Variables
booleans {
has_bell_been_rung : boolean "false"; // False is the default
}
integers {
number_of_times_visited_well : integer "0"; // 0 is default, 0 is min
number_of_times_visited_hut : integer "0" max="100"; // 0 is default, 0 is min, 100 is max
number_of_times_visited_lake : integer "0" min="-100" max="100"; // 0 is default, -100 is min, 100 is max
}
strings {
some_character_name : string "Susan"; // Susan is default
}
: set_string var="nice_location_description" {(
"I am in location with id " +
current_location()
)}
8.7. Objects
Objects are entities in the games that can be interacted with in some way. Even though they are called objects,
objects can also represent characters in the game too.
An object can exists and not exist. An object has a parent. The parent can be a location, or another object, or the
'ether', which is a special object which holds objects that don’t exist in the game world.
objects {
blue_spoon : object "a blue spoon";
}
objects {
blue_spoon : object "a blue spoon" start_at="inventory";
}
objects {
blue_spoon : object "a blue spoon" start_at="barn";
}
Objects are special in that their identifiers have TWO uses. The first use is to act as a unique identifier for the
purpose of referring to them from the code. The second use is to define the adjective and the noun associated
with the object.
key : object "a key"; Defines noun as "key", description as "a key";
blue_key : object "a key"; Defines noun as "key", adjective as "blue", description as "a key".
green_key : object "a key"; Defines noun as "key", adjective as "green", description as "a green key".
NOTE — The description does not have to relate to the noun or the adjective
at all - although it SHOULD unless the player will become confused.
e.g.
objects {
blue_spoon_1 : object "a blue spoon" start_at="barn";
blue_spoon_2 : object "a blue spoon" start_at="kitchen";
blue_spoon_3 : object "a blue spoon" start_at="well";
blue_spoon_4 : object "a blue spoon" start_at="castle";
blue_spoon_5 : object "a blue spoon" start_at="dungeon";
}
In all 5 cases, the objects will be created with noun = spoon, adjective = blue.
8.8. Barriers
Barriers represents a way of blocking (or intercepting) movement to another location, on a conditional basis.
block_path Blocks entry to a location, but only in one direction (from another particular
location)
Blocks are dynamically evaluated by Adventuron. They generally are controlled by the contents of a boolean
variable, or by the existence or non-existence of an object.
barriers {
throneroom_block : block {
block_when_exists = king
location = throne_room
message = The king is far too busy and orders you out of the room.
}
}
barriers {
mines_block : block {
block_when_not_carried = glowing_sword
location = emerald_mine_1
message = The mines are far too dark to venture into unaided.
}
}
barriers {
maze_block : block {
block_when_not = is_read_map
location = maze_1
message = You dare not enter the maze without knowing more about it first.
}
}
The throneroom_block can be anything, but it has to be in the identifier format with is alpha numeric, with
underscores.
barriers {
throneroom_block : block_path {
from = hallway
to = throne_room
block_when_exists = king
message = The king is far too busy and orders you out of the room.
}
}
Doors require a 'from' and 'to' locations, same as block path, but doors don’t require an activation condition
(like block_when_exists, block_when_not_carried, etc).
Doors might simply be open and close doors, but most doors require a key.
A Locked Door
barriers {
shed_door : door {
from = garden
to = shed
key = shed_key
}
}
Doors are closed and locked by default. A door defined without a key will not be locked, and will not be
lockable or unlockable.
The identifier for doors is currently (like object identifiers). It does not imply a noun or an adjective.
Each room is currently only permitted to have one door, but in a future release, multiple doors per location
will be permitted. This may not be appropriate for example for multiple doors in a corridor (yet).
The most common event handlers are documented here. There are actually additional event handlers, which
will be documented in the advanced guide, but to keep it simple, the most common and useful event handlers
are documented here.
8.9.1. on_startup {}
The startup event handler is executed when starting a new game. It is NOT executed when reloading a saved
game. It is only executed once per NEW GAME, and before any other event handler.
on_startup {
: print "Welcome to the world of nuts and bolts !!!!";
: press_any_key ;
}
8.9.2. on_command {}
The on_command{} event handler is used to process a submitted command entered by the player.
The on_command{} event handler usually contains : match {} records, which look for specific verb and noun
combinations. The _ character acts like a wildcard, and will match anything or nothing. The * character is also
a wildcard, represents something. The - character can be used to specify nothing.
Adventuron ignores zero inputs by default, so handling : match "- -" will not work.
on_command {
: match "throw rug" {
: if (is_carried "rug") {
: print "You throw the rug, the rug is now gone.";
: destroy "rug";
}
}
}
8.9.3. on_describe {}
On pre describe is a block of code that is executed when BEFORE describing a location (entering a new location
or redescribing it).
This block will execute before the any part of the location is described (graphic, object list, exit list, description).
A done executing in this block will not stop the rendering of the location.
Beware of using redescribe in this block (adventuron will detect redescribe recursion and report it).
If your location description contains some dynamic elements you can use this block to update those elements
first, or possibly implement 'floating' objects that can follow the player around.
on_pre_describe {
: if (is_just_entered() && is_at "forest_zone") {
: create "owl"; // Creates the owl in every forest location as the player moves
}
}
8.9.4. on_describe {}
On describe is a block of code that is executed when describing a location (entering a new location or
redescribing it). It can be used to embelish a location description, or to trigger game events.
on_describe {
: if (is_at "ice_cavern" && has_created_fire == false) {
: print "You shiver.";
}
}
8.9.5. on_tick {}
On tick is a block of code that is executed before processing the next command (prior to the prompt re-
appearing). The on_tick event can be used to perform NPC actions in the world, and is executed every turn.
on_describe {
: if (is_at "ice_cavern" && has_created_fire == false) {
: print "You shiver.";
}
}
8.9.6. on_debug {}
On debug is executed instead of on_startup{} (if defined). It is used for debugging particular scenerios in a
game.
on_debug {}, if used, should be commented out before packaging a game for release.
on_debug {
: goto "castle";
: create "elf";
: set_true "has_learned_elf_song";
}
Local handlers are useful if the author wishes to code location-specific logic in a single place. It also means that
the author doesn’t need to code is_at() conditions if the code is located underneath the location.
locations {
bottom_of_hill : location "You are standing at the bottom of the hill." {
on_command {
// Local command handlers here
}
on_describe {
// Local description events here
}
on_tick {
// Local tick events here
}
}
}
8.11. Commands
Commands represent actions to perform in a given context. Some actions may be conditional on a boolean
expression evaluating to a particular result.
Name Description
: match "VERB NOUN" {} Matches a verb and noun, and executes the contained commands if the
current logical sentence matches the verb and noun.
: if (CONDITION) { … } Executes the inner commands {…} IF the supplied boolean condition is true.
: else_if (CONDITION) { … }
: while (CONDITION) {…} While the condition evaluates to true, keep executing the inner commands.
NOTE: Adventuron does not yet have a BREAK command, so a while look
can be only be exited via its top condition.
: done ; Stops executing the current event handler, no further items are evaluated.
: return ; Stop executing the current subroutine and return to the calling handler.
: nope ; Print the system message like "You can’t do that", and then acts like : done
(Stops executing the current event handler, no further items are evaluated).
Name Description
: stagger "message text" ; Prints the given message and places 'press_any_key' inbetween each
paragraph (but not after the final paragraph printed).
: append "message text" ; Prints the given message, but does not start a new paragraph.
: goto "LOCATION_ID" ; Moves the player character to the given location (does not redescribe).
: beep Plays the nominated pitch for the nominated amount of milliseconds. 0 is
millis="MILLISECONDS" middle C.
pitch="PITCH";
: press_any_key ; Wait until the player presses ENTER, SPACE, touches the screen, or clicks the
mouse.
: create "OBJECT_ID" ; Creates the object with the given id in the current location. If the object
already exists somewhere else, it is moved to the present location.
: create "OBJECT_ID" target = Creates the object with the given id in nominated location. If the object
"LOCATION_ID" ; already exists somewhere else, it is moved to the nominated location.
: create "OBJECT_ID" target = Creates the object with the given id in the player inventory. A weight or item
"inventory" ; limit check is not performed.
: destroy "OBJECT_ID" ; Destroys the object with the given id. If held it is removed from the
inventory. Destroying moves the object to a special non-existence location.
: set_true "BOOLEAN_ID" ; Sets the boolean variable with the given id to contain a true value.
: set_false "BOOLEAN_ID" ; Sets the boolean variable with the given id to contain a false value.
: add var = "INTEGER_VAR" Adds a value onto the current value of an integer.
value = "VALUE" ;
: increment "INTEGER_VAR"; Increments the value in the referenced integer variable. If the integer
variable’s max value will be exceeded, then do nothing.
: decrement Decrements the value in the referenced integer variable. If the integer
"INTEGER_VAR"; variable’s min value will be exceeded, then do nothing.
: swap o1 = "OBJECT1_ID" o2 Swaps the location of object1 and object2. Swap will also swap the existence
= "OBJECT2_ID" ; of object 1 and object 2. Swap will also swap the existence status of an object
with the second object.
: redescribe ; Flags to Adventuron that it should redescribe the current location, and stops
executing the current event handler. This will retrigger on_describe{} and
on_tick{} from the top of both of the tables.
: end_game ; Prompts the player to press any key (Enter key, space bar, touch or mouse
click), then the game restarts - display intro screen/graphic, call
on_startup{}, etc.
: set_graphic graphic = Changes the default graphic for a location to a different graphic.
"GRAPHIC_ID" target =
"LOCATION_ID" ;
: get; Gets the object that corresponds to the adjective and noun in the current
parse sentence (only if object is available, and takeable in the current
location).
By default, this will print a message if the object is taken, or if the object
can’t be taken for some reason (too many items, not a takeable object).
: drop; Drop the object that corresponds to the adjective and noun in the current
parse sentence (only if object is available, and takeable/droppable in the
current location).
By default, this will print a message if the object is dropped, or if the object
can’t be dropped for some reason (not holding the object for example).
: get "OBJECT_ID"; Gets the object that corresponds to supplied object id (only if object is
available, and takeable in the current location).
By default, this will print a message if the object is taken, or if the object
can’t be taken for some reason (too many items, not a takeable object).
Note: This command will perform weight checks by default but these checks
can be disabled in the game settings. Be very careful if using this command
then moving the player immediately somewhere else. If the player can’t
hold the item you are taking for them, the item may end up inaccessible (if
the player can’t return to the location where the item was given). Consider
the : pocket "object_id" command instead which is fail-safe.
: drop "OBJECT_ID"; Drops the object that corresponds to supplied object id (only if object is
available, and takeable/droppable in the current location).
By default, this will print a message if the object is dropped, or if the object
can’t be dropped for some reason (not holding the object for example).
: pocket "OBJECT_ID"; Creates an item and attempts to place it in the players pocket (or inventory),
silently, if there is enough space in the inventory (uses weight + item limits).
If the player cannot take the object (too heavy or holding too many items),
then the object is created in the location where the player is located when
the location is redescribed or the prompt is redisplayed (whichever comes
first).
displayed.
If trying to pocket an item that the player already holds, then pocket does
nothing (no error, prints nothing, just does nothing).
: wear; Wears the object that corresponds to the adjective and noun in the current
parse sentence (only if object is available, and wearable).
: unwear; Takes off (unwear) the object that corresponds to the adjective and noun in
the current parse sentence (only if object is worn, and removable).
: wear "OBJECT_ID"; Wears the object that corresponds to supplied object id (only if object is
available, and wearable).
: unwear "OBJECT_ID"; Takes off (unwear) the object that corresponds to supplied object id (only if
object is worn, and removable).
: set_theme "THEME_ID"; Changes the current theme of the game to the specified theme, instantly
updating the screen style but not updating the screen content or issuing a
redescribe.
: ask_bool question = Asks a question and stores the result in a boolean variable.
"QUESTION TO ASK?" var =
"BOOL_VAR";
: ask_int question = Asks for an integer (a number) in a range and stores in an integer variable.
"QUESTION TO ASK?" var = Min and max must be specified.
"INT_VAR" min = "0" max =
"10" ;
: ask_string question = Asks for a string (some text) and stores in an string variable.
"QUESTION TO ASK?" var =
"STRING_VAR" empty_is_ok
= "false" ;
Name Description
: set_string var = Sets a string variable to be the result of the supplied expression.
"STRING_VAR" {("Some " + "
String " + "Expression")}
: set_integer var = Sets an integer variable to be the result of the supplied expression.
"INTEGER_VAR" {( 1 + 2 + 3 )}
e.g.
booleans {
has_brushed_teeth : boolean "false";
}
Name Description
is_present "OBJECT_ID" Returns true if the referenced object is present (in the current players
inventory, or in the current location).
is_beside "OBJECT_ID" Returns true if the referenced object is in the current location.
is_exists "OBJECT_ID" Returns true if the referenced object exists somewhere in the game world.
is_carried "OBJECT_ID" Returns true if the referenced object is carried (in the current players
inventory).
is_worn "OBJECT_ID" Returns true if the referenced object is carried and worn by the player.
is_pocketable "OBJECT_ID" Returns true if when hypothetically taking an object it would not exceed
weight or item carry limits (to be taken). If the referenced item is held by the
player, then this function will return true, and a subsequent call to ": pocket"
will simply do nothing. This function should not be used to test if an item is
already in the inventory.
has_not_created Returns true if the referenced object id has not been created (never been
"OBJECT_ID" created one time or more). This can be useful if guarding a part of the code
that creates the object, to ensure it can never be created more than once -
even if it is destroyed later in the game.
has_stashed_all_treasure () Returns true if all the treasure is currently in the treasure room.
is_at_initial_location Returns true if the referenced object is at the same location where it was
"OBJECT_ID" placed at the start of the game (not including any movements that happen in
the on_startup{} handler).
is_just_entered () Returns true if the player just entered the current location (the location id is
different to the location id in the previous tick).
is_first_entered () Returns true if the player just entered the current location for the first time.
NOTE : This command will always return false if used from an
on_command{} event handler.
is_mobile() Returns true if the current client is running on a smartphone. This should
return false for tablets.
chance (n) Returns true, n % of the time. (n is a value or an expression that evaluates to
a number between 0 and 100).
noun1_is "noun" Returns true if the 1st noun in the sentence equals the provided noun (or
synonym).
noun2_is "noun" Returns true if the 2nd noun in the sentence equals the provided noun (or
synonym).
adjective1_is "adjective" Returns true if the 1st adjective in the sentence equals the provided
adjective (or synonym).
adjective2_is "adjective" Returns true if the 2st adjective in the sentence equals the provided
adjective (or synonym). The second adjective must always come after the
first noun.
preposition_is "preposition" Returns true if the preposition in the sentence equals the provided
preposition (or synonym).
verb_is "verb" Returns true if the verb in the sentence equals the provided verb (or
synonym).
adverb_is "adverb" Returns true if the adverb in the sentence equals the provided verb (or
synonym).
e.g.
integers {
num_times_visited_hut : integer "0";
}
: if (number_times_visited_hut > 5) {
: print "You really like this hut !";
}
Name Description
abs(EXPRESSION) Returns a positive (absolute) version of the value returned by resolving the
inner expression (always 0 or above).
locno() Returns the locations number of the current location. If the current location
does not have a location number, the will return a value less than 0.
item_limit() Returns the limit of the number of items that is permitted to be carried by
the player.
linger() Returns the number of ticks that the player has been in the current location
since arriving (this is reset to zero upon entering a new location). This can
be useful for per-location timed events, or messages.
ticks() Returns the number of ticks that have been performed in the game. This will
return 0 in the on_startup {} block, but the first time on_tick is executed,
ticks() will contain a value of 1, incrementng by one every time the
on_ticks() block is executed.
turns() Returns the number of turns that have been performed in the game. This is
the number of individual sentences processed by on_command(). This is
incremented BEFORE on_command() runs. Note that a GET ALL or DROP all
will be processed as multiple sentences.
distance_to "LOCATION_ID" Returns the shortest number of moves required to move to the nominated
location from the current location. If the location is the same location as the
current player location, then return 0, if there is no path, then returns -1,
otherwise will return an integer number. Can be useful for environmental
messages.
treasure_total() Returns the total amount of treasure objects defined in the game (set the
treasure="true" attribute on an object).
treasure_deposited() Returns the total amount of treasure currently located in the treasure
destination location.
The ABSOLUTE minumum and maximum values that an integer variable can hold are -2,147,483,648 and
2,147,483,647 (inclusive) respectively.
8.14. Strings
8.14.1. String Functions
Name Description
parent_of "entity_id" Returns the direct parent of an object or entity (can be a location id, an
object id, 'inventory', or 'ether'. If an invalid item is specified, then
"unknown" is returned. If the item is carried by the player then 'inventory'
will be returned. If the item does not exist, then "ether" will be returned
(ether is the parent of non exitent objects).
original_verb() Returns the verb that the player entered (untrimmed and unaliased). If the
player types one word, then this is always the original verb.
original_noun1() Returns the first noun that the player entered (untrimmed and unaliased). If
the player types one word, then this may be empty. It will never be empty if
the player types two words, but it may be empty if the player types three or
more words and none of those words are matched nouns. When typing two
words, one word is always understood as a verb and one word is
understood as a noun, whether or not the verb or noun are found in the
vocabulary.
previous_location() Returns the location the player was in in the last tick.
start_at = village
locations {
village : location "You are in the village. Type SCORE to see your score." ;
}
integers {
// Set the default score to zero here
score : integer "0" ;
}
on_command {
: match "score _" {
// Note that CONTROL + SPACE only works on blank lines in these blocks
// Pressing CONTROL + SPACE once will show string functions only
// Pressing CONTROL + SPACE twice in a row will show all functions (integer, string, and boolean
functions)
: print {(
"Your score is " +
score +
"."
)}
}
}
The UUID must be unique, as it is used to make sure that the save game information can be found if you change
the short name of your game.
https://www.uuidgenerator.net/
game_information {
game_name = YOUR GAME NAME
game_version = 0.5.0
game_shortname = SHORT GAME NAME
written_by = YOUR NAME
uuid = UNIQUE UUID
year = 2019
copyright_message = YOUR COPYRIGHT MESSAGE
short_synopsis = ONE SENTENCE DESCRIPTION OF GAME.
}
As each website domain (base part of a url) has its own storage, it’s impossible for one website to corrupt the
save data of a game on a different website.
But … if you have multiple games on the same website, then you need to setup the game_information to ensure
that games won’t share the same save data.
Adventuron will complain if you have not set up the game_information{} section when you
NOTE
compile, to help you remember to do this.
Setup a UNIQUE uuid in the game_information {} section. It is EXTREMELY IMPORTANT for the uuid to be
unique. (generate a unique UUID here : https://www.uuidgenerator.net/ )
Slot 0 - Autosave
Slot 1 - User Slot 1
Slot 2 - User Slot 2
Slot 3 - User Slot 3
Slot 4 - Ramsave Slot
This save date will save using browser local storage (for the website domain).
The key for the save slot is as follows (taken from game information settings):
To avoid conflicts, please make a unique uuid identifier and/or game name.
If serving from Itch, then the domain will be of the virtual server that serves the iFrame. This will be unique
per Itch account.
8.16.1. Autosave
If a game has the game_information {} set up, then the game will start to autosave after the first move. Going
back to the same domain will display the loading screen, then after pressing enter or clicking the screen it will
take the player back to the exact moment they left off.
The game is actually saved immediately as a prompt appears. The state is snapshotted, compressed, and saved
every turn.
When reloading, the screen is re-rendered as it was (saved as part of the snapshot), then the prompt is
redisplayed without any ticks taking place.
To reload, type "LOAD" and select the slot you wish to load from. Or select the 4th option to cancel the load.
It saves in a fixed 4th slot, and again, uses the previous snapshot just before the prompt was displayed.
A ramload again is instant. To perform a ramload, the player just types "ramload". Adventuron will loads the
game from the ramsave snapshot and re-renders the screen as it was. No ticks are executed in the load as it
was actually saved after the ticks were executed.
8.16.5. Gotchas
As you might expect, if using a browser in a private / incognito mode, that the save data will be erased when
the browser is closed.
In real use, it uses real verbs and real nouns, such as:
You can also use a semi colon to add additional verb noun patterns to match. Any number of verb noun pairs
can be listed using ';' as the delimiter.
: if ( (verb_is "read" && noun1_is "sign") || (verb_is "examine" && noun1_is "sign") ) {
// Do something
}
In match records the following symbols can be used to test for the following conditions
start_at = my_location
locations {
my_location : location
"on_command {{\n : match \"yawn -\" {{ : print \"Yawn 1.\" ; }}\n : match \"yawn _\" {{ : print
\"Yawn 2.\" ; }}\n : match \"yawn *\" {{ : print \"Yawn 3.\" ; }}\n}}";
}
on_command {
: match "yawn -" { : print "Yawn 1." ; }
: match "yawn _" { : print "Yawn 2." ; }
: match "yawn *" { : print "Yawn 3." ; }
}
Some codes are as-yet undocumented whilst under review so only the stable codes will be listed here.
start_at = village
strings {
day_of_week : string "Wednesday" ;
}
locations {
village : location "You are in the village. It is {day_of_week}." ;
}
booleans {
is_wednesday : boolean "false" ;
}
You can also use the {boolean ? if_true_string_var : if_false_string_var} form in regular text to import the value
of a string variable.
start_at = village
strings {
wednesday : string "Wednesday" ;
not_wednesday : string "Not Wednesday" ;
}
locations {
village : location "You are in the village. It is {is_wednesday ? wednesday : not_wednesday}.\nType LOOK
to refresh the dynamic location description." ;
}
booleans {
is_wednesday : boolean "false" ;
}
on_tick {
: if (is_wednesday) {
: set_false "is_wednesday" ;
}
: else {
: set_true "is_wednesday" ;
}
}
Colour 8 is inhabited by orange, even though orange was not a colour on the ZX Spectrum (to
NOTE
make it easier to map to other palettes).
0 black #000
1 blue #00c
2 red #c00
3 magenta #c0c
4 green #0c0
5 cyan #0cc
6 yellow #cc0
7 grey #ccc
8 orange #f60
15 white #fff
A later release of Adventuron will let custom palettes be set that map to 0 - 255, 256 onwards
NOTE
will be reserved for effects.
// This will (by default) be the story colour if printed in the location description, or in the on_describe{}
block
// This will be (by default) the response colour (and if that is not set the story colour), if printed in the
on_tick{} or on_post_tick {} blocks.
// This will be (by default) the warn colour (and if that is not set the response colour and if that is not
set story colour), if printing a system error.
: print "Hello";
: print "This part of the text is <bright red<#f00>> using 12-bit RGB code #f00 (r = 15, g = 0, b
= 0).";
: print "^r^This paragraph is right aligned.\nAlso right aligned.\n^l^This paragraph is left aligned.";
: print "^c^This paragraph is centre aligned.\nAlso centre aligned.\n^l^This paragraph is left aligned.";
Adding ^m^ at the end will restore the paragraph space after the final paragraph.
: print "^n^No paragraph break space between paragraph 1.\nNo paragraph break space between paragraph 2.\nNo
paragraph break space between paragraph 1.^m^";
Firstly, the ' character (apostrophe) is not escaped. This is because it is a very commonly used
NOTE
character.
Some other uses of the […] brackets are in development, but if you find them, don’t depend on them working in
future releases.
All colours displayed on a computer screen are represented by combinations of primary colours, red, green,
and blue (RGB).
If we had a 1 bit per red, green and blue elements, there would be 8 different colours supported.
RGB
000 = black
001 = blue
010 = green
100 = red
110 = yellow
101 = magenta
011 = cyan
111 = white
12 bit colour uses 4 bits per red, green, and blue channel.
0=0
1=1
2=2
3=3
4=4
5=5
6=6
7=7
8=8
9=9
10 = a
11 = b
12 = c
13 = d
14 = e
15 = f
e.g.
12 bit colour gives a maximum of 4096 possible colour combinations (16 x 16 x 16 = 4096)
That should be enough for a text adventure. More colours can be used in images in adventuron, this is just for
text.
On the web, we use 8 bits per red, green, and blue channel (24 bits total).
8 bits can store 256 different values. 0 = zero intensity, 255 = maximum intensity.
The version of Adventuron that runs in the editor has a number of debugging functions built-into the game
engine itself (the non-editor version of adventuron has these features disabled by default to prevent game
cheating).
// Will list all the variables you have declared in the game as well as their current values
showvars
goto <<location_id>>
summon <<object_id>>
*variable_id = variable_value
The on_debug {} block, if provided, will be executed INSTEAD OF the on_startup {} event handler, and this can
be used to set up the game state prior to Adventuron describing the location for the first time.
Authors can use the on_debug {} event handler to move the player to a location, set variable values, move
objects around, give objects to players, prior to first redescribe.
Authors can "comment-in" and "comment-out" the on_debug {} event handler by selecting the entire block then
pressing CONTROL and / together. This will toggle comment markers on all the lines on and off.
Authors should put their debugging logic in on_debug {} and not modify their normal on_startup {} routine
when debugging, just as best practise so as not to accidentally break the startup logic when debugging.
start_at = study
on_debug {
// Setup the game ready for the test you want to perform.
// After this block of code is executed, Adventuron
// Will redescribe the location that the player is in.
: goto "library" ;
: pocket "book" ;
: set_true "has_talked_colonel" ;
}
locations {
study : location "You are in the study." ;
library : location "You are in the library." ;
}
connections {
from, direction, to = [
study, east, library,
]
}
objects {
book : object "an old book" ;
}
booleans {
has_talked_colonel : boolean "false" ;
}
start_at = study
// on_debug {
// // Setup the game ready for the test you want to perform.
// // After this block of code is executed, Adventuron
// // Will redescribe the location that the player is in.
// : goto "library" ;
// : pocket "book" ;
// : set_true "has_talked_colonel" ;
// }
locations {
study : location "You are in the study." ;
library : location "You are in the library." ;
}
connections {
from, direction, to = [
study, east, library,
]
}
objects {
book : object "an old book" ;
}
booleans {
has_talked_colonel : boolean "false" ;
}
Most modern software keyboard implementations on smartphones are greedy and can take up to 50% of the
vertical space of the screen leaving a screen are with very little space for graphics + text to peacefully co-exist
together.
It may be that games with a lot of text scroll upward off the screen when the screen is displayed for the first
time, it’s important to optimize your game for mobile and not to put TOO much information into the location
descriptions (focus on cutscenes + interactions for your text).
No images
8.22. Contact
Adventuron is written by Chris Ainsley, and Copyright of Adventuron Software Limited, All Rights Reserved.
Email: [email protected]
This section contains various recipes for common types of problems that are encountered.
If you wish to change this, then you must setup an inventory limit in the game settings (not to be confused with
the theme settings).
Upon executing the snippet below, type GET ALL at the prompt.
start_at = village
locations {
village : location "You are in the village" ;
}
objects {
lamp : object "a lamp" start_at = "village" ;
pen : object "a pen" start_at = "village" ;
sword : object "a sword" start_at = "village" ;
rock : object "a rock" start_at = "village" ;
}
integers {
inventory_limit : integer "3" ;
}
settings {
// By referencing an integer, we can dynamically change this limit in-game
// using : set_integer, or using a dynamic integer.
inventory_items_limit_var = inventory_limit
}
9.2. Vehicles
The following example shows how to create a vehicle (a boat), which can be moved between two location
(update the code to allow it to travel to many more locations, possibly using a string to track its location rather
than a boolean).
The boat is both an object, and a location. The boat object and the boat location cannot have the same
identifier.
If the player enters the boat from the same location as the boat can be in, then the player is sent to the
"inside_boat" location. From there rowing will move the location of the boat between two locations (lakeside,
and island_beach) - it will create the boat in one of two location, the opposite one of the current location.
This code sample also demostrates a "repair boat" puzzle, but without a pre-requisite. You can repair the boat
just by typing "repair boat".
Exiting the boat will take the player to the location containing the boat.
######################################
# Adventuron #
######################################
start_at = lakeside
######################################
# Booleans #
######################################
booleans {
is_boat_fixed : boolean "false" ;
is_boat_at_lakeside : boolean "true" ;
}
######################################
# Locations #
######################################
locations {
lakeside : location "You are at the lakeside" ;
inside_boat : location "You are a boat." ;
island_beach : location "You are at a beach on an island" ;
}
on_describe {
: if (is_at "inside_boat") {
: if (is_boat_fixed == false) {
: print "There is a hole in the boat." ;
}
}
}
######################################
# On Command #
######################################
on_command {
}
}
}
: else {
: print "You row the boat to the lakeside." ;
: set_true "is_boat_at_lakeside" ;
: create "old_boat" target = "lakeside" ;
}
}
: else {
: print "You can't row the boat with the hole in it." ;
}
}
}
}
objects {
old_boat : object "an old boat" start_at = "lakeside" ;
}
themes {
my_theme : theme {
lister_exits {
is_list_enter = false
is_list_exit = false
}
}
}
The is_carried check can be used to test that the get was successful. A failed get will always print the failure
message (your hands are full, you can’t take that, etc, - messages can be configured in the theme).
start_at = village
locations {
village : location "You are in a village." ;
}
objects {
lamp : object "a lamp" start_at = "village" ;
}
on_command {
: match "get lamp" {
: if (is_beside "lamp") {
: get "lamp" quiet = "true" ;
: if (is_carried "lamp") {
: print "You pick up the dusty lamp" ;
: press_any_key ;
: redescribe;
}
}
}
}
A simpler method exists too. This message will only be displayed if the object is taken.
start_at = village
locations {
village : location "You are in a village." ;
}
objects {
lamp : object "a lamp" start_at = "village" get_message = "You pick up the dusty lamp";
}
There is an issue here that the player may drop the lamp in forest_1, then leave forest_1, then permanently
block the path, but that can be taken place with in other parts of the code.
start_at = village
locations {
village : location "You are in the village" ;
forest_1 : location "You are in a forest" ;
forest_2 : location "You are in a spooky forest" ;
}
connections {
from, direction, to = [
village, east, forest_1,
forest_1, east, forest_2,
]
}
barriers {
block_forest_path : block {
location = forest_1
block_when_not_carried = lamp
message = You need a light source to go into the dark forest.
}
}
objects {
lamp : object "a magical glowing lamp" start_at = "village" ;
}
themes {
my_theme : theme {
font = clairsys_10
}
}
NOTE
This type of block is not compatible with Adventuron 2 PAW / Adventuron 2 DAAD (currently).
start_at = stream
locations {
stream : location "You are by the side of a lovely stream.\nType <WEAR CLOAK<12>> to enable block, type
<REMOVE CLOAK<12>> to disable block.";
forest : location "You are in a grand forest." ;
old_hut : location "You are in an old hut." ;
}
connections {
from, direction, to = [
stream, north, forest,
forest, east, old_hut,
]
}
barriers {
block_disorientate : block {
block_when_worn = cloak
message = You are so confused, you can't seem to move anywhere.
}
}
objects {
cloak : object "the cloak of disorientation" wearable = "true" start_at = "inventory" ;
}
themes {
my_theme : theme {
presentation_mode = 2
}
}
start_at = village
locations {
village : location "You are in the village. Type TELEPORT to go to the location of the lamp." ;
forest : location "You are in a forest. Type TELEPORT to go to the location of the lamp." ;
}
connections {
from, direction, to = [
village, east, forest,
]
}
on_command {
: match "teleport _" {
: print "You goto the location of the lamp" ;
: goto "lamp" ;
: press_any_key ;
: redescribe;
}
}
objects {
lamp : object "a lamp" start_at = "forest" ;
}
It’s very common operation for wanting to create an object when examining something for the first time. If an
object is created one time, even if it is destroy subsequently, then has_not_created will return false.
start_at = village
locations {
village : location "You are in the village." ;
}
objects {
letter : object "a letter" ;
postbox : scenery "a postbox" start_at = "village" ;
}
on_command {
: if_examine "postbox" {
: if (has_not_created "letter") {
: create "letter" ;
: print "You notice a letter stuck in the postbox" ;
: press_any_key ;
: redescribe;
}
}
}
start_at = village
locations {
village : location "You are in the village. Type SCORE to see your score." ;
}
integers {
// Set the default score to zero here
score : integer "0" ;
}
on_command {
: match "score _" {
// Note that CONTROL + SPACE only works on blank lines in these blocks
: print {(
"Your score is " +
score +
"."
)}
}
}
You can also use the {} form in regular text to import the value of a string variable.
start_at = village
strings {
day_of_week : string "Wednesday" ;
}
locations {
village : location "You are in the village. It is {day_of_week}." ;
}
booleans {
is_wednesday : boolean "false" ;
}
You can also use the {boolean ? if_true_string_var : if_false_string_var} form in regular text to import the value
of a string variable.
start_at = village
strings {
wednesday : string "Wednesday" ;
not_wednesday : string "Not Wednesday" ;
}
locations {
village : location "You are in the village. It is {is_wednesday ? wednesday : not_wednesday}.\nType LOOK
to refresh the dynamic location description." ;
}
booleans {
is_wednesday : boolean "false" ;
}
on_tick {
: if (is_wednesday) {
: set_false "is_wednesday" ;
}
: else {
: set_true "is_wednesday" ;
}
}
Here is another variation, but without the requirement for a string variable to reference
start_at = village
locations {
village : location "You are in the village. It is {is_wednesday ? `wednesday` : `not wednesday`}.\nType
LOOK to refresh the dynamic location description." ;
}
booleans {
is_wednesday : boolean "false" ;
}
on_tick {
: if (is_wednesday) {
: set_false "is_wednesday" ;
}
: else {
: set_true "is_wednesday" ;
}
}
Here is yet another variation, but in this variation, we only print something if it is a Wednesday, and we use
inline text.
start_at = village
locations {
village : location "You are in the village. {is_wednesday ? `It is wednesday.`}\nType LOOK to refresh the
dynamic location description." ;
}
booleans {
is_wednesday : boolean "true" ;
}
on_tick {
: if (is_wednesday) {
: set_false "is_wednesday" ;
}
: else {
: set_true "is_wednesday" ;
}
}
The outer {} only includes the text between the backtick (`) characters if the boolean reference resolves to
true.
the next {} only includes the {wed}. , if it is wednesday (true in this example).
the most inner {} refers to the variable 'wed', which contains a value of "Wednesday".
start_at = village
locations {
village : location "You are in the village. {is_wednesday ? `It is {is_wednesday ? `{wed}.`}.`}\nType
LOOK to refresh the dynamic location description." ;
}
strings{
wed : string "Wednesday";
}
booleans {
is_wednesday : boolean "true" ;
}
on_tick {
: if (is_wednesday) {
: set_false "is_wednesday" ;
}
: else {
: set_true "is_wednesday" ;
}
}
You can specify the 'survivor' scope on a variable to inform Adventuron to let the variable value survive at the
point of an end_game or restart occurring (the default value will be set on first game only and never be
reapplied upon restart).
In this snippet, completely unrelated, but we also demonstrate the % operator, which is the modulus (or
remainder) operator. game_count % 10 gives us the remainder of an integer division by 10. This number will
always be in the ranger of zero to nine.
start_at = my_location
locations {
my_location : location "You are in a room. This is your {gane_count_nice} game." ;
}
integers {
// The variable will survive a game restart (or game over)
game_count : integer "0" scope="survivor";
}
on_startup {
: increment "game_count" ;
}
strings {
gane_count_nice : string_dynamic {(
game_count +
(game_count % 10 == 1 ? "st" :
game_count % 10 == 2 ? "nd" :
game_count % 10 == 3 ? "rd" : "th")
)}
}
To print a score, use the advanced version of print. This version of print requires {( )} brackets as shown below.
A piece of text to be printed is still surrounded by double quotes, but variables can now be referenced in this
form. Append parts of the text together with the "+" operator as shown.
start_at = village
locations {
village : location "You are in the village.\nType JUMP to increase your score, type SCORE to see your
score." ;
}
integers {
// Set the default score to zero here
score : integer "0" ;
}
on_command {
: match "jump _" {
: if (score < 20) {
: increment "score" ;
: print "You do something very impressive" ;
}
}
: match "score _" {
: print {(
"Your score is " + score + "."
)}
}
}
The logic of a cycle command is that one command out of the command stored inside the cycle {} block will be
executed. When executed, the command will not be executed again until all other commands have been
exhausted via repeated runs of the cycle command.
At the start of each round, the iteration order is determined. By default, the order is randomised, but you can
set the order using predictable_order = "true|false".
Each cycle command requires a unique key as this will be used to store uniquely serialize the state of the cycle
command.
The key can be anything you like but it must be unique in your gamefile per : cycle {} block.
Please do not use else blocks inside this command as the behaviour if doing this is undefined
WARNING
right now. If statement are fine.
start_at = woods
locations {
woods : location "You are in the woods.\nType <WAIT<12>> repeatedly to cycle through the print commands."
{
on_tick {
: cycle key = "woods_events" predictable_order = "true" skip_interval = "0" {
: print "You step on some twigs." ;
: print "You hear the hoot of an owl." ;
: print "The wind blows through your hair." ;
: print "In the distance you hear the church bell chime." ;
: print "You are afraid." ;
}
}
}
}
start_at = woods
locations {
woods : location "You are in the woods.\nType <WAIT<12>> repeatedly to cycle through the print commands."
{
on_tick {
: cycle key = "woods_events" predictable_order = "false" skip_interval = "0" {
: print "You step on some twigs." ;
: print "You hear the hoot of an owl." ;
: print "The wind blows through your hair." ;
: print "In the distance you hear the church bell chime." ;
: print "You are afraid." ;
}
}
}
}
9.11.3. Skipping
By using skip="1" (or greater), then the cycle command will only be ignored for 1 or more ticks (depending on
the integer provided) after each execution.
start_at = woods
locations {
woods : location "You are in the woods.\nType <WAIT<12>> repeatedly to cycle through the print commands."
{
on_tick {
: cycle key = "woods_events" predictable_order = "false" skip_interval = "0" skip="1" {
: print "You step on some twigs." ;
: print "You hear the hoot of an owl." ;
: print "The wind blows through your hair." ;
: print "In the distance you hear the church bell chime." ;
: print "You are afraid." ;
}
}
}
}
This command will select one command (at random) from its direct descendents to execute and only run that
command.
Please do not use else blocks inside this command as the behaviour if doing this is undefined
WARNING
right now. If statement are fine.
start_at = village
locations {
village : location "You are in the village." ;
}
on_tick {
: execute_one_at_random {
: print "one" ;
: print "two" ;
: print "three" ;
: print "four" ;
}
}
start_at = my_location
locations {
my_location : location "Hello {name}. You are in a room." ;
}
strings {
name : string "";
}
on_startup {
: ask_string
question = "What is your name?"
confirm_negative_question = "You entered your name as \"{name}\".\nWould you like to change the name?"
var = "name"
;
}
In this snippet, some text in the game is conditionally displayed using a string_dynamic too, along with
a ? : operation
start_at = my_location
locations {
my_location : location "You are in a bright kitchen.\n{toast_thought}" ;
}
strings {
toast_thought : string_dynamic {(
is_liking_toast ?
"I can't stop thinking about delicious toast." :
"I can't stop thinking about how disgusting toast is."
)}
}
booleans {
is_liking_toast : boolean "false" ;
}
on_startup {
: ask_bool {
question = Do you like toast?
yes_answer = Yes, I like toast very much
no_answer = No, toast is not something that appeals to me at all
var = is_liking_toast
}
}
A STICKY HEADER is a header that sticks to the top of the screen (does not scroll out of view).
Sticky headers in Adventuron currently can only (currently) contain two slots, top left, and top right.
Within the header_layout section, you can use the 'dynamic_text' item to reference a string (which will contain
some piece of text that may change during the game).
You can also refer to the 'header_text' from the header_layout section, which will use the current location
header text for the slot.
There is a third option, not show here, where you can specify static_text, which is text that is literal and will not
change.
If TB is specified without any further configuration, then the location header will be listed in the topbar.
Generally speaking, you do not want to do this unless you have configured headers for all locations in your
game.
Type lots of inputs to see that the header text "Village" never flows off the screen.
start_at = village
locations {
village : location "You are in the village" header = "Village" ;
}
integers {
score : integer "0" ;
}
objects {
lamp : scenery "a magical glowing lamp" start_at = "village" ;
}
themes {
my_theme : theme {
layout = TB G D X O
colors {
header_bar_pen = 15
header_bar_paper = 9
}
}
}
This is a lazy way to configure the system, and generally speaking it’s better practise to explicitly create a
layout string.
If the header_layout{} section is not provided then an in line (non sticky) location header
NOTE
piece of text will be printed (as is usual behaviour).
start_at = village
locations {
village : location "You are in the village" header = "Village" ;
}
integers {
score : integer "0" ;
}
objects {
lamp : scenery "a magical glowing lamp" start_at = "village" ;
}
themes {
my_theme : theme {
header_layout {
: header_text;
: dynamic_text "score_topright" ;
}
colors {
header_bar_pen = 15
header_bar_paper = 9
}
}
}
In the sample below, type 'jump' at the prompt to increment the score (up to a max of 20). The header will
update. The header never scrolls off screen.
start_at = village
locations {
village : location "You are in the village" header = "Village" ;
forest_1 : location "You are in a forest" header = "Forest" ;
forest_2 : location "You are in a spooky forest" header = "Spooky Forest" ;
}
connections {
from, direction, to = [
village, east, forest_1,
village, west, forest_2,
]
}
strings {
score_topright : string_dynamic {(
score + " / 20"
)}
}
######################################
# On Command #
######################################
on_command {
integers {
score : integer "0" ;
}
objects {
lamp : scenery "a magical glowing lamp" start_at = "village" ;
}
themes {
my_theme : theme {
// TB = top bar
layout = TB G D X O
screen {
experimental_spacer_pre_text = 5
}
header_layout {
: header_text;
: dynamic_text "score_topright" ;
}
colors {
// 15 == white (#fff)
header_bar_pen = 15
// 9 = Blue (#00f)
header_bar_paper = 9
}
theme_settings {
header_capitalization = original
}
}
}
Another example:
start_at = village
locations {
village : location "You are in the village" header = "Village" ;
forest_1 : location "You are in a forest" header = "Forest" ;
forest_2 : location "You are in a spooky forest" header = "Spooky Forest" ;
}
connections {
from, direction, to = [
village, east, forest_1,
village, west, forest_2,
]
}
strings {
topright : string_dynamic {(
h() + " (" + turns() + " turns)"
)}
topleft : string_dynamic {(
/* If turns less than 10 then use "Morning" OTHERWISE ....*/
turns() < 10 ? "Morning" :
/* If turns less than 20 then use "Lunchtime" OTHERWISE ....*/
turns() < 20 ? "Lunchtime" :
/* Use "Lunchtime" OTHERWISE ....*/
"Evening"
)}
}
######################################
# On Command #
######################################
on_command {
integers {
score : integer "0" ;
}
objects {
lamp : scenery "a magical glowing lamp" start_at = "village" ;
}
themes {
my_theme : theme {
// TB = top bar
layout = TB G D X O
screen {
experimental_spacer_pre_text = 5
}
header_layout {
: dynamic_text "topleft" ;
: dynamic_text "topright" ;
}
colors {
// 15 == white (#fff)
header_bar_pen = 15
// 9 = Blue (#00f)
header_bar_paper = 9
}
theme_settings {
header_capitalization = original
}
}
}
To switch on treasure hunt mode, simply supply a treasure_room, and mark one or more object as a treasure
(using treasure="true").
In the code show below, dropping the lamp in the treasure room will display a (system) message of "You have
found all the treasures. You have won!".
The winning message can be customised using a theme, and the automatic win-game logic can be disabled in
the game settings, in case, you want to script a better ending, or have a more complex set of conditions for
completing the treasure hunt.
start_at = treasure_room
treasure_room = treasure_room
locations {
treasure_room : location "The treasure room";
tomb : location "A tomb" ;
}
connections {
from, direction, to = [
treasure_room, east, tomb,
]
}
objects {
lamp : object "a lamp" start_at = "tomb" treasure = "true" ;
}
start_at = treasure_room
treasure_room = treasure_room
locations {
treasure_room : location "The treasure room";
tomb : location "A tomb" ;
stream : location "A stream" ;
}
connections {
from, direction, to = [
treasure_room, east, tomb,
treasure_room, south, stream,
]
}
objects {
lamp : object "<a lamp<14>>" start_at = "tomb" treasure = "true" ;
ring : object "<a ring<14>>" start_at = "stream" treasure = "true" ;
}
start_at = cell
locations {
cell : location "You are in your cell. You see a door, a bed and bland wallpaper adorns the walls." ;
}
objects {
wallpaper : object "a strip of wallpaper" ;
pen : object "a pen" ;
key : object "a small key" ;
}
booleans {
is_key_in_keyhole : boolean "true" ;
is_key_on_paper : boolean "false" ;
is_paper_under_door : boolean "false" ;
}
vocabulary {
: noun / aliases = [wallpaper, paper]
}
on_command {
: press_any_key ;
: redescribe;
}
: else {
: print "You think you should leave the rest of the wallpaper in place." ;
}
}
}
: else {
: print "The key has already fallen" ;
}
}
It forms the basis of the Adventuron Cavejam, which is (or was) a gamejam to remix and improve this game.
// USEFUL SHORTCUTS
######################################
# Code Start #
######################################
start_at = lakeside
start_theme = my_theme
loading_screen = loading_screen
######################################
# locations #
######################################
locations {
forest : location "You are on the forest path.\nTall <TREES<4>> tower over you on both sides." ;
outside_cave : location "You are standing outside <THE CAVE OF MAGIC<5>>" ;
inside_cave : location "You are inside <THE CAVE OF MAGIC<5>>" ;
lakeside : location "You are by the side of a <BEAUTIFUL LAKE<2>>." ;
}
######################################
# connections #
######################################
connections {
from, direction, to = [
lakeside, north, forest,
forest, north, outside_cave,
outside_cave, north_oneway, inside_cave,
]
}
######################################
# Objects / Scenery #
######################################
objects {
troll : scenery "an enormous troll" start_at = "outside_cave" ;
sleeping_troll : scenery "an enormous troll (sleeping)" ;
apple : object "an apple" ;
treasure : object "a pile of treasure" start_at = "inside_cave" ;
}
######################################
# barriers #
######################################
barriers {
block_cave : block {
location = inside_cave
message = THE TROLL IS GUARDING THE CAVE.
block_when_exists = troll
show_blocked_exit = true
}
}
######################################
# on_startup #
######################################
// The on_startup hook runs at the start of the game, one time per game.
on_startup {
######################################
# on_command #
######################################
on_command {
// If the player has typed "pick apple" or "get apple" then run the code inside this block
// NOTE : Adventuron automatically associated verbs get with take, so this would
// automatically test for get apple, pick apple, or take apple.
// Colouring in text is possible using <sometext<n>> pattern (where n is a number between 0 and 15
representing a palette number)
// By default 0 = black, 1 = blue, 2 = red, 3 = magenta, 4 = green, 5 = cyan, 6 = yellow, 7 = white, 8
= black, 9 .. 15 are bright versions of 1 .. 17.
: if (is_present "troll") {
: print "<\"I'M SO HUNGRY\"<3>>, says the enormous TROLL in the deepest possible voice." ;
}
: else_if (is_present "sleeping_troll") {
: print "The troll is fast asleep." ;
}
// Destroying an object will move it into a non-existing state (into the ether)
: destroy "apple" ;
// Change the location of the troll and the sleeping troll
// (move troll to nowhere, and sleeping_troll
// to the location of the current troll)
: swap o1 = "troll" o2 = "sleeping_troll" ;
: beep millis = "100" pitch = "0" ;
: beep millis = "100" pitch = "6" ;
: beep millis = "100" pitch = "12" ;
// Wait for the player to press a key, touch the screen
// or click the mouse
: press_any_key ;
// Then redescribe the current location
: redescribe;
}
}
######################################
# on_tick #
######################################
// The on_tick code is executed after a command has been dealt with.
on_tick {
######################################
# On Describe #
######################################
on_describe {
// Put code here that is printed when a location is described.
}
######################################
# Subroutines #
######################################
subroutines {
// Add your subroutines here, could be useful for commonly
// used beep commands, or decorative game over screen
}
######################################
# Themes #
######################################
themes {
my_theme : theme {
theme_settings {
// H = Header
// G = Graphics
// D = Description
// X = Exit List
// O = Object (or entity) List
layout = H G D X O
######################################
# game_information #
######################################
game_information {
######################################
# Graphics #
######################################
assets {
graphics {
logo : placeholder;
loading_screen : placeholder;
inside_cave : placeholder;
lakeside : placeholder;
outside_cave : placeholder;
forest : placeholder;
}
}
start_at = village
locations {
village : location "You are in the village" ;
forest_1 : location "You are in a forest" ;
forest_2 : location "You are in a spooky forest" ;
}
connections {
from, direction, to = [
village, east, forest_1,
forest_1, east, forest_2,
]
}
objects {
lamp : object "a magical glowing lamp" start_at = "village" ;
}
themes {
my_theme : theme {
font = clairsys_10
}
}
User imported fonts (use the MENU / IMPORT option in the Adventuron Classroom editor) can be referenced
via pressing CONTROL (or ALT) + SPACE after "font = ", all user fonts are named userfont_xxxxxxxxxx (where
xxxxxxxxx is the filename of the ttf font imported).
As the content panel of the display area generally only scales in integer amounts (pixel doubling, tripling, etc),
then it will be likely that a lot more of the vertical section of the screen will be lost, in order to fit with this
request without blurring the bitmap text.
I’m using the spelling of "colour" in my description (because I’m British), but the name of the
NOTE color fields in Adventuron is in American English (as is the coding convention). I’m sure
Webster though he was making things easy.
This is simplified in Adventuron with theme inheritance. Simple write extends = theme_id (where theme is the
name of another theme), and all the settings of that theme will be applied, before the settings of the current
theme are applied.
You can extend to any depth you like, but do not specify circular inheritance (theme a extends theme b which
extends theme a which extends theme b, etc).
This feature, and theme inheritance was used in the final public-facing version of Excalibur.
Upon entering a location, in on_describe{} a theme would be set for the current location, which allowed the
border colour to match the artwork and the tone of the current location.
start_at = room
start_theme = base
locations {
room : location "You are in a room.\n^n^ Type 'GREEN' to set the border green.\n Type 'YELLOW' to set
the border yellow.^m^\n (non-mobile clients only).\n" ;
}
on_command {
: match "green _" {
: set_theme "green";
: print "OK" ;
}
: match "yellow _" {
: set_theme "yellow";
: print "OK" ;
}
: match "grey _" {
: set_theme "base";
: print "OK" ;
}
}
themes {
base : theme {
font = clairsys_10
columns = 50
screen {
content_width = 400
border_mode_vertical_percent = 1
paragraph_spacing_multiplier = 1
}
colors {
paper = 7
story_pen = 0
}
}
green : theme {
extends = base
colors {
border = 4
}
}
yellow : theme {
extends = base
colors {
border = 6
}
}
}
start_at = village
locations {
forest : location "You are in a forest." ;
village : location "You are in the village." ;
}
connections {
from, direction, to = [
village, east, forest,
]
}
objects {
lamp : object "a lamp" start_at = "village" ;
}
strings {
some_dynamic_string : string_dynamic {(
is_at "village" ? "You hear sounds of the village" :
is_at "forest" ? "You hear sounds of the forest" :
""
)}
}
themes {
my_theme : theme {
layout = H G D X P* "some_dynamic_string" O SEP "adv_line_red"
}
}
P* "string_id" = pointer to a string id of a string containing text to be rendered (this can be a dynamic string
which will resolve lazily).
O = Object list for conspicious objects in location (if exists for location)
SEP "seperator_id" = horizontal line break across the screen. Currently just supports 'adv_line_red'. DO NOT
USE CUSTOM SEPERATORS RIGHT NOW AS IMPLEMENTATION WILL CHANGE.
Mobile clients do not use this setting and always use 100% of horizontal width (high dpi
NOTE
means that artifacts are barely visible on mobile).
start_at = village
locations {
village : location "You are in the village." ;
forest : location "You are in a forest." ;
}
connections {
from, direction, to = [
village, east, forest,
]
}
######################################
# Themes #
######################################
themes {
my_theme : theme {
screen {
// Setting the width to 256 will snap the screen scaling factor in integer increments of 256 pixels
(meaning graphic scaling can be crisp for precise pixel art)
content_width = 256
}
}
}
9.20. Music
NOTE THIS IS VERY EXPERIMENTAL AND MAY NOT WORK WELL OR AT ALL
MP3s can be referenced via absolute url (starting with http:// or https:// or relative urls).
If using relative urls, then to test your game, you must compile the game and use it from your local file system,
or compile it and host it on a website. The relative urls
will not work using the classroom website as the assets will not be hosted there.
If there is a desktop version of Adventuron Classroom produces, this will not be an issue.
start_at = river
locations {
river : location "You are in the river.\n" ;
}
on_tick {
: if (is_just_entered () ) {
: if (is_at "river") {
: play_music sound="song_river";
}
: else {
: stop_music;
}
}
}
assets {
sounds {
// NOTE :: Make sure that only reference content you are
// licensed to use.
// ALSO :: You can use relative paths here, but you can only
// test in compiled versions of your code (not the
// web editor)
song_river : sound_sample "https://somedomainid.com/sounds/river.mp3" ;
}
}
9.21. Darkness
Darkness is a special state where a location cannot be described.
It’s not generally a very friendly state to leave the player in as it stops object lists and exit lists from being
displayed (by default) but some people might want to add this to their game.
Darkness requires:
3. (Optionally) Customizing the darkness message, and possibly the darkness text colour.
Before a location is described, the darkness expression is evaluated and if it is dark, then the darkness message
is displayed in place of the regular location text.
start_at = village
locations {
village : location "You are in the village" ;
forest_1 : location "You are in a forest" ;
forest_2 : location "You are in a spooky forest" ;
}
connections {
from, direction, to = [
village, east, forest_1,
forest_1, east, forest_2,
]
}
objects {
lamp : object "a magical glowing lamp" start_at = "village" ;
}
Boolean dynamics are used to simlify the logic in the on_command block.
start_at = start_room
locations {
on_command {
: match "test _" {
: print "Should be blocked in the dark!" ;
: done ;
}
}
}
}
objects {
// The crown is in the same location as the player at the start, but GET is blocked
// so cannot be taken even if the player knows it's there.
crown : object "a gold crown" start_at = "start_room" ;
booleans {
is_dark : boolean_dynamic {(
is_at "start_room" && is_lamp_lit == false
)}
on_pre_command {
// Blocks everything except movement, quit, save, load, inventory, turns, look
: if (is_dark && is_inaccessible_darkness_verb) {
: print "You fumble in the dark." ;
: done ;
}
}
settings {
// Tells Adventuron when to override the location description with
// the darkness message (in the theme system messages), plus will remove direction list
// and object list from the location layout (when is_dark resolves to true)
dark_expression = is_dark
}
themes {
my_theme : theme {
colors {
// Set the darkness pen colour to dark blue.
dark_pen = 9
}
system_messages {
it_is_dark = Darkness surrounds you.
}
}
}
Presentation Mode 2 is a work in progress, and changes the way that the event model works in Adventuron.
Essentially, the screen will refresh if the object list or exit list changes as a result of an action, automatically,
without having to issue a screen refresh.
The system handlers for get and drop are defaulted to being silent (as getting and dropping success will be
conveyed by the updated object list). You can override this if you wish in the on_command block by matching
"get _" and "drop _" then doing whatever you like.
Presentation mode 2 also changes the default layout to something more appropriate for object centric
gameplay. The layout can be manually restored to whatever you like in the theme. Presentation mode 2 just
affects the default.
If something is printed, then Adventuron will automatically insert a press_any_key command before refreshing
the screen.
There are a number of gotchas to this approach, the first of which is that an auto-refresh is currently not a full
refresh. It won’t call the on_describe() method.
There are a number of ways to mitigate this issue, and more will be forthcoming.
There is a bug that exists in GET ALL and DROP ALL right now in that one additional tick is
WARNING
being used, but no ticks are being registered. This will be resolved, no need to report it.
Why not just update the object list and exit list in place?
Well, firstly, it’s not as easy as it sounds on different screen sized devices. It may be that there are a lot of
objects to display, and adding them will push the screen down. It may be there is a judder. It almost certainly
requires a split window, which is something that doesn’t work very well on screens with limited vertical pixels
(such as phones with greedy keyboards or excessive notches or both). This approach is the simplest to code and
the simplest to use right now. Better approaches may follow.
##############################################
##
## Presentation Mode 2 will automatically
## clear down the screen when the visible objects
## or visible exits change in the current location
##
## In presentation mode 2, auto redescribes do not
## generate a call to on_describe() when
## redescribing. on_describe() is only called when
## a : redescribe; command is issued or when the
## player changes location.
##
##############################################
start_at = village
locations {
village : location "You are in the village.";
forest : location "You are in a forest" ;
}
objects {
lamp : object "a lamp" start_at = "village" ;
pen : object "a pen" start_at = "village" ;
sword : object "a sword" start_at = "village" ;
rock : object "a rock" start_at = "village" ;
}
connections {
from, direction, to = [
forest, east, village,
]
}
barriers {
block_forest : block {
location = forest
message = The path is blocked by rubble
block_when_carried = sword
}
}
themes {
my_theme : theme {
## NOTE :: Treat this as experimental for now ..
presentation_mode = 2
}
}
##############################################
##
start_at = village
locations {
village : location "You are in the village.";
forest : location "You are in a forest" ;
}
objects {
lamp : object "a lamp" start_at = "village" ;
pen : object "a pen" start_at = "village" ;
sword : object "a sword" start_at = "village" ;
rock : object "a rock" start_at = "village" ;
}
on_startup {
: print "<* Type UNLOCK to unlock the exit to the forest without printing anything (instant automatic
refresh).<10>>" ;
: print "<* Type UNLOCKP (after restarting) to unlock the exit to the forest whilst printing a message (a
press any key will automatically be placed after the final print message).<11>>" ;
: print "<* GET/DROP an object to auto refresh the screen.<12>>" ;
: print "<* GET ALL or DROP ALL to observe one screen refresh only.<13>>" ;
: print "<* When not unlocked the forest manually (seperate restart) getting the sword will unlock the
forest, dropping the sword will lock the forest (exit list automatically updates).<14>>" ;
: print "<* Auto redescribes do not trigger on_describe() as the describe happens after the on_tick()
event therefore it would be dangerous to execute out of sequence or to run another describe without a tick.
<15>>" ;
: press_any_key ;
connections {
from, direction, to = [
forest, east, village,
]
}
barriers {
block_forest : block {
location = forest
message = The path is blocked by rubble
block_when_not = is_forest_unblocked
}
}
booleans {
is_forest_unblocked : boolean_dynamic {(
is_carried "sword" || is_unlocked
)}
on_command {
: match "unlock _" {
// NOTICE :: We do not need to call redescribe here ...
// If there is no printing, then a describe is automatically
// called (but on_describe() will not be called in this instance)
: set_true "is_unlocked" ;
}
on_describe {
// Playing some beeps to demonstrate when on_describe is called
// If we printed on_describe here, then it would
: print "on-describe()" ;
}
on_tick {
: if (is_at "village" && is_first_entered()) {
: print "NOTE : There is a tick counting bug on GET ALL and DROP ALL at the moment, this will be fixed
shortly." ;
}
: beep millis = "80" pitch = "0" ;
}
themes {
my_theme : theme {
## NOTE :: Treat this as experimental for now ..
presentation_mode = 2
}
}
To use external graphics files, first put your graphics in a folder, then add records like this to your assets {
graphics {} } section.
graphics {
// The png file will be read from the same path as the game html file
blah : png "mypng.png";
// This file should be referencable from anywhere (but only if playing online). Absolute paths can be
convenient in development, but for packaging, relative paths are better.
blah2 : jpeg "https://somedomain.com/somepath/myjpeg.jpg";
}
Use the < parent_of "entity_id" > function to access the id of the direct parent (or holder) of an object.
start_at = village
locations {
village : location "You are in the village.";
}
objects {
sword : object "a sword" ;
lamp : object "a lamp" start_at = "inventory" ;
spoon : object "a spoon" start_at = "village" ;
fork : object "a fork" start_at = "bag";
bag : object "a bag" start_at = "inventory" container_type="bag";
}
on_tick {
: if (parent_of "lamp" == "inventory") {
: print "The lamp is in your inventory." ;
}
: if (parent_of "spoon" == current_location()) {
: print "The spoon is in the same location as you." ;
}
: print {( "Location of Lamp : " + parent_of "lamp" )}
: print {( "Location of Sword : " + parent_of "sword" )}
: print {( "Location of Spoon : " + parent_of "spoon" )}
: print {( "Location of Bag : " + parent_of "bag" )}
: print {( "Location of Fork : " + parent_of "fork" )}
start_at = village
locations {
village : location "You are in the village.\nType <SWORD<12>> to attempt to place a sword in your pocket
/ inventory (inventory limit is 1 in this game) then it will move the player to the forest." ;
forest : location "You are in a forest.\nType <SWORD<12>> to attempt to place a sword in your pocket /
inventory (inventory limit is 1 in this game)." ;
objects {
lamp : object "a lamp" start_at = "inventory" ;
pen : object "a pen" start_at = "village" ;
sword : object "a sword" ;
rock : object "a rock" start_at = "village" ;
}
integers {
inventory_limit : integer "1" ;
}
connections {
from, direction, to = [
village, east, forest,
]
}
on_tick {
: inventory;
}
on_command {
: match "sword _" {
: print "Attempting to create and put a sword in your pocket, then moving to the forest." ;
: pocket "sword" ;
: goto "forest" ;
: press_any_key ;
: redescribe;
}
}
settings {
inventory_items_limit_var = inventory_limit
}
start_at = village
locations {
village : location "You are in the village.";
}
themes {
my_theme : theme {
delays {
// 0 milliseconds of delay
default = 0
}
}
}
In the case that one word is entered, or two words are entered (language independent), then Adventuron
records the original verb and the original noun.
These will store the exact inputs the player entered. In English, the verb comes before the noun. In other
languages, vice versa. The parser is aware of which logic to apply depending on the language it is dealing with.
So, we can access the original verb with original_verb() and the original noun with original_noun(). These are
functions that return string values, empty if there was not a value provided.
When dealing with safe combinations, we want to check that the player either entered a number in the verb or
noun position.
To do this we simply check that we are in the correct context (in the same location as a safe), then we check to
see if either the verb or noun are numeric using the is_int() function (is integer?).
If the original verb contains an integer, then match it in the verb position using match. Match the correct
combination first. After matching the good combination, we use a : done; command to stop handling items in
the current event block (on_command{}).
We use a similar pattern for matching the combination in the noun position, except that we also check for
"dial" as the verb.
start_at = office
locations {
office : location "You are in an office." ;
}
objects {
safe : scenery "a safe" start_at = "office" examine_message="The safe has a keypad.\nType DIAL XXXX (where
XXXX is a number to try to open the safe).";
}
on_command {
: if (is_present "safe") {
: if (is_int (original_verb())) {
: match "1234 _" {
: print "You enter the correct safe combination" ;
: done ; // Stops it from matching anything else
}
: print "Wrong Combo" ;
}
: match "dial _" {
: if (is_int(original_noun1())) {
: match "dial 1234" {
: print "You enter the correct safe combination" ;
: done ; // Stops it from matching anything else
}
: print "Wrong Combo" ;
}
: else {
: print "Please type DIAL XXXX (where XXXX is a number)." ;
}
}
}
}
9.29. Containers
Containers are not yet supported by Adventuron (preliminary support is in the engine).
If you only declare one theme, this will become the default theme, no matter what the
NOTE
identifier of the theme is.
start_at = village
locations {
village : location "You are in the village" ;
forest_1 : location "You are in a forest" ;
forest_2 : location "You are in a spooky forest" ;
}
connections {
from, direction, to = [
village, east, forest_1,
forest_1, east, forest_2,
]
}
objects {
lamp : object "a magical glowing lamp" start_at = "village" ;
}
themes {
my_theme : theme {
lister_objects {
item_capitalization = original
}
}
}
System handlers such as get, drop, wear, remove, go east, go north, etc, are executed when the player input
doesn’t match something in the on_command {} block.
If something does match in the on_command{} block, and it’s not a control command (such as done, if, match,
else, else_if), then it overrides the system handler (the system handler doesn’t execute).
99% of the time, this is correct behaviour, but sometimes you may want to do something in addition to the
system even handler. In these cases, you need to hide your handler from Adventuron so it doesn’t know you’ve
executed your own code.
Anything inside the : mask {} command will hide the user handler from the system. This means that the system
handler will be executed in addition to the code inisde your mask{} block.
In the code below, try running it as is, then remove the : mask{} block (comment it out) and observe the
behaviour difference.
start_at = field
locations {
field : location "You are in a field." ;
meadow : location "You are in a meadow." ;
river_bank : location "You are at a river bank." ;
}
connections {
from, direction, to = [
field, east, meadow,
meadow, east, river_bank,
]
}
integers {
num_times_try_go_east : integer "0" ;
}
on_command {
: match "e _" {
// Anything inside a mask will not override a
// system handler. In this case, we wish to
// increment a counter everytime we try to
// head east, but we don't want to block the
// system movement handler.
: mask {
: increment "num_times_try_go_east" ;
}
}
}
on_tick {
: print "You have tried to move east {num_times_try_go_east} time(s)." ;
}
9.32. How to see which locations are adjacent to the current location
The try_move() function will return a string containing the id of the location in the direction of the verb that
the player entered. If there is no accessible location in that direction (no connection, or an active block), then a
blank string will be returned.
: if (try_move() != "") {
// Do something
}
: if (try_move() == "") {
// Do something
}
start_at = meadow
locations {
field : location "You are in a field." ;
meadow : location "You are in a meadow." ;
river_bank : location "You are at a river bank." ;
}
connections {
from, direction, to = [
field, east, meadow,
meadow, east, river_bank,
]
}
on_command {
: match "e _" {
: if (try_move() != "") {
// Note :: This overrides the system movement handler (see the mask section for more information on
this)
: print "You can go east, but you choose not to go.";
}
}
}
start_at = field
locations {
field : location "You are in a field." ;
meadow : location "You are in a meadow." ;
river_bank : location "You are at a river bank." ;
}
connections {
from, direction, to = [
field, east, meadow,
meadow, east, river_bank,
]
}
integers {
num_times_gone_east : integer "0" ;
}
on_command {
: match "e _" {
// Anything inside a mask will not override a
// system handler. In this case, we wish to
// increment a counter everytime we successfully
// head east, but we don't want to block the
// system movement handler.
: mask {
// Try move contains the id of the location
// correspondin to the direction verb in
// the logial sentence
// If the direction leads nowhere or it
// is blocked, then a blank string is returned.
: if (try_move() != "") {
: increment "num_times_gone_east" ;
}
}
}
}
on_tick {
: print "You have successfully gone east {num_times_gone_east} time(s)." ;
}
## int_b = int_a
: set_integer var = "int_b" {(int_a)}
## string_b = string_a
: set_string var = "string_b" {(string_a)}
## bool_b = bool_a
: set_boolean var = "bool_b" {(bool_a)}
A full demo of all three types of copy is included below (type COPY at the command to initial the copy.
The location text is formatted to debug the value of all the variables.
start_at = my_location
locations {
my_location : location "^n^int_a is {int_a}\nint_b is {int_b}\nbool_a is {bool_a}\nbool_b is
{bool_b}\nstring_a is {string_a}\nstring_b is {string_b}^m^\nType <COPY<12>> to copy A variables to B
variables.";
}
integers {
int_a : integer "5" ;
int_b : integer "0" ;
}
booleans {
bool_a : boolean "true" ;
bool_b : boolean "false" ;
}
strings {
string_a : string "toast";
string_b : string "eggs";
}
on_command {
: match "copy _" {
: set_integer var = "int_b" {(int_a)}
: set_string var = "string_b" {(string_a)}
: set_boolean var = "bool_b" {(bool_a)}
: print "Copied all A variables into B variables." ;
: press_any_key ;
: redescribe;
}
}
(Advanced)
# If we are running on a mobile client, then "copy the value of a and add 1 into b", else "copy the value of
a into b".
: set_integer var = "int_b" {(is_mobile() ? int_a + 1 : int_a)}
A future version of Adventuron will radically alter the matching system to assist with this so that all user
"match" patters can benefit from the same disambiguation without any specific code..
But, for now, here is an example of a workaround when you have multipke objects of scenery with the same
noun but different adjective.
Yes, yes, yes, this is a horrible workaround, but it does work, and only needs to be implemented for handlers of
objects that have shared nouns.
start_at = my_location
locations {
my_location : location "You are in a room." ;
my_location_2 : location "You are in a room 2." ;
}
connections {
from, direction, to = [
my_location, east, my_location_2,
]
}
objects {
white_horn : object "a white horn" start_at = "my_location" ;
magenta_horn : object "a magenta horn" start_at = "my_location" ;
cyan_horn : object "a cyan horn" start_at = "my_location" ;
}
integers {
horn_count : integer "0" ;
}
on_command {
: match "examine horn" {
// Use masking so that this setup part does not override the system handler.
: mask {
: set_integer var="horn_count" value="0";
: if (is_present "white_horn") { : increment var="horn_count"; }
: if (is_present "magenta_horn") { : increment var="horn_count"; }
: if (is_present "cyan_horn") { : increment var="horn_count"; }
}
: if (horn_count >= 1) {
: if (adjective1_is "white") {
: if (is_present "white_horn") {
: print "The white horn makes a DEEP booming sound.";
}
: else {
: print "Not here";
}
}
: else_if (adjective1_is "magenta") {
: if (is_present "magenta_horn") {
: print "The magenta horn makes a TINNY sound.";
}
: else {
: print "Not here";
}
}
: else_if (adjective1_is "cyan") {
: if (is_present "cyan_horn") {
: print "The cyan horn makes a SMOOTH GROOVY sound.";
}
: else {
: print "Not here";
}
}
: else {
: print "Be more specific please.";
}
: done;
}
: else {
: print "There are no horns present." ;
}
}
}
9.35. ADVANCED TOPIC - Understanding Turns and Ticks (Beginners do not read)
This is VERY advanced, and is only provided to better understand the Adventuron game
NOTE
lifecycle better. Beginners - DO NOT READ THIS SECTION - it’s generally not needed.
A tick is the number of times that the on_tick {} event handler block has occured in the game (excluding the
startup tick).
The first tick is tick 0, and the first turn is turn 1.
Tick 0 runs before first input has been entered by the game (upon presenting the first location). Tick 1 is the
first tick that can follow turn 1 (even though it’s technically the second tick). There is no turn 0.
#############################################
# The first tick is TICK 0 (after the first
# room is described). The first tick is enabled
# by defauly but this tick may be configurable in
# a later version of Adventuron.
# -----------------------------------------
# Every submitted command increments turns()
# But some system commands (such as SAVE)
# do not increment the tick counter.
# -----------------------------------------
#
# In the below sample code, the commands ONE, TWO, FOUR
# all generate ticks, INVENTORY and THREE do not generate
# ticks. THREE purposefully stops a tick with the : stop_ticks;
# command.
#
#############################################
start_at = my_location
locations {
my_location : location "You are in a room.\nType the following commands one at a time at the command line
(inventory will not generate a tick):\n^n^(1) ONE \n(2) TWO\n(3) THREE\n(4) INVENTORY\n^m^(5) FOUR" ;
}
on_command {
// Match all words
: match "_ _" {
// Do not match "inventory" (let the system handle it)
: if (verb_is "inventory" == false) {
// If the input is "three" then skip downstream ticks
// (this allows custom responses without the game world pproceeding)
: if (verb_is "three") {
: stop_tick;
}
// Print how many ticks and turns have elapsed so far
: print {(
"Ticks : " + ticks() + " Turns : " + turns()
)}
}
}
}
settings {
// This is set to false by default (inventory generates a tick by default, but we can disable that here)
// NOTE : This is an experimental setting, and may change in a future release.
experimental_inventory_stops_tick = true
}
on_tick {
: print {("TICK #" + ticks() )}
}
Expected results:
The turns() function will return a number that is incremented just before on_command() is executed (can
think of turns as commands processed so far).
The ticks() function will return a number that is incremented just before on_tick() is executed (can think of
ticks as ticks processed so far).
turns() and ticks() can be very much out of synch, and this is normal, as some commands are timeless.
Items in GET ALL | DROP ALL | etc. get their own turn followed by their own tick.
A general rule of thumb is only to use the ticks() function in the on_ticks{} block and only use turns() {} in the
on_command block.
start_at = village
locations {
village : location "You are in the village.";
}
objects {
lamp : object "a lamp" start_at = "village" ;
spoon : object "a spoon" start_at = "village" ;
}
on_startup {
: print {("- on_startup (ticks so far:"+ticks() + ", turns so far:" +turns()+")" )}
: press_any_key ;
}
on_command {
: if (true) {
// Masking makes sure that a command handler doesn't override a system handler.
: mask {
: print {("--------------------" )}
: print {("- on_command (ticks so far:"+ticks() + ", turns so far:" +turns()+")" )}
}
}
}
on_tick {
: print {("- on_tick (ticks so far:"+ticks() + ", turns so far:" +turns()+")" )}
}
on_describe {
: print {("- on_describe (ticks so far:"+ticks() + ", turns so far:" +turns()+")" )}
}
themes {
my_theme : theme {
theme_settings {
clear_screen_enable = false
}
}
}
10. Troubleshooting
10.1. Recursion Error
If you see an error message like the following, it (likely) means that you have accidentally triggered an infinite
redescribe loop.
or
When executing the code shown below, start the game, and move west. An error will be displayed in the
gameplay window.
start_at = village
locations {
village : location "You are in the village" ;
forest_1 : location "You are in a forest" ;
forest_2 : location "You are in a spooky forest" ;
}
connections {
from, direction, to = [
village, east, forest_1,
forest_1, east, forest_2,
]
}
on_describe {
: if (is_at "forest_1") {
: redescribe;
}
}
on_describe {
: if (is_at "forest_1") {
: redescribe;
}
}
Adventuron does the following logic upon describing a location (simplified to illustrate the point):
During step 3 (on_describe{})and step 4 (on_tick{}), Adventuron allows the author to execute the : redescribe
command, which will go back to step 2, and move forward again. This is sometimes necessary, for example, a
cut scene may occur, and some story delivered, then at the end of it, we wish to redisplay the location afresh.
The recursion error happens if the redescribe is not sufficiently "guarded". That is, every time it redescribes, it
re-runs the redescribe.
To stop this from happening, make sure that your redescribe is guarded, so that when you redescribe, it doesn’t
just redescribe again.
e.g.
If your sound isn’t playing when in development, check the following diagnostics
on_command {
: match "permissions _" {
: print {( "sysvar_features_sound : " + sysvar_bool "sysvar_features_sound" )}
: print {( "sysvar_features_music : " + sysvar_bool "sysvar_features_music" )}
: print {( "sysvar_features_blip : " + sysvar_bool "sysvar_features_blip" )}
: print {( "sysvar_has_asked_blip : " + sysvar_bool "sysvar_has_asked_blip" )}
: print {( "sysvar_has_asked_music : " + sysvar_bool "sysvar_has_asked_music" )}
: print {( "sysvar_has_asked_sound : " + sysvar_bool "sysvar_has_asked_sound" )}
: print {( "sysvar_blip_enabled : " + sysvar_bool "sysvar_blip_enabled" )}
: print {( "sysvar_sound_enabled : " + sysvar_bool "sysvar_sound_enabled" )}
: print {( "sysvar_music_enabled : " + sysvar_bool "sysvar_music_enabled" )}
: print {( "sysvar_sfx_enabled : " + sysvar_bool "sysvar_sfx_enabled" )}
: print {( "sysvar_ambient_enabled : " + sysvar_bool "sysvar_ambient_enabled" )}
: print {( "sysvar_graphics_enabled : " + sysvar_bool "sysvar_graphics_enabled" )}
}
}
Adventuron is intended to be a CREATIVE TOOL. Adventuron should NOT be used to recreate or resemble existing
game titles WITHOUT EXPRESS PERMISSION of all copyright holders.
In no event will Adventuron Software Limited be liable for any loss or damage including without limitation,
indirect or consequential loss or damage, or any loss or damage whatsoever arising from loss of data or
profits arising out of, or in connection with, the use of this website.
All adventure data is stored locally, and not transmitted nor stored on the server. Some functions may
communicate with the server but no personal information will be transmitted.
Adventuron's engine / generated HTML gamefiles are not licensed for commercial use.
By clicking on the "I Agree" button below, you agree to NOT infringe upon any copyright. In addition, by
clicking the "I Agree" button you also agree to the use of cookies and web storage for storing data pertinent
to the application purpose.
This tutorial may not be redistributed on any other domain than adventuron.io (https://adventuron.io).
The version used in this course written by Chris Ainsley based on the behaviour of the original.
The source code used in this tutorial was written by Chris Ainsley and is copyright of Adventuron Software
Limited.
Excalibur: Sword of Kings (all versions) is Copyright of Adventuron Software Limited, All Rights Reserved.
11.5. URLS
Adventuron Homepage:
https://adventuron.io
Adventuron Games:
https://adventuron.itch.io
https://adventuron.io/classroom
11.6. Acknowledgements
Thank you to Mark Harrison for the excellent art present in the embedded version of this document, in
addition to his superb work in the Retro Gamer full page ad (issue 193). Check out Mark’s Facebook group
here (https://www.facebook.com/artbymch/).
Thank you to the creators of the AsciiDoc documentation format, and the AsciiDoctor team, for the amazing
AsciiDoctor JS project.
Thank you to the GWT project, and especially to Colin Alworth for his support and passion behind the
project.
Thank you to Nick Manarin for the really rather good ScreenToGif (https://www.screentogif.com/) utility, which
was used in the production of this documentation.
Thank you to the Domino UI team, for their excellent UI framework (used in the documentation).
Thank you to Andy Green, Shaun McClure, Steve Horsley, Gareth Pitchford, Tim Gilberts, Richard Pettigrew,
Mark Hardisty, and others for their encouragement and support.
Thank you to Shaun McClure and Ian Smith for writing Excalibur - which I believe was an ideal adventure
game with which to teach the concepts of building a basic adventure.
Thank you to Alternative Software Limited for selling the rights to Excalibur, and to Ian & Shaun for their
blessing of the sale.
Thank you to the Font Awesome team for their icon set, and to the Mali Font creators for an excellent legible
yet fun font.
Thank you to John Wilson, Gareth Pitchford, and Richard Pettigrew for being early adopters of the system.
Thank you to Andrés Samudio for making the DAAD system, and the DAAD system font public domain, and
for his enthusiastic support of this project.
Thank you to Paul Van Der Laan, for making the Clairsys font, and for making the Clairsys 10 variant, both
available under the SIL font license.
Thank you to Fergus McNeill for allowing commercial and non-commercial use of the Delta 4 font (adapted
as the Delta 10 font).
11.7. Contact
Adventuron is written by Chris Ainsley, and Copyright of Adventuron Software Limited, All Rights Reserved.
Email: [email protected]
/* ------------------------------------------------------------------------------- */
/* OPEN SOURCE LICENSES */
/* ------------------------------------------------------------------------------- */
/* GWT - https://github.com/gwtproject */
/* */
/* Apache Version 2.0 License */
/* http://www.gwtproject.org/terms.html */
/* Elemental 2 - https://github.com/google/elemental2 */
/* Apache Version 2.0 License */
/* http://www.gwtproject.org/terms.html */
/* Blazing Chain LZW Library : */
/* https://github.com/tommyettinger/BlazingChain */
/* MIT License */
/* The above copyright notice and this permission notice shall be included in all */
/* copies or substantial portions of the Software. */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */
/* SOFWARE. */
/*! howler.js v2.0.14 | (c) 2013-2018, James Simpson of GoldFire Studios | MIT License | howlerjs.com */
/* ------------------------------------------------------------------------------- */
/* JSZip uses the library zlib.js released under the following license : */
/* zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */
/* ------------------------------------------------------------------------------- */
/*
Copyright (C) 2018 John Nesky
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/* ------------------------------------------------------------------------------- */
/* DOMINO UI - https://github.com/DominoKit/domino-ui */
/*
* Copyright 2019, Domino UI Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
/* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY */
/* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND */
/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* asciidoctor.js - https://github.com/asciidoctor/asciidoctor.js */