a one dimensional cellular automata, using comonads
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

91 line
2.7KB

  1. {-# LANGUAGE DeriveGeneric #-}
  2. module Automata where
  3. import Comonad
  4. import Spaces.Space1
  5. import Spaces.Space2
  6. import System.Random
  7. import GHC.Generics
  8. import Control.DeepSeq
  9. -----------------------
  10. -- cellular automata --
  11. -----------------------
  12. -- the states our cells can be in
  13. -- may need to provide an ordering
  14. -- may need to generalise the number
  15. -- of states
  16. data CellState = Rock | Paper | Scissors
  17. deriving (Eq, Bounded, Enum, Generic)
  18. instance NFData CellState
  19. instance Random CellState where
  20. random g = case randomR (fromEnum (minBound :: CellState), fromEnum (maxBound :: CellState)) g of
  21. (r, g') -> (toEnum r, g')
  22. randomR (a,b) g = case randomR (fromEnum a, fromEnum b) g of
  23. (r, g') -> (toEnum r, g')
  24. -- how the states are displayed on screen
  25. -- this should probably be input to a function
  26. -- rather than hardcoded
  27. instance Show CellState
  28. where
  29. show Rock = "⬤"
  30. show Paper = " "
  31. show Scissors = "_"
  32. -- -- a rule stating how a cell is determined
  33. -- rule :: Space CellState -> CellState
  34. -- rule (Space (l:_) _ (r:_))
  35. -- | l == r = Dead
  36. -- | otherwise = Alive
  37. --
  38. -- -- a second rule for example
  39. -- rule2 :: Space CellState -> CellState
  40. -- rule2 (Space (l1:l2:_) m (r1:r2:_))
  41. -- | m == Alive && numAlive == 1 = Dead
  42. -- | m == Alive && numAlive == 4 = Dead
  43. -- | m == Dead && numAlive == 3 = Alive
  44. -- | otherwise = m
  45. -- where
  46. -- ns = [l1, l2, r1, r2]
  47. -- numAlive = length $ filter (== Alive) ns
  48. --
  49. -- rule3 :: Space CellState -> CellState
  50. -- rule3 (Space (l:_) m (r:_))
  51. -- | l == r = m
  52. -- | otherwise = if m == Alive then Dead else Alive
  53. --------------
  54. -- 2d rules --
  55. --------------
  56. rps :: Space2 CellState -> CellState
  57. rps (Space2 u m d)
  58. = case me of
  59. Rock -> if (length $ filter (== Paper) ns) > 2 then Paper else Rock
  60. Paper -> if (length $ filter (== Scissors) ns) > 2 then Scissors else Paper
  61. Scissors -> if (length $ filter (== Rock) ns) > 2 then Rock else Scissors
  62. where
  63. f b (Space (l:_) m (r:_)) = [l,r] ++ (if b then [m] else [])
  64. f b (Space [] m (r:_)) = [r] ++ (if b then [m] else [])
  65. f b (Space (l:_) m []) = [l] ++ (if b then [m] else [])
  66. f b (Space [] m []) = if b then [m] else []
  67. safeHead _ [] = []
  68. safeHead b (x:_) = f b x
  69. ns = concat [ (safeHead True u), (f False m), (safeHead True d) ]
  70. me = extract m
  71. --conway :: Space2 CellState -> CellState
  72. --conway (Space2 (u:_) m (d:_))
  73. -- = case me of
  74. -- Alive -> if (length ns) == 2 || (length ns == 3) then Alive else Dead
  75. -- Dead -> if (length ns) == 3 then Alive else Dead
  76. -- where
  77. -- f b (Space (l:_) m (r:_)) = [l,r] ++ (if b then [m] else [])
  78. -- ns = filter (== Alive) $ concat [ (f True u), (f False m), (f True d) ]
  79. -- me = extract m