Execution of an Adventure Table of Contents Adventure Construction


This chapter will give you some ideas about how the various features of Alan may be used to implement common features in an Adventure game. These are only suggestions and you are, of course, welcome to invent your own, but these are probably some ideas that can get you started.

6.1 Use of Attributes

Attributes are primarily used for holding status information about the object, actor or location to which it belongs. This allows, for example, the water bottle to contain three levels of water.

OBJECT bottle
	HAS level 3.
	VERB drink
			IF level OF bottle > 0 THEN
				DECREASE level OF bottle.
				"There is no more water in the bottle."
			END IF.
	END VERB drink.
END OBJECT bottle.

Another example is the broken mirror.

OBJECT mirror
	IS NOT broken.
	VERB break
			MAKE mirror broken.
	END VERB break.
END OBJECT mirror.

The appropriate verbs defined in the objects may then modify the attributes and thus update the status information.

But attributes defined for all objects also allows a kind of classification of the objects (or locations or actors as appropriate). If the following declaration is made

	NOT takeable.

all objects receive the attribute "takeable" and if the attribute is not specifically redeclared for an object it will not be takeable. Note however that the semantic meaning of "takeable" must be implemented e.g. in the verb "take":

VERB take
		ELSE "You can't take the $o."
		LOCATE OBJECT IN inventory.
END VERB take.

In the same way restrictions concerning what is possible to eat, drink, open etc. may be implemented. This use of attributes to classify objects is "action-oriented", i.e. they imply that a particular action (verb) is applicable to the object.

An alternate approach is to classify objects after their characteristics. Consider:

VERB take
		ELSE "That is much too heavy."
		ELSE "The $o moves quickly away, just far enough
			for you not to reach it."
		LOCATE OBJECT IN inventory.
END VERB take.

This approach is more "class-oriented" as the objects are classified and a verb is possible to apply to certain classes of objects and not to others. This approach is more elegant but is harder to keep track of as you introduce new objects (which class or even classes does a new object belong to?).

6.2 Descriptions

The attributes are also used when presenting information about status to the player. The attributes are tested in IF-statements to modify the DESCRIPTIONs and possibly even the short description in the MENTIONED sections. For example:

OBJECT mirror
	IS NOT broken.
		"On the wall there is a beautiful mirror with an
		elaborate golden frame."
		IF mirror IS broken THEN
			"Some moron has broken the glass in it."
	VERB break
			MAKE mirror broken.
	END VERB break.
END OBJECT mirror.

To use this feature with the short descriptions makes the adventure feel a bit more consistent.

OBJECT bottle
	HAS level 3.
		IF level OF bottle > 0 THEN
			"a bottle of water"
			"an empty bottle"
END OBJECT bottle.
> inventory
You are carrying
	an empty bottle

6.3 Common Verbs

As your library of adventures grow you will find that some verbs are always needed, and always function the same way. Examples are "take", "drop", "invent", "look", "quit" and so on. It is advised to use an include file (see Files ) containing these verbs as well as their syntax definitions and any synonyms. Attributes needed for these particular verbs could also be placed in a default attribute declaration in this file.

All your adventures may then include this file, making these features immediately accessible when you start a new adventure. All that this takes is some thought as to what names to use for the attributes as discussed in Use of Attributes on page 63 .

6.4 Doors

Another common feature is the closed door. Here's how to implement it.

OBJECT treasury_door AT hallway
	VERB open
			MAKE treasury_door open.
			MAKE hallway_door open.
	END VERB open.
END OBJECT treasury_door.

LOCATION hallway
	EXIT east TO treasury
		CHECK treasury_door IS open
			ELSE "The door to the treasury is closed."

OBJECT hallway_door AT treasury
	VERB open
			MAKE treasury_door open.
			MAKE hallway_door open.
	END VERB open.
END OBJECT treasury_door.

LOCATION treasury
	EXIT west TO hallway
		CHECK hallway_door IS open
			ELSE "The door to the hallway is closed."
END LOCATION treasury.

Note that we need two doors, one at each location, but they are synchronised by always making them both open or closed at the same time. The check in the EXITs makes sure that the hero can not pass through a closed door.

6.5 Containers and Their Contents

Containers are either pure containers or objects or actors with the container property. A pure container is always considered to be where the hero is. This means that the inventory (what the hero is carrying), his clothes etc. are suitable to be pure containers.

For a container to be directly manipulable by the player it must be an object (or actor). This means that it always is located at a particular location in the same way as other objects. A container (in the following the term container is used to refer to objects with the container property) is always open, i.e the objects it contain are always accessible.

