~ubuntu-branches/ubuntu/vivid/inform/vivid

« back to all changes in this revision

Viewing changes to html/section2.html

  • Committer: Bazaar Package Importer
  • Author(s): Jan Christoph Nordholz
  • Date: 2008-05-26 22:09:44 UTC
  • mfrom: (2.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080526220944-ba7phz0d1k4vo7wx
Tags: 6.31.1+dfsg-1
* Remove a considerable number of files from the package
  due to unacceptable licensing terms.
* Repair library symlinks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<HTML><HEAD><TITLE>Section 2: The language of data structures</TITLE></HEAD>
2
 
<BODY BGCOLOR="#FFFFFF">
3
 
<TABLE><P>
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>
5
 
<P>
6
 
 
7
 
<P>
8
 
 
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.
18
 
<P>
19
 
 
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.)
24
 
<P>
25
 
 
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).
31
 
<P>
32
 
 
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
38
 
run.
39
 
<P>
40
 
 
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:
44
 
<PRE>
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        
51
 
Version     [
52
 
</PRE>
53
 
 
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.
59
 
<P>
60
 
 
61
 
This leaves 9 central directives for creating data structures, and these are
62
 
the ones which it is important to know about:
63
 
<PRE>
64
 
Array       Attribute   Class      Constant     Extend       Global
65
 
Object      Property    Verb
66
 
</PRE>
67
 
 
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>.
71
 
<P>
72
 
 
73
 
<P>
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
77
 
of <TT>Constant</TT>.
78
 
<PRE>
79
 
    Constant MAXIMUM_SCORE = 100;
80
 
 
81
 
    [ Main;
82
 
      print "You have scored ", random(MAXIMUM_SCORE),
83
 
      " points out of ", MAXIMUM_SCORE, ".^";
84
 
    ];
85
 
</PRE>
86
 
 
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.
94
 
<P>
95
 
 
96
 
If no value is specified for a constant, as in the line
97
 
<PRE>
98
 
    Constant DEBUG;
99
 
</PRE>
100
 
 
101
 
then the constant is created with value 0.
102
 
<P>
103
 
 
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>:
110
 
<PRE>
111
 
    Global score = 36;
112
 
</PRE>
113
 
 
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.
117
 
<P>
118
 
 
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
123
 
<PRE>
124
 
    Array pack_of_cards --&#62; 52;
125
 
</PRE>
126
 
 
127
 
creates a stock of 52 variables, referred to in the program as
128
 
<PRE>
129
 
    pack_of_cards--&#62;0   pack_of_cards--&#62;1   ...   pack_of_cards--&#62;51
130
 
</PRE>
131
 
 
132
 
There are two basic kinds of array: "word arrays'' (written using <TT>--&#62;</TT> as
133
 
above) and "byte arrays'' (written using <TT>-&#62;</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
137
 
arrays instead.)
138
 
<P>
139
 
 
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>.
144
 
<P>
145
 
 
146
 
For example, the array defined by
147
 
<PRE>
148
 
    Array continents table 5;
149
 
</PRE>
150
 
 
151
 
has six entries: <TT>continents--&#62;0</TT>, which holds the number 5, and five more
152
 
