๐Ÿ“ฆ sleepyfran / duets

๐Ÿ“„ Look.Command.fs ยท 159 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159namespace Duets.Cli.Components.Commands

open Duets.Agents
open Duets.Cli.Components
open Duets.Cli.SceneIndex
open Duets.Cli.Text
open Duets.Cli.Text.Prompts
open Duets.Cli.Text.World
open Duets.Entities
open Duets.Simulation

[<RequireQualifiedAccess>]
module LookCommand =
    let private listEntrances (interactions: InteractionWithMetadata list) =
        let entrances =
            interactions
            |> List.choose (fun interaction ->
                match interaction.Interaction with
                | Interaction.FreeRoam(FreeRoamInteraction.Enter(place)) ->
                    Some(place)
                | _ -> None)
            |> List.concat

        match entrances with
        | [] -> None
        | entrances ->
            let entrancesDescription =
                Generic.listOf entrances World.placeNameWithType

            Some(
                $"""There {Generic.pluralOf "is an entrance" "are entrances" entrancesDescription.Length} towards {entrancesDescription}."""
            )
        |> Option.iter showMessage

    let private listExits (interactions: InteractionWithMetadata list) =
        let state = State.get ()

        let exits =
            interactions
            |> List.choose (fun interaction ->
                match interaction.Interaction with
                | Interaction.FreeRoam(FreeRoamInteraction.GoOut(streetId)) ->
                    Some(streetId)
                | _ -> None)

        match exits with
        | [] -> None
        | exits ->
            let exitsDescription =
                Generic.listOf exits (fun streetId ->
                    let street =
                        Queries.World.streetInCurrentCity streetId state

                    $"{street.Name |> Styles.place}")

            Some(
                $"""There is an exit towards {exitsDescription} leading out of this place."""
            )
        |> Option.iter showMessage

    let private getConnectedStreets
        (interactions: InteractionWithMetadata list)
        =
        let connectedStreets =
            interactions
            |> List.choose (fun interaction ->
                match interaction.Interaction with
                | Interaction.FreeRoam(FreeRoamInteraction.GoToStreet(streets)) ->
                    Some(streets)
                | _ -> None)
            |> List.concat

        match connectedStreets with
        | [] -> None
        | exits ->
            Generic.listOf exits (fun street ->
                $"{street.Name |> Styles.place}")
            |> Some

    let private listRoomConnections
        (interactions: InteractionWithMetadata list)
        =
        let state = State.get ()
        let cityId, placeId, _ = state |> Queries.World.currentCoordinates
        let place = Queries.World.placeInCityById cityId placeId

        let connections =
            interactions
            |> List.choose (fun interaction ->
                match interaction.Interaction with
                | Interaction.FreeRoam(FreeRoamInteraction.Move(direction,
                                                                roomId)) ->
                    let roomType = Queries.World.roomById cityId placeId roomId

                    Some(direction, roomType)
                | _ -> None)

        let connectedStreetListOpt = getConnectedStreets interactions

        match connections with
        | [] -> World.noConnectionsToRoom place connectedStreetListOpt
        | connections ->
            World.connectingNodes place connections connectedStreetListOpt
        |> showMessage

    let private listPeople
        (knownPeople: Character list)
        (unknownPeople: Character list)
        roomType
        =
        let peopleDescription people =
            Generic.listOf people (fun person ->
                $"{person.Name |> Styles.person}")

        if knownPeople.IsEmpty |> not then
            $"""{peopleDescription knownPeople} {Generic.pluralOf "is" "are" knownPeople.Length} in the {World.roomName roomType}."""
            |> showMessage

        if unknownPeople.IsEmpty |> not then
            $"""There {Generic.pluralOf "is" "are" unknownPeople.Length} {unknownPeople.Length |> Styles.person} {Generic.pluralOf "person" "people" unknownPeople.Length |> Styles.person} you don't know in the {World.roomName roomType}."""
            |> showMessage

    let private listItems items =
        match items with
        | [] -> Command.lookNoObjectsAround |> showMessage
        | items ->
            items
            |> List.map (fun item -> Generic.itemName item |> Items.lookItem)
            |> Items.lookItems
            |> showMessage

    let create
        (interactions: InteractionWithMetadata list)
        (items: Item list)
        (knownPeople: Character list)
        (unknownPeople: Character list)
        =
        { Name = "look"
          Description = Command.lookDescription
          Handler =
            (fun _ ->
                let state = State.get ()

                let currentRoom = state |> Queries.World.currentRoom

                World.createRoomDescriptionPrompt state interactions
                |> LanguageModel.streamMessage
                |> streamMessage

                lineBreak ()

                listRoomConnections interactions
                listEntrances interactions
                listExits interactions
                listPeople knownPeople unknownPeople currentRoom.RoomType
                listItems items

                Scene.World) }