1
<HTML><HEAD><TITLE>Section 2: The language of data structures</TITLE></HEAD>
2
<BODY BGCOLOR="#FFFFFF">
4
<TR><TD Valign="top"><A HREF="contents.html">Contents</A><BR><A HREF="section1.html">Back</A><BR><A HREF="section3.html">Forward</A><TD bgcolor="#F5DEB3"><BLOCKQUOTE><H3>2. The language of data structures</H3></BLOCKQUOTE><TR><TD><TD>
9
<HR><BLOCKQUOTE><H3>2.1. Directives and constants</H3></BLOCKQUOTE><P>
10
Every example program so far has consisted only of a sequence of
11
routines, each within beginning and end markers <TT>[</TT> and <TT>]</TT>. Such routines
12
have no way of communicating with each other, and therefore of sharing
13
information with each other, except by making function calls back and forth.
14
This arrangement is not really suited to a large program whose task may be
15
to simulate something complicated (such as the world of an adventure game):
16
it would be useful to have some kind of central registry of information
17
which all routines have access to, as and when needed.
20
Information available to all routines in this way is said to be "global'',
21
rather than "local'' to any one routine. (As will appear in <A HREF="section3.html">Section 3</A>, there is
22
also an intermediate possibility where information is available only to a
23
cluster of routines working on roughly the same part of a program.)
26
This global information can be organised in a variety of ways. Such organised
27
groups are called "data structures''. For example, a typical data structure
28
might be a list of 10 values. The term "data structure'' did not appear in
29
<A HREF="section1.html">Section 1</A> because information was only ever held in variables, the simplest possible
30
kind of structure (one value on its own).
33
Data structures are added to Inform programs using commands called "directives''
34
in between definitions of routines. It's important to distinguish between
35
these, which direct Inform to do something now (usually, to create something)
36
and the statements which occur inside routines, which are merely translated in
37
some way but not acted on until the program has finished being compiled and is
41
In fact, one directive has already appeared: the one written <TT>[</TT>, which means
42
"translate the following routine up to the next <TT>]</TT>''. In all there are
43
38 Inform directives, as follows:
45
Abbreviate Array Attribute Class Constant Default
46
Dictionary End Endif Extend Fake_action Global
47
Ifdef Ifndef Ifnot Ifv3 Ifv5 Iftrue
48
Iffalse Import Include Link Lowstring Message
49
Nearby Object Property Release Replace Serial
50
Switches Statusline Stub System_file Trace Verb
54
Several of these are rather technical and will not be used by many
55
programmers (such as <TT>Trace</TT>, <TT>Stub</TT>, <TT>Default</TT>, <TT>System_file</TT>, <TT>Abbreviate</TT>,
56
<TT>Dictionary</TT>). Others control fine points of what is compiled and what isn't
57
(<TT>Ifdef</TT>, <TT>Ifnot</TT>, and so on; <TT>Message</TT>, <TT>Replace</TT>). These not-very important
58
directives are covered in Chapter II.
61
This leaves 9 central directives for creating data structures, and these are
62
the ones which it is important to know about:
64
Array Attribute Class Constant Extend Global
68
It is conventional to write these with the initial letter capitalised: this
69
makes directives look unlike statements. <TT>Attribute</TT>, <TT>Class</TT>, <TT>Object</TT> and
70
<TT>Property</TT> are the subject of <A HREF="section3.html">Section 3</A>.
74
The simplest directive with a "global'' effect on the program -- an effect
75
all over the program, that is, not just in one routine -- is <TT>Constant</TT>.
76
The following program, an unsatisfying game of chance, shows a typical use
79
Constant MAXIMUM_SCORE = 100;
82
print "You have scored ", random(MAXIMUM_SCORE),
83
" points out of ", MAXIMUM_SCORE, ".^";
87
The maximum score value is used twice in the routine <TT>Main</TT>. Of course the
88
program is the same as it would have been if the constant definition were not
89
present, and <TT>MAXIMUM_SCORE</TT> were replaced by 100 in both places where it
90
occurs. The advantage of using <TT>Constant</TT> is that it makes it possible to
91
change this value from 100 to, say, 50 with only a single change, and it
92
makes the source code more legible to the reader by explaining what the
93
significance of the number 100 is supposed to be.
96
If no value is specified for a constant, as in the line
101
then the constant is created with value 0.
104
<HR><BLOCKQUOTE><H3>2.2. Global variables</H3></BLOCKQUOTE><P>
105
As commented above, so far the only variables allowed have been "local
106
variables'', each private to their own routines. A "global variable'' is a
107
variable which is accessible to all code in every routine. Once a global
108
variable has been declared, it is used in just the same way as a local
109
variable. The directive for declaring a global variable is <TT>Global</TT>:
114
This creates a variable called <TT>score</TT>, which at the start of the program has
115
the value 36. <TT>score</TT> can be altered or used anywhere in the program after
116
the line on which it is defined.
119
<HR><BLOCKQUOTE><H3>2.3. Arrays</H3></BLOCKQUOTE><P>
120
An "array'' is an indexed collection of (global) variables, holding a set of
121
numbers organised into a sequence. It allows general rules to be given for
122
how a group of variables should be treated. For instance, the directive
124
Array pack_of_cards --> 52;
127
creates a stock of 52 variables, referred to in the program as
129
pack_of_cards-->0 pack_of_cards-->1 ... pack_of_cards-->51
132
There are two basic kinds of array: "word arrays'' (written using <TT>--></TT> as
133
above) and "byte arrays'' (written using <TT>-></TT> similarly). Whereas the
134
entries of a word array can hold any number, the entries of a byte array can
135
only be numbers in the range 0 to 255 inclusive. (The only advantage of this is
136
that it is more economical on memory, and beginners are advised to use word
140
In addition to this, Inform provides arrays which have a little extra
141
structure: they are created with the 0th entry holding the number of entries.
142
A word array with this property is called a <TT>table</TT>; a byte array with this
143
property is a <TT>string</TT>.
146
For example, the array defined by
148
Array continents table 5;
151
has six entries: <TT>continents-->0</TT>, which holds the number 5, and five more
152
entries, indexed 1 to 5. (The program is free to change <TT>continents-->0</TT>
153
later but this will not change the size: the size of an array can never change.)
154
As an example of using <TT>string</TT> arrays:
156
Array password string "DANGER";
157
Array phone_number string "1978-345-2160";
159
PrintString(password);
161
PrintString(phone_number);
163
[ PrintString the_array i;
164
for (i=1: i<=the_array->0: i++)
165
print (char) the_array->i;
169
The advantage of <TT>string</TT> arrays, then, is that one can write a general routine
170
like <TT>PrintString</TT> which works for arrays of any size.
173
To recapitulate, Inform provides four kinds of array in all:
175
--> -> table string
178
There are also four different ways to set up an array with its initial contents
179
(so the directive can take 16 forms in all). In all of the examples above,
180
the array entries will all contain 0 when the program begins.
183
Instead, we can give a list of constant values. For example,
185
Array primes --> 2 3 5 7 11 13;
188
is a word array created with six entries, <TT>primes-->0</TT> to <TT>primes-->5</TT>,
189
initially holding the values 2 to 13.
192
The third way to create an array gives some text as an initial value (because
193
one common use for arrays is as "strings of characters'' or
194
"text buffers''). The two string arrays above were set up this way.
197
Array players_name -> "Frank Booth";
200
sets up the byte array <TT>players_name</TT> as if the directive had been
202
Array players_name -> 'F' 'r' 'a' 'n' 'k' ' ' 'B' 'o' 'o' 't' 'h';
206
<P><TR><TD Valign="top"><IMG SRC="icons/ddbend.gif" ALT="/\/\"><TD bgcolor="#EEEEEE"><SMALL> The fourth way to create an array is obsolete and is kept
207
only so that old programs still work. This is to give a list of values in
208
between end-markers <TT>[</TT> and <TT>]</TT>, separated by commas or semi-colons. Please
209
don't use this any longer.
213
<P><TR><TD Valign="top"><IMG SRC="icons/warning.gif" ALT="!!"><TD><B>WARNING:</B><BR>
214
It is up to the programmer to see that no attempt is made
215
to read or write non-existent entries of an array. (For instance,
216
<TT>pack_of_cards-->1000</TT>.) Such mistakes are notorious for causing programs
217
to fail in unpredictable ways, difficult to diagnose. Here for example is
218
an erroneous program:
220
Array ten --> 10;
221
Array fives --> 5 10 15 20 25;
223
for (n=1: n<=10: n++) ten-->n = -1;
224
print fives-->0, "^";
228
This program ought to print 5 (since that's the <I>0</I>-th entry in the array
229
<TT>fives</TT>), but in fact it prints -1. The problem is that the entries of <TT>ten</TT>
230
are <TT>ten-->0</TT> up to <TT>ten-->9</TT>, not (as the program implicitly assumes)
231
<TT>ten-->1</TT> to <TT>ten-->10</TT>. So the value -1 was written to <TT>ten-->10</TT>, an entry
232
which does not exist. At this point anything could have happened. As it
233
turned out, the value was written into the initial entry of the next array
234
along, "corrupting'' the data there.
237
<HR><BLOCKQUOTE><H3>2.4. Example 7: Shuffling a pack of cards</H3></BLOCKQUOTE><P>
238
This program simulates the shuffling of a pack of playing cards.
239
The cards are represented by numbers in the range 0 (the Ace of Hearts) to 51
240
(the King of Spades). The pack itself has 52 positions, from position 0 (on
241
the top) to position 51 (on the bottom). It is therefore represented by the
244
pack_of_cards-->i
247
whose <TT>i</TT>-th entry is the card number at position <TT>i</TT>. A new pack as produced
248
by the factory, still in order, would therefore be represented with card <TT>i</TT> in
249
position <TT>i</TT>: the pack would have the Ace of Hearts on top and the King of
250
Spades on the bottom.
252
Constant SHUFFLES = 100;
253
Array pack_of_cards --> 52;
257
! Initially x and y are both zero
260
{ x = random(52) - 1; y = random(52) - 1;
263
! x and y are now randomly selected, different numbers
264
! in the range 0 to 51
266
z = pack_of_cards-->x;
267
pack_of_cards-->x = pack_of_cards-->y;
268
pack_of_cards-->y = z;
274
1 to 9: print n%13 + 1;
289
! Create the pack in "factory order":
290
for (i=0:i<52:i++) pack_of_cards-->i = i;
291
! Exchange random pairs of cards for a while:
292
for (i=0:i<SHUFFLES:i++) ExchangeTwo();
293
print "The pack has been shuffled to contain:^";
294
for (i=0:i<52:i++)
295
print (Card) pack_of_cards-->i, "^";
299
Note the use of a "printing rule'' called <TT>Card</TT> to describe card number <TT>i</TT>.
300
Note also that 100 exchanges of pairs of cards is only just enough to make
301
the pack appear well shuffled. Redefining <TT>SHUFFLES</TT> as 10000 makes the
302
program take longer; redefining it as 10 makes the result very suspect.
305
<P><TR><TD Valign="top"><IMG SRC="icons/dbend.gif" ALT="/\"><TD bgcolor="#EEEEEE"><SMALL> The example code shuffles the pack in a simple way, but
306
there are more efficient methods. Here's one supplied
307
by Dylan Thurston, giving perfect randomness in 51 exchanges.
309
pack_of_cards-->0 = 0;
310
for (i=1:i<52:i++)
311
{ j = random(i+1) - 1;
312
pack_of_cards-->i = pack_of_cards-->j; pack_of_cards-->j = i;
318
<HR><BLOCKQUOTE><H3>2.5. Seven special data structures</H3></BLOCKQUOTE><P>
320
<P><TR><TD Valign="top"><IMG SRC="icons/dbend.gif" ALT="/\"><TD bgcolor="#EEEEEE"><SMALL> All Inform programs automatically contain seven special
321
data structures, each being one of a kind: the object tree, the grammar,
322
the table of actions, the release number, the serial code,
323
the "statusline flag'' and the dictionary. These data structures are
324
tailor-made for adventure games and (except for the object tree) can
325
be ignored for every other kind of program. So they are mostly covered in
330
<TR><TD><TD bgcolor="#EEEEEE"><SMALL><P>
331
<P>1. -- For the object tree (and the directives <TT>Object</TT> and <TT>Class</TT>),
332
see <A HREF="section3.html">Section 3</A>.
333
<P>2. -- For grammar (and the directives <TT>Verb</TT> and <TT>Extend</TT>), see Chapter V,
334
<A HREF="section26.html">Section 26</A> and <A HREF="section27.html">Section 27</A>.
335
<P>3. -- For actions (and the <TT><...></TT> and <TT><<...>></TT> statements and the <TT>##</TT>
336
constant notation), see Chapter III, <A HREF="section9.html">Section 9</A>.
337
<P>4. -- The release number (which is printed automatically by the
338
library in an Inform-written adventure game) is 1 unless otherwise specified.
341
Release <number>;
344
<P> -- does this. Conventionally release 1 would be the first
345
published copy, and releases 2, 3, ... would be amended re-releases.
346
See Chapter III, <A HREF="section7.html">Section 7</A>, for an example.
347
<P>5. -- The serial number is set automatically to the date of compilation
348
in the form 960822 ("22nd August 1996''). This can be overridden if desired
354
<P> -- where the text must be a string of 6 digits.
355
<P>6. -- The "status line flag'' chooses between styles of "status line''
356
at the top of an adventure game's screen display. See Chapter IV, <A HREF="section18.html">Section 18</A>,
357
for use of the <TT>Statusline</TT> directive.
358
<P>7. -- The dictionary is automatically built by Inform. It is a stock
359
of all the English words which the game might want to recognise from what
360
the player has typed: it includes any words written in constants like
361
<TT>'duckling'</TT>, as well as any words given in <TT>name</TT> values or in grammar.
364
if (first_word == 'herring') print "You typed the word herring!";
367
<P> -- is a legal statement. Inform notices that <TT>herring</TT> -- because it is in
368
single quotes -- is a word the program may one day need to be able to
369
recognise, so it adds the word to the dictionary.
370
Note that the constant <TT>'herring'</TT> is a dictionary word but the constant <TT>'h'</TT>
371
is the ASCII value of lower-case H. (Single-letter dictionary words are seldom
372
needed, but can be written using an ugly syntax if need be: <TT>#n$h</TT> is the
373
constant meaning "the dictionary word consisting only of the letter H''.)
376
<P><TR><TD Valign="top"><IMG SRC="icons/ddbend.gif" ALT="/\/\"><TD bgcolor="#EEEEEE"><SMALL>
377
From this description, the dictionary appears to be something into which
378
words are poured, never to re-emerge. The benefit is felt when the <TT>read</TT>
379
statement comes to try to parse some input text:
381
read text_array parse_buffer;
384
It must be emphasized that the <TT>read</TT> statement performs only the simplest
385
possible form of parsing, and should not be confused with the very much more
386
elaborate parser included in the Inform library.
390
<TR><TD><TD bgcolor="#EEEEEE"><SMALL>
391
What it does is to break down the line of input text into a sequence of
392
words, in which commas and full stops count as separate words in their own
393
right. (An example is given in Chapter V, <A HREF="section24.html">Section 24</A>.) Before using <TT>read</TT>,
399
should be set to the maximum number of words which parsing is wanted for.
400
(Any further words will be ignored.) The number of words actually parsed
401
from the text is written in
406
and a block of data is written into the array for each of these words:
408
parse_buffer-->(n*2 - 1)
411
holds the dictionary value of the <TT>n</TT>-th word (if <TT>n</TT> counts 1, 2, 3, ...). If
412
the word isn't in the dictionary, this value is zero.
417
parse_buffer->(n*4)
418
parse_buffer->(n*4 + 1)
421
are set to the number of letters in word <TT>n</TT>, and the offset of word <TT>n</TT> in the
427
[ PleaseTypeYesOrNo i;
429
{ buffer->0 = 60;
431
print "Please type ~yes~ or ~no~> ";
433
if (parse-->1 == 'yes') rtrue;
434
if (parse-->1 == 'no') rfalse;
444
<HR><A HREF="contents.html">Contents</A> / <A HREF="section1.html">Back</A> / <A HREF="section3.html">Forward</A> <BR>
445
<A HREF="chapter1.html">Chapter I</A> / <A HREF="chapter2.html">Chapter II</A> / <A HREF="chapter3.html">Chapter III</A> / <A HREF="chapter4.html">Chapter IV</A> / <A HREF="chapter5.html">Chapter V</A> / <A HREF="chapter6.html">Chapter VI</A> / <A HREF="chapterA.html">Appendix</A><HR><SMALL><I>Mechanically translated to HTML from third edition as revised 16 May 1997. Copyright © Graham Nelson 1993, 1994, 1995, 1996, 1997: all rights reserved.</I></SMALL></BODY></HTML>