John Conway's 'Life' on ESP32.

Place your projects here
Post Reply
AndyGadget
Posts: 222
Joined: Mon Feb 15, 2021 1:44 pm
Has thanked: 125 times
Been thanked: 132 times

John Conway's 'Life' on ESP32.

Post by AndyGadget »

Here is a simple implementation of John Conway's 'Life' cellular automaton.
If you haven't heard of it, Wikipedia has plenty of information : https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life

'True' life assumes an infinite 'universe' but not having a suitably sized TFT panel and a quantum computer to hand I've done it on a TFT screen with a 32x24 cell grid which is re-entrant, so a pattern disappearing off one edge will reappear on the opposite edge. It could easily be modified for other sizes but I thought this gave a reasonable tradeoff between speed, activity and display aesthetics. It will also detect (in most cases) when the pattern has stabilised or died out and generate a new start pattern.

Once round the calculate / display loop with 50 or so cells alive is around 1210 milliseconds with my program.
I throw out the challenge to write a faster version :D

(Francesco, this is on Annex32 BLE CAN 1.50.1 LFS but inc/dec is not recognised. Is this only added in the newer versions with the VGA commands?)

Code: [Local Link Removed for Guests]

'
' John Conway's Life Cellular Automaton
' in a 32 x 24 cell re-entrant universe.
' No delays...this is flat out :¬)
'
tft.init 1
tft.brightness 255

dim Life(1,32,24)

INow = 0
INxt = 1
LiveCnt = 0
LiveCntx = 0
Stale = 0

Density = 6 ' Change this to make a more or less dense starting pattern.

gosub SetupLife


' Main Loop
do

T1 = millis

  gosub CalcLife
  gosub ShowLife
  
  ' Current / next screen alternates between Life array (0,x,y) and (1,x,y)
  ' Next screen is prepared in background so no calculation required when redrawing display.
  INow = INxt
  INxt = (INxt + 1) mod 2
  
  ' Basic check for a stale or empty screen and restart if so  
  if LiveCnt = LiveCntx then
    Stale = Stale + 1
    if (Stale = 8) or (LiveCnt = 0) then
      Stale = 0
      gosub SetupLife
    end if
  else
    Stale = 0
  end if

' Show live cells and loop time in milliseconds  
 wlog LiveCnt, (millis - T1) 
  
loop

SetupLife:
' Clear screen and set new random start pattern
tft.fill blue
INow = 0
INxt = 1
for x = 4 to 28
  for y = 4 to 20
    Life(0,x,y) = 0
    if rnd(Density) = 0 then Life(0,x,y) = 1
  next y
next x
return

CalcLife:
' Scan array and generate screen for next generation

LiveCntx = LiveCnt
LiveCnt = 0

for x = 0 to 31
  for y = 0 to 23
    Life(INxt,x,y) = 0
    
    AdjCnt = 0
    Xm1 = (x-1) mod 32
    Xp1 = (x+1) mod 32
    Ym1 = (y-1) mod 24
    Yp1 = (y+1) mod 24
    
    ' Count number of adjacent live AdjCntls
    if Life(INow,xm1,y) then AdjCnt = AdjCnt + 1
    if Life(INow,xp1,y) then AdjCnt = AdjCnt + 1
    if Life(INow,x, yp1) then AdjCnt = AdjCnt + 1
    if Life(INow,x,ym1) then AdjCnt = AdjCnt + 1
    if Life(INow,xm1,ym1) then AdjCnt = AdjCnt + 1
    if Life(INow,xp1,ym1) then AdjCnt = AdjCnt + 1
    if Life(INow,xm1,yp1) then AdjCnt = AdjCnt + 1
    if Life(INow,xp1,yp1) = 1 then AdjCnt = AdjCnt + 1
    
    if (Life(INow,x,y)) and (AdjCnt = 2)  then Life(INxt,x,y) = 1 : LiveCnt = LiveCnt + 1 ' Existing Cell alive if 2 neighbours
    if (AdjCnt = 3) then Life(INxt,x,y) = 1 : LiveCnt = LiveCnt + 1 ' New Cell if 3 neighbours
  next y
next x

return

ShowLife:
' Display next generation screen
for y = 0 to 23
  for x = 0 to 31
    if (Life(INow,x,y)) then
      tft.circle x*10,y*10,5,yellow,1
    else
      tft.circle x*10,y*10,5,blue,1
    end if
  next x
