In collaboration with @EdS I’ve devised a version of Conway’s Game of Life, which will work both on Commodore 8-bits and on the Beeb (BBC Micro). – You’ve just to set the config variable in the very first line appropriately.
Mind that there are two rather suitable online emulators for those machines,
for a PET 2001: Commodore PET 2001
and “JSBeeb” for the BBC Micro: https://bbc.godbolt.org/
On the emulated PET, you may simply drop a BASIC text file onto the emulated screen to import a source file, JSBeeb supports specially crafted data-URLs (as does the PET emulator).
To craft such links, I’ve provided a tool for each of those emulators:
For the PET: PET 2001 Link Console
and for JSBeeb: Beeb Link Console
And now for the script:
10 BB=0 : REM CONFIG, 1=BEEB, 0=COMMODORE
20 IF BB=0 THEN PRINTCHR$(147);CHR$(18);:GOTO 30
25 MODE 7
30 PRINT" CONWAY'S GAME OF LIFE "
40 PRINT:PRINT"IN MEMORIAM JOHN H CONWAY"
50 PRINT"26 DEC 1937 - 11 APR 2020":PRINT
60 INPUT"WIDTH, HEIGHT (EG, 8,8)";W,H
70 IF W<4 THEN W=4
80 IF W>39 THEN W=39
90 IF H<4 THEN H=4
100 IF H>24 THEN H=24
110 G=0:A=0:P=0:W=W+1:H=H+1:D1=W+1:D2=W-1:K=0:NG=1:XM=W-1:YM=W*H-W:N=0
120 IF BB=0 THEN 140
130 CS=12:CH=30:CO=79-32:R=1:GOTO150
140 CS=147:CH=19:CO=209-32:R=0
150 PRINT:PRINT"PROBABILITY OF INITIAL POPULATION:":INPUT"(0>P<1)";P
160 IF P<=0 OR P>=1 THEN P=0.5
170 DIM M%(1,W*H+W):PRINTCHR$(CS);
180 FORY=W TOYM STEPW:FORX=1TOXM:M%(0,Y+X)=RND(R)<P:NEXT:NEXT
190 PRINTCHR$(CH);"GEN.:";N
200 FORY=W TOYM STEPW:FORX=1TOXM:PRINTCHR$(32-M%(G,Y+X)*CO);:NEXT:PRINT:NEXT
210 FORY=W TOYM STEPW:FORX=1TOXM:A=Y+X
220 K=M%(G,A-D1)+M%(G,A-W)+M%(G,A-D2)+M%(G,A-1)+M%(G,A+1)
230 K=K+M%(G,A+D2)+M%(G,A+W)+M%(G,A+D1):M%(NG,A)=(K=-3)OR(K=-2 ANDM%(G,A)=-1)
240 NEXT:NEXT:G=NG:NG=1-G:N=N+1:GOTO190
Annotations
Commodore BASIC and BBC BASIC use -1
for true
and 0
for false
.
Thus, CHR$(32-V*CO)
will print either a space (CHR$(32)
) or a disk character (CHR$(209)
) on Commodore machines, and an “O” on the Beeb, depending on the boolean value in V.
The script uses extra rows and columns at the very edges so that the 3x3 kernel can iterate over the actual data:
00000000
0DDDDDD0
0DDDDDD0
0DDDDDD0
0DDDDDD0
00000000
Variables used:
W
, H
… width, height
YX
, XM
… upper boundary for loops
P
… threshold for initial population (0 > P < 1)
M%(G, A)
… field by generations (0,1) and rows x cols
N
… count of generations processed (total iterations)
G
… current generation (0,1)
NG
… next generation (0,1)
K
… sum of living neighboring cells
D1
, `D2’ … offsets row + 1 cell, row - 1 cell
Since Commodore BASIC supports arrays only in up to 2 dimensions, we calculate our own indices (offsets) into M%
:
K =
M%(G,A-D1) + M%(G,A-W) + M%(G,A-D2) +
M%(G,A- 1) + M%(G,A+1) +
M%(G,A+D2) + M%(G,A+W) + M%(G,A+D1)
which is the same as in 3D:
K =
M%(G,Y-1,X-1) + M%(G,Y-1,X) + M%(G,Y-1,X+1) +
M%(G,Y ,X-1) + M%(G,Y ,X+1) +
M%(G,Y+1,X-1) + M%(G,Y+1,X) + M%(G,Y+1,X+1)
Cross-Platform Related:
BP
… config flag: 1=Beeb, 0=Commodore BASIC
CS
… CHR$() code for clear screen
CH
… CHR$() code for cursor home
CO
… CHR$() code offset to add to 32 for the character of a living cell
R
… parameter for RND() to get a value 0 > v < 1
Ideas:
Can you alter the script so that it wraps?
(Hint, you may have to use modular additions inside the kernel, where there are currently D1, D2, W added or subtracted to the base index A. If you want too keep the script compatible, mind that there is no MOD() function in Commodore BASIC.)
Post your ideas and/or your own versions!