In a recent Usagi Electric video, we find a Basic program to run a 1-d Life simulation - it’s in github here. (As explained in the video, it’s not one of Wolfram’s, it’s by Jon Millen - see here.)
The video is BASIC on This 80’s Minicomputer is Terrible! (26 mins) and the machine in question is, of course, the refurbed Centurion mini. But it’s a simple Basic program, can be quite portable, here’s a grab showing it running at VCF on a DG Nova 1210
The Basic as written starts with a 69 cell initial random state, runs for 26 generations printing the middle 65 cells, and then starts again. It’s pretty portable. Here’s a barely modified version in BBC Basic, in Owlet. It runs 26 generations in just over a minute, but I’m quite certain a native BBC Basic version could go a lot faster.
I’ve posted over there with a couple of optimised versions in 8 bit BBC Basic - just under 4 seconds, compared to the baseline of 18 and a bit. I’m quite pleased!
/*
* 1dLife.b:
* 1 Dimensional cellular automation.
* Jon Millens idea.
* Gordon Henderson, 2026
*********************************************************************************
*/
GET "libhdr"
GET "vdu"
GET "sys"
GET "math"
GET "stringLib"
GLOBAL
{
tw: ug
th
universe0; universe1
maxWidth
}
/*
* initialLife
* Create the initial life
*********************************************************************************
*/
LET initialLife () BE
FOR i = 0 TO maxWidth DO
universe0!i := randno (2) = 1
/*
* printUniverse:
*/
AND printUniverse () BE
{
writes (" ")
FOR i = 2 TO maxWidth -2 DO
TEST universe0!i THEN
wrch ('@')
ELSE
wrch (' ')
writes ("*n")
}
/*
* nextGen:
* Work out the next Generation
*********************************************************************************
*/
AND nextGen () BE
{
FOR i = 2 TO maxWidth - 2 DO
{
LET neebs = 0 // Neighbours
LET thisCell = universe0!i // Me
FOR j = i-2 TO i+2 DO // YYxYY
{
IF j = i THEN LOOP // Don't count ourself
IF universe0!j THEN // We have a neighbour
{
neebs := neebs + 1
LOOP
}
}
universe1!i := FALSE // Start with nothing
TEST thisCell THEN // Live cell, now what?
IF (neebs = 2) | (neebs = 4) THEN // 2 or 4 neighbours, it lives on
universe1!i := TRUE
ELSE // Dead cell
IF (neebs = 2) | (neebs = 3) THEN // A new cell is born
universe1!i := TRUE
}
// Copy new universe to the original
FOR i = 0 TO maxWidth DO
universe0!i := universe1!i
}
/*
* setup:
* Initial setup, etc. ...
*********************************************************************************
*/
AND setup () BE
{
tw := vduProps!vduProps_tWidth // Terminal width
th := vduProps!vduProps_tHeight // Terminal height
maxWidth := tw - 2
universe0 := getvec (maxWidth)
UNLESS universe0 THEN
{
sawritef ("Out of memory*n")
exit (1)
}
universe1 := getvec (maxWidth)
UNLESS universe1 THEN
{
sawritef ("Out of memory*n")
freevec (universe0)
exit (1)
}
}
/*
* start:
* Where we begin
*********************************************************************************
*/
AND start (argc, argv) = VALOF
{
writef ("*n")
setup ()
initialLife ()
printUniverse ()
FOR generation = 1 TO th-2 DO
{
nextGen ()
printUniverse ()
}
IF universe1 THEN freevec (universe1)
IF universe0 THEN freevec (universe0)
RESULTIS 0
}
At least I think it’s right… Written and ran on my suitably retro 16Mhz 65c816 system. It runs in under 5 seconds and most of that is printing to the screen.