Thread Rating:
  • 1 Vote(s) - 4 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Thunderbird Methuselah (Game of Life)
#1
             
click each image to zoom in

CONWAY'S GAME OF LIFE
 Just a quick conversion to N7 

 Reference :
 "Thunderbird" methuselah evolution in the Game of Life
 https://rosettacode.org/wiki/Conway%27s_...e#BASIC256


Code:
'==============================================================
' CONWAY'S GAME OF LIFE
' Just a quick conversion to N7 
'
' Reference :
' "Thunderbird" methuselah evolution in the Game of Life
' https://rosettacode.org/wiki/Conway%27s_Game_of_Life#BASIC256
'==============================================================

'set window
#win32
set window "Game of Life",236,140,true
set redraw off

'color definition
black   = [0,0,0]
white   = [255,255,255]
purple  = [128,0,128]
green   = [0,255,0]
red     = [255,0,0]
yellow  = [255,255,0]

X = 59 ; Y = 35 ; H = 4

c = dim(X,Y)
cn = dim(X,Y)
cl = dim(X,Y)

'Thunderbird methuselah pattern
c[X/2-1][Y/3+1] = 1
c[X/2][Y/3+1]   = 1 
c[X/2+1][Y/3+1] = 1   
c[X/2][Y/3+3]   = 1
c[X/2][Y/3+4]   = 1
c[X/2][Y/3+5]   = 1

'initial value
s = 0
start = 1

'main loop
do
    'clear screen
    set color black
    cls
   
    alive = 0 
    stable = 1
    s = s + 1
   
    for y = 0 to Y-1
        for x = 0 to X-1
            xm1 = (x-1+X)%X
            xp1 = (x+1+X)%X
            ym1 = (y-1+Y)%Y
            yp1 = (y+1+Y)%Y
            cn[x][y] = c[xm1][y] + c[xp1][y]
            cn[x][y] = c[xm1][ym1] + c[x][ym1] + c[xp1][ym1] + cn[x][y]
            cn[x][y] = c[xm1][yp1] + c[x][yp1] + c[xp1][yp1] + cn[x][y]
           
            if c[x][y] = 1 then
                if cn[x][y] < 2 or cn[x][y] > 3 then
                    cn[x][y] = 0
                else
                    cn[x][y] = 1
                    alive = alive + 1
                endif
            else
                if cn[x][y] = 3 then
                    cn[x][y] = 1
                    alive = alive + 1
                else
                    cn[x][y] = 0
                endif
            endif
           
            if c[x][y] then
                if cn[x][y] then
                    if cl[x][y] then
                        set color purple        # adult
                    endif
                    if not cl[x][y] then
                        set color green         # newborn
                    endif
                else
                    if cl[x][y] then
                        set color red           # old
                    endif
                    if not cl[x][y] then
                        set color yellow        # shortlived
                    endif
                endif
               
                draw rect x*H,y*H,H,H,true
               
            endif
           
        next
    next
   
    redraw
    fwait 10
   
    # Copy arrays
    for i = 0 to X-1
        for j = 0 to Y-1
            if cl[i][j]<>cn[i][j] then stable = 0
            cl[i][j] = c[i][j]
            c[i][j] = cn[i][j]
        next
    next   
   
    if start then
        set color white
        set caret width()/2, height()-15
        center "Press Enter to Continue"
        redraw
        do;wait 1;until keydown(KEY_RETURN,true)
        start = false
    endif   
   
until not alive or stable

'final message
set color white
set caret width()/2,height()-15
if not alive then
    center "Died in "+s+" iterations"
else
    center "Stabilized in "+(s-2)+" iterations"   
endif
redraw

'Escape to quit
do;wait 1;until keydown(KEY_ESCAPE,true)
Reply
#2
Nice!

I believe there's a version of game of life in N7/examples/other too Smile
Reply
#3
I was wondering why I kept getting the same number of iterations each time I ran the program.

I figured that the randomize statement was missing. It was. But rnd() is never used. Curious. I searched through many 'versions' of Conway's Life and they too did not use randomization. I read through Conway's four "rules" and understood them. But still did not see any form of randomization. Which confirmed my first thought of repeating results... then I kept reading... "The initial pattern constitutes the seed of the system."

