Game of Life.

SYS 64738
User avatar
Shaun_B
Member
Member
Posts: 179
Joined: Tue May 06, 2014 12:12 pm
Location: UK
Contact:

Game of Life.

Post by Shaun_B » Mon Sep 22, 2014 1:33 am

Here's a rough conversion (which is partially bug-fixed) of the Game of Life thing that I entered in the 2013 CSS CGC for the Sinclair ZX81. It's quite slow, of course, and requires an accelerator real or emulated.

Code: Select all

0 r=rnd(0):poke 53280,0:poke 53281,0:print"{clear}{light gray}";:gosub 63990:gosub 4:goto 28
1 rem cleargrid()
2 for i=z to h:for j=z to w:g(i,j)=z:next j,i:return
3 rem fillarray()
4 for i=z to a:for j=o to b:r=int(rnd(ti)*x):if r<d then g(i,j)=o
5 next j,i:return
6 rem showarray()
7 for i=z to h:for j=z to w:if g(i,j) then print "0";:goto 9
8 print" ";
9 next j,i
10 rem checkneighbour()
11 for j=o to b:n=z:if g(z,j) and g(z,j-o) then n=n+o
12 if g(z,j) and g(z,j+o) then n=n+o
13 if g(z,j) and g(o,j) then n=n+o
14 if g(z,j) and g(o,j+o) then n=n+o
15 if g(z,j) and (n<e or n>d) then g(z,j)=z
16 if g(z,j)=z and n=d then g(z,j)=o
17 next j:for i=o to a:for j=o to b:n=z:if g(i,j) and g(i-o,j) then n=n+o
18 if g(i,j) and g(i-o,j-o) then n=n+o
19 if g(i,j) and g(i-o,j+o) then n=n+o
20 if g(i,j) and g(i+o,j) then n=n+o
21 if g(i,j) and g(i+o,j+o) then n=n+o
22 if g(i,j) and g(i+o,j-o) then n=n+o
23 if g(i,j) and g(i,j-o) then n=n+o
24 if g(i,j) and g(i,j+o) then n=n+o
25 if g(i,j) and (n<e or n>d) then g(i,j)=z
26 if g(i,j)=z and n=d then g(i,j)=o
27 next j,i
28 g=g+o:print"{home}generation:"g:get a$:on-(a$="")goto 7:gosub 3:g=0:print"{clear}":goto 28
63990 rem initialise()
63997 dim g(22,39), g, o, x, s, h, w, a, b, t, e, d, z, a$
63998 o=1: x=8: s=6: h=22: w=39: a=h-o: b=w-o: t=50: e=2: d=3: gosub 1
63999 return
Press the any key to start from generation one again.

For those who don't want to type, I've put a compressed disk image here. the file beginning with b. is the Blitz! compiled version.

Regards,

Shaun.


BASIC Programming - making the mistakes so that you don't have to.
Circles and Squares.
Nothing I post here will stand up in a court of law.

User avatar
Shaun_B
Member
Member
Posts: 179
Joined: Tue May 06, 2014 12:12 pm
Location: UK
Contact:

Re: Game of Life.

Post by Shaun_B » Mon Sep 22, 2014 10:06 am

Here is a partially minimized version which should make things a little quicker. Use an IDE like CBM prg Studio for long lines.

Code: Select all

0 r=rnd(0):poke 53280,0:poke 53281,0:print"{clear}{light gray}";:gosub 63990:gosub 4:goto 15
1 rem cleargrid()
2 for i=z to h:for j=z to w:g(i,j)=z:next j,i:return
3 rem fillarray()
4 for i=z to a:for j=o to b:g(i,j)=-(int(rnd(ti)*x)<d):next j,i:return
5 rem showarray()
6 for i=z to h:for j=z to w:if g(i,j) then print "0";:goto 8
7 print" ";
8 next j,i
9 rem checkneighbour()
10 for j=o to b:n=z:n=n+(g(z,j)and g(z,j-o))+(g(z,j)and g(z,j+o))+(g(z,j)and g(o,j))+(g(z,j)and g(o,j+o)):if g(z,j) and (n<e or n>d) then g(z,j)=z
11 if g(z,j)=z and n=d then g(z,j)=o
12 next j:for i=o to a:for j=o to b:n=z:n=n+(g(i,j)and g(i-o,j))+(g(i,j)and g(i-o,j-o))+(g(i,j)and g(i-o,j+o))+(g(i,j)and g(i+o,j))+(g(i,j)and g(i+o,j+o))+(g(i,j)and g(i+o,j-o))+(g(i,j)and g(i,j-o))+(g(i,j)and g(i,j+o)):if g(i,j) and (n<e or n>d) then g(i,j)=z
13 if g(i,j)=z and n=d then g(i,j)=o
14 next j,i
15 g=g+o:print"{home}generation:"g:get a$:on-(a$="")goto 6:gosub 4:g=0:print"{clear}":goto 15
63990 rem initialise()
63999 dim g(22,39), g, o, x, s, h, w, a, b, e, d, z, a$:o=1: x=9: s=6: h=22: w=39: a=h-o: b=w-o: e=2: d=3:gosub 1:return
Obviously, the REM lines may be removed to save a couple of more RAMs and maybe a few clicks, but it's not going to be a game-changer.

