Definitions in Detail

A JACL game file consists of two fundamental components: code and data. This chapter focuses on the data, and provides a detailed break down of all the possible elements that may be defined. In the case of objects and locations, all their associated properties are also listed.

Objects

    object Label : Name1 [Name2 Name3...]
      has        Attribute1 [Attribute2 Attribute3...]
      short      Pronoun ShortDescription
      long       LongDescription
      parent     ItemLabel
      mass       Integer / heavy / scenery
      capacity   Integer
      player
      static

Each object definition begins with the keyword object followed by the object's label. This label is a unique name by which the object will be referred to by any code within the program. The object's label is then followed by a space-delimited list of the object's names. There must be at least one name, and may be as many as can fit into a single line of JACL code. During the course of the game the object may be referred to by the player using one or more of these names. For more informations, see the section on Object Resolution.

Following this header are any properties you wish to specify that pertain to the object that you are currently defining. Below is a description of all the possible object properties:

A has keyword must be followed by a space-delimited list of attributes that the object is to have when the game begins. For more information, see the section on Attributes.

If this property is omitted, the object will start with no attributes.

A short property must be followed by two parameters: the object's Pronoun and the object's ShortDescription text.

The ShortDescription text, prefixed by the specified Pronoun, is displayed using the object's {list} macro in conjunction with a write command. When using the object's {the} macro, the ShortDescription text will normally be displayed prefixed with the word the instead of the specified pronoun.

If the word name is specified as the Pronoun, the ShortDescription text is not prefixed with anything, such as in the case of a proper noun. This applies to both the {list} and {the} macros.

If this property is omitted, the pronoun will be set to the and the short description will be set to the object's label. If the ShortDescription text is plural, the object should be given the attribute PLURAL to ensure the it is referred to appropriately by code in the library.

A long property must be followed by the text to be displayed when the object is in the current location and the player types a look command.

If this property is omitted, the object's label is used.

If the text following a long property is the name of a function name, this function will be executed whenever the long description text should be displayed. This provides the ability to have long or dynamic descriptions.

A parent property must be followed by either a location label (indicating that the object begins the game in that location), or an object label (indicating that the object begins the game within, on top of or being carried by that object).

If the object is specified as starting here, or the starts keyword is omitted, then the object will start in the last location to be defined before it in the game file.

A mass property indicates the physical size and weight of the object. It must be followed by an integer, the word heavy or the word scenery.

An integer indicates exactly how much the object encumbers the player or fills a container (see the capacity property below for further information).

The word scenery indicates that the object is immovable and that the interpreter should not advertise its presence at the end of a location description. For this reason, no long property is required for object with a mass of scenery.

The word heavy indicates that the object is immovable, but should have the text following its long description printed after the look function that is associated with its parent location is executed.

If this property is omitted, the mass for the object is set to scenery.
Behind the scenes, a mass of heavy translates to 99 and a mass of scenery translated to 100. It is important to keep this in mind if you change the capacity property for the player or create any containers.

A capacity keyword must be followed by an integer, indicating the number of mass units an object with the attribute CONTAINER, SURFACE or ANIMATE can hold.

If this property is omitted, the object will have a capacity of zero.

Due to this property's default, in order to allow an object to accept other objects it must be given on of the attirubtes CONTAINER, SURFACE or ANIMATE and have its capacity property set to a suitably large value. The exception to this rule is if the object being given or inserted have a mass of 0, but this value should only be used for insignificantly small objects.
In the file frame there is an object with a label of kryten that is set up to represent the player. This item has a capacity of 40. If left unchanged, the player can not simultaneously carry objects whose mass properties total more that 40. This figure of 40 should be used as a guide when setting the capacity property of other characters, containers or surfaces.

A player property mas no parameters and indicates that this object is to represent the player in the game. Behind the scenes this set the object pointer player to point to this object. The value of this pointer can be changed during the course of the game if required.

A static property mas no parameters and indicates that none of the object's properties should change during the course of the game. Nothing prevents you from modifying a static object's properties, but they will not be saved. Defining an object as static will increase performance and decrease the size of saved-game files.

The properties group, counter, index, status, one, two, three, next, previous and points have no pre-determined meaning. You are free to set and test these values as required.

When a command requires a numerical value as a parameter, the following object elements can be referred to:


object_label(group)0 object_label(mass)6
object_label(one)1 object_label(capacity)7
object_label(two)2 object_label(points)8
object_label(three)3 object_label(counter)9
object_label(next)4 object_label(index)10
object_label(previous)5 object_label(status)11
   object_label(parent)12

