|
@ -1,15 +1,15 @@ |
|
|
import Grid exposing (..) |
|
|
|
|
|
import RingList exposing (..) |
|
|
|
|
|
import Automaton exposing (..) |
|
|
import Automaton exposing (..) |
|
|
|
|
|
import Grid exposing (..) |
|
|
|
|
|
import Lazy.Zipper |
|
|
|
|
|
|
|
|
|
|
|
import Color exposing (Color) |
|
|
|
|
|
import Dict exposing (Dict) |
|
|
import Html exposing (..) |
|
|
import Html exposing (..) |
|
|
import Html.Attributes exposing (..) |
|
|
|
|
|
import Html.App as App |
|
|
import Html.App as App |
|
|
import Html.Events exposing (..) |
|
|
import Html.Attributes exposing (style) |
|
|
|
|
|
import Html.Events exposing (onClick) |
|
|
import Random |
|
|
import Random |
|
|
import Color exposing (..) |
|
|
import Time |
|
|
import Time exposing (Time, second) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
main = |
|
|
main = |
|
|
App.program |
|
|
App.program |
|
@ -19,13 +19,13 @@ main = |
|
|
, subscriptions = subscriptions |
|
|
, subscriptions = subscriptions |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
width = 62 |
|
|
width = 34 |
|
|
height = 33 |
|
|
height = 31 |
|
|
states = 3 |
|
|
states = 10 |
|
|
inputs = 2 |
|
|
inputs = 3 |
|
|
outputs = 3 |
|
|
outputs = 3 |
|
|
visSize = "20px" |
|
|
visSize = "20px" |
|
|
freq = 0.3 * second |
|
|
freq = 0.3 * Time.second |
|
|
|
|
|
|
|
|
-- MODEL |
|
|
-- MODEL |
|
|
|
|
|
|
|
@ -39,16 +39,16 @@ type alias Model = |
|
|
|
|
|
|
|
|
init : (Model, Cmd Msg) |
|
|
init : (Model, Cmd Msg) |
|
|
init = |
|
|
init = |
|
|
( { grid = Grid.generate width height initCell |
|
|
( { grid = generate width height initCell |
|
|
, system = [] |
|
|
, system = [] |
|
|
, neighbours = [] |
|
|
, neighbours = [] |
|
|
}, Random.generate NewRandomAut (genAut states inputs) ) |
|
|
}, Random.generate NewRandomAut (genAut states inputs) ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initCell x y = case (x > 5, y > 5) of |
|
|
initCell x y = case (x, y) of |
|
|
(True, _) -> Just 1 |
|
|
(18, 16) -> Just 3 |
|
|
(_, True) -> Just 1 |
|
|
(17, 16) -> Just 1 |
|
|
_ -> Just (1 + (x + y * width) % states) |
|
|
_ -> Just 2 |
|
|
|
|
|
|
|
|
-- UPDATE |
|
|
-- UPDATE |
|
|
|
|
|
|
|
@ -56,21 +56,50 @@ type Msg |
|
|
= Update World |
|
|
= Update World |
|
|
| NewRandomAut AutomatonT |
|
|
| NewRandomAut AutomatonT |
|
|
| Regen |
|
|
| Regen |
|
|
|
|
|
| Init |
|
|
| BigStep |
|
|
| BigStep |
|
|
|
|
|
|
|
|
output m = case m of |
|
|
output m = case m of |
|
|
Nothing -> 1 |
|
|
Nothing -> 1 |
|
|
Just s -> 1 + s % outputs |
|
|
Just s -> 1 + s % outputs |
|
|
|
|
|
|
|
|
getNBOutputs grid = let |
|
|
counts : List Int -> Dict Int Int |
|
|
ret = grid |> Grid.getNeighbours |> List.map output |> List.sum |
|
|
counts ls = let |
|
|
in 1 + ret % inputs |
|
|
succ n = case n of |
|
|
|
|
|
Just m -> Just (m + 1) |
|
|
|
|
|
Nothing -> Just 1 |
|
|
|
|
|
in List.foldr (\x m -> Dict.update x succ m) Dict.empty ls |
|
|
|
|
|
|
|
|
|
|
|
uniqSingleton : List Int -> Maybe Int |
|
|
|
|
|
uniqSingleton ls = let cs = counts ls |
|
|
|
|
|
in case Dict.toList cs of |
|
|
|
|
|
[(n, 1), (m, 3)] -> Just n |
|
|
|
|
|
[(n, 3), (m, 1)] -> Just m |
|
|
|
|
|
[(1, 2), (2, 2)] -> Just 3 |
|
|
|
|
|
[(1, 2), (3, 2)] -> Just 2 |
|
|
|
|
|
[(2, 2), (3, 2)] -> Just 1 |
|
|
|
|
|
_ -> Nothing |
|
|
|
|
|
|
|
|
|
|
|
getNBOutputs : World -> Maybe Int |
|
|
|
|
|
getNBOutputs grid = grid |
|
|
|
|
|
|> getNeighbours |
|
|
|
|
|
|> List.filterMap identity |
|
|
|
|
|
|> uniqSingleton |
|
|
|
|
|
--|> List.map output |
|
|
|
|
|
--|> List.map2 (\x y -> x * y) [2,2,1,0] |
|
|
|
|
|
--|> List.sum |
|
|
|
|
|
--|> \x -> 1 + x % inputs |
|
|
|
|
|
|
|
|
|
|
|
step2 : AutomatonT -> Maybe Int -> Maybe Int -> Maybe Int |
|
|
|
|
|
step2 aut s i = case i of |
|
|
|
|
|
Nothing -> s |
|
|
|
|
|
Just i2 -> Automaton.step aut s i2 |
|
|
|
|
|
|
|
|
cellStep : AutomatonT -> World -> Maybe Int |
|
|
cellStep : AutomatonT -> World -> Maybe Int |
|
|
cellStep aut grid = let |
|
|
cellStep aut grid = let |
|
|
i = getNBOutputs grid |
|
|
i = getNBOutputs grid |
|
|
s = grid |> Grid.extract |
|
|
s = extract grid |
|
|
t = Automaton.step aut s i |
|
|
t = step2 aut s i |
|
|
in t |
|
|
in t |
|
|
|
|
|
|
|
|
update : Msg -> Model -> (Model, Cmd Msg) |
|
|
update : Msg -> Model -> (Model, Cmd Msg) |
|
@ -79,7 +108,8 @@ update msg model = |
|
|
Update grid -> ({ model | grid = grid }, Cmd.none) |
|
|
Update grid -> ({ model | grid = grid }, Cmd.none) |
|
|
NewRandomAut aut -> ({ model | system = aut }, Cmd.none) |
|
|
NewRandomAut aut -> ({ model | system = aut }, Cmd.none) |
|
|
Regen -> (model, Random.generate NewRandomAut (genAut states inputs)) |
|
|
Regen -> (model, Random.generate NewRandomAut (genAut states inputs)) |
|
|
BigStep -> ({ model | grid = Grid.extend (cellStep model.system) model.grid }, Cmd.none) |
|
|
BigStep -> ({ model | grid = model.grid =>> cellStep model.system }, Cmd.none) |
|
|
|
|
|
Init -> ({ model | grid = generate width height initCell }, Cmd.none) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- SUBSCRIPTIONS |
|
|
-- SUBSCRIPTIONS |
|
@ -93,19 +123,18 @@ subscriptions model = Time.every freq (\a -> BigStep) |
|
|
(=>) = (,) |
|
|
(=>) = (,) |
|
|
|
|
|
|
|
|
output2Color : Int -> Color |
|
|
output2Color : Int -> Color |
|
|
output2Color n = hsl (degrees (toFloat n)*77) 1.0 (0.8 - 0.6 * (toFloat n + 0.5)/outputs) |
|
|
output2Color n = Color.hsl (degrees (toFloat n)*77) 1.0 (0.8 - 0.6 * (toFloat n + 0.5)/outputs) |
|
|
|
|
|
|
|
|
color2String : Color -> String |
|
|
color2String : Color -> String |
|
|
color2String c = let rgb = toRgb c in "rgb(" ++ toString rgb.red ++ ", " ++ toString rgb.green ++ ", " ++ toString rgb.blue ++ ")" |
|
|
color2String c = let rgb = Color.toRgb c in "rgb(" ++ toString rgb.red ++ ", " ++ toString rgb.green ++ ", " ++ toString rgb.blue ++ ")" |
|
|
|
|
|
|
|
|
block aut grid = let |
|
|
block aut grid = let |
|
|
col = output2Color <| output <| Grid.extract grid |
|
|
col = output2Color <| output <| extract grid |
|
|
but = text "" -- button [ onClick (Update (Grid.edit (\_ -> cellStep aut grid) grid)) ] [ text "." ] |
|
|
but = text "" -- button [ onClick (Update (Grid.edit (\_ -> cellStep aut grid) grid)) ] [ text "." ] |
|
|
in div [style ["background-color" => color2String col, "width" => visSize, "height" => visSize, "display" => "inline-block"]] [ but ] |
|
|
in div [style ["background-color" => color2String col, "width" => visSize, "height" => visSize, "display" => "inline-block"]] [ but ] |
|
|
|
|
|
|
|
|
view model = let |
|
|
view model = let |
|
|
dupmodel = Grid.duplicate model.grid |
|
|
butts = model.grid =>> block model.system |
|
|
butts = Grid.map (block model.system) dupmodel |
|
|
|
|
|
listm = Grid.toList butts |
|
|
listm = Grid.toList butts |
|
|
viewm = List.map (\row -> div [style ["height" => visSize]] row) listm |
|
|
viewm = List.map (\row -> div [style ["height" => visSize]] row) listm |
|
|
in div [] <| viewm ++ [button [onClick BigStep] [text "big step"], button [onClick Regen] [text "regenerate"]] |
|
|
in div [] <| viewm ++ [button [onClick BigStep] [text "big step"], button [onClick Regen] [text "regenerate"], button [onClick Init] [text "restart"]] |
|
|