This example is a text-base adventure game. The game gives a textual description of the player's surroundings and the player then enters simple text commands to interact with the game. Command take the form "verb object" where the object may be left off for some commands. Example commands are "south" or "take apple".
// Copyright 1983 by A. Clapman - Design and original ZX BASIC programming
// Copyright 1996,2006 by H. Bezemer - Structured design and Arena programming
// Permission is granted by the author to use and distribute this software
// provided these copyright notices are preserved.
// This file is part of the Arena interpreter package
// Extract from a time-travellers diary discovered in the pyramid of
// Ikhotep, pharoah of the ninth dynasty, on the planet Sirius B,
// in the dog star system.
// "I have been attempting to discover the secret of the pyramid for some
// months now. It is the only way I will be able to escape this barren
// planet. After my time-machine was destroyed by the warrior tribe I
// found my way to this dusty monument after consulting a man they regard
// as a wizard. He is in fact a fellow traveller in time and space exiled
// by the Time Lords to this lost planet. He has decided to stay and
// persue his black arts amoung the warrior folk. But he has told me of
// a time gate which will lead me back to the main time lanes and freedom.
// He said the gate was hidden within the pyramid. I have uncovered some
// clues but not enough to lead me to the final solution. I can only keep
// trying. But I feel that, for me at least, time is running out."
// The diary was found next to a small pile of oddly shaped bones deep
// within the heart of the pyramid.
// Can you find your way out of the pyramid and off the barren planet?
// You will find several rooms within the pyramid and several objects
// within those rooms which must be collected to solve the riddle of the
// ancient monument. The program uses the standard two word entry system
// and adjectives should not be entered. To move simply type in the
// direction you want to go, for example 'N' or 'north'. Other useful
// words are TAKE, GET, THROW, DROP, INVENTORY.
cmd = ""; // command line
todo = 0; // is still alive
done = 1; // is already dead
seen = 2; // dragon has seen you
is_dragon = todo; // is dragon alive
is_tree = todo; // is tree uncut
is_door = todo; // is the door intact
is_wall = todo; // is the wall closed
is_helmet = todo; // is the helmet off
is_power = todo; // is the power off
watch = 0; // objects in grid
dragon = 1;
generator = 2;
tree = 3;
slab = 4;
door = 5;
saw = 6;
mirror = 7;
reflector = 8;
coin = 9;
knife = 10;
dagger = 11;
helmet = 12;
axe = 13;
Nobjects = 14; // number of objects in grid
objects = mkstruct (
"watch", watch ,
"dragon", dragon ,
"generator", generator ,
"tree", tree ,
"slab", slab ,
"door", door ,
"saw", saw ,
"mirror", mirror ,
"reflector", reflector ,
"coin", coin ,
"knife", knife ,
"dagger", dagger ,
"helmet", helmet ,
"axe", axe
);
stays = 0; // cannot be moved
moves = 1; // can be moved
attributes = mkarray ( // map attributes to objects
"\twrist watch\n", moves ,
"\tmagenta, firebreathing dragon\n", stays ,
"\tmobile electricity generator\n", moves ,
"\tCanadian Redwood tree\n", stays ,
"\tgranite slab\n", moves ,
"\tthick wooden door\n", stays ,
"\telectric saw\n", moves ,
"\tpurple mirror\n", moves ,
"\tgreen reflector\n", moves ,
"\t10 pence coin\n", moves ,
"\tbutter knife\n", moves ,
"\trazor sharp dagger\n", moves ,
"\tsafety helmet\n", moves ,
"\tsharp axe\n", moves
);
_Exit_ = _Person_ = -1; // locations
_NoWhere_ = 0;
_RoadWE_ = 1;
_RoadBend_ = 2;
_ShackW_ = 3;
_ShackE_ = 4;
_RoadNS_ = 5;
_RoadN_ = 6;
_Pyramid_ = 7;
_Embalm_ = 8;
_Recreation_ = 9;
_ANKH_ = 10;
_Triangular_ = 11;
_Oblong_ = 12;
_Funeral_ = 13;
_Treasure_ = 14;
_Cave_ = 15;
_Garden_ = 16;
locations = mkarray ( // map locations to directions
"a road leading west and east. Two things are pointing to the west.\n",
_NoWhere_ , _NoWhere_ , _Exit_ , _RoadBend_ ,
"a bend in the road.\n",
_NoWhere_ , _RoadNS_ , _RoadWE_ , _NoWhere_ ,
"a small dark shack.\n",
_NoWhere_ , _NoWhere_ , _NoWhere_ , _RoadNS_ ,
"a small dark shack.\n",
_NoWhere_ , _NoWhere_ , _RoadNS_ , _Cave_ ,
"a road leading north and south. There are shacks either side.\n",
_RoadBend_ , _RoadN_ , _ShackW_ , _ShackE_ ,
"a road leading north. There is a pyramid south.\n",
_RoadNS_ , _Pyramid_ , _NoWhere_ , _NoWhere_ ,
"the entrance hall of the pyramid. There is a road north.\n",
_RoadN_ , _Oblong_ , _Embalm_ , _Recreation_ ,
"the embalming room.\n",
_NoWhere_ , _NoWhere_ , _ANKH_ , _Pyramid_ ,
"the recreation room. An exit to the garden is east.\n",
_NoWhere_ , _Funeral_ , _Pyramid_ , _Garden_ ,
"the room of ANKH.\n",
_NoWhere_ , _NoWhere_ , _NoWhere_ , _Embalm_ ,
"a small triangular room.\n",
_NoWhere_ , _NoWhere_ , _NoWhere_ , _Oblong_ ,
"a long oblong room.\n",
_Pyramid_ , _Treasure_ , _Triangular_ , _NoWhere_ ,
"the funeral parlour.\n",
_Recreation_ , _NoWhere_ , _NoWhere_ , _NoWhere_ ,
"the treasure room. It has been looted. There is a smashed door north.\n",
_Oblong_ , _NoWhere_ , _NoWhere_ , _NoWhere_ ,
"a small circular cave.\n",
_NoWhere_ , _NoWhere_ , _ShackE_ , _NoWhere_ ,
"a small garden.\n",
_NoWhere_ , _NoWhere_ , _Recreation_ , _NoWhere_
);
map = mkarray(
_ShackW_ , // watch in west shack
_ShackE_ , // dragon in east shack
_RoadBend_ , // generator in bend of the road
_Garden_ , // tree in the garden
_Funeral_ , // slab in funeral parlor
_Oblong_ , // door in oblong room
_Triangular_ , // saw in triangular room
_ANKH_ , // mirror in room of ANKH
_Cave_ , // reflector in cave
_Treasure_ , // coin in treasure room
_RoadNS_ , // knife on north/south road
_NoWhere_ , // dagger is nowhere
_Pyramid_ , // helmet in pyramid
_NoWhere_ // axe is nowhere
);
void CANNOT () { // default warning
print ("YOU CAN'T, IDIOT!!\n\n");
}
void DEAD () { // exit game
print ("YOU'RE DEAD!!\n\n");
exit (0);
}
void IDUNNO (string a) { // I don't know!
printf ("I don't know what a %s is.\n\n", a);
}
void OUTSIDE () { // not here!
print ("It isn't here!!\n\n");
}
void MISSING () {
print ("You aren't carrying it, stupid!!\n\n");
}
north = _NoWhere_;
south = _NoWhere_;
west = _NoWhere_;
east = _NoWhere_;
where = _RoadBend_; // room where you are
string verb () {
x = strchr (cmd, " ");
return (x == () ? cmd : left (cmd, x));
}
string noun () {
x = strrchr (cmd, " ");
return (x == () ? cmd : trim (right (cmd, strlen (cmd) - x)));
}
void execute (string command) {
action = struct_get (actions, command);
if (action == ()) printf ("I don't know how to %s.\n\n", command);
else action ();
}
int room () {
return ((where - 1) * 5);
}
// keep locked until task is done
int noentry (int done, int here, int dir) {
if (where == here) return (done ? dir : _NoWhere_);
else return (dir);
}
void directions (int here) {
north = locations [here + 1];
south = locations [here + 2];
west = locations [here + 3];
east = locations [here + 4];
global ("north", "south", "west", "east");
}
void is_north () { // going north ?
if (north) print ("North\t");
}
void is_south () { // going south ?
south = noentry (is_door, _Oblong_, south);
if (south) print ("South\t");
global ("south");
}
void is_west () { // going west ?
west = noentry (is_wall, _Embalm_, west);
if (west) print ("West\t");
global ("west");
}
void is_east () { // going east ?
east = noentry (is_dragon, _ShackE_, east);
if (east) print ("East\t");
global ("east");
}
void is_lastroom () {
if (where == _Exit_) { // make sure we're there
print ("LASER BOLTS FLASH OUT FROM THE KILLO-ZAP GUNS FIXED TO THE ROAD!\n");
// can't we reflect anything?
if ((map [mirror] != _Person_) && (map [reflector] != _Person_)) {
print ("FRIZZLE!!\n"); DEAD ();
}
// are we missing a reflector
if ((map [reflector] != _Person_)) {
print ("THE LEFT RAY IS REFLECTED BY THE MIRROR. THE RIGHT ONE ISN'T!!\n"); DEAD ();
}
// are we missing a mirror
if ((map [mirror] != _Person_)) {
print ("THE RIGHT RAY IS REFLECTED BY THE REFLECTOR. THE LEFT ONE ISN'T!!\n"); DEAD ();
}
// we got them both!
print ("BOTH THE RAYS ARE REFLECTED BY THE MIRROR AND THE REFLECTOR!!\n");
print ("YOU HAVE MANAGED TO ESCAPE ALIVE!!\n\n");
exit (0);
}
}
void contents () {
t = 0; // show the contents of a room
for (x = 0; x < Nobjects; x++) // loop through the map for a match
if (map [x] == where) {
t++; print (attributes [x * 2]);
}
if (t == 0) print ("\tNone\n"); // nothing in this room..
// all exceptions
if ((where != _ShackE_) && (is_dragon == seen))
is_dragon = todo; // if we aren't in the shack but the
// dragon has seen us we make him forget
if ((where == _ShackE_) && (is_dragon == seen)) {
print ("\nThe dragon doesn't like you so he kills you.\n"); DEAD ();
}
if ((where == _ShackE_) && (is_dragon == todo)) {
print ("\nThe dragon blocks a hole in the EAST wall.\n");
is_dragon = seen;
}
if ((where == _ShackE_) && (is_dragon == done))
print ("\nThe dragon is dead.\n");
if ((where == _Garden_) && (is_tree == done))
print ("\nThe tree is lying on the ground\n");
if ((where == _Garden_) && (is_tree == todo))
print ("\nThere is something glistening at the top of the tree.\n");
if ((where == _Embalm_) && (is_wall == todo))
print ("\nThere is a small slot on the west wall.\n");
if ((where == _Oblong_) && (is_door == done))
print ("\nThe door is smashed down\n");
global ("is_dragon");
}
void showroom () { // describe a room
is_lastroom (); // are we in the last room?
print ("You are at ");
print (locations [room ()]);
directions (room ());
print ("Directions you may proceed in:\n\t");
is_north (); is_south ();
is_west (); is_east (); // show exits and items
print ("\n\nThings of interest here:\n");
contents ();
}
void do_move () {
execute (noun ());
}
void do_go (int x) {
if (x) where = x; else CANNOT ();
global ("where");
}
void go_north () { // go north
do_go (north);
}
void go_south () { // go south
do_go (south);
}
void go_west () { // go west
do_go (west);
}
void go_east () { // go east
do_go (east);
}
void do_take () { // take an object
thing = noun ();
object = struct_get (objects, thing);
if (object == ()) IDUNNO (thing);
else {
if (map [object] == _Person_) { // do we already have it?
print ("YOU ARE ALREADY CARRYING IT!!\n\n"); return;
}
// do we have a watch?
if ((object != watch) && (map [watch] != _Person_)) {
print ("YOU HAVEN'T GOT ANYTHING TO CARRY IT IN!!\n\n"); return;
}
// is it here?
if (map [object] != where) {
OUTSIDE (); return;
}
// can we move it?
if (attributes [(object * 2) + 1] == stays) {
CANNOT (); return;
}
// zoom it in your watch
print (object == watch ?
"YOU STRAP IT ON YOUR WRIST.\n\n" :
"IT ZOOMS SAFELY INTO YOUR WATCH!\n\n");
// now you carry it
map [object] = _Person_; global ("map");
}
}
void do_drop () { // drop object
thing = noun ();
object = struct_get (objects, thing);
if (object == ()) IDUNNO (thing);
else {
if (map [object] != _Person_) MISSING ();
else {
map [object] = where;
if (object == helmet) is_helmet = todo;
global ("map", "is_helmet");
}
}
}
void do_saw () { // saw tree
thing = noun ();
object = struct_get (objects, thing);
if (object == ()) IDUNNO (thing);
else {
if ((object != tree) || (is_tree == done) ||
(map [generator] != _Person_) || (map [saw] != _Person_)) {
CANNOT (); return; // saw a tree or is it already cut?
} // do we have a generator and a saw?
if (where != _Garden_) { // are we in the garden?
OUTSIDE (); return;
}
if (is_power == todo) { // do we have power?
print (" The saw won't work without electricity!!\n\n"); return;
}
if (is_helmet == todo) { // are we wearing a helmet?
print ("The tree falls on your unprotected head. Crunch.\n\n");
DEAD ();
}
is_tree = done; // now cut the tree
print ("The tree falls down on your safety helmet.\n");
print ("An axe falls out of the top of the tree.\n\n");
map [axe] = where; // and show the axe
global ("map", "is_tree");
}
}
void do_smash () { // smash door
thing = noun ();
object = struct_get (objects, thing);
if (object == ()) IDUNNO (thing);
else {
if ((object != door) || (map [axe] != _Person_) || (is_door == done)) {
CANNOT (); return; // do we smash a door?
} // do we have an axe?
// is the door smashed?
if (where != _Oblong_) { // are we in the oblong room?
OUTSIDE (); return;
}
print ("Chop chop smash smash.. The door has been smashed down.\n\n");
is_door = done; global ("is_door");
} // now smash the door
}
void do_wear () { // wear helmet
thing = noun ();
object = struct_get (objects, thing);
if (object == ()) IDUNNO (thing);
else {
if (object != helmet) {
CANNOT (); return; // want to wear a helmet?
}
if (map [helmet] != _Person_) { // do we have a helmet?
MISSING (); return;
}
is_helmet = done; global ("is_helmet");
} // now put on the helmet
}
void do_connect () { // connect generator
thing = noun ();
object = struct_get (objects, thing);
if (object == ()) IDUNNO (thing);
else {
if ((object != generator) && (object != saw)) {
CANNOT (); return; // do we connect a generator
} // or a saw?
if (map [object] != _Person_) { // do we have it?
MISSING (); return;
}
if ((map [saw] != _Person_) || (map [generator] != _Person_)) {
CANNOT (); return; // do we miss anything?
}
// ok, power is on!
is_power = done; global ("is_power");
}
}
void do_push () { // push wall
thing = noun ();
object = struct_get (objects, thing);
if (object == ()) IDUNNO (thing);
else {
if (object != coin) {
CANNOT (); return; // do we insert a coin?
}
if (map [coin] != _Person_) { // do we have it?
MISSING (); return;
}
if (where != _Embalm_) // are we in the embalming room?
print ("I can't see anywhere to insert it!!");
else {
map [coin] = _NoWhere_; // coin disappears in slot
print ("The wall suddenly shakes and glides one side leaving a doorway west!!");
is_wall = done; global ("map", "is_wall");
} // the wall is open!
print ("\n\n");
}
}
void do_file () { // file knife
thing = noun ();
object = struct_get (objects, thing);
if (object == ()) IDUNNO (thing);
else {
if (object != knife) {
CANNOT (); return; // do we want to file a knife?
}
if (map [knife] != _Person_) {
MISSING (); return;
}
if (map [slab] != _Person_)
print ("You haven't got anything to sharpen it on!!");
else {
print ("The knife turns extra sharp!!");
map [knife] = _NoWhere_; // the knife turns into a dagger
map [dagger] = _Person_; global ("map");
}
print ("\n\n");
}
}
void do_kill () { // kill dragon
thing = noun ();
object = struct_get (objects, thing);
if (object == ()) IDUNNO (thing);
else { // do we want to kill a dragon?
if ((object != dragon) || (map [dagger] != _Person_)) {
CANNOT (); return; // and do we have a dagger?
}
if (where != _ShackE_) { // are we in the east shack?
OUTSIDE (); return;
}
if (is_dragon == done) // is the dragon alive?
print ("The poor thing is already dead.");
else {
is_dragon = done; global ("is_dragon");
print ("Squelch. The dagger sinks to the hilt in the dragon.\n");
print ("It's dead. Poor thing.");
} // now he is!
print ("\n\n");
}
}
void do_list () { // shows the inventory
print ("You are carrying:\n");
t = 0; // show the contents of a room
for (x = 0; x < Nobjects; x++) // loop through the map for a match
if (map [x] == _Person_) {
t++; print (attributes [x * 2]);
}
if (t == 0) print ("\tNothing\n"); // nothing in this room..
print ("\n");
}
void do_die () { // end game quickly
print ("There is no easy way out of here!!\n");
print ("So you decide to commit suicide.\n");
DEAD ();
}
/*
void do_flags () { // debugging code
print ("Dragon: ", is_dragon);
print ("\nTree: ", is_tree);
print ("\nHelmet: ", is_helmet);
print ("\nPower: ", is_power);
print ("\nDoor: ", is_door);
print ("\nWall: ", is_wall);
print ("\n\n");
}
*/
actions = mkstruct ( // map vocabulary to actions
// "flags", do_flags ,
"go", do_move ,
"move", do_move ,
"run", do_move ,
"walk", do_move ,
"north", go_north ,
"n", go_north ,
"south", go_south ,
"s", go_south ,
"west", go_west ,
"w", go_west ,
"east", go_east ,
"e", go_east ,
"get", do_take ,
"take", do_take ,
"steal", do_take ,
"drop", do_drop ,
"throw", do_drop ,
"leave", do_drop ,
"saw", do_saw ,
"cut", do_saw ,
"fell", do_saw ,
"chop", do_smash ,
"smash", do_smash ,
"axe", do_smash ,
"wear", do_wear ,
"connect", do_connect ,
"insert", do_push ,
"push", do_push ,
"sharpen", do_file ,
"file", do_file ,
"kill", do_kill ,
"stab", do_kill ,
"knife", do_kill ,
"invent", do_list ,
"objects", do_list ,
"inventory", do_list ,
"list", do_list ,
"die", do_die ,
"exit", do_die ,
"quit", do_die
);
void venture () {
for (;;) {
showroom ();
print ("\nCommand: ");
cmd = tolower (trim (fgets (stdin))); global ("cmd");
print ("\n"); execute (verb ());
}
}
venture ();