1+ module SaveTheCow
2+
3+ open System
4+
5+ let allowedFailures = 9
6+
7+ type Progress =
8+ | Win
9+ | Lose
10+ | Busy of int
11+
12+ type State = { progress: Progress ; maskedWord: string ; guesses: Set < char > }
13+
14+ let updateProgress word guess ( state : State ) =
15+ match state.progress with
16+ | Win -> { state with progress = Win }
17+ | Lose -> { state with progress = Lose }
18+ | Busy x ->
19+ if state.maskedWord = word then
20+ { state with progress = Win }
21+ elif x <= 0 then
22+ { state with progress = Lose }
23+ elif not <| word.Contains( string guess) || Set.contains guess state.guesses then
24+ { state with progress = Busy ( x - 1 ) }
25+ else
26+ state
27+
28+ let updateMaskedWord word guess ( state : State ) =
29+ let updatedGuesses = Set.add guess state.guesses
30+ let updatedMaskedWord =
31+ word
32+ |> Seq.map ( fun x -> if Set.contains x updatedGuesses then x else '_' )
33+ |> Seq.toArray
34+ |> System.String
35+
36+ { state with maskedWord = updatedMaskedWord }
37+
38+ let updateGuesses guess ( state : State ) = { state with guesses = Set.add guess state.guesses }
39+
40+ let updateState word guess ( state : State ) =
41+ state
42+ |> updateMaskedWord word guess
43+ |> updateProgress word guess
44+ |> updateGuesses guess
45+
46+ let mkStartState ( word : string ) = { progress = Busy allowedFailures; maskedWord = String( '_' , word.Length); guesses = Set.empty }
47+
48+ type Game ( word ) =
49+ let initialState = new Event< State>()
50+ let guesses = new Event< char>()
51+ let startState = mkStartState word
52+
53+ member this.States = Observable.merge initialState.Publish ( Observable.scan ( fun state guess -> updateState word guess state) startState guesses.Publish)
54+ member this.Start () = initialState.Trigger( startState)
55+ member this.MakeGuess ( guess ) = guesses.Trigger( guess)
56+
57+ let createGame word = new Game( word)
58+ let startGame ( game : Game ) = game.Start()
59+ let makeGuess guess ( game : Game ) = game.MakeGuess( guess)
60+ let statesObservable ( game : Game ) = game.States
0 commit comments