Skip to content

Commit

Permalink
The vimscript (and Haskell) presented at the Boston Vim meetup, showi…
Browse files Browse the repository at this point in the history
…ng Conway's Game of Life.
  • Loading branch information
mike-burns committed Jan 24, 2012
0 parents commit 00eadae
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 0 deletions.
59 changes: 59 additions & 0 deletions gameOfLife.hs
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,59 @@
import Data.Maybe

data Cell = Alive | Dead deriving (Eq, Show)

tick board = rowsTick 0 board board

rowsTick _ [] _ = []
rowsTick rowNumber (row:rows) board =
(rowTick row board rowNumber 0):(rowsTick (rowNumber+1) rows board)

rowTick [] _ _ _ = []
rowTick (cell:cells) board rowNumber columnNumber =
tickedCell:(rowTick cells board rowNumber (columnNumber+1))
where tickedCell = cellTick cell board rowNumber columnNumber

cellTick cell board rowNumber columnNumber =
transition cell $ liveNeighborsCount board rowNumber columnNumber

liveNeighborsCount board rowNumber columnNumber =
length $ filter (Alive==) neighboringCells
where neighboringCells = [
board `at` (rowNumber-1,columnNumber-1),
board `at` (rowNumber-1,columnNumber),
board `at` (rowNumber-1,columnNumber+1),
board `at` (rowNumber, columnNumber-1),
board `at` (rowNumber, columnNumber+1),
board `at` (rowNumber+1, columnNumber-1),
board `at` (rowNumber+1, columnNumber),
board `at` (rowNumber+1, columnNumber+1)]

transition Alive 2 = Alive
transition Alive 3 = Alive
transition Dead 3 = Alive
transition _ _ = Dead

at board (rowNumber, columnNumber)
| rowNumber < 0 || columnNumber < 0 = Dead
| otherwise = maybe Dead id foundCell
where
foundCell =
(listToMaybe $ drop rowNumber board) >>=
listToMaybe . drop columnNumber


inputBoard = [
[Alive,Alive,Dead ,Dead ]
,[Dead ,Alive,Dead ,Dead ]
,[Alive,Alive,Dead ,Alive]
,[Dead ,Dead ,Dead ,Dead ]
]

outputBoard = [
[Alive,Alive,Dead ,Dead ]
,[Dead ,Dead ,Dead ,Dead ]
,[Alive,Alive,Alive,Dead ]
,[Dead ,Dead ,Dead ,Dead ]
]

main = putStrLn $ show $ tick inputBoard == outputBoard
84 changes: 84 additions & 0 deletions game_of_life.vim
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,84 @@
function! Transition(cell, numberOfLiveNeighbors)
if a:cell == "*" && (a:numberOfLiveNeighbors == 2 || a:numberOfLiveNeighbors == 3)
return "*"
elseif a:cell == "o" && a:numberOfLiveNeighbors == 3
return "*"
else
return "o"
endif
endfunction

function! At(matrix, x, y)
if a:x < 0 || a:y < 0
return "o"
else
return get(get(a:matrix, a:x, []), a:y, "o")
endif
endfunction

function! NeighboringCells(board, x, y)
return [ At(a:board, a:y-1, a:x-1), At(a:board, a:y-1, a:x), At(a:board, a:y-1, a:x+1), At(a:board, a:y, a:x-1), At(a:board, a:y, a:x+1), At(a:board, a:y+1, a:x-1), At(a:board, a:y+1, a:x), At(a:board, a:y+1, a:x+1) ]
endfunction

function! LiveNeighborsCount(board, x, y)
let l:neighbors = NeighboringCells(a:board, a:x, a:y)
return count(l:neighbors, "*")
endfunction

function! CellTick(cell, board, x, y)
let l:neighborsCount = LiveNeighborsCount(a:board, a:x, a:y)
return Transition(a:cell, l:neighborsCount)
endfunction

function! RowTick(row, board, x, y)
if a:row == []
return []
else
let l:cell = a:row[0]
let l:cells = a:row[1:]
let l:transitionedCell = CellTick(l:cell, a:board, a:x, a:y)
return [l:transitionedCell] + RowTick(l:cells, a:board, a:x+1, a:y)
endif
endfunction

function! RowsTick(y, rs, board)
if a:rs == []
return []
else
let l:row = a:rs[0]
let l:rows = a:rs[1:]
let l:transitionedRow = RowTick(l:row, a:board, 0, a:y)
return [l:transitionedRow] + RowsTick(a:y+1, l:rows, a:board)
endif
endfunction

function! Tick(board)
return RowsTick(0, a:board, a:board)
endfunction

function! UITick()
let l:board = []
for unparsedRow in getbufline(bufnr('%'), 1, '$')
let l:parsedRow = split(unparsedRow, ' ')
let l:board = add(l:board, l:parsedRow)
endfor

let l:nextBoard = Tick(l:board)

let l:nextBuffer = []
for nextRow in l:nextBoard
let l:nextLine = join(nextRow, ' ')
let l:nextBuffer = add(l:nextBuffer, l:nextLine)
endfor

normal! ggdG
exe "normal! i".join(l:nextBuffer, "\<cr>")."\<esc>"
endfunction

function! RunGameOfLife()
while 1
call UITick()
redraw
sleep 1
endwhile
endfunction
9 changes: 9 additions & 0 deletions game_of_life_test.vim
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,9 @@
source test_unit.vim
source game_of_life.vim

call AssertEqual(Transition("*", 2), "*" )
call AssertEqual(Transition("*", 3), "*" )
call AssertEqual(Transition("o", 3), "*" )
call AssertEqual(Transition("*", 4), "o" )

call AssertEqual(At([["a","b"],["c","d"]], 4, 5), "o")
7 changes: 7 additions & 0 deletions test_unit.vim
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,7 @@
function! AssertEqual(actual, expected)
if a:actual == a:expected
echon "."
else
echom "Expected " . a:expected . " but got " . a:actual
end
endfunction

0 comments on commit 00eadae

Please sign in to comment.