These elements can be referred to by name or number. For example, the following two commands are equivalent:

   set noun4(parent) = chest
   set noun4(13) = chest

   ; ...and to interate through all properties
   set INDEX = 0
   repeat
      write "PROPERTY " INDEX ": " noun4(INDEX)
      set INDEX = 0
   until INDEX = 13

If an object element is to be given a game-specific use, it is often wise to define a constant that described its use. For example:

   constant fuel_left	1

   {+accelerate
       set space_ship(fuel_left) - 1
       ...
   }

Locations

      location Label : Name1 [Name2 Name3...]
      has           Attribute1 [Attribute2 Attribute3...]
      short         Pronoun ShortDescription
      north         LocationLabel / nowhere
      northeast     LocationLabel / nowhere
      east          LocationLabel / nowhere
      southeast     LocationLabel / nowhere
      south         LocationLabel / nowhere
      southwest     LocationLabel / nowhere
      west          LocationLabel / nowhere
      northwest     LocationLabel / nowhere
      up            LocationLabel / nowhere
      down          LocationLabel / nowhere
      in            LocationLabel / nowhere
      out           LocationLabel / nowhere
      static 

Each location definition begins with the keyword location followed by the location's label. This label is a unique name by which the location will be referred to by any code within the game file. The location's label is then followed by the location's space-delimited list of names. There must be at least one name, and may be as many as can fit into a single line of JACL code. During the course of the game the location may be referred to by the player using one or more of these names. For more informations, see the section on Object Resolution.

Following this header are any properties you wish to specify that pertain to the location you are currently defining. Below is a description of all the possible location properties:

A has keyword must be followed by a space-delimited list of attributes that the location is to begin with. For more information, see the section on Attributes.

If this property is omitted, the only attribute the location will have when the game is started is LOCATION.

Internally, objects and locations are both stored using the same data-structure. In fact, once the game is running, the only difference between the two is that a location has the attribute LOCATION.

A short property must be followed by two parameters: the location's Pronoun and the location's ShortDescription text.

The ShortDescription text, prefixed by the specified Pronoun, is displayed using the location's {list} macro in conjunction with a write statement. When using the location's {the} macro, the ShortDescription text will normally be displayed prefixed with the word the instead of the specified pronoun.

If the word name is specified as the Pronoun, the ShortDescription text is not prefixed with anything, such as in the case of a proper noun. This applies to both the {list} and {the} macros.

If this property is omitted, the pronoun will be set to the, and the short description will be set to the location's label. If the ShortDescription text is plural, the location should be given the attribute PLURAL to ensure the it is referred to appropriately.

The directions the player can travel in from this location are defined by the properties north, northeast, northwest, south, southeast, southwest, east, west, up, down, in and out. The label of the location that the direction leads to when the game is started must follow any direction property. The links between locations may be modified during the course of the game to reflect doors opening etc. The keyword nowhere may be used in place of a location label to indicate that the player may not move in that direction. If a direction is not listed, nowhere is the default.

A static property mas no parameters and indicates that none of the location's properties should change during the course of the game. Nothing prevents you from modifying a static location's properties, but they will not be saved. Defining an object as static will increase performance and decrease the size of saved-game files.

Following each completed location definition should be an associated function called look. This function will be executed every time the description for the location is due to be displayed.

When a command requires a numerical value as a parameter, the following object elements can be referred to:


location_label(north)0

location_label(southeast)

6
location_label(south)1 location_label(southwest)7
location_label(east)2 location_label(up)8
location_label(west)3 location_label(down)9
location_label(northeast)4 location_label(in)10
location_label(northwest)5 location_label(out)11
   location_label(parent)12

These elements can be referred to by name or number. For example, the following two commands are equivalent:

   set noun4(west) = beach
   set noun4(3) = beach

   ; ...or iterating across all properties to trap 
   ; the player in the current locaiton
   set INDEX = 0
   repeat
      set here(INDEX) = nowhere
   until INDEX = 12

Variables

Variables are defined using the keyword variable followed by the name of the variable. The default value for the variable can be set by following the name of the variable with an integer, the word true or the word false. If no value is specified on definition, the variable is initialised with a value of zero.

The following are some examples of variable definitions:

   variable AIR_LEFT          100
   variable LAGERS_DRUNK      ; Set to zero by default 
   variable AIRLOCK_SEALED    true
