Screen Display

Interactive fiction is primarily a text-based medium and this chapter discusses all the features of JACL that relate to the output of text. Depending on the Glk library used, JACL interpreters may also provide the ability to add graphics and sound to your games. The use of these features is covered in the following chapter, Glk and Multimedia.

The WRITE Command

The write command is the most flexible method of outputting text. It takes one or more parameters, each separated by a whitespace, and prints the result to the screen. A parameter can either be plain text, a string or integer variable, a string or integer constant or an object macro.

For example, the following command:

write Hello, world!

contains two separate parameters, the string Hello and the string world! (the comma after hello is considered to be white space.) When executed it will produce the following output:

Helloworld!

This is obviously not the desired result. The correct way to print this familiar greeting is:

write "Hello, world!"

The reason for this demonstration of how not to print text is that it demonstrates how the write command operates. Each of the parameters supplied to the write command is printed directly after the one before it. In the second example a single parameter containing both a space and comma is printed.
Warning As with all other JACL commands, any single parameter that contains spaces must be enclosed in quotes. Failing to do this is a common cause of error.

Special Characters

When printing text, the write command recognises the following special characters:

Character Output
^ A caret will be translated into a newline.
~ A tilde will be translated into a double quote.

To print the first two special characters (^ and ~) literally, the words caret and tilde should be used as parameters of a write command.

Below is an example of the use of the above special characters:

write "~Hello,~ said the boy.^"
write "~Hello,~ said the girl in reply.^"

Each of these write commands prints a single parameter enclosed in quotes and together will display:

"Hello," said the boy.

"Hello," said the girl in reply.

Printing the Value of Variables

If the value of a variable is to be printed, as opposed to verbatim text, the name of the variable must be entered as a separate parameter that is not enclosed in double quotes. For example, consider the following line from the +score function of the standard library, a write command with five parameters:

write "Your score is " score "% in " total_moves " moves.^"

The output of this five parameter command will vary depending on the current value of the two variables being printed. Typed as the very first command of the game it would display:

Your score is 0% in 0 moves.

Printing the Value of Item Elements

The current value of object and location elements may also be printed using a write command. This is done by enclosing the name of the element in brackets directly after the object or location label. For example:

write "The dial is set to " dial(status) "Mhz.^"

The elements of each object and location are stored in a sixteen element array (0-15). A number between 0 and 15 can be used between the brackets as an index to the object element rather than its name. For a mapping of default element names to index numbers, see the chapter Definitions in Detail. Constants can also be defined as a way of renaming any given element to a name that more clearly indicates its purpose. For example:

constant fuel_left	2

{+show_status
set submarine(fuel_left) = 42
write "FUEL: " submarine(fuel_left) ^
}

This code defines fuel_left as the constant 2, then sets the second element of the object submarine to equal 42. Finally, it uses a write statement to output the current value of submarine(2) by using the constant fuel_left to improve the readability of the code. This results in the following output:

FUEL: 42

Printing the Names and Descriptions of Objects

As you can see in the file verbs.library, it is a common need to print the short description of the object or objects that the player referred to in his or her last move. This is done using the integer variables noun1 and noun2. When used as parameters of a write command, these variables may be followed by either a {the} or a {list} macro to display the object's short description. Given the following object:

object wooden_box : small wooden box
  has          CONTAINER CLOSED CLOSABLE
  short        a "small wooden box"

if the player refers to this box as the first object in their command, then the write command:

write noun1{list}

would display, "a small wooden box", while

write noun1{the}

would display, "the small wooden box".

If you require the output to be capitalised when using these macros, use {The} or {List} instead. For example, with noun1 still set to the box object:

write noun1{The} " is no good to eat.^"

will display, "The small wooden box is no good to eat."

If you need the object's description without any leading article, use {plain} (or {Plain} for the capitalised form). With noun1 still set to the box object:

write noun1{plain} " sits on the shelf.^"

would display, "small wooden box sits on the shelf." The {plain} macro returns the noun phrase exactly as stored in the object's inventory slot — useful when you need to compose the article yourself, or when the object name is being used as a label rather than as part of a sentence.

Sentences Referring to Varying Objects

There are several other macros that may be used with the write command to assist in constructing sentences that refer to different objects at different times. They are designed to simplify the process of displaying the correct text for objects based on whether they have the attributes PLURAL, ANIMATE or FEMALE. They are:

Macro Output
object_label{long} Prints the objects long description.
object_label{that} Prints either the word them if the object has the attribute PLURAL, him if the object has the attribute ANIMATE, her if the object has the attributes ANIMATE and FEMALE, or the word that if the object doesn't have any of these attributes.
object_label{it} Prints either the word they if the object has the attribute PLURAL, he if the object has the attribute ANIMATE, she if the object has the attributes ANIMATE and FEMALE, or the word it if the object doesn't have any of these attributes.
object_label{does} Prints the word do if the object has the attribute PLURAL, or the word does if the object doesn't have the attribute PLURAL.
object_label{doesnt} Prints the word don't if the object has the attribute PLURAL, or the word doesn't if the object doesn't have the attribute PLURAL.
object_label{is} Prints the word are if the object has the attribute PLURAL, or the word is if the object doesn't have the attribute PLURAL.
object_label{isnt} Prints the word aren't if the object has the attribute PLURAL, or the word isn't if the object doesn't have the attribute PLURAL.
object_label{s} Prints the letter s if the object hasn't got the attribute PLURAL, or nothing if the object does have the attribute PLURAL.
object_label{label} Prints internal label of the object. This is useful for debugging, building function names internally and generating web code for the browser.
object_label{sub} Prints the word you if the object is the current player, he if the object has the attribute ANIMATE, she if the object has both the ANIMATE and the FEMALE attribute, it if the object has neither the ANIMATE nor the FEMALE attribute or the word they if the object being referred to has the attribute PLURAL.
object_label{obj} Prints the word yourself if the object is the current player, him if the object has the attribute ANIMATE, her if the object has both the ANIMATE and the FEMALE attribute, it if the object has neither the ANIMATE nor the FEMALE attribute or the word them if the object being referred to has the attribute PLURAL.

