{-# LANGUAGE DeriveGeneric #-} module Automata where import Comonad import Spaces.Space1 import Spaces.Space2 import System.Random import GHC.Generics import Control.DeepSeq ----------------------- -- cellular automata -- ----------------------- -- the states our cells can be in -- may need to provide an ordering -- may need to generalise the number -- of states data CellState = Rock | Paper | Scissors deriving (Eq, Bounded, Enum, Generic) instance NFData CellState instance Random CellState where random g = case randomR (fromEnum (minBound :: CellState), fromEnum (maxBound :: CellState)) g of (r, g') -> (toEnum r, g') randomR (a,b) g = case randomR (fromEnum a, fromEnum b) g of (r, g') -> (toEnum r, g') -- how the states are displayed on screen -- this should probably be input to a function -- rather than hardcoded instance Show CellState where show Rock = "⬤" show Paper = " " show Scissors = "_" -- -- a rule stating how a cell is determined -- rule :: Space CellState -> CellState -- rule (Space (l:_) _ (r:_)) -- | l == r = Dead -- | otherwise = Alive -- -- -- a second rule for example -- rule2 :: Space CellState -> CellState -- rule2 (Space (l1:l2:_) m (r1:r2:_)) -- | m == Alive && numAlive == 1 = Dead -- | m == Alive && numAlive == 4 = Dead -- | m == Dead && numAlive == 3 = Alive -- | otherwise = m -- where -- ns = [l1, l2, r1, r2] -- numAlive = length $ filter (== Alive) ns -- -- rule3 :: Space CellState -> CellState -- rule3 (Space (l:_) m (r:_)) -- | l == r = m -- | otherwise = if m == Alive then Dead else Alive -------------- -- 2d rules -- -------------- rps :: Space2 CellState -> CellState rps (Space2 u m d) = case me of Rock -> if (length $ filter (== Paper) ns) > 2 then Paper else Rock Paper -> if (length $ filter (== Scissors) ns) > 2 then Scissors else Paper Scissors -> if (length $ filter (== Rock) ns) > 2 then Rock else Scissors where f b (Space (l:_) m (r:_)) = [l,r] ++ (if b then [m] else []) f b (Space [] m (r:_)) = [r] ++ (if b then [m] else []) f b (Space (l:_) m []) = [l] ++ (if b then [m] else []) f b (Space [] m []) = if b then [m] else [] safeHead _ [] = [] safeHead b (x:_) = f b x ns = concat [ (safeHead True u), (f False m), (safeHead True d) ] me = extract m --conway :: Space2 CellState -> CellState --conway (Space2 (u:_) m (d:_)) -- = case me of -- Alive -> if (length ns) == 2 || (length ns == 3) then Alive else Dead -- Dead -> if (length ns) == 3 then Alive else Dead -- where -- f b (Space (l:_) m (r:_)) = [l,r] ++ (if b then [m] else []) -- ns = filter (== Alive) $ concat [ (f True u), (f False m), (f True d) ] -- me = extract m