Like all other data definitions, variables can not be defined within the body of a function.

Internal Variables

The following is a list of variables defined internally by the JACL interpreter.

Variable Description
COMPASS This variable is used to store the direction the player moved in when they travel between locations. This variable may be tested in either of the movement functions allowing you to prevent the move from occurring or displaying some special text as required. The direction traveled is encoded as an integer that can be tested using a set of constants listed later in this section.
TOTAL_MOVES This variable records the number of successful moves entered by the player so far. This variable defaults to 0 and is incremented each time a valid command is entered by the player. This is indicated by the value of the variable TIME (see below).
SCORE This variable indicates how may points the player has scored during the course of the game.
DISPLAY_MODE

This variable indicates whether the interpreter is in verbose or brief mode, with a value of 1 being verbose and 0 being brief. Default value is 0. In brief mode, each location is given the attribute VISITED when th player enters it, this is not the case when in verbose mode.

INTERNAL_VERSION This variable is set to the major version number of the JACL interpreter that you are using. This should be tested for in the +intro function to ensure compatibility between your game and the version of the interpreter being used to play it.
TIME This variable is set to true when the player first types a command. If at no time during the processing of that command it is set to false, two things will happen. Firstly, the variable TOTAL_MOVES will be incremented by one. Secondly, the eachturn functions will be executed if they exist.
MAX_RAND When the word random is supplied as a parameter to a command expecting an integer value, a random number between zero and the current value of MAX_RAND will be generated. The default value is 100.
ARGUMENT When a function is passed an argument, that value is copied into the object pointer noun4 and the variable ARGUMENT.

Variable Defined in the Library File

There are several variables defined within the library file. These are:

Variable Description
OBJECT_BACKUP1
OBJECT_BACKUP2
OBJECT_BACKUP3
OBJECT_BACKUP4
These variables are used to store the values of noun1, noun2, noun3 and noun4 if another verb is executed from a function using the proxy command. When the new function is returned from, the original settings are restored from these variables.
GAME_VERSION This variable should be incremented as you revise your game. Its current value should be displayed in the +about function.
OXYGEN_LEFT This variable is decremented by one for every turn the player spends in a location that has the attribute WITHOUT_AIR until the player dies. If they return to a location that doesn't have the attribute WITHOUT_AIR, it is set back to its default setting of 5.
INDEX This all-purpose counter is used throughout the library code. It is used as temporary variable and stores no long-term data.
DIRECTION
DESTINATION
These variables are used by the code for moving non-player characters around in the game. See below for details.

There are some functions defined in the library file to help simulate the natural movement of objects, such as a non-player character walking around. In addition to moving the object, these functions will display the appropriate message required to announce the movement to the player.

There are four steps to using these functions:

  1. Set the object pointer noun4 to the label of the object to be moved.
  2. Set the variable DIRECTION to the direction that the object is to move (see the variables below).
  3. Set the variable DESTINATION to the label of location the object is to end up in.
  4. Execute the global function +push_object.

The variable DIRECTION can be set to the appropriate integer value by using one of the following constants. The same constants can be used to test the value of the DIRECTION_TRAVELED variable in the movement functions. These constants are defined in the library file.

Direction Integer Value
NORTH 0
SOUTH 1
EAST 2
WEST 3
NORTHEAST 4
NORTHWEST 5
SOUTHEAST 6
SOUTHWEST 7
UP 8
DOWN 9
IN 10
OUT 11

Below is an example of the procedure for making an object move from one location to another:

    set noun4 = guard
    set DIRECTION = NORTH
    execute +push_object

Synonyms

Synonyms are a way of substituting a word in the player's command for another word. They are defined using the keyword synonym, followed by the word to be substituted, then the word to be put in its place. Care should be taken when defining synonyms, as duplicate grammar statements are often the better approach. Consider the following examples:


    synonym get	take
    synonym grab	take

With the above synonyms defined, the command 'get note' would be translated to 'take note' before being parsed. With the below grammar statements defined, but no synonyms in place, the command "get note" would be parsed as is, but will still be mapped to the take function.


    grammar take *here	>take
    grammar get *here	>take
    grammar grab *here	>take
The problem with the synonym approach is that if we were then to go to define the following grammar statement, we would run into trouble:
    grammar get out		>exit

As you can see, the command 'get out' would be translated to 'take out' before being parsed — a sentence that the game would not understand.

There are right and wrong times to use both approaches to broadening your game's vocabulary. Just be sure to take care and consider the potential effects of any synonyms you define.

