module Simulation where import Data.Array data State = Alive | Dead deriving (Eq) type Row = Array Int State type Grid = Array Int Row data Board = Board {bGrid :: Grid, bRows :: Int, bCols :: Int} deriving (Show) data Coord = Coord Int Int deriving (Show) instance Num Coord where Coord a b + Coord c d = Coord (a+c) (b+d) Coord a b - Coord c d = Coord (a-c) (b-d) instance Show State where show Alive = "■" show Dead = " " directions :: [Coord] directions = [Coord y x | y <- [-1..1], x <- [-1..1], not (x==0 && y==0)] neighbors :: Board -> Coord -> [Coord] neighbors board coord = filter (\c -> state board c == Alive) validCoords where validCoords = filter (validCoord board) coordsAround coordsAround = map (+ coord) directions validCoord :: Board -> Coord -> Bool validCoord board (Coord y x) = xValid && yValid where xValid = x >= 0 && x < bCols board yValid = y >= 0 && y < bRows board numNeighbors :: Board -> Coord -> Int numNeighbors board coord = length $ neighbors board coord state :: Board -> Coord -> State state board (Coord y x) = (bGrid board) ! y ! x singleStep :: Board -> Coord -> State singleStep board coord = stepCell currentState bors where currentState = state board coord bors = numNeighbors board coord stepCell :: State -> Int -> State stepCell Dead 3 = Alive stepCell Dead _ = Dead stepCell Alive n | n < 2 = Dead | n > 3 = Dead | otherwise = Alive step :: Board -> Board step board = board {bGrid = newGrid} where newGrid :: Grid newGrid = listArray (0, rs-1) $ map newRow [0..rs-1] newRow :: Int -> Row newRow y = listArray (0,cs-1) $ [singleStep board (Coord y x) | x <- [0..(cs)-1]] cs = bCols board rs = bRows board