next y
return
Last edited by AndyGadget on Mon Jul 31, 2023 12:27 pm, edited 3 times in total.
User avatar
cicciocb
Site Admin
Posts: 2055
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 439 times
Been thanked: 1354 times
Contact:

Re: John Conway's 'Life' on ESP32.

Post by cicciocb »

yes, inc and dec are not yet "officially" supported
User avatar
cicciocb
Site Admin
Posts: 2055
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 439 times
Been thanked: 1354 times
Contact:

Re: John Conway's 'Life' on ESP32.

Post by cicciocb »

This is a version "cheated" using the VGA
I removed the "then" (optional) and used the INC
I use a double pages for having a redraw without transitions
It takes around 820 msec

Code: [Local Link Removed for Guests]

'' John Conway's Life Cellular Automaton
' in a 32 x 24 cell re-entrant universe.
' No delays...this is flat out :¬)
'
vga.pinout 4,5,6, 7,15,16, 17, 18, 8,3
vga.delete
vga.init 0, 2

tft.init 1
tft.brightness 255

dim Life(1,32,24)

INow = 0
INxt = 1
LiveCnt = 0
LiveCntx = 0
Stale = 0
gosub SetupLife


' Main Loop
do

T1 = millis

  gosub CalcLife
  gosub ShowLife
  
  ' Current / next screen alternates between Life array (0,x,y) and (1,x,y)
  ' Next screen is prepared in background so no calculation required when redrawing display.
  INow = INxt
  INxt = (INxt + 1) mod 2
  
  ' Basic check for a stale or empty screen and restart if so  
  if LiveCnt = LiveCntx then
    Stale = Stale + 1
    if (Stale = 8) or (LiveCnt = 0) then
      Stale = 0
      gosub SetupLife
    end if
  else
    Stale = 0
  end if

' Show live cells and loop time in milliseconds  
wlog LiveCnt, (millis - T1) 
  
loop

SetupLife:
' Clear screen and set new random start pattern
vga.writepage 1
vga.fill blue
vga.writepage 0
vga.fill blue
act = 0 ' active page
vga.showpage 1
tft.fill blue

INow = 0
INxt = 1
for x = 4 to 28
  for y = 4 to 20
    Life(0,x,y) = 0
    if rnd(6) = 0 then Life(0,x,y) = 1
  next y
next x
return

' Scan array and generate screen for next generation
CalcLife:
LiveCntx = LiveCnt
LiveCnt = 0
for x = 0 to 32
  for y = 0 to 24
    Life(INxt,x,y) = 0
    AdjCnt = 0
    Xm1 = (x-1) mod 32
    Xp1 = (x+1) mod 32
    Ym1 = (y-1) mod 24
    Yp1 = (y+1) mod 24
    if Life(INow,xm1,y) = 1 inc AdjCnt     ' Count number of adjacent live cells
    if Life(INow,xp1,y) = 1 inc AdjCnt
    if Life(INow,x, yp1) = 1 inc AdjCnt
    if Life(INow,x,ym1) = 1 inc AdjCnt
    if Life(INow,xm1,ym1) = 1 inc AdjCnt
    if Life(INow,xp1,ym1) = 1 inc AdjCnt
    if Life(INow,xm1,yp1) = 1 inc AdjCnt
    if Life(INow,xp1,yp1) = 1 inc AdjCnt
    if (Life(INow,x,y) = 1) and (AdjCnt = 2) Life(INxt,x,y) = 1 : LiveCnt = LiveCnt + 1 ' Existing Cell alive if 2 neighbours
    if (AdjCnt = 3) Life(INxt,x,y) = 1 : LiveCnt = LiveCnt + 1 ' New Cell if 3 neighbours
  next y
next x
return

' Display next generation screen
ShowLife:
vga.writepage act
vga.fill blue
for y = 0 to 24
  for x = 0 to 32
    if (Life(INow,x,y) = 1) vga.circle x*10,y*10,5,yellow,1
  next x
next y
vga.showpage act
act = 1-act
vga.writepage act
return

User avatar
Electroguard
Posts: 860
Joined: Mon Feb 08, 2021 6:22 pm
Has thanked: 274 times
Been thanked: 322 times

Re: John Conway's 'Life' on ESP32.

Post by Electroguard »

The 'big screen' VGA version looks good (3 TFT references to comment out).
Was also impressed just by the smoothness of the vga background gradient (am interested in seeing how that was done).
Offers another interesting screensaver to add to the VGA collection.
RonS
Posts: 115
Joined: Thu Mar 02, 2023 10:15 pm
Location: germany
Has thanked: 64 times
Been thanked: 23 times