Custom Macros

It is also possible to define your own custom macros by creating a function with the name +macro_ followed by the name of the macro. This is primarily of use when writing a JACL game or library using a language other than English. The object the macro is being applied to will be passed to the function as an argument. The output of the macro is specified by setting the value of the string variable return_value. For example:

{some_function
write noun1{The} " " noun1{is} " verrouillé" noun1{es} ".^"
}

{+macro_es
if arg[0] has FEMALE
   if arg[0] has PLURAL
      setstring return_value "es"
   else
      setstring return_value "e"
   endif
else
   if arg[0] has PLURAL
      setstring return_value "s"
   else
      setstring return_value ""
   endif
endif
}

As you can see, the macro is used using the name {es} while the function is defined using the full name of +macro_es. The text to be returned by the macro is placed in the string variable return_value which is created internally by the interpreter.

Printing the Value of Strings

If the value of a string is to be printed, as opposed to verbatim text, the name of the string variable or string constant must be entered as a separate parameter that is not enclosed in quotes. For example:

constant game_title  "Tutorial Game"
constant game_author "I. F. Author" 

{+intro
write "Welcome to " game_title " by " game_author ".^"
}

The output of the +intro function will be:

Welcome to Tutorial Game by I. F. Author.

The PRINT Command

The print command is the primary way to output plain text. Unlike the write command, the values of variables, macros or string constants cannot be displayed. In fact the only thing that can be displayed by a print command is plain literal text. A print command has no parameters. On executing a print command the interpreter will begin printing all the text from the following line onwards until it encounters a line with a period (.) as the first non-whitespace character. The lines of text will be displayed verbatim with the following considerations:

  1. if a line does not end with a caret (^), an implicit space will be printed after the line and the following line of text will continue straight after it, following the usual word wrapping rules;
  2. if a line ends with a backslash (\) or a caret (^), no implicit space will be added to the line;
  3. a vertical bar will be translated into a space to allow formatting such as paragraph indenting to be done.

Below is an example of the print command in action (note that the colon after the word print is optional whitespace):

{+intro
clear
print:
   This text will be printed to the screen and
   word wrapped in the appropriate places.
   The backslash at the end of this line will prev\
   ent an implicit space being printed as will
   the caret at the end of this line.^
   ||These two vertical bars will allow this line
   to be indented two spaces.^
.
}

The OUTPUT Command

The output command reads the entire contents of a file and writes it to the game's output stream. The file is read from the game's data directory. A single parameter specifying the filename is required:

output FileName

For example, the following command will read and display the contents of a file called welcome_text from the data directory:

output welcome_text

This command is useful for including large blocks of pre-written text that would be unwieldy to embed directly in the game source code.

The LOOK Command

The look command will print the long description of the current location and any visible objects that are in the current location. A look command is executed implicitly by the JACL interpreter whenever a description of the player's current location is required. This is at times such as when then player moves into a location for the first time or restores a saved game.
Information In verbose mode (display_mode = true) the long-form description fires every time, even on a re-visit. Internally the library strips VISITED just before calling the location's look function and re-sets it immediately after, so the attribute is still set after every look — it is just briefly cleared so the long form runs.

The very first thing the look command will do is remove the attribute VISITED from the current location, then call +display_location to do the actual work. The flow is:

  1. Execute +before_look (then the location-specific here.before_look). If either returns true, nothing more is done.
  2. If the location has the attribute DARKNESS, execute +no_light and return.
  3. Call +title. This is an opportunity to print extra information relevant to every location. For example, the +title function in frame.jacl tests if the player is currently sitting down and displays the text "(sitting)". It is also common to add the following line to the top of +title to give each location description a title:
    write here{The} ^
    
  4. Execute the location's look function (or the global +look if the location has none).
  5. Ensure the current location has the attributes KNOWN, VISITED and MAPPED.
  6. Execute +object_descriptions to display the long text for each object in the current location that doesn't have a mass of scenery. If an object's long property is set to function, the interpreter calls a function named long_label (where label is the object's label) instead of printing literal text. This is useful for descriptions that are too long to fit on a single line, or that change during the course of the game.
  7. Execute the location's after_look function and the global +after_look.

It is a convention to have a look command at the end of the +intro function so the player can see where they are and what objects are nearby when the game begins.

The MORE Command

The more command will print a message and then wait for the player to press a key before continuing. The message to print is passed as the only parameter of a more command. If no message is provided, the message [MORE] is used as a default. Below is an example of using the more command with a custom message:

more "Hit any key to continue"

Back to Contents