To be able to "close" a container, i.e. to make it impossible for the hero to take or see things inside a container, the following technique may be used (other techniques may be possible and even better!). Create an extra object with the container property, this container is used as a temporary storage for objects in the first container (the one the player is seeing). Place this at a location not accessible to the player (the limbo location Nowhere always comes in handy!).

The verbs "open" and "close" then get the following definition within the object:

OBJECT chest AT treasury
	IS NOT open.

	VERB close
			MAKE chest NOT open.
			EMPTY chest IN chest_contents.
	END VERB close.

	VERB open
			MAKE chest open.
			EMPTY chest_contents IN chest.
			"Opening the chest reveals its contents."
			LIST chest.
	END VERB open.

The trick used here is to make all the things in the container disappear when it is closed. To do this, the extra container chest_contents is used as a temporary holding place for the things inside the chest. Note that we need to make chest_contents an actual object since pure containers are always accessible (they are where the hero is!). When the chest is opened again we simply empty the contents of the chest_contents container into the chest, and Voila !

6.6 Actors

Actors are a vital component to make a story dynamic. They move around and act according to their scripts. To make the player aware of the other actor's actions they need to be described. This must be done so that the player always get the correct perspective on the actions of the actors.

A way to ensure this is to rely on the fact that output statements are not shown unless the hero is at the location where the output is taking place. This means that for every actor action, especially movement, you need to first describe the actions, then let the actor perform them and, finally, possibly describe the effects.

An example is the movement of an actor from one location to another. In this case the step could look something like

"Charlie Chaplin goes down the stairs to the hallway."
LOCATE charlie_chaplin AT hallway.
"Charlie Chaplin comes down the stairs and
 leaves the house through the front door."
LOCATE charlie_chaplin AT outside_house.
"Charlie Chaplin comes out from the nearest house."

An actor is described, for example, when a location is entered or as the result of a LOOK in the same way as objects are. This means that a good idea is to include the description of an actor's activities in the description of him. One way to do this would be to use attributes to keep track of the actors state and test these in the description clause.

ACTOR george NAME George Formby
		NOT cleaning_windows.
		NOT tuning.
		IF george IS cleaning_windows THEN
			"George Formby is here cleaning windows."
		ELSIF george IS tuning THEN
			"George Formby is tuning his ukelele."
			"George Formby is here."

Although quite feasible, this is a bit tedious. As, at least a part of, the state is indicated by the script the actor is executing, this could be used to avoid the potentially large IF -chain. The optional descriptions tied to each script will be executed instead of the main description when the actor is following that script. So this would allow

ACTOR george NAME George Formby
		"George Formby is here."
			"George Formby is here cleaning windows."
			"George Formby is tuning his ukelele."

This makes it easier to keep track of what an actor is doing. Another hint here is to describe the change in an actor's activities at the same time as executing the USE statement, like

EVENT start_cleaning
	USE SCRIPT 1 FOR george.
	"All of a sudden, George starts to clean the windows."

This makes the descriptions of changes to be shown when it takes place and the description of the actor is always consistent. You can, of course, still have attributes describing the actor's state to customize the description of the actor on an even more detailed level, but it generally suffices to describe an actor in terms of what script he is executing.

6.7 Distant Events

A slight problem with the feature that output is not visible unless the hero is present, is that a description of an event might not always be presented to the player.

EVENT explosion
	"A gigantic explosion fills the whole room with smoke
	 and dust. Your ears ring from the loud noise. After a
	 while cracks start to show in the ceiling, widening
	 fast, stones and debris falling in increasing size
	 and numbers until finally the complete roof falls down
	 from the heavy explosion."
	MAKE LOCATION destroyed.

If the hero isn't at the location where the event is executed, he will never know anything about what has happened. The solution is to create an event that goes of where the hero is.

EVENT distant_explosion
	"Somewhere far away you can hear an explosion."
	SCHEDULE distant_explosion AT HERO AFTER 0.

6.8 Vehicles

The current version of Alan does not support actors being inside containers or inside other actors, which could be a straight forward way to implement vehicles. However, as the reader/player does not need to know how the output is generated we can use a location and a row of events to substitute for the vehicle. Try the following complete example:

  car = ferrari.

  drive = drive.
  park = park.

SYNTAX l = l.



LOCATION parking_lot NAME 'Large Parking Lot'

OBJECT car NAME little red sporty ferrari
  AT garage
    NOT running.
    position 0.

  VERB enter
      LOCATE hero AT inside_car.
  END VERB enter.


