/// m13 life app: the same wiring as Snake and Pong, with a third kind of input, the mouse. module Snake.Life.App open Snake open Snake.IO open Snake.Stream open Snake.Life.Model open Snake.Life.Rules open Snake.Life.View /// Milliseconds between two generations while the world runs. let GEN_MS = 150L /// A key press to a `LifeAction`, if any: " " -> TogglePause, "n"/"N" -> Step, "c"/"C" -> Clear, /// "r"/"R" -> Randomize. Any other key -> `None`. let lifeKey (key: string) : LifeAction option = failwith "TODO m13" /// A click at canvas pixel `(x, y)` to `Toggle` of the cell under it (`x / LCELL` and `y / LCELL`, rounded down), /// or `None` when the pixel is not on the board (left of it, above it, right of it, or in the status strip below it). /// Careful: F# integer division rounds towards zero, so `-1 / 16` is 0. Check the pixel before you divide. let lifeClick (x: int) (y: int) : LifeAction option = failwith "TODO m13" /// Everything that can happen to the world: `Frame` every GEN_MS (from `Stream.interval`), merged with `lifeKey` of /// every key press, merged with `lifeClick` of every click (`Stream.clicks`), in that order. /// (The stub is wrapped in `Stream` so the TODO only fires when the stream is stepped.) let lifeActions: Stream = Stream(fun _ -> failwith "TODO m13") /// Fold the actions into a stream of states: start from `initialLife seed`, `lifeUpdate` for each action, emit the /// initial state first. let lifeStates (seed: uint32) (actions: Stream) : Stream = failwith "TODO m13" /// The whole program as a value, like `App.main`: ask for a seed, turn the stream of states into a stream of drawings /// of `lifeView`, and wrap that stream in `Stream.clampTime App.MAX_GAP_MS`. A function of `unit`, like `App.main`. let lifeMain () : IO>> = failwith "TODO m13"