Main.elm 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. module Cellular exposing (..)
  2. import Html exposing (..)
  3. import Html.Events exposing (..)
  4. import Html.Attributes exposing (id, class, classList, style)
  5. import Array
  6. import Time exposing (Time, second)
  7. type Cell
  8. = Alive
  9. | Dead
  10. type alias Board = Array.Array (Array.Array Cell)
  11. type alias Rule = Int -> Cell -> Cell
  12. type alias Model =
  13. { width : Int
  14. , height : Int
  15. , board : Board
  16. , rule : Rule
  17. }
  18. initModel : Int -> Int -> Model
  19. initModel w h =
  20. { width = w
  21. , height = h
  22. --, board = Array.repeat h <| Array.repeat w Dead
  23. --, board = modify 3 2 Alive <| Array.repeat h <| Array.repeat w Dead
  24. , board = modify 4 4 Alive <| modify 4 3 Alive <| modify 3 4 Alive <| modify 3 2 Alive <| Array.repeat h <| Array.repeat w Dead
  25. , rule = (\livingNeighbours cell ->
  26. case cell of
  27. Alive ->
  28. if livingNeighbours < 2 || livingNeighbours > 3 then
  29. Dead
  30. else
  31. Alive
  32. _ ->
  33. if livingNeighbours == 3 then
  34. Alive
  35. else
  36. Dead)
  37. }
  38. type Msg
  39. = NoOp
  40. | Step
  41. viewRow row =
  42. tr
  43. []
  44. <|
  45. Array.toList
  46. <|
  47. Array.map (\c ->
  48. let
  49. colour =
  50. case c of
  51. Alive ->
  52. "yellow"
  53. Dead ->
  54. "grey"
  55. in
  56. td
  57. [ style
  58. [ ("background-color", colour)
  59. ]
  60. ]
  61. [text (toString c)]
  62. ) row
  63. viewBoard : Board -> Html Msg
  64. viewBoard board =
  65. table
  66. []
  67. <|
  68. Array.toList
  69. <|
  70. Array.map (\r -> viewRow r) board
  71. view : Model -> Html Msg
  72. view model =
  73. div
  74. [ onClick Step
  75. ]
  76. [ text "cellular-elm"
  77. , viewBoard model.board
  78. ]
  79. modify : Int -> Int -> Cell -> Board -> Board
  80. modify x y newState board =
  81. case Array.get y board of
  82. Just oldRow ->
  83. let
  84. newRow = Array.set x newState oldRow
  85. newBoard = Array.set y newRow board
  86. in
  87. newBoard
  88. Nothing ->
  89. board
  90. valueAt : Int -> Int -> Board -> Cell
  91. valueAt r c board =
  92. Maybe.withDefault Dead <| Array.get c <| Maybe.withDefault Array.empty (Array.get r board)
  93. surroundings : Int -> Int -> Board -> Int
  94. surroundings r c board =
  95. let
  96. living cell =
  97. case cell of
  98. Alive -> 1
  99. _ -> 0
  100. ul = living <| valueAt (r - 1) (c - 1) board
  101. uc = living <| valueAt (r - 1) c board
  102. ur = living <| valueAt (r - 1) (c + 1) board
  103. ml = living <| valueAt r (c - 1) board
  104. mr = living <| valueAt r (c + 1) board
  105. ll = living <| valueAt (r + 1) (c - 1) board
  106. lc = living <| valueAt (r + 1) c board
  107. lr = living <| valueAt (r + 1) (c + 1) board
  108. in
  109. ul + uc + ur + ml + mr + ll + lc + lr
  110. replaceRow : Rule -> Board -> Int -> Array.Array Cell -> Array.Array Cell
  111. replaceRow rule board rn row =
  112. let
  113. prevRow =
  114. Maybe.withDefault Array.empty <| Array.get (rn - 1) board
  115. nextRow =
  116. Maybe.withDefault Array.empty <| Array.get (rn + 1) board
  117. in
  118. Array.indexedMap
  119. (\cn cell ->
  120. --TODO: insert rules
  121. rule (surroundings rn cn board) cell
  122. ) row
  123. step : Rule -> Board -> Board
  124. step rule board =
  125. Array.indexedMap (replaceRow rule board) board
  126. update : Msg -> Model -> (Model, Cmd Msg)
  127. update msg model =
  128. case msg of
  129. Step ->
  130. ( { model | board = step model.rule model.board }, Cmd.none )
  131. _ ->
  132. ( model, Cmd.none )
  133. subscriptions : Model -> Sub Msg
  134. subscriptions model =
  135. Sub.batch
  136. [ Time.every second (\_ -> Step)
  137. ]
  138. main =
  139. Html.program
  140. { init = ((initModel 20 10), Cmd.none)
  141. , view = view
  142. , update = update
  143. , subscriptions = subscriptions
  144. }