Permalink
Browse files

The vimscript (and Haskell) presented at the Boston Vim meetup, showi…

…ng Conway's Game of Life.
  • Loading branch information...
0 parents commit 00eadae9a27c34c597363139225bf6039e6d22d6 @mike-burns committed Jan 24, 2012
Showing with 159 additions and 0 deletions.
  1. +59 −0 gameOfLife.hs
  2. +84 −0 game_of_life.vim
  3. +9 −0 game_of_life_test.vim
  4. +7 −0 test_unit.vim
@@ -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
@@ -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
@@ -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")
@@ -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.