Awesome
Elm Puzzler
A framework for creating puzzles & solutions written in Elm, to help newcomers learn the language and then move on to building their own puzzles.
N.B. This is very much a work in progress. Inspired at and by Elm London and intended as an educational tool. Contributions immensely welcome.
A Puzzle
Puzzler exports the Puzzle
type, which provides a standardised interface for
designing puzzles:
type alias Puzzle state event action =
{ init : state
, view : state -> Html ()
, handleTick : state -> Tick -> ( state, Maybe event )
, handleAction : state -> action -> ( state, Maybe event )
}
The state
defines the internal puzzle state at any given moment
An event
is passed from the Puzzle to the Solution, which the Solution may
choose to respond to with an
action
, which is a Puzzle-defined response to an Event that a Solution may
offer
The view
function converts the current state into a view for the user.
The handleTick
function allows the puzzle to update the game state and emit
events asynchronously
The handleAction
function provides a synchronous response to a Solution's
Action
A Solution
type alias Solution memory event action =
{ init : memory
, handleEvent : memory -> event -> ( memory, Maybe action )
}
A solution has an internal memory
that can be used for tracing moves etc. It's
initialised with the init
function.
The main game logic then is encapsulated in a handleEvent
function, which
receives the current memory
, a new puzzle event
, and returns a new memory
with an optional action
, if required.
Getting Started
git clone https://github.com/jwbrew/elm-puzzler.git
cd elm-puzzler
Running A Puzzle
run :
Puzzle state event action
-> Solution memory event action
-> Program Flags (Model memory state) (Msg action)
Puzzler
exports run
, which returns a Program
. Running the puzzle & solution
is as simple as Puzzler.run puzzle solution
.
Recommendation: use elm-live
with -debug
on to enable the time-travelling
debugger when developing solutions.
npm i -g elm-live
elm reactor
Puzzles
NoughtsCrosses
Bundled intially there's a naieve implmentation of noughts and crosses. Your opponent is 0, you are X. Your opponent moves first, but has a pretty rubbish strategy.
The demo solution always loses. Try to find a way to make it win.
Writing your own solution
- Create a file in src/solutions eg
src/solutions/MyNoughtsCrossesSolution.elm
- Import
Puzzler.Solution
andAction
,Event
andState
fromPuzzles.NoughtsCrosses
- Define a
solution : Solution Memory Event Action
function, and export.
module Solutions.MyNoughtsCrossesSolution exposing (solution)
import Puzzler exposing (Solution)
import Puzzles.NoughtsCrosses exposing (Action(..), Event(..), State)
type alias Memory =
...
takeGo : Memory -> Event -> ( Memory, Maybe Action )
takeGo memory (OpponentMove x y) =
...
solution : Solution Memory Event Action
solution =
{ init = []
, handleEvent = takeGo
}
- Modify
import Solutions.NoughtsCrosses exposing (solution)
inMain.elm
to import your solution - Run as above!