Therefore, change the pattern, change the results. Cool. (was this a veiled suggestion of a random pattern generator? lol)

Try this pattern:

c[X/2-1][Y/3+1] = 1
c[X/2][Y/3+1] = 1
c[X/2+1][Y/3+1] = 1 
c[X/2-1][Y/3+1] = 1
c[X/2][Y/3+2] = 1
c[X/2+1][Y/3+3] = 1

Do not interpret my curiosity as a criticism of your version... Just trying to understand how the beastie works....

By the way, well done! I even like the inclusion of colour... very cool.
Logic is the beginning of wisdom.
Reply
#4
 Game of life (MOD)
 Just another modified version

 Features :
 - Two modes:
    R reset mode, where you can create your own pattern or use preset patterns
    S life animation mode, where life is in action
 - Allow intervention (add 1 or more cells) to break a stable & oscillator pattern in the "S" mode
 - Ready to use some preset patterns (1,2,3) either in the "R" or "S" mode
   Then launch preset patterns several times in the "S" mode
 - Sound effect

 Control Key :
 - Left/Right mouse    = add/remove 1 cell
 - 1,2,3                     = preset patterns
 - S                          = start life animation
 - R                          = reset
 - ESC                      = exit

 References :
 - Game of Life by Marcus in N7 folder /examples/other
 - CreateSineSfx by Marcus

 Need help / future improvement :
 - Turn on / off wrapping pattern on the world boundaries
 - Stable pattern in the R mode should stay stable in the S mode
 - Zoom in / out
 - Save and load customized pattern to/from JSON file format
 - Ability to resize the world
 - Add more preset patterns
 - Find and fix any bugs



Code:
'============================================================================
' Game of life (MOD)
' ------------------
' Just another modified version
'
' Features :
' - Two modes:
'     R reset mode, where you can create your own pattern or use preset patterns
'     S life animation mode, where life is in action
' - Allow intervention (add 1 or more cells) to break a stable & oscillator pattern in the "S" mode
' - Ready to use some preset patterns (1,2,3) either in the "R" or "S" mode
'   Then launch preset patterns several times in the "S" mode.
' - Sound effect
'
' Control Key :
' - Left/Right mouse    = add/remove 1 cell
' - 1,2,3               = preset patterns
' - S                   = start life animation
' - R                   = reset
' - ESC                 = exit
'
' References :
' - Game of Life by Marcus in N7 folder /examples/other
' - CreateSineSfx by Marcus
'
' Need help / future improvement :
' - Turn on / off wrapping pattern on the world boundaries
' - Stable pattern in the R mode should stay stable in the S mode
' - Zoom in / out
' - Save and load customized pattern to/from JSON file format
' - Ability to resize the world
' - Add more preset patterns
' - Find and fix any bugs
'============================================================================

constant W = 48, H = 48

'set window size
set window "Game of life (MOD)", W, H, 10
set redraw off

'sound definition (duration, startFreq, endFreq, fadeOut, sampleRate)
visible tiktok = CreateSineSfx(0.02,1500,500,0.05,5000)

' Create a world.
world = CreateWorld(W, H)

'Initial value
visible start = true

'draw grid
Grid(H,W)


