Tiny Implementation of Conway’s Life…

I had a few minutes, so I thought I’d try making a graphics demo that runs on the tiny little 0.96″ OLED display I mentioned last week. One of the first programs I ever wrote was an implementation of Conway’s Game of Life, having learned about it from Martin Gardner’s Mathematical Games column in Scientific American. I remember that on my old Atari 400, it took a couple of seconds at least per generation, at a resolution of just 40×20 or so. Because of the limited memory (and small size of the display) I decided a 96×64 resolution. There is just enough memory to handle two full sized bit buffers. With a bit more work, I could make it work at the full resolution of the OLED display, but you need to do some of the updates in place, which makes it a bit harder.

[sourcecode lang=”cpp”]
//
// a tiny implementation of Conway’s Life
// written by Mark VandeWettering (brainwagon@gmail.com)
// https://brainwagon.org
//

#include "U8glib.h"

#define XSIZE (128-32)
#define XSIZE_UINT8 (XSIZE/8)
#define YSIZE (64)

uint8_t current[YSIZE][XSIZE_UINT8] ;
uint8_t next[YSIZE][XSIZE_UINT8] ;

#define MODX(x) (((x)+XSIZE)%XSIZE)
#define MODY(y) (((y)+YSIZE)%YSIZE)

#define ISSET(a, x, y) \
(a[MODY(y)][MODX(x)/8] & (0x1<<(MODX(x)&7)))

#define SET(a, x, y) \
a[MODY(y)][MODX(x)/8] |= (0x1<<(MODX(x)&7))

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);

void
init()
{
int i, j ;
for (j=0; j<YSIZE; j++)
for (i=0; i<XSIZE_UINT8; i++)
current[j][i] = random(256) ;
}

void
setup()
{
randomSeed(analogRead(0));
init() ;
}

void
draw()
{
u8g.setDefaultBackgroundColor() ;
u8g.drawBox(0, 0, 128, 64) ;
u8g.setDefaultForegroundColor() ;
u8g.drawXBM(16, 0, XSIZE, YSIZE, (const uint8_t *) next) ;
}

void
loop()
{
int i, j ;

memset((void *) next, 0, sizeof(next)) ;
for (j=0; j<YSIZE; j++) {
for (i=0; i<XSIZE; i++) {
int sum = 0 ;
if (ISSET(current, i-1, j-1)) sum ++ ;
if (ISSET(current, i , j-1)) sum ++ ;
if (ISSET(current, i+1, j-1)) sum ++ ;
if (ISSET(current, i-1, j )) sum ++ ;
if (ISSET(current, i+1, j )) sum ++ ;
if (ISSET(current, i-1, j+1)) sum ++ ;
if (ISSET(current, i , j+1)) sum ++ ;
if (ISSET(current, i+1, j+1)) sum ++ ;

if (ISSET(current, i, j)) {
if (sum == 2 || sum == 3)
SET(next, i, j) ;
} else {
if (sum == 3)
SET(next, i, j) ;
}
}
}

memcpy((void *) current, (void *) next, sizeof(current)) ;

u8g.firstPage() ;
do {
draw() ;
} while (u8g.nextPage()) ;
}
[/sourcecode]

It works! It initializes the display to random values, and then runs Life. If the display gets boring, just hit the result button….


One thought on “Tiny Implementation of Conway’s Life…

  1. Dak

    Funny parallels: one of the first programs I wrote was Life. In, ah, Fortran. Had a loop detector, too.

Comments are closed.