entries, indexed 1 to 5.  (The program is free to change <TT>continents--&#62;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:
155
 
<PRE>
156
 
    Array password string "DANGER";
157
 
    Array phone_number string "1978-345-2160";
158
 
    ...
159
 
    PrintString(password);
160
 
    ...
161
 
    PrintString(phone_number);
162
 
    ...
163
 
    [ PrintString the_array i;
164
 
        for (i=1: i&#60;=the_array-&#62;0: i++)
165
 
            print (char) the_array-&#62;i;
166
 
    ];
167
 
</PRE>
168
 
 
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.
171
 
<P>
172
 
 
173
 
To recapitulate, Inform provides four kinds of array in all:
174
 
<PRE>
175
 
    --&#62;   -&#62;   table   string
176
 
</PRE>
177
 
 
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.
181
 
<P>
182
 
 
183
 
Instead, we can give a list of constant values.  For example,
184
 
<PRE>
185
 
    Array primes --&#62; 2 3 5 7 11 13;
186
 
</PRE>
187
 
 
188
 
is a word array created with six entries, <TT>primes--&#62;0</TT> to <TT>primes--&#62;5</TT>,
189
 
initially holding the values 2 to 13.
190
 
<P>
191
 
 
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.
195
 
As another example,
196
 
<PRE>
197
 
    Array players_name -&#62; "Frank Booth";
198
 
</PRE>
199
 
 
200
 
sets up the byte array <TT>players_name</TT> as if the directive had been
201
 
<PRE>
202
 
    Array players_name -&#62; 'F' 'r' 'a' 'n' 'k' ' ' 'B' 'o' 'o' 't' 'h';
203
 
</PRE>
204
 
<P>
205
 
 
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.
210
 
</SMALL>
211
 
<TR><TD><TD><P>
212
 
 
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--&#62;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:
219
 
<PRE>
220
 
    Array ten --&#62; 10;
221
 
    Array fives --&#62; 5 10 15 20 25;
222
 
    [ Main n;
223
 
      for (n=1: n&#60;=10: n++) ten--&#62;n = -1;
224
 
      print fives--&#62;0, "^";
225
 
    ];
226
 
</PRE>
227
 
 
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--&#62;0</TT> up to <TT>ten--&#62;9</TT>, not (as the program implicitly assumes)
231
 
<TT>ten--&#62;1</TT> to <TT>ten--&#62;10</TT>.  So the value -1 was written to <TT>ten--&#62;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.
235
 
<P>
236
 
 
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
242
 
array
243
 
<PRE>
244
 
    pack_of_cards--&#62;i
245
 
</PRE>
246
 
 
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.
251
 
<PRE>
252
 
    Constant SHUFFLES = 100;
253
 
    Array pack_of_cards --&#62; 52;
254
 
 
255
 
    [ ExchangeTwo x y z;
256
 
 
257
 
      !   Initially x and y are both zero
258
 
 
259
 
      while (x==y)
260
 
      {   x = random(52) - 1; y = random(52) - 1;
261
 
      }
262
 
 
263
 
      !   x and y are now randomly selected, different numbers
264
 
      !   in the range 0 to 51
265
 
 
266
 
      z = pack_of_cards--&#62;x;
267
 
      pack_of_cards--&#62;x = pack_of_cards--&#62;y;
268
 
      pack_of_cards--&#62;y = z;
269
 
    ];
270
 
 
271
 
    [ Card n;
272
 
      switch(n%13)
273
 
      {   0: print "Ace";
274
 
          1 to 9: print n%13 + 1;
275
 
          10: print "Jack";
276
 
          11: print "Queen";
277
 
          12: print "King";
278
 
      }
279
 
      print " of ";
280
 
      switch(n/13)
281
 
      {   0: print "Hearts";
282
 
          1: print "Clubs";
283
 
          2: print "Diamonds";
284
 
          3: print "Spades";
285
 
      }
286
 
    ];
287
 
 
288
 
    [ Main i;
289
 
      !   Create the pack in "factory order":
290
 
      for (i=0:i&#60;52:i++) pack_of_cards--&#62;i = i;
291
 
      !   Exchange random pairs of cards for a while:
292
 
      for (i=0:i&#60;SHUFFLES:i++) ExchangeTwo();
293
 
      print "The pack has been shuffled to contain:^";
294
 
      for (i=0:i&#60;52:i++)
295
 
          print (Card) pack_of_cards--&#62;i, "^";
296
 
    ];
297
 
</PRE>
298
 
 
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.
303
 
<P>
304
 
 
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.
308
 
<PRE>
309
 
        pack_of_cards--&#62;0 = 0;
310
 
        for (i=1:i&#60;52:i++) 
311
 
        {   j = random(i+1) - 1;
312
 
            pack_of_cards--&#62;i = pack_of_cards--&#62;j; pack_of_cards--&#62;j = i;
313
 
        }
314
 
</PRE>
315
 
</SMALL>
316
 
<TR><TD><TD><P>
317
 
 
318
 
<HR><BLOCKQUOTE><H3>2.5. Seven special data structures</H3></BLOCKQUOTE><P>
319
 
 
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
326
 
Book Two.
327
 
</SMALL>
328
 
<TR><TD><TD><P>
329
 
 
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>&#60;...&#62;</TT> and <TT>&#60;&#60;...&#62;&#62;</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.
339
 
The directive
340
 
<PRE>
341
 
    Release &#60;number&#62;;
342
 
</PRE>
343
 
 
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
349
 
with the directive
350
 
<PRE>
351
 
    Serial "dddddd";
352
 
</PRE>
353
 
 
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.
362
 
For example
363
 
<PRE>
364
 
    if (first_word == 'herring') print "You typed the word herring!";
365
 
</PRE>
366
 
 
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''.)
374
 
<P>
375
 
 
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:
380
 
<PRE>
381
 
    read text_array parse_buffer;
382
 
</PRE>
383
 
 
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.
387
 
</SMALL>
388
 
<TR><TD><TD><P>
389
 
 
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>,
394
 
the entry
395
 
<PRE>
396
 
    parse_buffer-&#62;0
397
 
</PRE>
398
 
 
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
402
 
<PRE>
403
 
    parse_buffer-&#62;1
404
 
</PRE>
405
 
 
406
 
and a block of data is written into the array for each of these words:
407
 
<PRE>
408
 
    parse_buffer--&#62;(n*2 - 1)
409
 
</PRE>
410
 
 
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.
413
 
<P>
414
 
 
415
 
(In addition,
416
 
<PRE>
417
 
    parse_buffer-&#62;(n*4)
418
 
    parse_buffer-&#62;(n*4 + 1)
419
 
</PRE>
420
 
 
421
 
are set to the number of letters in word <TT>n</TT>, and the offset of word <TT>n</TT> in the
422
 
text array.)
423
 
<P>
424
 
 
425
 
For example,
426
 
<PRE>
427
 
    [ PleaseTypeYesOrNo i;
428
 
      for (::)
429
 
      {   buffer-&#62;0 = 60;
430
 
          parse-&#62;0 = 1;
431
 
          print "Please type ~yes~ or ~no~&#62; ";
432
 
          read buffer parse;
433
 
          if (parse--&#62;1 == 'yes') rtrue;
434
 
          if (parse--&#62;1 == 'no')  rfalse;
435
 
      }
436
 
    ];
437
 
</PRE>
438
 
 
439
 
</SMALL><TR><TD><TD>
440
 
<P>
441
 
 
442
 
 
443
 
</TABLE>
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 &#169; Graham Nelson 1993, 1994, 1995, 1996, 1997: all rights reserved.</I></SMALL></BODY></HTML>