LOCATION inside_car NAME 'Inside the Ferrari'
    "This sporty little red vehicle can really take you

  EXIT out TO inside_car -- just a dummy, since we are
											-- going to change it below
    CHECK car IS NOT running
    	ELSE "I think you should stop the car before getting
      IF position OF car = 0 THEN
        LOCATE hero AT garage.
      ELSIF position OF car = 1 THEN
        LOCATE hero AT parking_lot.
      --- Etc.
      END IF.

  VERB drive
    CHECK car IS NOT running
      ELSE "You are already driving it!"
      "You start the car and drive off."
      MAKE car running.
      SCHEDULE drive1 AFTER 1.
  END VERB drive.

  VERB park
    CHECK car IS running
      ELSE "You are not driving it!"
      "You slow to a stop and turn the engine off."
      MAKE car NOT running.
      CANCEL drive1. CANCEL drive2. --- Etc.
  END VERB park.
END LOCATION inside_car.

EVENT drive1
  "You drive out from your garage and approach a large
parking lot."

  SET position OF car TO 1.
  LOCATE car AT parking_lot.
  SCHEDULE drive2 after 1.
END EVENT drive1.

EVENT drive2
  "You drive out from the parking lot and approach your
 own garage."
  SET position OF car TO 0.
  LOCATE car AT garage.
  SCHEDULE drive1 after 1.
END EVENT drive2.

START AT garage.

The main idea is that the player/reader is inside the car, and the events are executed at this location thus emulating movement. It is possible to exchange the events for script steps and the car object for an actor. However as the car object is not where the hero is ('inside_car') the output from the scripts will not be shown. There are (at least) two different ways to deal with this (one involving attributes, the other involving an extra object), but the solutions are left as an exercise to the reader!

Sincere thanks go to Walt (sandsquish@aol.com) for inspiring communication that brought this example to life.

6.9 Questions and Answers

Sometimes it may be necessary to ask the player for an answer to some question. One example is if you want to confirm an action. The following example delineates one simple way to do this which could be adopted for various circumstances.

ACTOR hero IS NOT quitting.

	'quit' = 'quit'.
	yes = yes.

	y = yes.
	q = 'quit'.

VERB 'quit' DOES "Do you really want to give up?
							Type 'yes' to quit, or to carry on
							type your next command."
	MAKE hero quitting.
END VERB 'quit'.

VERB yes CHECK hero IS quitting
				ELSE "That does not seem to answer any question."

EVENT unquit MAKE hero NOT quitting.
END EVENT unquit.

Thanks to Tony O'Hagan (aoh@maths.nott.ac.uk) for this excellent idea.

6.10 Floating Objects

Floating objects is a term used for objects that are available everywhere or at least at many places. Usually they are available wherever the hero is.

Examples of floating objects are the air, the ground and such semi-abstract objects. But sometimes you also need to make actual objects be floating objects such as parts of the heroes body.

To create floating objects you can use a particular feature of containers, namely the fact that they are always located where the hero is.

So to have the hero's body parts and the air and the sky to be available wherever the hero goes you can use:

CONTAINER body_parts
END CONTAINER body_parts.

CONTAINER outdoor_things
END CONTAINER outdoor_things.

OBJECT right_arm NAME right arm IN bocy_parts ...
OBJECT head NAME head IN body_parts ...
OBJECT sky IN outdoor_things ...
OBJECT air IN outdoor_things ...

Of course you would not want the outdoor things to be available when you are indoors, but this can be fixed in a way similar to the container contents trick shown in Containers and Their Contents on page 66 . Simply create a container object and place it where the hero can never be:

OBJECT outdoor_things_storage AT limbo
END OBJECT outdoor_things_storage.

WHEN location IS outdoors =>
	EMPTY outdoor_things_storage IN outdoor_things.
WHEN location IS NOT outdoors =>
	EMPTY outdoor_things IN outdoor_things_storage.

And Voila', every time the hero arrives at an outdoor location he will find the air and the sky. And every time he enters a location that has the attribute outdoors set to false he will not find them available.

Well, perhaps he would like to have the air available indoors too, but that is left as an exercise for the reader...

6.11 Darkness and Light Sources

A very common puzzle in old time adventures (so much so that it has possibly been exploited beyond its potential) is the problem of dark locations and finding a source of light.

This puzzle can be implemented in Alan in a rather general way by using a default object attribute, a default location attribute and a few additions to the descriptions of the dark locations and the look verb.

Object Attributes
  lightsource 0.	
Location Attributes

