bl791/IFDB / articles /byte87_betz.html
bl791's picture
download
raw
36.2 kB
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xml:lang="en">
<head>
<title>An Adventure Authoring System</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<meta name="Description" content="&quot;An Adventure Authoring System&quot; is an overview of AdvSys by its author,
David Betz. Originally published in the May 1987 issue of BYTE magazine.
Transcribed into HTML by David Welbourn." />
<style type="text/css">
pre { margin-left:1em; }
div.rinset {float:right; margin-left:1em; margin-bottom:0.5em; }
table.flowchart tr td {font-family:Arial,Helvetica,sans-serif; text-align:center; background-color:#EEE; color:black; }
table.flowchart tr td.box {border:solid red 1px; background-color:#FEE; color:black; }
table.flowchart tr td.arr {background-color:#EEE; color:red; }
td.clshdr {background-color:#FED ; color:black; }
td.prophdr {border-top: solid black 1px; }
td.prop {text-indent:1em; }
</style>
</head>
<body style="padding-left:0.5in;padding-right:0.5in;background-color:white;color:black">
<p style="text-align:right"><big>David Betz</big></p>
<h1>An Adventure Authoring System</h1>
<h2 style="font-family:Arial;Helvetica;sans-serif"><i>A tour of AdvSys, a tool for writing text adventure games</i></h2>
<p>[Editor's note: <i>&ldquo;Interactive Fiction as Literature,&rdquo; a companion piece to this article,
begins on <a href="byte87_buckles.html">page 135</a>.</i>]</p>
<p>AdvSys is a system I designed for writing text adventure games. In adventure games, the player acts as an
adventurer in a simulated world (real or imaginary). Players determine their own course of action by typing commands
that trigger events in the simulated world.</p>
<p>You can approach the writing of an adventure game in many ways, and a number of books describe how to use
traditional programming languages to write adventures. The most commonly used language is BASIC. But while you can
certainly build very complex and interesting adventures using BASIC, it was not designed specifically for that purpose.</p>
<p>Much of the task of building an adventure game program consists of constructing complex data structures that model
the game universe. BASIC has no convenient means for describing these data structures. Even Pascal, which is rich in data
structuring facilities, has no easy means of constructing complex initialized data structures.</p>
<p>Another approach to writing adventures is to use a special language specifically designed for the purpose. This
article describes such a language.</p>
<p>A language for writing adventures must have three essential features: a parser to handle commands typed by the
player, an object-description facility, and a language for specifying the events that take place in response to the
players' commands.</p>
<div style="float:right;border-top:solid black 3px;border-bottom:solid black 3px;padding-left:1em;
padding-top:0.5em;padding-bottom:0.5em;font-family:Arial,Helvetica,sans-serif;font-style:italic;width:25%">Adventure
games generally take place in a world made up of a network of interconnected 'locations.'</div>
<h3>The Parser</h3>
<p>The parser is responsible for prompting the player to enter a command. It must read the command from the keyboard
and break it into pieces that can be digested by the action code. All commands are broken into one of five different
types of phrases:</p>
<ol>
<li>an actor phrase</li>
<li>a verb phrase</li>
<li>a list of direct-object noun phrases</li>
<li>a preposition</li>
<li>an indirect-object noun phrase</li>
</ol>
<p>Not all of these phrases are present in every command, and the parser recognizes only a limited set of command
forms. AdvSys recognizes these forms:</p>
<ol>
<li>[actor,] verb</li>
<li>[actor,] verb direct-objects</li>
<li>[actor,] verb direct-objects preposition indirect-object</li>
<li>[actor,] verb indirect-object direct-objects</li>
</ol>
<p>where &ldquo;direct-objects&rdquo; is defined as:</p>
<p style="margin-left:1em">direct-object [conjunction direct-object]*</p>
<p>(In this article, phrases within square brackets are optional. Phrases followed by an asterisk may be repeated
zero or more times.)</p>
<p>The terms &ldquo;actor,&rdquo; &ldquo;direct-object,&rdquo; and &ldquo;indirect-object&rdquo; all represent noun
phrases. Each noun phrase is of the form</p>
<p style="margin-left:1em">[article] adjective* noun</p>
<p>In other words, a noun phrase consists of an optional article followed by zero or more adjectives followed by a noun.
Here are some examples of noun phrases recognized by the AdvSys parser:</p>
<p style="margin-left:1em">sword<br />the angry man<br />the thick red book</p>
<p>Now that we have defined the command forms that are handled by the parser, let's look at some complete commands.
I will precede each example with a number indicating the form on which it is based:</p>
<ol>
<li value="1">Look</li>
<li value="1">Fred, wake up</li>
<li value="2">Drop the book</li>
<li value="2">Take the sword and the orange vial</li>
<li value="3">Give the book to the librarian</li>
<li value="4">Librarian, give me the book</li>
<li value="4">Show the librarian the book</li>
</ol>
<p>The second example illustrates another feature of the parser. Verb phrases can consist of either a single word like
&ldquo;take&rdquo; or a pair of words like &ldquo;pick up&rdquo; or &ldquo;wake up.&rdquo; If a verb phrase consists of
two words, the words do not have to be immediately adjacent to each other in the command. Either &ldquo;Pick up the
book&rdquo; or &ldquo;Pick the book up&rdquo; will produce the intended result.</p>
<p>After breaking the command into phrases, the parser sets a small number of global variables to communicate the
results of its work to the rest of the adventure system. The parser stores each noun phrase in an internal array,
indexed by the noun phrase number. The index associated with the actor noun phrase is stored in the global variable
<code>$actor</code>, the index associated with the first direct-object noun phrase is stored in the variable
<code>$dobject</code>, and the index of the indirect-object noun phrase is stored in the variable
<code>$iobject</code>. If a noun phrase is missing from the command, its corresponding variable is set to <code>nil</code>
(which is the same as zero in this system). These noun phrase numbers will be used later to determine which objects
the noun phrases refer to.</p>
<p>The parser uses the verb phrase and the preposition to select an action to handle the command. It stores the
selected action in the global variable <code>$action</code>. (More details about actions later.) The adventure language
statements you use to define the vocabulary used by the parser are</p>
<p style="margin-left:1em"><code>(adjective word*)<br />(preposition word*)<br />
(conjunction word*)<br />(article word*)</code></p>
<p>In addition, it is useful to define synonyms of some words. This is accomplished by the statement</p>
<p style="margin-left:1em"><code>(synonym word synonym*)</code></p>
<h3>Objects</h3>
<p>Adventure games generally take place in a world made up of a network of interconnected &ldquo;locations.&rdquo;
Each location has a set of exits that connect it with adjacent locations. The player explores the game world by moving
an actor from location to location through these exits.</p>
<p>In the course of exploring these locations, the player encounters &ldquo;things&rdquo; and other &ldquo;actors.&rdquo;
In a fantasy adventure, for example, the player might encounter a magic sword or an angry dwarf.</p>
<p>AdvSys groups locations, actors, and things in the general category of <i>objects</i>. Each object in the adventure
has an associated set of <i>properties</i>. Each property has an associated <i>value</i>.</p>
<p>A location object, for example, has a property for each of its exits. The values of these exit properties are the
locations a player will reach by passing through the corresponding exits. Location objects also have <i>description</i>
properties whose values are text strings describing the location under different circumstances. The concept of objects
with properties is very general in this system, leaving you, as you write your game, free to invent new properties
appropriate to a particular type of game and to define new classes of objects that share common properties, structure,
and behavior.</p>
<p>For instance, a location object might be defined as</p>
<pre>(location living-room
(property
description "You are in the living room.\n"
north library
south entrance
east dining-room))</pre>
<p>This is a definition of <code>living-room</code>, a location object with the properties <code>description</code>,
<code>north</code>, <code>south</code>, and <code>east</code>. The description property has the string <code>"You are
in the living room.\n"</code> as its value. (A back slash followed by the letter <code>n</code> instructs the program
to start a new line). The property <code>north</code> has the value <code>library</code> (the lcoation the player
reaches when traveling north from the living room), the property <code>south</code> has the value <code>entrance</code>,
and the property <code>east</code> has the value <code>dining-room</code>.</p>
<p>Things are objects that the player can manipulate. A thing must have a noun associated with it. And since the
same noun can refer the different objects, you can associate adjectives with the objects to make references to the
objects umambiguous. Here is an example of an object description:</p>
<pre>(thing sword
(noun sword weapon)
(adjective red)
(property
description "a red sword"
weight 20
value 10
initial-location entrance))</pre>
<p>This definition describes the object <code>sword</code>, which has the nouns <code>sword</code> and
<code>weapon</code> and the adjective <code>red</code>. Thus, a player could refer to this object as &ldquo;the
sword,&rdquo; &ldquo;the weapon,&rdquo; &ldquo;the red sword,&rdquo; or &ldquo;the red weapon.&rdquo;</p>
<p>The <code>sword</code> object also has four properties: <code>description</code> has the value <code>a red sword</code>,
<code>weight</code> has the value <code>20</code>, <code>value</code> has the value <code>10</code>, and
<code>initial-location</code> has the value <code>entrance</code>.</p>
<p>The <code>weight</code> property might be used to provide the player with a limited carrying capacity. If each object
has a weight, you can prevent the player from carrying a set of objects whose combined weight exceeds the player's load
capacity. Similiarly, the <code>value</code> property could be used for scoring. Each object has an associated value that
the game will add to the player's score when the object is carried to some specified location. The meaning of these
properties is up to you, the game author.</p>
<h3>Defining Objects</h3>
<p>Actors are objects that represent characters in the adventure. The player controls a special actor that is the
&ldquo;player character.&rdquo; The player &ldquo;sees&rdquo; through this actor's eyes and takes part in the action
by controlling this actor's movements. In AdvSys, the player character is called the &ldquo;adventurer.&rdquo;
Other actor objects represent nonplayer characters. These nonplayer characters are controlled by the adventure program
(the code that you have written) rather than by the player, and they may include both friendly and hostile characters
with whom the adventurer must interact to solve the adventure. An example of a nonplayer character might be</p>
<pre>(actor troll
(noun troll dwarf)
(adjective angry)
(property
description "There is an angry troll here."
short-description "an angry troll"
initial-location "dungeon"))</pre>
<p>This defines a <code>troll</code> that the player can refer to as &ldquo;the angry troll,&rdquo; &ldquo;the dwarf,&rdquo;
and so on, and is initially found in the dungeon, where the adventure will see the words <code>"There is an angry troll
here"</code> upon entering.</p>
<p>So far we have seen how to describe the static portions of an adventure game. Location objects allow us to build
the adventure universe, things allow us to place interesting objects in this universe, and actors allow us to populate
the universe with other characters.</p>
<p>I have defined locations, things, and actors as part of a run-time package that comes with AdvSys, but you can define
your own objects if you wish. The statements used to define these objects, as shown in the previous examples, are</p>
<pre>(object object-type
object-statement*)
(object-type name
object-statement*)</pre>
<p>where the <code>object-statement</code> may be defined using one of the following:</p>
<pre>(noun word*)
(adjective word*)
(property [property-name initial-value]*)
(class-property [property-name initial-value]*)
(method (selector arg-name* [&amp;aux tmp-name*]) expression*)</pre>
<p>Now we will explore how things happen in the adventure universe.</p>
<div class="rinset" style="width:25%">
<table class="flowchart" cellspacing="0" style="width:100%">
<tr><td class="box">init</td><td colspan="4" rowspan="2" /></tr>
<tr><td class="arr">&darr;</td></tr>
<tr><td class="box">update</td><td class="arr">&larr;&mdash;</td>
<td class="arr">&mdash;&mdash;&mdash;</td><td class="arr">&mdash;&mdash;</td><td /></tr>
<tr><td class="arr">&darr;</td><td colspan="3" /><td class="arr">|</td></tr>
<tr><td>(parse)</td><td class="arr">&mdash;&rarr;</td><td class="box">error</td>
<td class="arr">&mdash;&rarr;</td><td class="arr">|</td></tr>
<tr><td class="arr">&darr;</td><td colspan="3" /><td class="arr">&uarr;</td></tr>
<tr><td class="box">before</td><td colspan="3" /><td class="arr">|</td></tr>
<tr><td class="arr">&darr;</td><td colspan="3" /><td class="arr">|</td></tr>
<tr><td>(action)</td><td colspan="3" /><td class="arr">|</td></tr>
<tr><td class="arr">&darr;</td><td colspan="3" /><td class="arr">|</td></tr>
<tr><td class="box">after</td><td class="arr">&mdash;&mdash;</td><td class="arr">&mdash;&mdash;&mdash;</td>
<td class="arr">&mdash;&mdash;</td><td /></tr>
</table>
<p style="margin-top:0.5em"><b>Figure 1:</b> <i>The action in an AdvSys game is controlled by &ldquo;handlers,&rdquo;
described below.</i></p>
</div>
<h3>Handlers</h3>
<p>All action within an AdvSys adventure is controlled by a set of &ldquo;handler&rdquo; and &ldquo;action&rdquo;
procedures. There are five different handlers that are part of the main control loop. Each of these handlers contains
user-defined code written in the adventure language. Figure 1 illustrates the control flow of the adventure system.</p>
<p>At the beginning of the game, the AdvSys interpreter calls the &ldquo;init&rdquo; handler. The init handler is
responsible for printing any introductory text explaining the initial situation and for performing any initialization.
Here is an example of an init handler definition:</p>
<pre>(init
(print "Welcome to the sample adventure!\n")
(setq curloc nil))</pre>
<p>This example handler prints a welcome message and sets the variable <code>curloc</code> (the current location of
the adventurer) to <code>nil</code>.</p>
<p>The first handler in the main loop is the &ldquo;update&rdquo; handler, which is responsible for handling changes
in the game state. If the player has moved to a new location, the update handler should print a description of the new
location. Here is an example:</p>
<pre>(update
(if (not (= (getp adventurer parent) curloc))
(progn
(setq curloc (getp adventurer parent))
(send curloc describe))))</pre>
<p>This handler checks to see if the adventurer's new location is different from the current one. If it is, the handler
updates the current location and prints a description of the new location by sending the message <code>describe</code>
to the new location object. (Note that on the first pass through the control loop, the update handler sees the location
of the adventurer as being different from that stored in <code>curloc</code> and prints a description of the initial
location.)</p>
<p>After the update handler has finished, the AdvSys interpreter calls the parser. The parser prompts the player for a
new command, allows the player to enter the command, and parses the command according to the description above. The
parser communicates its results to the remaining handlers by setting the global variables <code>$actor</code>,
<code>$action</code>, <code>$dobject</code>, <code>$ndobjects</code>, and <code>$iobject</code>. If an error occurs
during the parsing of the command, the system prints an error message, calls the error handler, and goes back to the
start of the main loop (the update handler).</p>
<p>Assuming that the parser succeeds in parsing a syntactically valid command, the AdvSys interpreter calls the
&ldquo;before&rdquo; handler, which handles any general preprocessing that needs to be done before the command-specific
code is performed.</p>
<p>Next, the action associated with the player's command is performed. This is the action that was stored in the global
variable <code>$action</code> by the parser. This code is responsible for actually carrying out the player's request
(if it is allowed in the current situation).</p>
<p>The last handler in the main loop is the &ldquo;after&rdquo; handler, which handles any processing that must happen
after the action is complete, such as updating the game clock or the player's score, or anything that should happen
only at the end of a successful turn.</p>
<p>The adventure language statements that are used to define handlers are:</p>
<pre>(init expression*)
(update expression*)
(before expression*)
(after expression*)
(error expression*)</pre>
<h3>Actions</h3>
<p>The only part of the adventure system left to describe is the method for defining actions. Each action definition
handles a specific command form and verb/preposition combination. Let's look at an example:</p>
<pre>(action a-take
(verb take get (pick up))
(direct-object)
(code
(setq %dobject (in-location $dobject))
(if (getp %dobject takeable)
(progn
(if (send %actor carrying? %dobject))
(complain "You are already carrying the " $dobject "!\n"))
(send %actor take %dobject)
(print-noun $dobject)
(print " taken.\n"))
(complain "You can't take the " $dobject "!\n"))))</pre>
<p>This action definition handles commands like &ldquo;take the lamp&rdquo; or &ldquo;pick up the sword.&rdquo;
It handles any command with the verbs &ldquo;take,&rdquo; &ldquo;get,&rdquo; or &ldquo;pick up&rdquo; and at least one
direct object. The code begins by determining to which object the direct-object noun phrases refers. The function
<code>in-location</code> looks for an object in the current location (<code>curloc</code>) that matches the noun phrase
it receives as its argument. The function returns the matching object or signals an error if no object in the current
location matches the noun phrase.</p>
<p>Assuming that <code>in-location</code> finds a matching object, the <code>action</code> code assigns that object
to the variable <code>%dobject</code> and then checks to see if it is possible to pick up the object. This is done by
checking the value of the property <code>takeable</code>. If the result is <code>true</code>, the object may be taken.
If not, the program prints an error message and the turn ends.</p>
<p>If the object is takeable, the code then checks to see if the player is already carrying it. It does this by sending
the message <code>carrying?</code> to the <code>actor</code> object. This message checks to see if the object is currently
being carried by the actor receiving the message. Both actor and location objects support the concept of containment.
If the adventurer is already carrying the object, the program prints a message saying so and the action is complete.
If not, the program adds the object to the adventurer's inventory by sending the <code>actor</code> object the
<code>take</code> message and the program prints a message indicating the successful completion of the command.</p>
<p>This example illustrates the use of object-oriented programming techniques in the specification of action code.
AdvSys lets you define &ldquo;methods&rdquo; to handle messages sent to objects. Each message requests that the object
perform some operation. The specific operation that is performed in response to a message is determined by a method
definition associated with the object that receives the message. AdvSys supports hierarchical inheritence of both
properties and methods so you can define classes of objects that share the same property structure and behavior.</p>
<p>The default run-time environment in AdvSys adventures (contained in the file OBJECTS.ADI) defines methods that
implement the default behavior for the built-in object classes. But the power of the system is that it lets you define
subclasses of these default classes that implement either objects or classes of objects whose behavior and properties
are unique to a particular adventure. This allows you to build on the existing classes rather than &ldquo;reinventing
the wheel.&rdquo; The default run-time environment is thus a framework for building an adventure rather than merely
a sample program.</p>
<p>If a command contains multiple direct objects, the parser will store the first direct object noun phrase number in
<code>$dobject</code> and the number of direct objects in <code>$ndobjects</code>. If your action code doesn't touch
the value of <code>$ndobjects</code>, at the end of the after handler, the system will assign the next direct object
ot the variable <code>$dobject</code>, decrement the count stored in <code>$ndobjects</code>, and loop back to the
before handler again. This means that you don't need to do anything special to handle commands with multiple direct
objects. However, if you have a reason to want to handle all of the objects yourself, you can do so on the first pass
through the action code and then set the variable <code>$ndobjects</code> to nil to prevent the system from looping
back to handle the additional direct objects.</p>
<p>The adventure language statements used to define actions are:</p>
<pre>(action name
action-statement*)</pre>
<p>with <code>action-statement</code> defined as one of the following:</p>
<pre>(actor [flag])
(verb [word | (word1 word2)]*)
(direct-object [flag])
(preposition word*)
(indirect-object [flag])
(code expression*)</pre>
<p>and where <code>flag</code> is one of the following:</p>
<pre>required
optional
forbidden</pre>
<h3>Expressions</h3>
<p>Handlers, actions, and methods all contain executable statements called expressions. The complete list of
expressions allowed in AdvSys is shown in table 1. Each of the forms shown computes a result, which is returned as
the value of the expression.</p>
<p>Here is an example of an expression derived from table 1:</p>
<pre>(setq x (+ (* a b) (* c d)))</pre>
<p>This executable statement is an arithmetic expression that multiplies <code>a</code> times <code>b</code> and
<code>c</code> times <code>d</code>, adds the two products, and stores the result in the variable <code>x</code>.
Even the <code>setq</code> form returns a value. Its value is the new value of the variable after the assignment
is done.</p>
<div style="width:100%;border:black solid;border-width:3px 1px;padding:5px;">
<caption><b>Table 1:</b> <i>The executable statements used in actions and handlers to control an adventure
game written with AdvSys.</i></caption>
<table>
<tr><td style="height:0.5em" /></tr>
<tr><td>
<table>
<tr><td>(+ expr1 expr2)</td><td>Add two numbers</td></tr>
<tr><td>(&minus; expr1 expr2)</td><td>Subtract two numbers</td></tr>
<tr><td>(* expr1 expr2)</td><td>Multiply two numbers</td></tr>
<tr><td>(/ expr1 expr2)</td><td>Divide two numbers</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td>(% expr1 expr2)</td><td>Remainder after dividing two numbers</td></tr>
<tr><td>(& expr1 expr2)</td><td>Bit-wise AND of two numbers</td></tr>
<tr><td>(: expr1 expr2)</td><td>Bit-wise OR of two numbers</td></tr>
<tr><td>( expr)</td><td>Bit-wise complement of a number</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td>(&lt; expr1 expr2)</td><td>Is expr1 less than expr2?</td></tr>
<tr><td>(= expr1 expr2)</td><td>Is expr1 equal to expr2?</td></tr>
<tr><td>(&gt; expr1 expr2)</td><td>Is expr1 greater than expr2?</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td>(setq sym value)</td><td>Set the value of a variable</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td>(getp obj prop)</td><td>Get the value of a property</td></tr>
<tr><td>(setp obj prop val)</td><td>Set the value of a property</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td>(and [expr]*)</td><td>Logical AND of a set of expressions</td></tr>
<tr><td>(or [expr]*)</td><td>Logical OR of a set of expressions</td></tr>
<tr><td>(not expr)</td><td>Logical NOT of an expression</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td>(cond [clause]*)</td><td>LISP style conditional</td></tr>
<tr><td>(if expr then-expr [else-expr])</td><td>Traditional &ldquo;IF&rdquo; statement</td></tr>
<tr><td>(while expr [expr]*)</td><td>Traditional &ldquo;WHILE&rdquo; statement</td></tr>
<tr><td>(progn [expr]*)</td><td>Group expressions into a block</td></tr>
<tr><td>(return [expr])</td><td>Return from a function</td></tr>
</table>
</td><td style="vertical-align:top">
<table>
<tr><td>(expr [expr]*)</td><td>Call a user-defined function</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td>(class obj)</td><td>Get the class of an object</td></tr>
<tr><td>(send obj sel [expr]*)</td><td>Send a message to an object</td></tr>
<tr><td>(send-super sel [expr]*)</td><td>Send a message to the superclass of an object</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td>(randomize)</td><td>Initialize the random-number generator</td></tr>
<tr><td>(rand expr)</td><td>Generate a random number between 0 and n-1</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td>(yes-or-no)</td><td>Prompt the user and accept YES or NO</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td>(print expr)</td><td>Print a string</td></tr>
<tr><td>(print-number expr)</td><td>Print a number</td></tr>
<tr><td>(print-noun expr)</td><td>Print a noun phrase</td></tr>
<tr><td>(terpri)</td><td>Start a new print line</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td>(match np obj)</td><td>Does this noun phrase match this object?</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td>(finish)</td><td>Finish this turn (go to the AFTER handler)</td></tr>
<tr><td>(chain)</td><td>Exit this handler and go to the next</td></tr>
<tr><td>(abort)</td><td>Abort this turn (go to the UPDATE handler)</td></tr>
<tr><td>(exit)</td><td>Exit the adventure (back to DOS)</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td>(save)</td><td>Save the current game state to a file</td></tr>
<tr><td>(restore)</td><td>Restore the game state from a file</td></tr>
</table>
</td></tr>
</table>
</div>
<h3>Run-Time Functions</h3>
<p>Not all of the functions that I have used in the examples are listed in table 1. The missing functions are part
of the run-time package OBJECTS.ADI (see table 2) and are not built into the language. These functions are defined
in adventure code and can be changed by the adventure author to suit a variety of tasks.</p>
<p>I wrote the run-time package so that you would not have to start from scratch when writing adventures. The run-time
package defines commonly used object types such as locations, actors, and things; common actions such as look and take;
game control commands like save and restore; and methods for handling common messages. These methods define the default
behavior of objects, but can be easily supplemented or overrideen by methods defined in objects or subclasses defined
by the adventure author. In this way, you can build your adventure game on the basic framework provided by the run-time
package. For example, the run-time package supplies a method for the message <code>leave</code>, which allows an actor
to leave a location.</p>
<div style="width:100%;border:black solid;border-width:3px 1px;padding:5px;">
<caption><b>Table 2:</b> <i>The functions included in the basic run-time package for the AdvSys adventure writing
system, OBJECTS.ADI.</i></caption>
<table cellspacing="0" style="width:100%">
<tr><td style="height:0.5em" /></tr>
<tr><td class="clshdr" colspan="2">BASIC-THING</td>
<td rowspan="37" style="border-right:solid black 1px;width:5px;" />
<td rowspan="37" style="width:5px;" />
<td class="clshdr">THING</td><td class="clshdr">Things that can be taken.</td></tr>
<tr><td colspan="2">superclass:</td><td colspan="2">superclass:</td></tr>
<tr><td class="prop">object</td><td /><td class="prop">basic-thing</td></tr>
<tr><td class="prophdr" colspan="2">properties:</td><td class="prophdr" colspan="2">properties:</td></tr>
<tr><td class="prop">initial-location</td><td>Initial location of the object.</td>
<td class="prop">takeable</td><td>Can the thing be taken? (defaults to T)</td></tr>
<tr><td class="prop">parent</td><td>Current location of the object.</td>
<td class="prophdr" colspan="2">methods:</td>
<tr><td class="prop">sibling</td><td>Next object in the location.</td>
<td class="prop">(none)</td></tr>
<tr><td class="prophdr" colspan="2">methods:</td></tr>
<tr><td class="prop">(none)</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td class="clshdr">ACTOR</td><td class="clshdr">The adventurer or non-player characters.</td>
<td class="clshdr">STATIONARY-THING</td><td class="clshdr">Things that cannot be taken.</td></tr>
<tr><td colspan="2">superclass:</td><td colspan="2">superclass:</td></tr>
<tr><td class="prop">basic-thing</td><td />
<td class="prop">basic-thing</td></tr>
<tr><td class="prophdr" colspan="2">properties:</td>
<td class="prophdr" colspan="2">properties:</td></tr>
<tr><td class="prop">child</td><td>First object carried by the actor.</td>
<td class="prop" rowspan="3" style="vertical-align:top">(takeable)</td>
<td rowspan="3" style="vertical-align:top">Can the thing be taken? (Because this<br />property is missing, GETP will return<br />NIL as its value.)</td></tr>
<tr><td class="prophdr" colspan="2">methods:</td></tr>
<tr><td class="prop">(move dir)</td><td>Move in the specified direction.</td></tr>
<tr><td class="prop">(take obj)</td><td>Take an object.</td>
<td class="prophdr" colspan="2">methods:</td></tr>
<tr><td class="prop">(drop obj)</td><td>Drop an object.</td>
<td class="prop">(none)</td></tr>
<tr><td class="prop">(carrying? obj)</td><td>Is actor carrying the specified object?</td></tr>
<tr><td class="prop">(inventory)</td><td>Show the actor's inventory.</td></tr>
<tr><td style="height:0.5em" /></tr>
<tr><td class="clshdr">PORTAL</td><td class="clshdr">Connections between locations.</td>
<td class="clshdr">LOCATION</td><td class="clshdr">Locations in the adventure.</td></tr>
<tr><td colspan="2">superclass:</td><td colspan="2">superclass:</td></tr>
<tr><td class="prop">basic-thing</td><td />
<td class="prop">object</td></tr>
<tr><td class="prophdr" colspan="2">properties:</td>
<td class="prophdr" colspan="2">properties:</td></tr>
<tr><td class="prop">other-side</td><td>Counterpart in the other location.</td>
<td class="prop">description</td><td>Long description.</td></tr>
<tr><td class="prop">closed</td><td>Is it closed?</td>
<td class="prop">short-description</td><td>Short description.</td></tr>
<tr><td class="prop">locked</td><td>Is it locked?</td>
<td class="prop">visited</td><td>Has the player been here?</td></tr>
<tr><td class="prop">key</td><td>Key to lock and unlock.</td>
<td class="prop">child</td><td>First object in this location.</td></tr>
<tr><td class="prophdr" colspan="2">methods:</td>
<td class="prop">(exit directions)</td><td>Exits.</td></tr>
<tr><td class="prop">(knock? obj)</td><td>Can this object enter?</td>
<td class="prophdr" colspan="2">methods:</td></tr>
<tr><td class="prop">(enter obj)</td><td>Cause this object to enter the location.</td>
<td class="prop">(knock? obj)</td><td>Can this object enter?</td></tr>
<tr><td class="prop">(open)</td><td>Open the portal.</td>
<td class="prop">(enter obj)</td><td>Cause this object to enter the location.</td></tr>
<tr><td class="prop">(close)</td><td>Close the portal.</td>
<td class="prop">(leave obj dir)</td><td>Leave in the specified direction.</td></tr>
<tr><td class="prop">(lock key)</td><td>Lock the portal.</td>
<td class="prop">(describe)</td><td>Describe the location.</td></tr>
<tr><td class="prop">(unlock key)</td><td>Unlock the portal.</td></tr>
</table>
</div>
<h3>Associated Definitions</h3>
<p>The following method definition could be associated with a particular location and would require the actor
to be carrying the &ldquo;rusty key&rdquo; in order to leave the location:</p>
<pre>(method (leave obj dir)
(if (send obj carrying? rusty-key)
(send-super leave obj dir)
(print "You seem to be missing
something!\n")))</pre>
<p>This example also illustrates the use of the <code>send-super</code> form. Send-super passes a message to the parent
(or super) class of the current object. This definition says that if the actor (the value of <code>obj</code>) is
carrying the rusty key, the <code>leave</code> message should be handled normally. If not, the program prints a message
and the action is aborted.</p>
<p>The adventure language statements used to define constants, functions, variables, and property-names are:</p>
<pre>(define symbol value)
(define (function-name symbol*) expression*)
(variable symbol*)
(property symbol*)</pre>
<h3>Summary</h3>
<p>AdvSys is a tool for writing adventure games, much as a word processor is a tool for writing novels. It is not
a substitute for good creative writing, but a tool for the writer. I hope the availability of this system will
inspire potential adventure authors to write adventure games and share them with the rest of us. (See the
article &ldquo;Interactive Fiction as Literature,&rdquo; which begins on <a href="byte87_buckles.html">this page</a>.)
<span style="font-family:Webdings">&#x3C;</span></p>
<p style="margin-top:2em">Editor's note: <i>The source code for AdvSys, the adventure game writing system,
was written in C and includes the following files: ADVCOM, the adventure game compiler;
ADVINT, the adventure game interpreter; OBJECTS.ADI, a run-time package containing the basic definitions
needed for a game; and the AdvSys documentation.</i></p>
<p><i>The files are available on disk, in print, and on BIX. See the insert card following page 324 for details.
Listings are also available on BTYEnet. See page 4. In order to run the programs, you will need a C compiler
appropriate for your computer system.</i></p>
<hr style="margin-bottom:0" />
<p style="margin-top:0.25em"><i>David Betz is a BIX senior editor. He can be reached at BIX, One Phoenix Mill Lane,
Peterborough, NH 03458.</i></p>
<p style="text-align:right"><small>MAY 1987 &nbsp;&bull;&nbsp; B Y T E &nbsp;&nbsp;&nbsp; <b>125&ndash;135</b></small></p>
</body>
</html>

Xet Storage Details

Size:
36.2 kB
·
Xet hash:
647f71a8b68ff52b243c3bd7b636c347e796af690392d9888b82d8f4e3c797c5

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.