Import Z-LIFE by Julian Arnold
[z-life.git] / z-life.inf
1 ! ---------------------------------------------------------------------------
2 !                                   Z-LIFE
3 !                 by Julian Arnold <jools@arnod.demon.co.uk>
4 !             This program has been placed in the Public Domain.
5 ! ---------------------------------------------------------------------------
6
7 ! ---------------------------------------------------------------------------
8 ! ** Release History
9 !    1/960117: (See below).
10 !    2/960118: (See below).
11 !    3/960121: It's all changed. Previous releases were WRONG. Apart from
12 !              making it work properly then, the main addition is the
13 !              optional colour support (Z-Cells lighten as they age until,
14 !              after seven generations, they die of old age).
15 ! ---------------------------------------------------------------------------
16
17 ! ---------------------------------------------------------------------------
18 ! ** To Do
19 !    Add mouse support (when I've figured out how).
20 ! ---------------------------------------------------------------------------
21
22 #SWITCHES sv5x;
23
24 #RELEASE 3;
25 #SERIAL  "960121";
26
27 #CONSTANT DENSITY 15;  ! Percentage chance of Z-Cell being filled
28 #CONSTANT EMPTY   ' '; ! Character for empty cell
29 #CONSTANT CELL    '*'; ! Character for filled cell
30
31 #GLOBAL oldcomm    -> 1474;
32 #GLOBAL newcomm    -> 1474;
33 #GLOBAL generation =  1;
34 #GLOBAL usecolour  =  0;
35
36 [ Main;
37
38     Initialise();
39
40     Borders();
41
42     RandomizeCommunity();
43
44     for (::)
45     {
46         CheckKeypress();
47
48         NewGeneration();
49     }
50
51 ];
52
53 [ Initialise  pkey;
54
55     if (0->33 < 80 || 0->32 < 24)
56     {
57         print "[You must have a screen width of 80 characters and a screen \
58             height of 24 lines to run ~Z-Life~.]^^[Any key to quit]";
59         @read_char 1 pkey;
60         quit;
61     }
62
63     box "~Cellular Automata, of which Life is an example, were"
64         " suggested by Stanislaw Ulam in the 1940s, and first"
65         " formalized by von Neumann. Conway's 'Game of Life'"
66         " was popularized in Martin Gardner's mathematical"
67         " games column in the October 1970 and February 1971"
68         " issues of Scientific American.~"
69         ""
70         "    -- Mark Kantrowitz, ~Answers to Frequently Asked"
71         "       Questions about Artificial Intelligence~,"
72         "       comp.ai, January, 1996,"
73         "       ftp.cs.cmu.edu:/user/ai/pubs/faqs/ai/ai_?.faq,"
74         "       mkant+ai-faq@@64cs.cmu.edu";
75
76     print "[Any key]";
77     @read_char 1 pkey;
78     @erase_window -1;
79
80     style bold; print "^^^Z-LIFE"; style roman;
81     print "^A not-very interactive journey into ~AI~ (honest :)^by Julian \
82         Arnold <jools@@64arnod.demon.co.uk>^This program has been placed in \
83         the Public Domain.^^";
84
85     print "~Z-Life~ was written using Graham Nelson's Inform compiler (5.5, \
86         v1503) and tested mainly on Kevin Bracey's Acorn Z-Machine \
87         interpreter, Zip 2000 (v1.15).^^";
88
89     if (50-->0 == 0)
90         print "[Your interpreter is not Standard. Certain features of \
91             ~Z-Life~ may not work properly.]^^";
92
93     if (0->1 & 128 == 0)
94         print "[Your interpreter does not support timed-input. You'll have \
95             to press SPACE to proceed to the next generation.]^^";
96
97     if (0->1 & 1 ~= 0)
98     {
99         print "Do you want to represent age by colour (dark -> light)? \
100             (Y/N) >";
101         do
102         {
103             @read_char 1 pkey;
104             if (pkey ~= 'y' or 'n') @sound_effect 1;
105         } until (pkey == 'y' or 'n');
106         if (pkey == 'y') { usecolour = 1; print "YES"; }
107         else             { usecolour = 0; print "NO"; }
108     }
109     else
110         print "[Your interpreter can't display colours (so no age-by-colour \
111             I'm afraid).]";
112
113     print "^^[Any key]";
114     @read_char 1 pkey;
115     @erase_window -1;
116
117     @split_window 24;
118     @set_window 1;
119     @buffer_mode 0;
120     font off;
121
122 ];
123
124 [ Borders  i;
125
126     @set_cursor 1  2;
127     for (i = 1: i <= 78:i++) print "-";
128     @set_cursor 24 2;
129     for (i = 1: i <= 78:i++) print "-";
130
131     for (i = 2: i <= 23: i++)
132     {
133         @set_cursor i 1;  print "|";
134         @set_cursor i 69; print "|";
135         @set_cursor i 80; print "|";
136     }
137
138     @set_cursor 1  1;  print "+";
139     @set_cursor 1  69; print "+";
140     @set_cursor 1  80; print "+";
141     @set_cursor 24 1;  print "+";
142     @set_cursor 24 69; print "+";
143     @set_cursor 24 80; print "+";
144
145     @set_cursor 2  70; print "GENERATION";
146     style bold;
147     @set_cursor 5  72; print "Z-LIFE";
148     style roman;
149     @set_cursor 7  71; print (0-->1) & $03ff, "/";
150     for (i = 18: i < 24: i++) print (char) 0->i;
151     @set_cursor 9  70; print "Programmed";
152     @set_cursor 10 74; print "by";
153     @set_cursor 11 71; print "J Arnold";
154     @set_cursor 13 73; print "with";
155     @set_cursor 14 70; print "Inform 5.5";
156     @set_cursor 16 72; print "PUBLIC";
157     @set_cursor 17 72; print "DOMAIN";
158     @set_cursor 19 73; print "1996";
159     @set_cursor 22 70; print "(N)ew game";
160     @set_cursor 23 72; print "(Q)uit";
161
162 ];
163
164 [ RandomizeCommunity  x y c;
165
166     for (y = 1: y <= 22: y++)
167         for (x = 1: x <= 67: x++)
168         {
169             c = CalcLoc(x, y);
170
171             if (random(100) <= DENSITY) oldcomm->c = 1;
172             else                        oldcomm->c = 0;
173         }
174
175 ];
176
177 [ CheckKeypress  pkey;
178
179     @read_char 1 1 #r$NewGeneration pkey;
180
181     switch (pkey)
182     {
183         'q': quit;
184         'n': @restart;
185     }
186
187 ];
188
189 [ NewGeneration  n x y c;
190
191     @set_cursor 3 74; print generation++;
192
193     for (y = 1: y <= 22: y++)
194         for (x = 1: x <= 67: x++)
195         {
196             c = CalcLoc(x, y);
197             n = Neighbours(x, y, c);
198
199             switch (oldcomm->c)
200             {
201                 0:      if (n == 3)
202                         {   if (usecolour == 1)
203                                 newcomm->c = (oldcomm->c) + 1;
204                             else newcomm->c = 1;
205                         }
206                 1 to 6: if (n <= 1) newcomm->c = 0;
207                         if (n == 2 or 3)
208                         {   if (usecolour == 1)
209                                 newcomm->c = (oldcomm->c) + 1;
210                             else newcomm->c = 1;
211                         }
212                         if (n >= 4) newcomm->c = 0;
213                 7:      newcomm->c = 0;
214             }
215         }
216
217     for (y = 1: y <= 22: y++)
218         for (x = 1: x <= 67: x++)
219         {
220             c = CalcLoc(x, y);
221
222             PlotCell(x + 1, y + 1, newcomm->c);
223
224             oldcomm->c = newcomm->c;
225         }
226
227 ];
228
229 [ PlotCell x y c;
230
231     if (usecolour == 1) ColourAge(c);
232     @set_cursor y x;
233     if (c > 0) print (char) CELL; else print (char) EMPTY;
234     if (usecolour == 1) @set_colour 2 9;
235
236 ];
237
238 ! ** Rules:
239 !      (a) If a Z-Cell is empty,
240 !            it becomes inhabited if 3 of its neighbouring Z-Cells are
241 !            filled,
242 !            otherwise it remains empty.
243 !      (b) If a Z-Cell is filled,
244 !            it dies of loneliness if it only has 1 or 0 neighbours,
245 !            it lives on, unchanged, if it has 2 or 3 neighbours,
246 !            it dies of overcrowding if it has 4 or more neighbours.
247 !      (Neighbours include diagonals.)
248 !    Also, if you have the colour/age option on:
249 !      (c) A Z-Cell, notwithstanding loneliness or overcrowding, has a life
250 !          expectancy of seven generations.
251 !      (d) The age of a Z-Cell is shown graphically by its colour. This
252 !          ranges from dark (black, first generation) to light (yellow,
253 !          seventh generation).
254 [ Neighbours x y c  n;
255
256     if (y > 1)
257         if (oldcomm->(c - 67)     > 0) n++;
258     if (x < 67 && y > 1)
259         if (oldcomm->(c - 67 + 1) > 0) n++;
260     if (x < 67)
261         if (oldcomm->(c + 1)      > 0) n++;
262     if (x < 67 && y < 22)
263         if (oldcomm->(c + 67 + 1) > 0) n++;
264     if (y < 22)
265         if (oldcomm->(c + 67)     > 0) n++;
266     if (x > 1 && y < 22)
267         if (oldcomm->(c + 67 - 1) > 0) n++;
268     if (x > 1)
269         if (oldcomm->(c - 1)      > 0) n++;
270     if (x > 1 && y > 1)
271         if (oldcomm->(c - 67 - 1) > 0) n++;
272
273     return n;
274
275 ];
276
277 [ CalcLoc x y  c;
278
279     if (x > 67 || x < 1 || y > 22 || y < 1) c = 1474;
280     else c = ((y * 67) - 67 + x) - 1;
281
282     return c;
283
284 ];
285
286 [ ColourAge c;
287
288     switch (c)
289     {   1: @set_colour 2 9; ! Black
290         2: @set_colour 6 9; ! Blue
291         3: @set_colour 3 9; ! Red
292         4: @set_colour 7 9; ! Magenta
293         5: @set_colour 4 9; ! Green
294         6: @set_colour 8 9; ! Cyan
295         7: @set_colour 5 9; ! Yellow
296     }
297
298 ];
299
300 #END;