'------------
' MAIN LOOP
'------------
' Loop until ESC is pressed.
do
    '--------PRESET PATTERNS-----------------'
   
    set color 255,255,255 
   
    'Johnno's pattern   
    if keydown (KEY_1,true) then
        for i = 23 to 25
            SetCell(world,i,30,1); set pixel i,30
        next
        SetCell(world,24,31,1); set pixel 24,31
        SetCell(world,25,32,1); set pixel 25,32
    endif   
   
    'Glider spaceships pattern
    if keydown(KEY_2,true) then
        SetCell(world,5,5,1); set pixel 5,5
        SetCell(world,6,6,1); set pixel 6,6
        for i = 4 to 6
            SetCell(world,7,i,1);set pixel 7,i
        next
    endif

    'Pentadecathlon pattern
    if keydown(KEY_3,true) then
        for i = 23 to 25
            SetCell(world,i,10,1);set pixel i,10
            SetCell(world,i,19,1);set pixel i,19
        next
        for i = 14 to 15
            SetCell(world,20,i,1); set pixel 20,i
            SetCell(world,28,i,1); set pixel 28,i
        next
        SetCell(world,21,12,1);set pixel 21,12
        SetCell(world,21,17,1);set pixel 21,17
        SetCell(world,22,11,1);set pixel 22,11
        SetCell(world,22,18,1);set pixel 22,18
        SetCell(world,26,11,1);set pixel 26,11
        SetCell(world,26,18,1);set pixel 26,18
        SetCell(world,27,12,1);set pixel 27,12
        SetCell(world,27,17,1);set pixel 27,17
    endif

    '-----------------------------------------'   

    'mouse interactivity
    if mousex()<W-1 then 'boundary limit
        if mousebutton(0)  ModifyLife(world, mousex(), mousey(), 1)
        if mousebutton(1)  ModifyLife(world, mousex(), mousey(), 0)
    endif

    'start
    if start then
        set color 0,0,0
        set caret 52,35
        wln "S"
        set color 255,0,0
        set caret 52,35
        wln "R" 
    endif
   
    'S mode
    if keydown(KEY_S) or start= false then
        UpdateWorld(world,W,H)
        DrawWorld(world, 0, 0, false)
        start = false
        set color 0,0,0
        set caret 52,35
        wln "R"
        set color 0,255,0
        set caret 52,35
        wln "S"
    endif
   
    'restart in R mode
    if keydown(KEY_R) then
        set color 0,0,0
        cls
        set color 255,255,255       
        Grid(H,W)
        world = CreateWorld(W, H) 'reset world
        start = true
        set color 0,0,0
        set caret 52,35
        wln "S"
        set color 255,0,0
        set caret 52,35
        wln "R"
    endif
   
    redraw
    fwait 10
until keydown(KEY_ESCAPE)


'-------------
' FUNCTIONS
'-------------

' CreateWorld
' -----------
function CreateWorld(w, h)
    world = []
    ' These arrays represents the word's current and previous state. We need the
    ' previous when generating the current. They're simply swapped in
    ' UpdateWorld.
    world.c = fill(0, w, h)
    world.p = fill(0, w, h)
    world.w = w   
    world.h = h
    ' UpdateWorld only updates cells that are present in this table. Whenever a
    ' change is made to a cell, it and its neighbors are added to the table.
    ' The table is reset (or rather replaced) every time UpdateWorld executes.
    world.ch = []
   
    world.img = createimage(w, h)
    return world
endfunc

' ModifyLife
' ----------
function ModifyLife(w, cx, cy, value)
    SetCell(w,cx,cy,value)
    if value then
        set color 255,255,255
        set pixel cx,cy
    else
        set color 30,30,30
        set pixel cx,cy
    endif
endfunc

' SetCell
' -------
function SetCell(world, x, y, value)
    x = x%world.w
    y = y%world.h
    world.c[x][y] = value

    ' Only cells that MAY change are handled in UpdateWorld. So add the current
    ' cell and its neighbors to the ch table.
    ' Rather than storing the cell x and y coordinates as values, we
    ' transform them into a key using the forumula k = y*w + x. We can then
    ' extract the coordinates from the key as y = int(k/w) and x = k%w.
    world.ch[((y - 1)%world.h)*world.w + (x - 1)%world.w] = unset
    world.ch[((y - 1)%world.h)*world.w + (x)] = unset
    world.ch[((y - 1)%world.h)*world.w + (x + 1)%world.w] = unset
    world.ch[(y)*world.w + (x - 1)%world.w] = unset
    world.ch[(y)*world.w + (x)] = unset
    world.ch[(y)*world.w + (x + 1)%world.w] = unset
    world.ch[((y + 1)%world.h)*world.w + (x - 1)%world.w] = unset
    world.ch[((y + 1)%world.h)*world.w + (x)] = unset
    world.ch[((y + 1)%world.h)*world.w + (x + 1)%world.w] = unset
endfunc

