One dimensional Life in Basic

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.

How about some ports to other Basics, with appropriate speed-ups? No machine code!

To make comparisons easier, let’s time either 26 generation at 69 cells wide, or 16 generations at 35 cells wide.


(BBC Basic on Beeb, original portable code, 18.48 seconds)

See previously
(Conway’s) Life in BASIC

via Lardo Boffin on stardot.

1 Like

TBF, that looks like early Dartmouth-standard IF ... GOTO BASIC. It might even be TinyBASIC compatible. There was a lot of that kind of thing about.

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!

1 Like

And since we’re talking about Dr. Tim King…

Here is a version written in BASIC CPL…

/*
 * 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
}

And a sample output:

  @ @@@  @@  @@@  @  @@ @@ @@ @ @ @ @@@ @   @ @  @  @@ @ @ @@@@  @    @   @@@@  @  @@ @@     @   
   @ @@@@  @@@@@@@ @@ @ @@ @@@@@@@@@ @ @  @  @ @@ @@ @@@@@@   @@@       @@@  @@@ @@ @ @ @        
  @@@   @@@@ @@@   @@@@@@@   @@@@@  @@@ @@ @@ @@@ @@   @@ @@@@@@@@     @@@@@@@@  @@@@@@@        @
  @ @@@@@     @@@@@@ @@@ @@@@@ @ @@@@@  @@ @@  @  @ @@@ @   @@@@ @@   @@ @@@@ @@@@ @@@ @@      @@
      @ @@   @@ @@    @    @  @@@  @ @@@ @ @ @@ @@ @ @ @  @@@    @ @@@ @            @  @ @    @@ 
  @    @@ @@@ @ @ @         @@@@@@@ @ @ @@@@@@@ @@@@@@@ @@@@@@    @ @ @              @@ @    @ @ 
  @@  @ @  @ @@@@@         @@ @@@  @@@@@  @@@     @@@     @@ @@    @@@              @ @@      @@@
   @@@ @ @@ @  @ @@       @ @  @@@@@ @ @@@@@@@   @@@@@   @ @ @ @  @@@@@              @@ @    @@ @
    @ @@@@@@ @@ @@ @       @ @@@ @  @@@  @@@ @@@@@ @ @@@  @@@@@ @@@ @ @@            @ @@    @ @  
  @@ @  @@   @@ @@@         @ @ @ @@@@@@@@@    @  @@@ @@@@@ @    @ @@@@ @            @@ @    @ @@
    @ @@  @@@ @  @@@         @@@@@  @@@@@ @@    @@@@    @  @      @    @            @ @@      @  
  @@ @@ @@@@ @ @@@@@@       @@ @ @@@@ @   @ @  @@  @@    @@                          @@ @      @@
     @@     @@@  @@ @@     @ @@@@    @  @  @ @@  @@  @  @  @                        @ @@      @@ 
  @@@  @   @@@@@@ @ @ @     @   @@    @@ @@ @@ @@  @@ @@ @@                          @@ @    @ @ 
  @ @@@  @@@ @@  @@@@@        @@  @  @ @ @@ @@ @ @@ @ @@ @ @                        @ @@      @@@
     @@@@@@  @ @@@ @ @@      @  @@ @@ @@@@@ @@@@@@@@@@@@@@@                          @@ @    @@ @
  @@@@ @@ @@@ @ @ @@@@ @      @@ @ @@   @     @@@@@@@@@@@ @@                        @ @@    @ @  
  @@   @@  @ @@@@@    @      @ @@@@@ @@      @@ @@@@@@@   @ @                        @@ @    @ @@
   @@@@  @@ @  @ @@           @  @   @ @    @ @   @@@ @@@  @                        @ @@      @  
      @@@ @@ @@ @@ @           @@  @  @      @  @@@@   @@@@                          @@ @      @@
  @  @@@  @@ @@ @@@           @  @@ @@        @@@  @@@@@  @@                        @ @@      @@ 
  @@@@@@@@ @ @@  @@@           @@ @ @ @      @@@@@@@ @ @@@  @                        @@ @    @ @ 
  @@@@@@  @@@@ @@@@@@         @ @@@@@@      @@ @@@  @@@ @@@@                        @ @@      @@@
  @@@@ @@@@      @@ @@         @  @@ @@    @ @  @@@@@@     @@                        @@ @    @@ @
  @@      @@    @ @ @ @         @@ @ @ @    @ @@@ @@ @@   @  @                      @ @@    @ @  
   @@    @  @    @@@@@         @ @@@@@@      @ @  @@ @ @@  @@                        @@ @    @ @@
   @ @    @@    @@ @ @@         @  @@ @@      @ @@ @@@@@ @@  @                      @ @@      @  
  @@@    @  @  @ @@@@@ @         @@ @ @ @      @@@   @   @ @@                        @@ @      @@
  @ @@    @@ @@ @  @  @         @ @@@@@@      @@@@@@   @  @@ @                      @ @@      @@ 
    @ @  @ @ @@@ @@ @@           @  @@ @@    @@ @@ @@@  @@ @@                        @@ @    @ @ 
  @@ @ @@ @@@ @  @@ @ @           @@ @ @ @  @ @ @@  @@@@ @ @ @                      @ @@      @@@
    @@@@@  @ @ @@ @@@@           @ @@@@@@ @@ @@@@ @@@   @@@@@                        @@ @    @@ @
  @@@ @ @@@ @@@@@    @@           @  @@   @@       @@@@@@ @ @@                      @ @@    @ @  
  @  @@@ @    @ @@  @  @           @@  @@@  @     @@ @@  @@@@ @                      @@ @    @ @@
  @@@@@ @      @@ @@ @@           @  @@@@@@@     @ @ @ @@@   @                      @ @@      @  
  @@@  @      @ @ @@ @ @           @@@ @@@ @@     @@@@@ @@@@                         @@ @      @@
  @ @@@        @@@@@@@@           @@@   @  @ @   @@ @      @@                       @ @@      @@ 
     @@@      @@ @@@@ @@         @@@@@@  @@ @  @@ @@      @  @                       @@ @    @ @ 
  @@@@@@@    @ @      @ @       @@ @@ @@@ @@ @@ @ @ @      @@                       @ @@      @@@
  @@@@@ @@    @        @       @ @ @@  @  @@ @@@@@@@      @  @                       @@ @    @@ @
  @@@   @ @                     @@@@ @@ @@ @   @@@ @@      @@                       @ @@    @ @  
  @ @@@  @                     @@    @@ @@@  @@@@  @ @    @  @                       @@ @    @ @@
     @@@@                     @  @  @ @  @@@@@  @@@ @      @@                       @ @@      @  
  @@@@  @@                     @@ @@ @ @@@ @ @@@@@ @      @  @                       @@ @      @@
  @@ @@@  @                   @ @ @@@@@ @ @@@  @  @        @@                       @ @@      @@ 
      @@@@                     @@@  @  @@@ @@@@ @@        @  @                       @@ @    @ @ 
  @  @@  @@                   @@@@@@ @@@@       @ @        @@                       @ @@      @@@
  @@@  @@  @                 @@ @@      @@       @        @  @                       @@ @    @@ @
  @ @@@  @@                 @ @ @ @    @  @                @@                       @ @@    @ @  
     @@@@  @                 @@@@@      @@                @  @                       @@ @    @ @@
  @@@@  @@@                 @@ @ @@    @  @                @@                       @ @@      @  
  @@ @@@@@@@               @ @@@@@ @    @@                @  @                       @@ @      @@
       @@@ @@               @  @  @    @  @                @@                       @ @@      @@ 
  @   @@@  @ @               @@ @@      @@                @  @                       @@ @    @ @ 
  @@@@@@@@@ @               @ @ @ @    @  @                @@                       @ @@      @@@
  @@@@@@@  @                 @@@@@      @@                @  @                       @@ @    @@ @
  @@@@@ @@@                 @@ @ @@    @  @                @@                       @ @@    @ @  
  @@@    @@@               @ @@@@@ @    @@                @  @                       @@ @    @ @@
  @ @@  @@@@@               @  @  @    @  @                @@                       @ @@      @  
Time: 4857mS

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.

-Gordon

2 Likes

ooh, your compiler’s all fancy-like and accepts { … }. I had to make do with $( etc with the Arnor BCPL compiler for the Amstrad CPC.

2 Likes