Edit: I managed to get the whole listing into one screen here.

Regards,

Shaun.
BASIC Programming - making the mistakes so that you don't have to.
Circles and Squares.
Nothing I post here will stand up in a court of law.

MarcWalters
Member
Member
Posts: 50
Joined: Wed Jun 11, 2014 2:33 pm
Location: Lake Macquarie, NSW, Australia

Re: Game of Life.

Post by MarcWalters » Thu Oct 09, 2014 5:45 am

I was inspired to have a go at this to see if it was possible to speed things up a bit. Much of the original program's "feeling" was retained, such as the use of PRINT instead of POKE. The program turned out to be no faster, but was still an interesting exercise.

The borders are kept clear of cells. Processing of each cell occurs line by line. The rules are that a cell lives if it has 2 or 3 neighbours, otherwise it dies. A cell is created if an empty space has 3 neighbours.

The arrangement of code is for readability, and can be crunched significantly - packed to lines, spaces removed, "+abs(boolean)" changed to "-(boolean)" and so on.

The design reduces the amount of code for individual neighbour searches and removes the need to store a generation's values before an update.

The neighbour-search routine pairs the current cell with its immediate right, right-lower, lower, and left-lower neighbours. A 2-dimensional array contains a single value represents the state of the cell area. Cell area state comprises neighbour-count and existence-flag. Neighbour data is stored in the lower 4 bits of the cell area state (equals between zero and 8). Bit 5 (equals 16) stores the flag, set if a cell exists, clear if a cell is non-existent.

Variable H in line 20 holds the dish height. W holds the width. Change the height of the dish to between 2 and 23. Width between 2 and 39.

Lines 230-260 are where the cell information is processed. Data is partially processed for use in the next iteration of the loop, allowing the current cell state to be stored without affecting the processing of current neighbours not yet fully processed.

Code: Select all

10 rem initialise
20 h=7: w=39: e=2: d=3
25 cn=15: c0=16: c1=17: c2=18: c3=19: c4=20 : rem c0 is 5th bit
26 n0=0: n1=1: n2=2: n3=3: n4=4: n5=5: n6=6: n7=7
30 dim g(h,w)
40 dim c$(c0+8): c$(0)=" ": c$(c0) = "0" : rem c$ max is c0 + max neighbours
50 :
60 poke 53280,2: poke 53281,0: print"{clear}{down}{light gray}";:
70 goto 160
80 :
90 rem fill array
100 for i=n0 to h:for j=n0 to w
110 g(i,j)=c0*((-int(rnd(n1)*n5)=n0) and abs((i>n0 and i<h) and (j>n0 and j<w)))
120 print c$(g(i,j));
130 next j,i
140 :
150 rem main loop
160 g = g + n1: print"{home}generation:"g
170 if g = n1 then 90
175 :
180 rem check neighbour
200 :
210 for i = n0 to h: for j = n0 to w
220 t = g(i,j) : a = abs(t>n7)
224 :
225 if (i=n0 or i=h or j=n0 or j=w) then g(i,j) = n0: goto 310
226 i1=i+n1: j1=j+n1: i0=i-n1: j0=j-n1
230 b=g(i,j1): t = t + abs(b>cn): g(i,j1) = b + a
240 b=g(i1,j1): t = t + abs(b>cn): g(i1,j1) = b + a
250 b=g(i1,j): t = t + abs(b>cn): g(i1,j) = b + a
260 b=g(i1,j0): t = t + abs(b>cn): g(i1,j0) = b + a
270 :
280 rem rules
290 if t=n3 then t=c0: goto 340 : rem 3 around empty = birth
300 if (t=c2) or (t=c3) then t=c0: goto 340 : rem 2 or 3 neighbours = live
310 t=n0 : rem <2 or >3 neighbours = die
320 :
330 rem print cells
340 g(i,j) = t
350 print c$(t);
360 :
370 next j,i
380 goto 160

Post Reply Previous topicNext topic