' UpdateWorld
' -----------
function UpdateWorld(world,W,H)
    tmp = world.p
    world.p = world.c
    world.c = tmp

    ' Grab the ch table, containing cells that may change.
    ch = world.ch
    ' Create a new ch list for the world.
    world.ch = []
    ' Iterate cells that may have changed.
    set image world.img
   
    Grid(W,H)
   
    foreach k, v in ch
        ' Convert the key k into coordinates.
        y = int(k/world.w)
        x = k%world.w
        ' Count neighbors.
        t = (y - 1)%world.h
        b = (y + 1)%world.h
        l = (x - 1)%world.w
        r = (x + 1)%world.w
        n = world.p[l][t] + world.p[x][t] + world.p[r][t]
        n = n + world.p[l][y] + world.p[r][y]
        n = n + world.p[l][b] + world.p[x][b] + world.p[r][b]
        ' Alive?
        if world.p[x][y]
            ' Die.
            if n < 2 or n > 3
                SetCell(world, x, y, 0)
                set color 0, 0, 0
                set pixel x, y
            else
                world.c[x][y] = 1
            endif
        ' Dead.
        else
            ' Live.
            if n = 3
                SetCell(world, x, y, 1)
                set color 55+rnd(200),200+rnd(55),128+rnd(55)
                set pixel x, y
                play sound tiktok,0.5
            else
                world.c[x][y] = 0
            endif
        endif   
    next
   
    set color 155,155,155
    draw rect 0,0,W,H
   
    set image primary
    ' The previous ch list of the world, that we kept in ch, will eventually be
    ' garbage collected. But to avoid high memory usage we can clear it before
    ' it is lost in garbage space.
    clear ch
endfunc


' DrawWorld
' ---------
function DrawWorld(world, x, y, plotAll)
    if plotAll
        set color 0, 0, 0
        draw rect x+1, y+1, world.w-2, world.h-2, true
        set color 255, 255, 255
        for cy = 0 to world.h - 2  for cx = 0 to world.w - 2
            if world.p[cx][cy]  then
                set pixel x + cx, y + cy
            endif
        next
    else
        set color 255, 255, 255
        draw image world.img, x, y
    endif
endfunc

'grid function
function Grid(H,W)
    for i = 1 to H-1 step 2
        for j = 1 to W-1 step 2
            set color 50,50,50
        set pixel j,i
        next
    next
    for i = 2 to H-2 step 2
        for j = 2 to W-2 step 2
            set color 50,50,50
            set pixel j,i
        next
    next
    set color 155,155,155
    draw rect 0,0,W,H
endfunc

'sound effect function
function CreateSineSfx(duration, startFreq, endFreq, fadeOut, sampleRate)
    data = []
    a = 0
    da = 2*PI*startFreq/sampleRate
    dda = (2*PI*endFreq/sampleRate - 2*PI*startFreq/sampleRate)/(duration*sampleRate)
    vol = 1
    fadeOut = fadeOut*duration*sampleRate
    fadeOutDelta = 1/(duration*sampleRate - fadeOut)
    for i = 0 to duration*sampleRate - 1
        data[i] = sin(a)*vol
        a = a + da
        da = da + dda
        if i > fadeOut  vol = vol - fadeOutDelta
    next
    return createsound(data, data, sampleRate)
endfunc
Reply
#5
"just" a mod? You are being too modest. I think even John Conway would be proud of your efforts... Well done!
Logic is the beginning of wisdom.
Reply
#6
Did you check out https://conwaylife.com/wiki/Category:Patterns? I tried some of the space ships from that page in your program Smile
Reply
#7
.. at least 9 pages of Conway patterns .. tested "turtle" and it performed as stated .. Thanks for the link...
Logic is the beginning of wisdom.
Reply
#8
(01-24-2025, 05:57 PM)Marcus Wrote: Did you check out https://conwaylife.com/wiki/Category:Patterns? I tried some of the space ships from that page in your program Smile

In Conway’s Life, the spaceships glide,
Through grids where alien dreams reside.
If Galaga's swarm met their pixel parade,
A cosmic arcade would surely be made!

Cool
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)