Re: John Conway's 'Life' on ESP32.

Post by RonS »

I'm getting a "syntax error"
in the case of the " IF Statments" - presumably because of the "inc"
use :Annex32-S3 CAN DMT VGA 1.51.1 qio opi LFS

Ron


[Local Link Removed for Guests] wrote: [Local Link Removed for Guests]Mon Jul 31, 2023 5:35 pm This is a version "cheated" using the VGA
I removed the "then" (optional) and used the INC
I use a double pages for having a redraw without transitions
It takes around 820 msec

Code: [Local Link Removed for Guests]

'' John Conway's Life Cellular Automaton
' in a 32 x 24 cell re-entrant universe.
' No delays...this is flat out :¬)
'
vga.pinout 4,5,6, 7,15,16, 17, 18, 8,3
vga.delete
vga.init 0, 2

tft.init 1
tft.brightness 255

dim Life(1,32,24)

INow = 0
INxt = 1
LiveCnt = 0
LiveCntx = 0
Stale = 0
gosub SetupLife


' Main Loop
do

T1 = millis

  gosub CalcLife
  gosub ShowLife
  
  ' Current / next screen alternates between Life array (0,x,y) and (1,x,y)
  ' Next screen is prepared in background so no calculation required when redrawing display.
  INow = INxt
  INxt = (INxt + 1) mod 2
  
  ' Basic check for a stale or empty screen and restart if so  
  if LiveCnt = LiveCntx then
    Stale = Stale + 1
    if (Stale = 8) or (LiveCnt = 0) then
      Stale = 0
      gosub SetupLife
    end if
  else
    Stale = 0
  end if

' Show live cells and loop time in milliseconds  
wlog LiveCnt, (millis - T1) 
  
loop

SetupLife:
' Clear screen and set new random start pattern
vga.writepage 1
vga.fill blue
vga.writepage 0
vga.fill blue
act = 0 ' active page
vga.showpage 1
tft.fill blue

INow = 0
INxt = 1
for x = 4 to 28
  for y = 4 to 20
    Life(0,x,y) = 0
    if rnd(6) = 0 then Life(0,x,y) = 1
  next y
next x
return

' Scan array and generate screen for next generation
CalcLife:
LiveCntx = LiveCnt
LiveCnt = 0
for x = 0 to 32
  for y = 0 to 24
    Life(INxt,x,y) = 0
    AdjCnt = 0
    Xm1 = (x-1) mod 32
    Xp1 = (x+1) mod 32
    Ym1 = (y-1) mod 24
    Yp1 = (y+1) mod 24
    if Life(INow,xm1,y) = 1 inc AdjCnt     ' Count number of adjacent live cells
    if Life(INow,xp1,y) = 1 inc AdjCnt
    if Life(INow,x, yp1) = 1 inc AdjCnt
    if Life(INow,x,ym1) = 1 inc AdjCnt
    if Life(INow,xm1,ym1) = 1 inc AdjCnt
    if Life(INow,xp1,ym1) = 1 inc AdjCnt
    if Life(INow,xm1,yp1) = 1 inc AdjCnt
    if Life(INow,xp1,yp1) = 1 inc AdjCnt
    if (Life(INow,x,y) = 1) and (AdjCnt = 2) Life(INxt,x,y) = 1 : LiveCnt = LiveCnt + 1 ' Existing Cell alive if 2 neighbours
    if (AdjCnt = 3) Life(INxt,x,y) = 1 : LiveCnt = LiveCnt + 1 ' New Cell if 3 neighbours
  next y
next x
return

' Display next generation screen
ShowLife:
vga.writepage act
vga.fill blue
for y = 0 to 24
  for x = 0 to 32
    if (Life(INow,x,y) = 1) vga.circle x*10,y*10,5,yellow,1
  next x
next y
vga.showpage act
act = 1-act
vga.writepage act
return

Modules : 3xESP32-Cam MB (Chip"DM ESP32 S" ),AI-Thinker Audio Kit (ES8388), ESP32 Dev Kit with Display
User avatar
cicciocb
Site Admin
Posts: 2055
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 439 times
Been thanked: 1354 times
Contact:

Re: John Conway's 'Life' on ESP32.

Post by cicciocb »

Yes, simply replace inc with incr
Post Reply