a one dimensional cellular automata, using comonads
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

123 lignes
3.5KB

  1. {-# LANGUAGE DeriveGeneric #-}
  2. module Spaces.Space2 where
  3. import Comonad
  4. import Spaces.Space1
  5. import System.Random
  6. import Data.Maybe
  7. import Control.DeepSeq
  8. import GHC.Generics
  9. -- a nested space
  10. data Space2 t = Space2 [(Space t)] (Space t) [(Space t)]
  11. deriving (Generic, Generic1, Show)
  12. -- generating strict data instances
  13. instance NFData a => NFData (Space2 a)
  14. instance NFData1 Space2
  15. -- we can fmap into this structure by recursively fmapping
  16. -- the inner spaces
  17. instance Functor Space2 where
  18. fmap f (Space2 u m d) =
  19. Space2 (fmap (fmap f) u) (fmap f m) (fmap (fmap f) d)
  20. -- map a partial function, converting to non maybe values
  21. fintermap :: (a -> Maybe a) -> [a] -> [a]
  22. fintermap _ [] = []
  23. fintermap f (a:as) = case f a of
  24. Nothing -> []
  25. Just y -> y : fintermap f as
  26. f :: ((Space2 a) -> Maybe (Space2 a)) -> Space (Space2 a) -> Maybe (Space (Space2 a))
  27. f g (Space l m r) = case (g m) of
  28. Nothing -> Nothing
  29. Just y -> Just $ Space (fintermap g l) y (fintermap g r)
  30. -- comonad instance for our 2d space
  31. instance Comonad Space2 where
  32. -- to duplicate we must recursively duplicate in all directions
  33. -- the focussed space becomes the whole space, with left and right
  34. -- mapped to each side.
  35. -- to do the up and down lists, each needs to be the middle space
  36. -- mapped up and down as far as we can.
  37. -- up2 and down2 will return Nothing when they cant go further
  38. duplicate w =
  39. Space2 (finterate (f up2) dm) dm (finterate (f down2) dm)
  40. where
  41. dm = Space (finterate left2 w) w (finterate right2 w)
  42. -- to extract we simply recursively extract
  43. extract (Space2 _ m _) = extract m
  44. -- directional moving of focus
  45. up2 :: Space2 t -> Maybe (Space2 t)
  46. up2 (Space2 [] _ _) = Nothing
  47. up2 (Space2 (u:us) m d) = Just $ Space2 us u (m:d)
  48. down2 :: Space2 t -> Maybe (Space2 t)
  49. down2 (Space2 _ _ []) = Nothing
  50. down2 (Space2 u m (d:ds)) = Just $ Space2 (m:u) d ds
  51. noLeft :: Space t -> Bool
  52. noLeft (Space [] _ _) = True
  53. noLeft _ = False
  54. noRight :: Space t -> Bool
  55. noRight (Space _ _ []) = True
  56. noRight _ = False
  57. -- left and right require mapping further
  58. -- we are assuming things are rectangular (maybe a bad idea?)
  59. left2 :: Space2 t -> Maybe (Space2 t)
  60. left2 (Space2 u m d) =
  61. if check
  62. then Nothing
  63. else Just $ Space2 (fmap (f . left) u) (f $ left m) (fmap (f . left) d)
  64. where
  65. check = noLeft m
  66. f l = fromJust l
  67. right2 :: Space2 t -> Maybe (Space2 t)
  68. right2 (Space2 u m d) =
  69. if check
  70. then Nothing
  71. else Just $ Space2 (fmap (f . right) u) (f $ right m) (fmap (f . right) d)
  72. where
  73. check = noRight m
  74. f l = fromJust l
  75. -- clamp as we do in 1d Spaces
  76. clampRel2 :: Int -> Int -> Int -> Int -> Space2 t -> Space2 t
  77. clampRel2 w x y z (Space2 u m d) = Space2 (take w $ fmap f u) (f m) (take x $ fmap f d)
  78. where
  79. f = clampRel y z
  80. clamp2 :: Int -> Int -> Space2 t -> Space2 t
  81. clamp2 w h = clampRel2 nu nd nl nr
  82. where
  83. nu = h `div` 2
  84. nd = nu - (if even h then 1 else 0)
  85. nr = w `div` 2
  86. nl = nr - (if even w then 1 else 0)
  87. mat2 :: Space2 t -> [[t]]
  88. mat2 (Space2 u m d) = (reverse (fmap mat u)) ++ ((mat m):(fmap mat d))
  89. matn2 :: Int -> Int -> Space2 t -> [[t]]
  90. matn2 w h = mat2 . (clamp2 w h)
  91. step :: Comonad w => (w t -> t) -> w t -> w t
  92. step f w = w =>> f
  93. -- create a randomly filled space
  94. createRandSpace2 :: Random a => StdGen -> Space2 a
  95. createRandSpace2 rng =
  96. Space2 (tail $ map snd $ iterate f (r1, (createRandSpace r1)))
  97. (createRandSpace rng)
  98. (tail $ map snd $ iterate f (r2, (createRandSpace r2)))
  99. where
  100. f (r,s) = let (nr1,nr2) = split r in (nr2, (createRandSpace nr1))
  101. (r1,r2) = split rng