|Tutorial||Table of Contents||Lexical Definitions|
This chapter describes the Alan language in detail. For each construct the exact syntax can be found in the form of BNF productions in ALAN LANGUAGE GRAMMAR .
An adventure starts with an optional options section (see below) followed by a set of units .
The units constitute the major part of the adventure. The units are rules, synonyms, syntax definitions, verbs, locations, objects, containers, actors and events can be declared in any order. Any combination and number are allowed. Default attributes (see below) for objects, locations and actors may be declared in any number of places.
The adventure source text must end with a start section. It indicates where the hero is when the game starts and can also be used to set things up, welcome the player and so on. The start section is mandatory.
START AT bedroom. SCHEDULE alarm_clock AFTER 2. "Slowly you come to your senses, your numb limbs starting to feel the blood flowing through them..."
Options define things concerning the overall behaviour of the generated Alan adventure. An option is for example written either as
(for multiple-valued options) or
PACK. NO PACK.
(for boolean options).
The options are
|Pack||Boolean||Off (No Pack)|
|Debug||Boolean||Off (No Debug)|
The Language option specifies in which language the adventure is intended to be played, and selects different default message texts. Alan is primarily designed for adventures in the English language, but it is also possible to write adventures in other languages. To make this possible, the default messages output by the interpreter may be generated in different languages.
The Alan compiler and interpreter will always allow multinational 8-bit characters as input and the default messages is generated for 8-bit character sets, internally representing national characters according to the ISO multinational character set (ISO8859-1) requiring 8 bits. On output this is converted to the native character set of the machine (whenever possible) which means that portability between platforms should be good even for text containing non-ASCII characters.
Width specifies how long the lines the interpreter outputs should be (formatting is automatic!). The Length option will instruct the interpreter to how many lines to show on the screen without any player interaction ( <More> ).
The Pack option will cause the compiler to compress the texts to occupy less space. As a bonus this also makes it impossible for the player to cheat by dumping the adventure text data file. As a drawback it does make the execution of the adventure a bit slower (quite noticeable on some smaller computers).
In order to allow debugging of the generated adventure (see Debugging ), the debug option must be turned on. This may also be performed using the debug compiler flag (see also Compiler Switches ).
An attribute is a definition of a property of either an object, an actor or a location (for a description of these see the appropriate sections below). An attribute can be boolean (having the value TRUE or FALSE ), numeric or of string type. The type of an attribute is automatically inferred from the type of its initial value. Attributes may either be given to all objects, actors and locations ( DEFAULT ATTRIBUTES ), to all object, actors or locations respectively ( OBJECT/ACTOR/LOCATION ATTRIBUTES ) or for a single object, actor or location (local attributes, see for example Attributes for attributes for locations).
A boolean attribute is declared by simply giving the attribute name, or the name preceded with the keyword NOT (indicating a FALSE initial value:
thirsty. NOT human.
Numeric and string attributes are declared by simply typing the value after the attribute name:
weight 42. message "Enter password:".
General attributes that every object, actor and location (all entities ) have by default should be declared in a DEFAULT ATTRIBUTES section. To declare a boolean attribute that all objects, actors and location will have in common the following code can be used:
DEFAULT ATTRIBUTES NOT human.
This attribute will now be available in all entities, and if it is not set to a different value it will be false. To get another value for a particular object, actor or location you can declare it in its declaration and give it its desired value, which will be effective only for that object, actor or location.
Attributes that every object, actor or location respectively has by default should be declared in an OBJECT/ACTOR/LOCATION ATTRIBUTES (respectively) section. A numeric attribute that all objects must have can be declared by:
OBJECT ATTRIBUTES weight 5.
All objects will have the attribute weight with the default value 5.
ACTOR ATTRIBUTES NOT hungry. weight 50.
By combining these two level of defaults you can create attributes that all objects, actors and locations have but with different default values for each of these classes. For example:
DEFAULT ATTRIBUTES NOT human. ACTOR ATTRIBUTES human.
will give all entitites the attribute human but the default value of the attribute will be different for objects and locations (false) and actors (true).
Note that string valued attributes are mainly intended for saving string parameters from the player input, like in
> scribble "Kilroy was here" on the wall
It is not intended for keeping long strings of descriptions, especially not as default attributes as they (in the current implementation) require much space and takes long time to initialise when starting the game.
Any number of default attributes sections are allowed. This makes it possible to group verb declarations (see below) and the declaration of the default attributes that a particular verb requires. For example:
OBJECT ATTRIBUTES NOT takeable,
VERB take CHECK OBJECT IS takeable ELSE "You can not take that." ...
This is a practical structuring aid which allows localisation of dependencies between verbs and attributes.
Synonyms declare words that, when used as player input, are interchangeable at all times.
SYNONYMS 'i', 'invent' = 'inventory'. 'q' = 'quit'.
The word on the right hand side of the equal sign must be a word defined elsewhere in the adventure source, such as (part of) an object or actor name (a noun or adjective) or a direction. The list of words on the left hand side are new words ( NOT defined elsewhere) that always will be replaced by the word on the right in the player input.
When defining synonyms remember that this only defines player words that are interchangeable. Defining synonyms for verb names etc. will not always give you the result that you expect. For example
SYNONYMS 'examine' = look_at. SYNTAX look_at = 'look' 'at' (obj). VERB look_at ...
This will result in the compiler issuing an error message indicating that the synonym word 'look_at' is not defined. This is because the SYNTAX (see below) defined the verb look_at to have the specified syntax (including the player words 'look' and 'at'), the player word 'look_at' is not defined, which is as well as the player would not be able to input a word with an underscore (see Player Input ).
You can achieve the desired effect by instead giving multiple verb identifiers in the verb declarations, this will give the same verb bodies (checks and actions) to multiple verbs. See Verbs for details on verb declarations.
It is also possible to define multiple names for an object or actor to achieve other effects similar to synonyms. See Objects for a description of this.
The Alan system has a number of standard messages built in. These messages are presented to the player in various situations, both normal and otherwise. An example is the following:
> go north You can't go that way.
The response "You can't go that way." is a typical example of such system messages (for details see RUN-TIME MESSAGES ).
To make the user dialogue more adapted to the settings you select Alan allows you to define your own versions of these messages. An example of this is:
: MESSAGE NOWAY: "There is no exit in that direction." :
If the above is used in the source for same game as the previous example, it would instead look like:
> go north There is no exit in that direction.
The MESSAGE constructs allows general statements following the message identifier:
MESSAGE: NOWAY: IF RANDOM 1 TO 2 = 1 THEN "There is no way in that direction." ELSE "You can't go there." END IF.
The standard message for NOWAY is replaced by the output from the statements in the definition. For a complete list of all the identifiers of messages and their use see RUN-TIME MESSAGES .
The syntax construct is used to specify the allowed structure of the input from the player. Each definition defines the syntax for one VERB . The effects triggerd by the player inpu are declared using the VERB construct (see Verbs below).
The syntax is defined as a number of syntax elements each being either a player word or the name of a parameter (an identifier enclosed in parenthesis).
SYNTAX quit = 'quit'. examine = 'examine' (obj).
When the player inputs a command the set of allowed syntaxes are checked for match, giving a very flexible way to extend the allowed command set (see also Player Input for details on general player input).
After a player input has been matched to an allowed syntax the parameters are bound to the entities referred to by the player. The identifiers in the syntax declaration then refers to those entities and tests for attributes etc. will be done in the entity referred by the parameter.
In the example above the parameter obj can be used in the declaration of the verb examine and will refer to such a bound entity.
Following a parameter indicators are allowed. These indicators can be one of
SYNTAX take = 'take' (obj)*. drop = 'drop' (obj).
This shows the syntax definitions for the verbs take and drop , take also allowing multiple objects. This would allow inputs like
> take everything except the pillow > drop the vase
> drop the shovel and the bucket
Another example using the '!' indicator:
SYNTAX talk_about = 'talk' 'to' (act) 'about' (sub)!. find = 'find' (obj)!.
This will give the player the possibility to say
> talk to the policeman about the robber > find the key
even though the robber or the key are not present.
For more information on player inputs refer to Player Input .
To restrict the types of entities the player may refer to in the place of a parameter its class can be defined by using explicit test in the syntax declaration.
The following example describes the syntax for a verb which only allows OBJECTs as its parameters (this is however also the default, see below).
SYNTAX take = 'take' (obj) WHERE obj ISA OBJECT ELSE "You can't take that."
Each parameter may be restricted to refer only to certain kinds (classes) of entities: objects, objects with the container property, actors, numeric literals, string literals or some combination of these. The statements following the ELSE will be executed if that restriction is not met, i.e. if the player made a reference to an entity not in the specified class or classes. The default is OBJECT , i.e. if no class tests are supplied for that parameter identifier the player may only refer to objects at that position in his input.
So a more elaborate example of prerequisites for conversation might look like:
SYNTAX talk_about = 'talk' 'to' (act) 'about' (sub)! WHERE act ISA ACTOR ELSE "Don't you think talking to a person might be better?!?!" ...
The classes defined for a parameter are also used by the compiler to analyse statements and expressions in which that parameter occurs to ensure that the entity referenced is guaranteed to have the properties required during run-time. A parameter identifier defined using ISA OBJECT may for example not be used in a LIST statement as this requires the entity to have the container property ( ISA CONTAINER would of course restrict the entities to only those entities that are containers and would do the trick).
As both actors and objects may have the container property it is possible to restrict parameters to only objects that are containers ( CONTAINER OBJECT ), only actors that are containers ( CONTAINER ACTOR ), or that it need just have the container property (either an object or an actor). This last case will only allow access to global default attributes (see Attributes and Default Attributes ) of the parameter, as you can not be sure if it is an actor or an object.
If no SYNTAX is defined for a VERB at all, this is equivalent to specifying
SYNTAX ? = ? (object).
The question marks represents the name of the VERB . This means that normal verb/object type of VERBs by default have the correct syntax and may only refer to objects. It also implies that the default name for the single parameter is OBJECT (see WHAT specifications for the implications of this).
A verb declaration specifies the checks that has to be performed and the effects of something the player does (commands using a syntactically legal input).
VERB take, get ... END VERB take.
A verb can be declared at three different levels, global (outside any other declaration), inside a declaration of a location or and inside an object or actor. The meaning of this is that the global declaration will always be considered, a declaration inside a location will only be considered if the hero is at this location when the verb is executed. Finally a verb declaration inside an object or actor declaration will only be considered if that object or actor is used as a parameter in the input.
The identifiers in the list (take and get in the example) will by default be the player words that can be used to invoke the verb. But if a SYNTAX is declared for the VERB (see Syntax Definitions above), the identifiers in the list will not be accessible to the player, instead the sequence of words and parameters specified in the SYNTAX must be used.
If more than one identifier is used in the list, as in the example above, this can be viewed as a short hand for declaring identical checks and bodies for all the verbs in the list. This in effect will create synonymous actions for different verbs on the level where the verb declaration is. They can differ in implementation at other places, i.e. if take and get are declared in the same verb declaration on the global level, they can still have different bodies in a particular location, in fact if they must have the same implementation they must both be declared together where this is required. For example
VERB take, get ... LOCATION untakable_place VERB take ... END LOCATION untakable_place.
Suppose that the declaration of take in the location prohibits taking things, the global action of get will still function.
To decide if the action is possible to carry out, the CHECK s are executed. First the global checks are tried, then the checks in the verb declaration at the current location (if the verb has a specification in the current location) and finally the checks declared for the verb in the objects or actors bound to the parameters (if any).
VERB take CHECK obj IS moveable ELSE "you can't take that." ... END VERB take.
If no expression is specified for a check, the check will always fail, in effect an unconditional check. This is useful for preventing certain actions at specific locations for example, since the checks are always executed first.
LOCATION l VERB jump CHECK "You can't do that here." END VERB jump. END LOCATION l.
If any check should fail, the execution of the current verb is interrupted and the statements following the failing check are executed. The user (player) is then prompted for another command.
In addition the CHECK is used when handling the user input ALL (see Player Input for details on possible player input). The mechanisms for this involves examining all objects at the current location and evaluating all checks for the verb. Any objects that does not pass the checks are not considered for execution. This restricts the handling of ALL to only executing the verb bodies for objects which are reasonable, and will not fail in the CHECK .
For example assuming the above definition of the verb take and a location containing the two objects ball and box of which only the ball is takeable the player input
would result in all representing only the ball. See Player Input for an explanation of the player view of this.
If all checks succeed the DOES -part(s) of the VERB will be carried out. The order is normally to first execute the body of any global declaration, then the body in the verb declaration for the current location. Finally each parameter is examined to find any declarations of the VERB inside what it refers to, those verb bodies are then executed in the order in which the parameters occurred in the syntax declaration. This is the most natural order and covers most cases but in some infrequent situations another order may be necessary. By using the qualifiers BEFORE/AFTER/ONLY the author can decide which verb bodies will be executed and in which order (see Verb Qualification below for details).
VERB take CHECK obj NOT IN inventory ELSE "You already have that." DOES LOCATE obj IN inventory. END VERB take.
When a VERB is declared inside an OBJECT , verb_alternatives are allowed. These alternatives are used in conjunction with the SYNTAX declaration defined for the verb and allows differentiating between the object or actor occurring in different places in the input.
When a player inputs a command each parameter in the syntax (see above) is bound to an actual object or actor or receives the value of a literal, depending on the specified syntax. To find out which CHECK s to test and verb bodies to execute the parameters are examined in turn according to the algorithm described in Verb Qualification below. Each object may have different verb bodies executed depending on at which position it occurred (to which parameter it was bound).
For example with the syntax definition
SYNTAX break_with = 'break' (o) 'with' (w).
the VERB body for break_with to execute for the delicate_vase could differ if it occurs as the direct object (o), or if it occurs as the indirect object (w). For each such parameter in the syntax you may define different actions by supplying a verb_alternative for each parameter identifier. The verb declaration could look like
OBJECT feather VERB break_with WHEN o DOES "The feather is even more flat than before." MAKE feather flat. WHEN w DOES "There is not much that you can break with a feather!" END VERB break_with. END OBJECT feather.
The order in which the different verb definitions are executed is normally from the outside in, i.e. the global definition is executed first if a global definition exists, then any possible definition of this verb in the current location. Lastly, the verb bodies in the parameters (in the order they appeared in the syntax definition) on which the verb was applied (if any) is examined to find and execute their verb definitions.
In most circumstances this is the most logical order, but if another order is required the verb qualifiers AFTER , BEFORE and ONLY may be used to alter this behaviour. The qualifiers alter the order of execution and a strict definition of this is described below.
First, the verb in the last parameter (if any) is investigated and, if this definition had the BEFORE or ONLY qualifier it is executed. If the qualifier was ONLY the execution is also aborted at this stage and no more verb definitions are examined, otherwise the other parameters are examined in the same way.
In the next step, the current location is examined and, if it contained a verb definition with a BEFORE or ONLY qualifier, that definition is now executed (and if it was ONLY , execution is aborted). As a result a BEFORE qualifier in the verb definition in an object will supersede an ONLY qualifier in the location.
At this stage, all BEFORE and ONLY qualifiers are handled appropriately since the global definition is now in turn anyway. This leaves the definitions without any qualifier or with the AFTER qualifier. The global definition is examined and if it did not have the AFTER specification, it is executed (if it had a ONLY qualifier execution is stopped after executing it). Any definition of the verb in the current location is again examined and, if it did not have the AFTER qualifier, it is executed. What remains is to execute the verb definition in the parameters if they have not been executed already, and to execute the location definition and the global definition (in that order) if they where declared with the AFTER qualifier.
So in short (with global definitions being the outermost and the definition in the entity bound to the last syntax parameter the innermost):
The normal order of execution is represented by the second item in the above list.
The qualifiers are a powerful but confusing concept. The normal order of execution is usually appropriate and only in special cases should qualifiers be used. When they are needed, you will find that one qualifier at the correct definition will normally do the trick. The above algorithm is used to get a strict definition of the execution order. It is not expected that this complex behaviour will be needed in practice.
An example of the use of qualifiers is to ensure that only the verb body within the object is executed:
OBJECT bomb VERB take DOES ONLY "Your curious fingering at the intricate mechanism sets it of. BOOOM!" QUIT. END VERB examine. END OBJECT bomb.
A location is a declaration of a place (a "room") in the game that (normally) can be visited by the player, have objects lying around, etc. In fact the map of your game is a set of interconnected locations.
The ID is the identifier used by the author throughout the source when referring to this location. By default, this will also be the name of the location written out to the player. But by using the NAME clause you can give a different name to the location when presenting it to the player (see Objects and Identifiers and Names ). For example
LOCATION south_of_house NAME 'South of House' ...
Identifiers and Names also for an explanation of the quoted identifiers used in this example.
A location can have attributes (see Attributes and Default Attributes ). These can be local attributes available only for this location or override declared default attributes.
LOCATION south_of_house NAME 'South of House' IS outdoors. ...
The statements in the DESCRIPTION clause should print a description of the location. These statements are executed when the hero enters the location or when executing a LOOK statement. See also Special Statements , concerning the VISITS statement.
LOCATION south_of_house NAME 'South of House' IS outdoors. DESCRIPTION "You are facing the south side of a white house. There is no door here, and all the windows are barred." ...
The optional DOES clause contains statements performed when any actor enters the room (is located there). An example usage of this would be if there was a weak bridge that only allows a certain total weight before it collapsed. The DOES clause of that location could contain actions for this which would be executed whenever any actor enters that location, not only the hero.
To build a world of locations, these must be connected. This is done by using exits. An exit consists of an id_list , all of which are considered directional words, i.e. when input by the player, they will move him to the location identified by the ID . It is possible to customize the exit using CHECKs (see Verbs for a definition), that must be satisfied to allow passage through the exit, and statements that will be executed when the player passes through.
Two interconnected locations might be declared like:
LOCATION east_end NAME 'East End of Hall' DESCRIPTION "This is the east end of a vast hall. Far away to the west you can see the west end." EXIT w TO west_end. END LOCATION east_end. LOCATION west_end NAME 'West End of Hall' DESCRIPTION "From this western end of the large hall it is almost impossible to discern the opposite end to the east." EXIT e TO east_end. END LOCATION west_end.
Local verbs may also be declared in a LOCATION . See Verbs for a description of how to declare verbs.
Objects are all the things that can be manipulated by the player. They can be picked up, examined and thrown away (if the author has allowed it). They will usually be described when the player enters a location containing objects.
As for locations, the ID is the name you use to refer to this object. It is also the default name for what is presented to the player and what he has to use when referring to the object.
By using the NAME clause you can give the object an other name, e.g.
OBJECT chair3 NAME little wooden chair
In this example the word "chair" is a noun and "little" and "wooden" would be adjectives. When the player refers to the object with the author name chair3 , he may use just "chair" if it is the only object with "chair" as its noun at the current location, or he may distinguish between multiple chairs by also giving one or more adjectives to pin down the chair he wanted.
It is possible to give an object multiple names by listing a number of name clauses. Each one will define adjectives and a noun as described above. The result being that the player can use any of the names to refer to the object. For example:
OBJECT rod AT grate NAME rusty rod NAME dynamite ...
This would allow the player to refer to the object using either of 'rusty rod' or 'dynamite'.
It is possible to set the initial location of an object by using an optional where clause. If no such clause is used the object will not be present in the game until it is moved somewhere by a LOCATE statement. Only the AT what and IN what forms of the where construct (see WHERE specifications ) are allowed when describing an initial location of an object.
OBJECT chest AT tresury ...
An object can also be a container. This is declared by means of the CONTAINER property clause, which looks like an ordinary container declaration (see Containers ).
OBJECT chest CONTAINER LIMITS ... HEADER ... DESCRIPTION ... : END OBJECT chest.
An object can have attributes (see Attributes and Default Attributes ). These can be local attributes or override values of declared default attributes.
OBJECT chest AT tresury IS NOT open. ...
The optional article can be used to define the indefinite article that should be placed before the object name in e.g. inventory listings and when presenting objects that have no DESCRIPTION clause. For example
OBJECT owl ARTICLE "an" :
would result in things like
There is an owl here. You are carrying an owl.
The article is not used when mentioning the object when acting on multiple objects:
> take everything (owl) Taken.
For objects that should not have any article, like 'some money', an ARTICLE clause containing no statements must be used:
OBJECT money NAME some money ARTICLE :
This will lead to:
There is some money here.
There is a some money here.
The optional MENTIONED clause specifies a short form for this object that will be used when mentioned e.g. in listings of containers or when the ALL form is used. If no MENTIONED clause is present an appropriate default message, constructed from the object name, is supplied by the system.
MENTIONED IF mirror IS broken THEN "broken" END IF. "mirror" ...
> take all (little black book) OK! (green pearl) OK! (broken mirror) OK!
The MENTIONED clause is also used when describing objects that have no DESCRIPTION , by inserting the article (see above) and the short description in a default message. In the following example output the article is underlined and the short description is emphasised, the rest is the default message templates.
There is a little black book, a green pearl and an owl here.
The same principle is used by the interpreter when constructing lists of objects in container contents lists (as the result of the execution of a LIST statement, see List ).
Objects can of course have descriptions, statements describing the object. This description will normally be printed when the player enters the location where the object currently is. It will also be given as a result of the DESCRIBE statement, and indirectly by executing a LOOK statement at the location where the object is. If the DESCRIPTION clause is missing the Alan system will supply a default description such as "There is a round ball here.". If there is a DESCRIPTION clause but it contains no statements the object will be `invisible', i.e. no description of it will printed. This can be useful for objects already described by the location description, or of objects with particular properties.
DESCRIPTION "On the floor there is a heavy golden chest. Its sides and top are completely encrusted with jewels." ...
As for locations, local verbs can be declared inside an object. The verb declarations inside objects is only used when that verb is applied to the object. See Verbs for details on verb declaration and usage.
A container is something that can contain objects. A container can either be an object (or an actor) in itself (in which case it is declared as an object or actor with the CONTAINER property, see Objects ) or be a pure container. A container that is not an object or actor, a pure container, can NOT be manipulated directly by the player. It can, however, be manipulated indirectly, if the author has supplied some verbs to do this, such as take and drop , which usually are implemented to manipulate the inventory container. A container for worn objects, is a common example of a pure container.
A container can only contain objects, not actors or locations.
The LIMITS clause put limitations on what and how much can be put in the container. If any of these limits are exceeded when trying to locate anything inside the container, the statements in the corresponding THEN -part will be executed and the players turn aborted. In fact these checks are performed as a consequence of the execution of a LOCATE statement (not actually the player placing anything inside the container). This means that the execution of a sequence of statements can actually be interrupted by these limitations.
The specification of an attribute, which must be a numeric object default attribute, implies that the sum of this attribute of all objects in the container can not exceed the value specified. The special attribute COUNT is also allowed and indicates a limitation on the number of objects allowed.
CONTAINER inventory LIMITS weight 50 THEN "You can not lift that much." COUNT 2 THEN "You only have two hands!"
HEADER is used when the contents of the container are listed. It is intended to produce something like
"The box contains"
"You are carrying"
The ELSE -part is used instead of the header if the container is empty.
If LIMITS or HEADER is missing the Alan system supplies the default of no limits, and the messages "The $o contains" and "The $o is empty." respectively.
The inventory, i.e. the container containing all objects carried by the hero is predeclared 2 , so that it already exists and can be used for common purposes. It can however be redeclared if required, for example to provide limits and a different header. Its default declaration is
END CONTAINER inventory.
One possible redeclaration of the inventory can serve as a more example of a container declaration.
CONTAINER inventory LIMITS weight 50 THEN "You can not lift that much." HEADER "You are carrying" ELSE "You are not carrying anything." END CONTAINER inventory.
An event is a sequence of statements executed at a specified time (count of turns). It is also executed at some specific location. An event can e.g. be used to create an explosion where the bomb is three moves from now or to let the ceiling of the cave fall down in five moves.
EVENT nearby_explosion "Somewhere in the distance there is an explosion." MAKE bomb gone_off. SCHEDULE small_avalanche AFTER 2. END EVENT.
The body of an event can be any sequence of statements. They can however not refer to any parameters, including OBJECT (since no verb is executing), or the ACTOR . See Run-time Contexts .
Events may be scheduled and cancelled with the SCHEDULE and CANCEL statements (see Event Statements ).
An actor is something that seems to live its own life in the game. Another common name for actors is NPC, non-player character. The author refers to the actor by using the ID , and it is also the default name presented to the player.
By means of the NAME clause, a different name can be assigned to the actor in the same way as for an object (see Objects ).
The optional property ( CONTAINER ) clause may be used to indicate that this actor can be used as a container, i.e it may contain things, thereby implying that the actor is carrying the things contained. This is analogous to objects having the container property (see Objects ).
An actor can have attributes (see Attributes and Default Attributes ). These can be local attributes or override values of declared default attributes.
ACTOR kirk NAME Captain Kirk AT control_room HAS health 25. CONTAINER HEADER "Kirk is carrying" ELSE "Captain Kirk is not carrying anything." DESCRIPTION "Your superior, Captain Kirk, is in the room." END ACTOR kirk.
In the DESCRIPTION clause, a description of this actor can be given. The statements describing the actor will be executed when the player enters a location where the actor currently is. This description will also be given as a result of the DESCRIBE statement. An exception is if the actor is currently executing a script for which there is a separate description (see below).
The SCRIPT is the actor's way of performing things. In a way it corresponds to what the hero is ordered to do by the player's typed-in commands.
Every script has a name (or to be compatible with previous versions, a number) to identify it. A script is selected by the USE statement. When a script is started it will continue until it reaches the end or another USE statement is executed for this actor.
The optional description allowed in the beginning of a script is used instead of the general description (in the beginning of the actor declaration) whenever the actor is executing that particular script. If it is not present the general description is used.
ACTOR george NAME George Formby DESCRIPTION "George Formby is here." SCRIPT cleaning. DESCRIPTION "George Formby is here cleaning windows." STEP ... SCRIPT tuning. DESCRIPTION "George Formby is tuning his ukelele." STEP... :
A script is divided into steps. Each step contains statements representing what the actor will do in what corresponds to one player move. A step can be defined to be executed immediately next move, to wait a number of moves before it is executed or even to wait for a special situation (condition) to arise.
STEP WAIT UNTIL HERO HERE "From the shadows a waiter emerges: $p'-Bonjour, monsieur', he says."
When an actor has executed the last step of the current script, it will do nothing more until the next USE statement is executed for this actor (the actor will be "dead", but still present at the location where it was). If this is not what is wanted, it is recommended to end each script with a new USE statement.
There is one very special actor, the hero, which is the player. This actor is always predeclared, but if necessary it can be redeclared. One situation when this is required is if you like to have attributes on the hero, such as "sleepy" or "hungry". Then a declaration like the following is possible:
ACTOR hero NAME me IS NOT hungry. CONTAINER VERB examine DOES IF hero IS hungry THEN "Examining yourself reveals a poor, hungry soul." ELSE "You find nothing but a poor beggar." END IF. END VERB examine. END ACTOR hero.
The container property of the hero is actually the inventory container, which is also predeclared, see The inventory .
A rule is an arbitrary expression, which, when true, results in execution of the given statements. Rules can be used to make things happen when certain situations arise, such as starting an actor when the hero enters the cave.
WHEN hero AT cave AND monster NOT active => USE SCRIPT 3 FOR monster.
The statements that are to be executed can not refer to parameters (including OBJECT ), but may refer to ACTOR .
The rules are tested after each actor (including the player) has made his move and after each event that is executed. So rules must be designed to be executed multiple times for each player turn. Rules can be considered to be executed at the location where the last activity (actor move or event) was performed (see also A Turn of Events ). This is important to consider especially concerning use of WHERE specifications (see WHERE specifications ) in rules.
The start section defines where the player (the hero) will be at the start of the game. This must be a location. Optionally this may be followed by statements to be executed at the beginning of the game, such as hello-messages or short instructions as well as starting any actors and scheduling events.
START AT outside_house. SCHEDULE bird_chirp AFTER 5.
Only the AT what form of the where construct (see WHERE specifications ) is allowed in the start section. Any statements are allowed in the start section except that they can not refer to any parameters.
An output statement is in the simplest case just a string, i.e. any text, possibly stretching over multiple lines, surrounded by double quotes. Whenever it is executed, the string will be printed on the players terminal with the following exception: if an output statement is executed at a location in the game where the hero not presently is the output will not be shown. This can be used in the following way in a script for the actor charlie_chaplin :
"Charlie Chaplin leaves the house through the front door." LOCATE charlie_chaplin AT outside_house. "Charlie Chaplin comes out from the nearest house."
If the hero is inside the house or out in the street he will now get different views of the situation. This feature ensures that the player only sees what is going on at the current location, and allows for easy adaption to various viewpoints on the events without the need for any variable tests.
There are some character combinations that have special meaning for the printout:
$l The name of the current location $v The verb the player used (the first word) $p New paragraph (one empty line) $n New line $i Indent on a new line $t Insert a tabulation $$ Do not insert a space $a The name of the actor that is executing $o The current object (first parameter) $<n> The parameter with number <n> (<n> is a digit)
The DESCRIBE statement executes the description part for an actor, an object or a location. If no such description exists a default description, such as
"There is a $o here."
is used instead. If the object has the container property a LIST statement is also executed for that object automatically (see below).
If a DESCRIBE statement is used for an object in the description part of a location, the system will recognise this and make sure that the object is not described more than once during the execution of a LOOK statement or when the hero enters that location. This makes it possible to use objects as parts of a location and embedding their description at the correct place in the longer description of the location.
"This office is dusty and probably hasn't been used for many years." DESCRIBE desk.
The SAY statement will output a short description of what is referred to by the what part. If it refers to an entity (a LOCATION , OBJECT or ACTOR ) it will print the name of that entity or execute its MENTIONED clause if one is available. If it refers to an attribute it will print its value (integer or string). Parameter names are also allowed in the SAY statement, which, of course will result in a short description of the entity to which it is bound, or a printing of the literal (if the parameter was a STRING or INTEGER parameter).
IF contents OF bottle > 0 THEN "In the bottle there are still" SAY contents OF bottle. "litres of water left." ELSE "The bottle is empty." END IF.
The LIST statement lists all objects in a container together with the header as specified for the container. If the container is empty the statements in the empty clause of the container are executed instead.
"The chest is heavy." IF chest IS open THEN LIST chest. END IF.
QUIT prints a question giving the player the choice of restarting the game, reloading a previously saved game or to quit. Any scoring or other printouts has to be made explicitly before executing the QUIT statement.
LOOK describes the current location and what it contains. The DESCRIPTION part for the location is executed, which may include describing objects or actors by explicitly executing DESCRIBE statements. Then objects and actors that have not already been described will automatically be described.
SAVE saves the game on a file for later use with RESTORE . Both save and restore asks for a file name to use for storing and restoring.
If the player should be shown the current surroundings after a RESTORE , you will have to implement a player verb like
VERB oops DOES RESTORE. LOOK. END VERB oops.
SCORE is a way of rewarding the player by giving points for certain actions. This is done by the statement
SCORE points .
The first time every such statement is executed the points given are added to the players current score. SCORE without any arguments prints a message indicating the current accumulated score.
The VISITS statement changes the number of times a location can be visited before the long description is presented again:
VISITS count .
The value of the argument ( count ) controls the number of visits to a particular location between full descriptions. The default setting (0) indicates that every time a particular location is visited its full description will be shown (which can also be expressed as: the full description will not be shown 0 times in between). Thus, a setting of 1 (one) would give a full description every second time the same location is visited. So
will always show long descriptions (this is also the initial setting).
The LOCATE statement is a way of transferring objects and actors. When executed, the indicated object or actor will be placed at the location given. For a description on how to specify where, see WHERE specifications . When an actor is located at a new location the DOES clause of that location is always executed.
One special case of the LOCATE statement is when the predefined actor HERO is located somewhere. This is analogous to what happens when the player types in a direction, i.e. the player is located at the appropriate location. Under particular circumstances, you may want to locate the player at a different location as a side effect of another action. For example:
EVENT explosion "Suddenly the door seems to bulge outwards, it bursts open throwing rocks and splinters everywhere. The impact of the explosion literally throws you back out in the hallway." LOCATE HERO AT hallway. END EVENT explosion.
In this case the new location will be described and the DOES clause of that location executed.
Another special case is when locating something inside a container. The LOCATE statement will then cause the execution of the limits of that container, and if any of the limits are exceeded the complete player turn is aborted immediately, resulting in that no more statements are executed. So if a player command should result in the location of an object inside a container, a good thing is to place the LOCATE statement as early as possible, as this enforces the limit checks in the beginning of this player turn.
The EMPTY statement locates all objects in the given container (or object or actor with the CONTAINER property) at a certain place. The meaning of the where part is as for LOCATE .
EMPTY inventory HERE. "You seem to have lost most of your possessions. Well, you can't have everything." LOCATE hero AT restart_point.
SCHEDULE means that the named event will occur at the specified location after the number of moves specified by the expression.
SCHEDULE ringing AT clock AFTER 60 - minutes OF clock.
The number of moves can be zero, i.e. AFTER 0 means that the event will occur now (during this player turn). If no location is specified, HERE is assumed, i.e. it will be executed at the current location, the location where the statement itself was executed at.
The semantics of specifying the location ( where ) as AT id , where the identifier represents an object or an actor, is that wherever that object or actor is when the event occurs, the event will be executed at that place.
Executing a second SCHEDULE statement for the same event before it has occurred will reschedule the event to the new time. So an event can only be scheduled for one execution at a time.
CANCEL will remove the event referenced from the queue of scheduled events.
EVENT ticking "Tick..." IF timer OF bomb = 0 THEN SCEHDULE explosion AFTER 1. ELSE DECREASE timer OF bomb. SCHEDULE ticking AFTER 1. END IF. END EVENT ticking. VERB defuse DOES CANCEL ticking. CANCEL explosion. "Phuuui! That was close." END VERB defuse. START AT office. "The bomb is ticking..." SCHEDULE ticking AFTER 1.
There are a number of statements for changing values of attributes.
The MAKE statement is used to set or reset boolean attributes.
MAKE door open.
The INCREASE and DECREASE statements modifies the values of numeric attributes by increasing or decreasing them by the value of the expression given in the optional BY clause. If no BY clause is specified the attributes are changed by 1 (one).
INCREASE level OF bottle BY contents OF mug. DECREASE lives OF HERO.
The SET statement is used when assigning values to numeric or string valued attributes.
SET mood OF king_tut TO 3. SET hour OF clock TO hour OF clock + 1.
In Alan there are two conditional statements the common IF statement and the DEPENDING ON statement.
The IF statement is essential for being able to vary the output and otherwise change the activities in the game. The expression is evaluated (see Expressions below for details and examples of expression) and if it evaluates to true , the statements following the THEN are executed, otherwise the expressions in any following ELSIF clauses are evaluated (in order) and the statements following the first expression that results in a true value is executed. If none of the expressions in the ELSIF clauses evaluated to true, or there are no ELSIF clauses, the statements following the ELSE are executed. The ELSE clause is also optional.
IF minute OF clock = 59 THEN SET minute OF clock TO 0. INCREASE hour OF clock. ELSE INCREASE minute OF clock. END IF.
IF level OF bottle = 0 THEN "You have no water" ELSIF level OF bottle < 5 THEN "YOu have almost no water left." ELSE "You have plenty of water." END IF.
The DEPENDING ON statement is a provided to select one of a number of possible conditional cases depending on an expression. A simple example of the DEPENDING ON statement is:
DEPENDING ON weight OF OBJECT = 1 : "light as a feather" BETWEEN 2 AND 10 : "carryable" BETWEEN 10 AND 20 : "heavy" > 20 : "immobile" ELSE : "weightless" END DEPENDING.
The meaning of this example is to test the weight OF OBJECT and select one of the cases depending on that. If equal to one the first case will be executed. If none of the cases catch the optional ELSE case will be executed (in this case it will only be executed for weights of zero or less).
The cases are tested in the order specified and at most one will be executed. In the example, weight 10 will render as "carryable".
The USE statement starts execution of a given script for a given actor. It is possible to leave out the FOR id -part when writing code within a certain actor; in this case the actor that the code is in is assumed.
USE SCRIPT playing FOR george.
Many constructs in the Alan language require a specification of where the construct should operate. The general intention of a where specification is to return a location. The meaning of the constructs above are as follows
Constructs in the grammar for the Alan language often refer to some entity defined in the Alan source. This is generally called a what specification, as it specifies what the construct refers to. The what specification may have the following forms
The grammar for Alan also refers to expression . This is a generic name for a number of constructs yielding a value.
Expressions are needed e.g. in IF and SET statements. The IF statement requires a boolean expression, i.e. an expression yielding a true or false value, while the SET statement needs a numeric or a string value. Some types of expressions return a value referring to an entity (an object, an actor or a location) in the Alan source as is, for example, the case with an identifier bound to a parameter allowing actors or objects. So, the possible types of expressions in Alan are
A single integer (e.g. 42) is of course a numeric expression.
The expression RANDOM integer TO integer is also a numeric value which is randomly selected between and including the two integers.
SET eyes OF first_die TO RANDOM 1 TO 6.
A string can be used in expressions and then represents a string value, e.g.
SET password OF terminal TO "xyzzy".
The AND and OR operators are standard binary boolean operators. AND has higher priority, but parenthesis may be used to change the order of evaluation.
IF kalif HERE AND mood OF sultan IS 0 THEN ...
All binary operators (plus, minus, multiplication, division) may be used on integer expressions. The result is another integer expression. The exact set of available operators are
+, -, *, /
Relational operators ( = , < , > , <= , >= , meaning: equals, less than, greater than, less than or equal, greater than or equal respectively ) are used to compare expressions. The result is TRUE or FALSE and may be negated by using an optional NOT.
IF temperature OF oven NOT > 100 THEN... IF weather OF world NOT < protection OF hero THEN...
Comparing two string expressions using the binary operator `= ' will make a case insensitive comparison, i.e. it will give a true value if the strings are the same without considering the case of the characters. The special identity operator, `==', only works on strings and compares the strings for an exact match (i.e. considering character case).
There is also a string containment operator, CONTAINS , which can be used to test if a string contains another string. The test ignores any differences in character case. An expression which would give a TRUE value is
"A string" CONTAINS "a S"
An optional NOT (before CONTAINS) can be used to reverse the test.
Two identifiers referring to entities may be compared with the `=' and `<>' operators, and may be used to test if a parameter refers to a particular entity or the same as another parameter. For example
SYNTAX put_in = 'put' (o) 'in' (c) WHERE c ISA CONTAINER ELSE "You can't put anything in the $2" VERB put_in CHECK o <> c ELSE "That would be a good trick if you could do it!!" DOES ...
Relational operations are not allowed on entities or strings, nor is it possible to compare values of different types.
A special relational operator is the BETWEEN operator which makes it possible to test if a numeric expression is within a range of values. For example
IF level OF water BETWEEN 2 AND capacity OF bottle THEN ...
Expressions following the pattern primary is something is used to test the setting of boolean attributes of the entity referred to by something . For example
IF bottle IS empty THEN ...
The test can be reversed by adding a NOT :
IF hero IS NOT hungry THEN...
To get the value of a numeric or string attribute the expression ID `OF' what is used.
IF s = password OF terminal THEN ... "You have" SAY capacity OF bottle. "sips left."
The expression primary optional_not where is used to test if a particular entity as specified by the what is (or is not) at the place indicated by the where , as in
IF bottle IN inventory THEN ...
IF HERO NEARBY THEN ...
Aggregates are functions to calculate values from sets of other values.
COUNT counts the number of objects at the specified place, e.g.
"You are carrying" SAY COUNT IN inventory. "things."
The SUM and MAX aggregates return the sum and the maximum value respectively of an attributes of all objects at the specified location. This implies that the attribute must be a default object attribute in order to ensure that the attribute is available for all objects. For example
IF SUM OF weight AT bridge > 500 THEN ... IF MAX OF size IN inventory > size OF small_door THEN ...
The last example could be adopted to make various restrictions in the possible travels of the hero.