Filters

There are a few filters defined in the library, and chances are you will never need to define any of your own. They are defined using the keyword filter followed by the word to be filtered from the player's input before it is parsed.

The following are some examples of filter definitions (taken from the library):

    filter the
    filter quickly

With the above filters defined, when the player typed the command:

    quickly take the coin from the bag

the parser would process:

    take coin from bag
Filters should be defined very sparingly. They are a designed to give the illusion of the parser understanding more than it really does. Although at times this can be good, at other times it can be very, very bad.

Constants

Constants are defined in the same manner as a variable that is given an initial value. For example:

    constant ordered	4

Unlike a variable, the initial value of a constant is not an optional parameter. A value must be specified and this value will remain unchanged for the duration of the game.
Although a variable can be used wherever a constant can be used, if a value is not to change during the game, there are two advantages to using a constant. The first is that the value cannot be changed by accident using a set command. The second is the constants are not saved each time the player makes a move. For this reason they also provide a performance increase over the use of variables.

Parameters

Parameters are a web-based feature and therefore only be used with the JACL interpreter. The basic syntax for a parameter statement is:

     

parameter ParameterName [Container] [LowestValue HighestValue]

A parameter is a connection between an HTML form parameter and a JACL container. When a defined parameter is passed in the URL, its value is copied into the specified container before the player's move is processed. Also, a group of two integers may be specified after the container in the parameter definition. These numbers indicate the parameter's range bounds. The first integer is the lowest possible value for the parameter, the second is its highest. When a parameter is updated, it will automatically be adjusted to fall within the supplied bounds if required. If no low and high range bounds are specified, they are set to -65535 and 65535 respectively.

Below is a complete JACL program demonstrating the use of parameter statement in combination with an HTML form.

   #!/usr/local/apache/jacl/bin/jacl
   prefix          FORM-
   
   parameter TEST  kryten(status)          1       4
   
   location here : here
   
   variable INDEX
   
   {form
   write "STATUS: " kryten(status)
   
   write "<form>"
   hidden
   
   set INDEX = 1
   repeat
      write "<input type=radio name=TEST value=~" INDEX ~
      if INDEX = kryten(status)
         write " checked"
      endif
      write ">" INDEX
      set INDEX + 1
   until INDEX = 5
   
   write "<input type=submit>"
   
   write "</form>"
   }
   
   object kryten : myself
     player
   
   {+header
   write "Content-type: text/html^^"
   write "<HTML><HEAD></HEAD><BODY>"
   }
   
   {+footer
   write "</BODY></HTML>"
   }
   {+intro
   execute "here.form"
   }
   
   grammar blankjacl >form

When run it will produce the following output:

Selecting one of the radio buttons, then clicking the submit button will cause the value of kryten(status) to be updated before the player's command is processed. As there is no move to process, a blankjacl command is proxied on the players behalf. This command has been mapped to the form function, which re-displays the form.

Grammar Statements

The basic syntax for a grammar statement is:

     

grammar CommandConstruct >FunctionName

The keyword grammar defines a command that may be typed by the player and the function that it corresponds to. The CommandConstruct section may consist of one or more parameters that may either be a word to be typed verbatim, a scope indicator or the token $text. A scope indicator states that an item should be supplied at that point in the player's move and be within the specified scope (see below). The token $text indicates that an arbitrary text string may be used at that point in the command. If this text string is to contain spaces, it must be enclosed in double quotes. The last parameter of a grammar statement is a greater-than symbol directly followed by the core name of the function to be executed if a command of this format is typed by the player.

Scope Indicator Description
*here Indicates that the object must be in the current location.
*held Indicates that the object must be held by the player.
*present Indicates that the object must be in the current location or held by the player.
*anywhere Indicates that the object may be anywhere in the game world

For example, the following are some valid grammar statements:

    grammar take *here >take
    grammar insert *held in *present >insert_in

The first statement says that if the player types the word take, followed by an item that is in the current location, then the function take should be executed. The second states that if the player types the word insert, followed by and object that is being held, followed by the word in, followed by an object that is either being held or is in the current location, then the function insert_in should be executed. Feel free to add extra grammar statements that map to library functions into your program. Keeping these extra grammar statements within the game-specific part of your code means that you can upgrade the library at a later date without needing to re-enter your additions. The exact way in which these functions are executed is detailed in the section on Functions.
When entering a new grammar definition, be sure not to leave a space between the greater-than symbol (>) and the name of the function to be executed.