1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
4
<title>DM4 §2: The state of play</title>
5
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
6
<link rel="stylesheet" type="text/css" href="dm4.css">
10
<a href="index.html">home</a> /
11
<a href="contents.html">contents</a> /
12
<a href="ch1.html" title="Chapter I: The Inform Language">chapter I</a> /
13
<a href="s1.html" title="§1: Routines">prev</a> /
14
<a href="s3.html" title="§3: Objects and classes">next</a> /
15
<a href="dm4index.html">index</a>
18
<a id="p48" name="p48"></a>
19
<h2>§2 The state of play</h2>
21
<a id="s2_1" name="s2_1"></a>
22
<h3>§2.1 Directives construct things</h3>
24
<p class="normal"><span class="atleft"><img src="dm4-048_1.jpg" alt=""></span>
25
Every example program so far has consisted only of
26
a sequence of routines, each within beginning and end markers <code>[</code>
27
and <code>]</code>. Such routines have no way of communicating with each
28
other, and therefore of sharing information with each other, except by
29
calling each other back and forth. This arrangement is not really suited
30
to a large program whose task may be to simulate something complicated,
31
such as the world of an adventure game: instead, some central registry
32
of information is needed, to which all routines can have access.
33
In the author's game ‘Curses’, centrally-held
34
information ranges from the current score, held in a single variable
35
called <code>score</code>, to Madame Sosostris's tarot pack, which
36
uses an array of variables representing the cards on the pack, to a
37
slide-projector held as an “object”: a bundle of variables
38
and routines encoding the relevant rules of the game, such as that
39
the whitewashed wall is only lit up when the slide projector is
42
<p class="indent">Every Inform source program is a list of constructions,
43
made using commands called “directives”. These are quite
44
different from the statements inside routines, because directives create
45
something at compilation time, whereas statements are only instructions
46
for the interpreter to follow later, when the story file is being
49
<p class="indent">In all there are 38 Inform directives, but most of
50
them are seldom used, or else are just conveniences to help you organise
51
your source code: for instance <code>Include</code> means “now
52
include another whole file of source code here”, and there
53
are directives for “if I've set some constant at the start of
54
the code, then don't compile this next bit” and so on. The 10
55
directives that matter are the ones creating data structures, and
58
<p class="lynxonly"></p>
60
[ Array Attribute Class Constant
61
Extend Global Object Property Verb
64
<p class="normal">The directive written <code>[</code>, meaning
65
“construct a routine containing the following statements,
66
up to the next <code>]</code>”, was the subject of
67
<a href="s1.html">§1</a>. The four directives to do
68
with objects, <code>Attribute</code>, <code>Class</code>,
69
<code>Object</code> and <code>Property</code>, will be the subject of
70
<a id="p49" name="p49"></a>
71
<a href="s3.html">§3</a>. The two directives to do with laying
72
out grammar, <code>Verb</code> and <code>Extend</code>, are intimately
73
tied up with the needs of adventure games using the Inform library,
74
and are useless for any other purpose, so these are left until
75
<a href="s30.html">§30</a>. That leaves just <code>Array</code>,
76
<code>Constant</code> and <code>Global</code>.</p>
78
<a id="s2_2" name="s2_2"></a>
79
<h3>§2.2 Constants</h3>
81
<p class="normal">The simplest construction you can make is of
82
a <code>Constant</code>. The following program, an unsatisfying
83
game of chance, shows a typical usage:</p>
85
<p class="lynxonly"></p>
87
Constant MAXIMUM_SCORE = 100;
90
print "You have scored ", random(MAXIMUM_SCORE),
91
" points out of ", MAXIMUM_SCORE, ".^";
95
<p class="normal">The maximum score value is used twice in the routine
96
<code>Main</code>. The resulting story file is exactly the same as it
97
would have been if the constant definition were not present, and
98
<code>MAXIMUM_SCORE</code> were replaced by 100 in both places
99
where it occurs. But the advantage of using <code>Constant</code> is
100
that it makes it possible to change this value from 100 to, say, 50
101
with only a single change to the source code, and it makes the source
102
code more legible.</p>
104
<p class="indent">People often write the names of constants in full
105
capitals, but this is not compulsory. Another convention is that the
106
<code>=</code> sign, which is optional, is often left out if the
107
value is a piece of text rather than a number. If no value is specified
108
for a constant, as in the line</p>
110
<p class="lynxonly"></p>
111
<pre class="code">Constant BETA_TEST_VERSION;</pre>
113
<p class="normal">then the constant is created with value 0.</p>
115
<p class="indent">A constant can be used from anywhere in the source
116
code after the line on which it is declared. Its value cannot be
119
<a id="s2_3" name="s2_3"></a>
120
<h3>§2.3 Global variables</h3>
122
<p class="normal">The variables in <a href="s1.html">§1</a>
123
were all “local variables”, each owned privately by its
124
own routine, inaccessible to the rest of the program and destroyed as
125
soon as the routine stops. A “global variable” is permanent
126
and its value can be used or altered from every routine.</p>
128
<a id="p50" name="p50"></a>
129
<p class="indent">The directive for declaring a global variable is
130
<code>Global</code>. For example:</p>
132
<p class="lynxonly"></p>
133
<pre class="code">Global score = 36;</pre>
135
<p class="normal">This creates a variable called <code>score</code>, which
136
at the start of the program has the value 36. (If no initial value
137
is given, it starts with the value 0.)</p>
139
<p class="indent">A global variable can be altered or used from anywhere in the source
140
code <em>after</em> the line on which it is declared.</p>
142
<a id="s2_4" name="s2_4"></a>
143
<h3>§2.4 Arrays</h3>
145
<p class="normal">An “array” is an indexed collection of
146
variables, holding a set of numbers organised into a sequence. To
147
see why this useful, suppose that a pack of cards is to be simulated.
148
You could define 52 different variables with <code>Global</code>, with
149
names like <code>Ace_of_Hearts</code>, to hold the position of each
150
card in the pack: but then it would be very tiresome to write a routine
151
to shuffle them around.</p>
153
<p class="indent">Instead, you can declare an array:</p>
155
<p class="lynxonly"></p>
156
<pre class="code">Array pack_of_cards --> 52;</pre>
158
<p class="normal">which creates a stock of 52 variables, called the
159
“entries” of the array, and referred to in the source
162
<p class="lynxonly"></p>
163
<pre class="code">pack_of_cards-->0 pack_of_cards-->1 ... pack_of_cards-->51</pre>
165
<p class="normal">and the point of this is that you can read or alter
166
the variable for card number <code>i</code> by calling it
167
<code>pack_of_cards-->i</code>.
168
Here is an example program, in full, for shuffling the pack:</p>
170
<p class="lynxonly"></p>
172
Constant SHUFFLES = 100;
173
Array pack_of_cards --> 52;
175
! Randomly choose two different numbers between 0 and 51:
177
x = random(52) - 1; y = random(52) - 1;
179
z = pack_of_cards-->x; pack_of_cards-->x = pack_of_cards-->y;
180
pack_of_cards-->y = z;
184
0: print "Ace";
185
1 to 9: print n%13 + 1;
186
10: print "Jack";
187
11: print "Queen";
188
12: print "King";
190
print " of ";
191
switch(n/13) {<a id="p51" name="p51"></a>
192
0: print "Hearts"; 1: print "Clubs";
193
2: print "Diamonds"; 3: print "Spades";
197
! Create the pack in quot;factory order":
198
for (i=0:i<52:i++) pack_of_cards-->i = i;
199
! Exchange random pairs of cards for a while:
200
for (i=1:i<=SHUFFLES:i++) ExchangeTwo();
201
print "The pack has been shuffled into the following order:^";
202
for (i=0:i<52:i++)
203
print (Card) pack_of_cards-->i, "^";
207
<p class="normal">The cards are represented by numbers in the range
208
0 (the Ace of Hearts) to 51 (the King of Spades). The pack itself has
209
52 positions, from position 0 (top) to position 51 (bottom). The
210
entry <code>pack_of_cards-->i</code> holds the number of the
211
card in position <code>i</code>. A new pack as produced by the factory
212
would come with Ace of Hearts on top (card 0 in position 0), running
213
down to the King of Spades on the bottom (card 51 in position 51).</p>
215
<p class="aside"><span class="warning">▲</span>
216
A hundred exchanges is only just enough. Redefining <code>SHUFFLES</code> as 10,000
217
takes a lot longer, while redefining it as 10 makes for a highly suspect
218
result. Here is a more efficient method of shuffling (contributed
219
by Dylan Thurston), perfectly random in just 51 exchanges.</p>
221
<p class="lynxonly"></p>
223
pack_of_cards-->0 = 0;
224
for (i=1:i<52:i++) {
226
pack_of_cards-->i = pack_of_cards-->j; pack_of_cards-->j = i;
230
<p class="dotbreak">� � � � �</p>
232
<p class="normal">In the above example, the array entries are all
233
created containing 0. Instead, you can give a list of constant values.
236
<p class="lynxonly"></p>
237
<pre class="code">Array small_primes --> 2 3 5 7 11 13;</pre>
239
<a id="p52" name="p52"></a>
240
<p class="normal">is an array with six entries, <code>small_primes-->0</code>
241
to <code>small_primes-->5</code>, initially holding 2, 3, 5, 7, 11
244
<p class="indent">The third way to create an array gives some text
245
as an initial value, occasionally useful because one popular use for
246
arrays is as “strings of characters” or “text
247
buffers”. For instance:</p>
249
<p class="lynxonly"></p>
250
<pre class="code">Array players_name --> "Frank Booth";</pre>
252
<p class="normal">is equivalent to the directive:</p>
254
<p class="lynxonly"></p>
255
<pre class="code">Array players_name --> 'F' 'r' 'a' 'n' 'k' ' ' 'B' 'o' 'o' 't' 'h';</pre>
257
<p class="normal">Literal text like "Frank Booth" is a constant,
258
not an array, and you can no more alter its lettering than you could
259
alter the digits of the number 124. The array <code>players_name</code> is
260
quite different: its entries can be altered. But this means it cannot
261
be treated as if it were a string constant, and in particular can't
262
be printed out with <code>print (string)</code>. See below for the right
265
<p class="normal" style="margin-top:1em"><span class="warning"><b>•</b> <b>WARNING</b></span><br>
266
In the pack of cards example, the entries are indexed 0 to 51. It's
267
therefore impossible for an interpreter to obey the following statement:</p>
269
<p class="lynxonly"></p>
270
<pre class="code">pack_of_cards-->52 = 0;</pre>
272
<p class="normal">because there is no entry 52. Instead, the following
273
message will be printed when it plays:</p>
275
<p class="output">[** Programming error: tried to write to -->52
276
in the array “pack_of_cards”, which has entries 0 up
279
<p class="normal">Such a mistake is sometimes called breaking the
280
bounds of the array.</p>
282
<p class="dotbreak">� � � � �</p>
284
<p class="normal">The kind of array constructed above is sometimes
285
called a “word array”. This is the most useful kind and
286
many game designers never use the other three varieties at all.</p>
288
<p class="aside"><span class="warning">▲</span>
289
The first alternative is a “byte array”, which is identical
290
except that its entries can only hold numbers in the range 0 to 255,
291
and that it uses the notation <code>-></code> instead of <code>--></code>. This
292
is only really useful to economise on memory usage in special circumstances,
293
usually when the entries are known to be characters, because ZSCII
294
character codes are all between 0 and 255. The “Frank Booth”
295
array above could safely have been a byte array.</p>
297
<a id="p53" name="p53"></a>
298
<p class="aside"><span class="warning">▲</span>
299
In addition to this, Inform provides arrays which have a little extra
300
structure: they are created with the 0th entry holding the number
301
of entries. A word array with this property is called a <code>table</code>;
302
a byte array with this property is a <code>string</code>.
303
For example, the table</p>
305
<p class="lynxonly"></p>
306
<pre class="code">Array continents table 5;</pre>
308
<p class="aside">has six entries: <code>continents-->0</code>, which holds
309
the number 5, and further entries <code>continents-->1</code>
310
to <code>continents-->5</code>. If the program changed
311
<code>continents-->0</code> this would not magically change the
312
number of array entries, or indeed the number of continents.</p>
314
<p class="aside"><span class="warning">▲▲</span>
315
One main reason you might want some arrangement like this is to write
316
a general routine which can be applied to any array. Here is an example
317
using <code>string</code> arrays:</p>
319
<p class="lynxonly"></p>
321
Array password string "danger";
322
Array phone_number string "0171-930-9000";
324
print "Please give the password ", (PrintStringArray) password,
325
" whenever telephoning Universal Exports at ",
326
(PrintStringArray) phone_number, ".";
328
[ PrintStringArray the_array i;
329
for (i=1: i<=the_array->0: i++) print (char) the_array->i;
333
<p class="aside">Such routines should be written with care, as the
334
normal checking of array bounds isn't performed when arrays are
335
accessed in this indirect sort of fashion, so any mistake you make
336
may cause trouble elsewhere and be difficult to diagnose.</p>
338
<p class="aside"><span class="warning">▲▲</span>
339
With all data structures (i.e., with objects, strings, routines and
340
arrays) Inform calls by reference, not by value. So, for instance:</p>
342
<p class="lynxonly"></p>
344
[ DamageStringArray the_array i;
345
for (i=1: i<=the_array->0: i++) {
346
if (the_array->i == 'a' or 'e' or 'i' or 'o' or 'u')
347
the_array->i = random('a', 'e', 'i', 'o', 'u');
348
print (char) the_array->i;
353
<p class="aside">means that the call <code>DamageStringArray(password_string)</code>
354
will not just print (say) “dungor” but also alter the one
355
and only copy of <code>password_string</code> in the story file.</p>
357
<a id="p54" name="p54"></a>
358
<a id="s2_5" name="s2_5"></a>
359
<h3>§2.5 Reading into arrays from the keyboard</h3>
361
<p class="normal">Surprisingly, perhaps, given that Inform is a language
362
for text adventure games, support for reading from the keyboard is
363
fairly limited. A significant difference of approach between Inform
364
and many other systems for interactive fiction is that mechanisms for
365
parsing textual commands don't come built into the language itself.
366
Instead, game designers use a standard Inform parser program which
367
occupies four and a half thousand lines of Inform code.</p>
369
<p class="indent">Reading single key-presses, perhaps with time-limits,
370
or for that matter reading the mouse position and state (in a Version
371
6 game) requires the use of Inform assembly language: see
372
<a href="s42.html">§42</a>.</p>
374
<p class="indent">A statement called <code>read</code> does however
375
exist for reading in a single line of text and storing it into a
378
<p class="lynxonly"></p>
379
<pre class="code">read text_array 0;</pre>
381
<p class="normal">You must already have set <code>text_array->0</code>
382
to the maximum number of characters you will allow to be read. (If
383
this is <i>N</i>, then the array must be defined with at least
384
<i>N</i> + 3 entries, the last of which guards against overruns.)
385
The number of characters actually read, not counting the carriage
386
return, will be placed into <code>text_array->1</code> and
387
the characters themselves into entries from <code>text_array->2</code>
388
onwards. For example, if the player typed “GET IN”:</p>
390
<p class="lynxonly"></p>
391
<table border="1" style="margin-left:30px;margin-top:1em;margin-bottom:1em">
392
<tr><td><code>->0</code></td>
393
<td><code>1</code></td>
394
<td><code>2</code></td>
395
<td><code>3</code></td>
396
<td><code>4</code></td>
397
<td><code>5</code></td>
398
<td><code>6</code></td>
399
<td><code>7</code></td></tr>
400
<tr><td><i>max</i></td>
401
<td><i>characters</i></td>
402
<td colspan="6" style="text-align:center"><i>text typed by player, reduced to lower case</i></td></tr>
405
<td><code>'g'</code></td>
406
<td><code>'e'</code></td>
407
<td><code>'t'</code></td>
408
<td><code>' '</code></td>
409
<td><code>'i'</code></td>
410
<td><code>'n'</code></td></tr></table>
412
<p class="normal">The following echo chamber demonstrates how to
413
read from this array:</p>
415
<p class="lynxonly"></p>
417
Array text_array -> 63;
420
print "^> ";
421
text_array->0 = 60;
423
for (x=0:x<text_array->1:x++) {
424
c = text_array->(2+x);
425
print (char) c; if (c == 'o') print "h";
431
<p class="dotbreak">� � � � �</p>
433
<a id="p55" name="p55"></a>
434
<p class="aside"><span class="warning">▲</span>
435
<code>read</code> can go further than simply reading in the text:
436
it can work out where the words start and end, and if they are words
437
registered in the story file's built-in vocabulary, known as the
438
“dictionary”. To produce all this information, <code>read</code>
439
needs to be supplied with a second array:</p>
441
<p class="lynxonly"></p>
442
<pre class="code">read text_array parse_array;</pre>
444
<p class="aside"><code>read</code> not only stores the text (just
445
as above) but breaks down the line into a sequence of words, in
446
which commas and full stops count as separate words in their own right.
447
(An example is given in <a href="ch4.html">Chapter IV</a>,
448
<a href="s30.html">§30</a>.) In advance of this
449
<code>parse_array->0</code> must havebeen set to <i>W</i>, the
450
maximum number of words you want to parse. Any further text will be
451
ignored. <code>parse_array</code> should have at least 4<i>W</i>
452
+ 2 entries, because <code>parse_array->1</code> is set to the
453
actual number of words parsed, and then a four-entry block is written
454
into the array for each word parsed. Numbering the words as 1, 2, 3,
455
…, the number of letters in word <i>n</i> is written into
456
<code>parse_array->(n*4)</code>, and the position of the start
457
of the word in <code>text_array</code>. The dictionary value of
458
the word, or zero if it isn't recognised, is stored as
459
<code>parse_array-->(n*2-1)</code>. The corresponding parsing
460
array to the previous text array, for the command “GET IN”,
463
<p class="lynxonly"></p>
464
<table border="1" style="margin-left:30px;margin-top:1em;margin-bottom:1em">
465
<tr><td><code>->0</code></td>
466
<td><code>1</code></td>
467
<td><code>2</code></td>
468
<td><code>3</code></td>
469
<td><code>4</code></td>
470
<td><code>5</code></td>
471
<td><code>6</code></td>
472
<td><code>7</code></td>
473
<td><code>8</code></td>
474
<td><code>9</code></td></tr>
475
<tr><td><i>max</i></td>
476
<td><i>words</i></td>
477
<td colspan="4" style="text-align:center"><i>first word</i></td>
478
<td colspan="4" style="text-align:center"><i>second word</i></td></tr>
481
<td colspan="2"><code>'get'</code></td>
484
<td colspan="2"><code>'in'</code></td>
486
<td>2</td></tr></table>
488
<p class="aside">In this example both words were recognised. The
489
word “get” began at position <code>->2</code> in
490
the text array, and was 3 characters long; the word “in”
491
began at <code>->5</code> and was 2 characters long.
492
The following program reads in text and prints back an analysis:</p>
494
<p class="lynxonly"></p>
496
Array text_array -> 63;
497
Array parse_array -> 42;
498
[ Main w x length position dict;
499
w = 'mary'; w = 'had'; w = 'a//'; w = 'little'; w = 'lamb';
501
print "^> ";
502
text_array->0 = 60; parse_array->0 = 10;
503
read text_array parse_array;
504
for (w=1:w<=parse_array->1:w++) {
505
print "Word ", w, ": ";
506
length = parse_array->(4*w);
507
position = parse_array->(4*w + 1);
508
dict = parse_array-->(w*2-1);
509
for (x=0:x<length:x++)
510
print (char) text_array->(position+x);<a id="p56" name="p56"></a>
511
print " (length ", length, ")";
512
if (dict) print " equals '", (address) dict, "'^";
513
else print " is not in the dictionary^";
519
<p class="aside">Note that the pointless-looking first line of <code>Main</code>
520
adds five words to the dictionary. The result is:</p>
522
<p class="output"><tt>>MARY, hello</tt><br>
523
Word 1: mary (length 4) equals 'mary'<br>
524
Word 2: , (length 1) is not in the dictionary<br>
525
Word 3: hello (length 5) is not in the dictionary</p>
527
<p class="aside"><span class="warning">▲</span>
528
What goes into the dictionary? The answer is: any of the words given
529
in the name of an object (see <a href="s3.html">§3</a>),
530
any of the verbs and prepositions given in grammar by <code>Verb</code>
531
and <code>Extend</code> directives (see §26), and anything
532
given as a dictionary-word constant. The last is convenient because
533
it means that code like</p>
535
<p class="lynxonly"></p>
536
<pre class="code">if (parse_array -->(n*2-1)) == 'purple';</pre>
538
<p class="aside">does what it looks as if it should. When compiling
539
this line, Inform automatically adds the word “purple”
540
to the story file's dictionary, so that any <code>read</code> statement
541
will recognise it.</p>
543
<p class="aside"><span class="warning"><b>•</b> <b>REFERENCES</b></span><br>
544
Evin Robertson's function library <code>"array.h"</code>
545
provides some simple array-handling utilities.
546
<span class="warning"><b>•</b></span>L. Ross Raszewski's function
547
library <code>"istring.h"</code> offers Inform versions of
548
the ANSI C string-handling routines, including <code>strcmp()</code>,
549
<code>strcpy()</code> and <code>strcat()</code>. The further extension
550
<code>"znsi.h"</code> allows the printing out of string
551
arrays with special escape sequences like <code>[B</code> interpreted
552
as “bold face.” (See also the same author's
553
<code>"ictype.h"</code>.)
554
<span class="warning"><b>•</b></span>Adam Cadre's function library
555
<code>"flags.h"</code> manages an array of boolean values
556
(that is, values which can only be <code>true</code> or <code>false</code>)
557
so as to use only one-sixteenth as much memory as a conventional array,
558
though at some cost to speed of access.</p>
562
<a href="index.html">home</a> /
563
<a href="contents.html">contents</a> /
564
<a href="ch1.html" title="Chapter I: The Inform Language">chapter I</a> /
565
<a href="s1.html" title="§1: Routines">prev</a> /
566
<a href="s3.html" title="§3: Objects and classes">next</a> /
567
<a href="dm4index.html">index</a>