This will give all objects the value of 0 of the attribute lightsource . Any object that provide light should set this to something larger than zero. The attribute might of course change value dynamically, e.g. when the lamp is lit and extinguished. We can thus sum all the values of the attribute lightsource at a location and if the sum is above zero there is some light provided. So the look verb could be reworked to:

Verb 'look'
    If Sum Of lightsource Here = 0
        And Location Is Not lit Then
      "You cannot see anything without any light."
    End If.
End Verb 'look'.

Of course we must also modify the dark locations:

Location indoors
    Not lit.
    If Sum Of lightsource Here > 0 Then		
      "This is usually a very dark room. But in this light
       you can see..."
      "You can not see anything in the dark."
    End If.
  Exit out To outdoors.
End Location.

Location outdoors
    "Out here in the sun you can see everything."
  Exit 'in' To indoors.
End Location.

So for every location which should be dark we must add the above test to the description clause.

There is however still a small problem with this solution. Objects available at the location are visible (described) as you enter the location. This must be taken care of, e.g. by moving all objects present to a limbo location (analogous to the container contents trick described in Containers and Their Contents ) in the dark part of the IF statement, and back in the ELSE clause.

Thanks goes to Thomas Ally (Thomas_Ally(at)freenet.richland) for prompting this solution.

6.12 Distant & Imaginary Objects

A feature introduced in v2.7 made the following section almost obsolete. The new feature is the ability to refer to distant objects and actors (see Syntax Definitions on page 27 for a discussion on the omnipotent '!' indicator). I.e. the previous restriction that the player could only refer to objects and actors at the same location was removed. However there are instances where it may still be required to separate the handling of an object when it is present and when it is not, therefore this section gives a few examples of what can be done using some trickery with the mechanisms of Alan.

Sometimes you need to make it possible for the player to refer to things either far away, that are not really objects or that may be at many places at once. Examples of these are a distant mountain that may be examined through a set of binoculars, the melody in "whistle the melody", and water or walls.

For objects that should be visible from a distance the easiest method is to introduce a ` shadow object'. This is a second object acting on behalf of, or representing, the distant object at the locations where it should be possible to refer to it. For example:


OBJECT mountain AT hills
END OBJECT mountain.

LOCATION scenic_vista NAME Scenic Vista
END LOCATION scenic_vista.

OBJECT shadow_mountain
	NAME distant mountain AT scenic_vista
		"Far in the distance you can see the Pebbly
		Mountain raising towards the sky."
END OBJECT shadow_moutain.

This would allow for example at scenic_vista:

Scenic Vista.
Far in the distance you can see the Pebbly Mountain raising
towards the sky.

> look at mountain through the binoculars

which would otherwise be impossible. If the mountain should be visible and manipulable from a number of locations, you might implement one shadow object for each location but this is a bit tedious if they are identical. One trick here is to use something like the following rule:

WHEN hero AT scenic_vista OR hero AT hill_road =>
	LOCATE shadow_mountain AT hero.

This will ensure that whenever the hero moves to any of the places from where the mountain is visible, the shadow_mountain is sure to follow. However, as the rules are executed after the hero has moved, a better strategy might be to make the shadow_mountain `silent', i.e. to have no description. Instead the description of it should be embedded in the description of the adjacent locations. Yet another possibility would be to move the pseudo-object around using statements in the exits, like

LOCATION scenic_vista NAME Scenic Vista
	EXIT east TO hills
			LOCATE shadow_mountain AT hills.
	END EXIT east.
END LOCATION scenic_vista.

Objects that are always present, such as the air or the parts of the hero's body, may be treated like normal objects. I.e. they are defined as the objects they represent. They are then placed in a container that is not an object, which makes the objects always accessible, since containers (that are not objects) are considered to be where the hero is (cf. the inventory). This is also a simple way to create other compartments on the hero, such as a belt.

	LIMIT count 2
		ELSE "You can't fit more in your belt."

VERB invent
		LIST inventory.
		LIST belt.
END VERB invent.


OBJECT air IN pseudo
	VERB breathe
	END VERB breathe.

6.13 Structure

A good thing to do when designing an interactive fiction story is to separate the geography from the story. In Alan you can use the include facility to structure your Alan source. One approach could be to place the description of each location in a separate file together with any objects that could be considered part of the scenery or at least is not only a tool in a puzzle. These files can then be included in a 'map' file which in turn is included by the top level file.

The story line can be divided into files too, one for each 'scene'. A scene being comments describing the important things that are suppose to happen, any prerequisites and objects, events, rules etc. which are specific for this part of the story.

