Thread Rating:
  • 1 Vote(s) - 4 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Thunderbird Methuselah (Game of Life)
#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


Messages In This Thread
RE: Thunderbird Methuselah (Game of Life) - by 1micha.elok - 01-23-2025, 08:50 AM

Forum Jump:


Users browsing this thread: 1 Guest(s)