diff --git a/BriansBrain.hs b/BriansBrain.hs
new file mode 100644
--- /dev/null
+++ b/BriansBrain.hs
@@ -0,0 +1,49 @@
+import Data.Array             -- Used to store the world state for processing
+import System.Random          -- Used to generate the initial random world
+import Control.Monad          -- Used for some fancy looping constructs
+import Control.Concurrent     -- Used to fork the quit event handler
+import Graphics.UI.SDL as SDL -- Used to draw the pretty pictures
+import Control.Parallel.Strategies
+
+data Cell  = Off | Dying | On deriving (Eq, Enum)
+
+worldX   = 90                -- The horizontal size of the world
+worldY   = 90                -- The vertical size of the world
+cellSize = 8                 -- The overall size of a cell
+border   = 1                 -- The border width between cells
+screenX  = worldX * cellSize -- The horizontal size of the world, in pixels
+screenY  = worldY * cellSize -- The vertical size of the world, in pixels
+fillSize = cellSize - border -- The size of the filled area in each cell
+
+stepCell (Off,   2) = On     -- If a dead cell has 2 live neighbors, turn on
+stepCell (Off,   _) = Off    --   Otherwise, just stay turned off
+stepCell (Dying, _) = Off    -- Dying cells always turn off
+stepCell (On,    _) = Dying  -- Live cells always start to die
+
+indexArray x y = listArray ((1,1),(x,y)) [(a,b) | a <- [1..x], b <- [1..y]]
+stepWorld w    = newWorld `using` parArr rwhnf
+  where newWorld = fmap (stepCell . getPeers w) $ indexArray worldX worldY
+
+getPeers world (x,y) = (world ! (x,y), length . filter (== On) $ neighbors)
+  where neighbors    = [getCell x y | x <- [x-1 .. x+1], y <- [y-1 .. y+1]]
+        getCell x y  = world ! (clip worldX x, clip worldY y)
+        clip max val | val <  1  = clip max $ val + max - 1
+                     | val > max = clip max $ val - max + 1
+                     | otherwise = val
+
+main = do rng <- newStdGen
+          SDL.init [SDL.InitVideo]
+          SDL.setCaption "Brian's Purely Functional Brain" "Brian's Brain"
+          surface <- SDL.setVideoMode screenX screenY 24 [SDL.DoubleBuf]
+          forkIO . forever $ waitEvent >>= \e -> when (e == Quit) quit
+          mapM (drawWorld surface) (iterate stepWorld $ world rng)
+  where world = listArray ((1,1),(worldX,worldY)) . map toEnum . randomRs (0,2)
+
+drawWorld s w = do sequence [draw x y | x <- [1..worldX], y <- [1..worldY]]
+                   SDL.flip s
+  where draw x y = SDL.fillRect s (Just rect) . color $ w ! (x,y)
+          where rect        = SDL.Rect (scale x) (scale y) fillSize fillSize
+                scale n     = (n - 1) * cellSize
+                color On    = SDL.Pixel 0x00FFFFFF
+                color Dying = SDL.Pixel 0x00888888
+                color Off   = SDL.Pixel 0x00000000
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,28 @@
+Copyright (c) 2009, Will Donnelly
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the name of the software nor the names of its contributors
+      may be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,5 @@
+#!/usr/bin/env runhaskell
+
+import Distribution.Simple
+
+main = defaultMain
diff --git a/brians-brain.cabal b/brians-brain.cabal
new file mode 100644
--- /dev/null
+++ b/brians-brain.cabal
@@ -0,0 +1,27 @@
+name:          brians-brain
+version:       0.0.1
+category:      Game
+synopsis:      A Haskell implementation of the Brian's Brain cellular automaton
+
+description:   The Brian's Brain cellular automaton implemented in just 49 lines
+               of Haskell, with fancy GUI and everything.
+
+homepage:      http://github.com/willdonnelly/brians-brain
+bug-reports:   http://github.com/willdonnelly/brians-brain/issues
+stability:     alpha
+author:        Will Donnelly
+maintainer:    Will Donnelly <will.donnelly@gmail.com>
+copyright:     (c) 2009 Will Donnelly
+license:       BSD3
+license-file:  LICENSE
+
+build-type:    Simple
+cabal-version: >= 1.6
+
+executable "brians-brain"
+  main-is:       BriansBrain.hs
+  build-depends: base >= 4 && < 5, parallel, SDL, random, array
+
+source-repository head
+  type:      git
+  location:  git://github.com/willdonnelly/brians-brain.git