This strategy will both give you a better structure of your adventure as well as help you design a better story, much like the storyboarding technique used in making movies or plays.

6.14 Debugging

To simplify the development of adventures written in the Alan language, the interpreter Arun incorporates some features for debugging. There are a few debugging switches available when starting the interpreter:

-l		Create a log of the player commands
-t		Enable trace mode
-s		Enable single instruction trace
-d		Enable debug mode
Command Log

For various purposes, such as debugging, an actual log of the player commands can be handy. Such a log is created if the option -l is given to the interpreter when starting a game. The log file is created in the directory which is current when the interpreter is started, the name of the log file will be the same as the game with the extension .log .

Interpreter and Instruction Trace

Trace mode can also act as an aid in debugging. It will print information about each invocation of the instruction interpreter, making it easier to see which parts of the code are being executed.

Single instruction trace will, in addition to the trace mode information, also trace every single Acode instruction.

Debug mode

Finally, debug mode will execute the start up sequence and then prompt for a debug command with

  • None of the above switches are effective unless the adventure was compiled with the debug option set (see Options on page 23 ).

Abug may also be entered by typing the single command

> debug

during the execution of an Adventure that was compiled with the debug option.

A question mark or an `h' will give a brief listing of the commands available in Abug:

a		Display a list of all actors.
c		Display a list of all containers.
e		Display a list of all events and their status.
g		Go on. I.e. proceed by executing the next turn. Abug
will stop and prompt for a new command again before the player is next in turn.
l		Display a list of all locations.
o		Display a list of all objects.
q		Quit the adventure (and Abug).
s		Toggle single instruction trace.
t		Toggle trace mode (off and on).
x		Exit Abug, i.e. proceed without stopping.

The commands A , C , L and O may optionally be followed by a number. Abug will then display detailed information about the entity requested, such as values of attributes, its present location etc.

Currently there is no way to modify anything using Abug.

The following is a short excerpt from a debugging session (user input in bold face):

<Arun, Adventure Interpreter version 2.6 alpha>
<Version of 'saviour' is 2.6(0)a>
Welcome to the game of SAVIOUR!
[introductory text deleted for brevity]
Step on.
Trace on.
> n
<EXIT 1 (n) from 22 (Outside The Tall Building),Executing:>
 dd9: PUSH          1
 dda: SCORE         1           (5)
 ddb: RETURN
<EXIT 1 (n) from 22 (Outside The Tall Building), Moving:>
 de4: PUSH          4
 de5: PUSH       6229
 de6: PRINT      6229,     4    "Hall"
 de7: RETURN
 de8: PUSH        158
 de9: PUSH       6235
 dea: PRINT      6235,   158    "Inside the entrance is a hallway full of
	dust and pieces of the ceiling have fallen to the floor. At the west
	end is a staircase, and to the south is the exit."
 deb: PUSH          1
 dec: DESCRIBE      1
 620: PUSH         30
 621: PUSH       1428
 622: PRINT      1428,    30    " To the east is a folding door."
 623: PUSH          6
 624: PUSH          1
 625: ATTRIBUTE     1,     6    (1)
 626: IF         TRUE
 627: PUSH         13
 628: PUSH       1446
 629: PRINT      1446,    13    " It is closed."
 62a: ELSE
 62f: RETURN
 ded: RETURN
     17: Hero
ABUG> a 17
ACTOR 17 : Hero 
    Location = 23 Hall 
    Script = 0 
    Step = 0 
    Attributes =
      1: door 
      2: rats 
      3: spool of computer tape 
      4: old book 
      5: 3 metre long ladder 
      6: rather heavy computer terminal 
      7: small coin 
      8: birds nest 
      9: set of rusty keys 
     10: clock 
     11: drawer 
     12: desk 
     13: dirty manual 
     14: computer 
     15: vending machine 
     16: old mouldy candy bar
ABUG> o 6
OBJECT 6 : rather heavy computer terminal 
    Location = 30 Terminal Room 
    Attributes = 
      1: 1 (takeable) 
      2: 1 (readable) 
      3: 0 (openable) 
      4: 0 (startable) 
      5: 1 (examinable) 
      6: 0 (connected) 
      7: 0 (showing_msg1) 
      8: 0 (showing_msg2)

Lines of '+' characters indicates the start of interpretation, thus they can be present inside other single step traces (like the DESCRIBE in the example above). Likewise lines of '-' indicates the return from one such level of interpretation.

Execution of an Adventure Table of Contents Adventure Construction