-
-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathdocumentation.json
239 lines (239 loc) · 16.3 KB
/
documentation.json
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
[
{
"name": "Engine",
"comment": "\nThe story engine handles storing and advancing the state of the \"world model\" by running through your story rules on each interaction and updating the world model appropriately. It is designed to be embedded in your own Elm app, allowing for maximum flexibility and customization.\n\nYou can base your app on the [interactive story starter repo](https://github.com/jschomay/elm-interactive-story-starter.git).\n\n@docs Model\n\n## Embedding the engine\n\n@docs init, changeWorld, chooseFrom\n\n## Accessors\n\nThe engine exposes many accessor functions for each part of the story world. Note that each of these only return ids. It is up to the client to map an id to the appropriate associated display content. It is useful to follow an \"Entity Component System\" pattern in the client for this purpose (see the story starter).\n\n@docs getCurrentScene, getCurrentLocation, getItemsInCurrentLocation, getCharactersInCurrentLocation, getItemsInInventory, getLocations, getEnding\n\n\n## Story rules\n\nRules are how you progress the story. They are made up of conditions to match against and commands to perform if the rule matches. On each call of `update`, the engine will run through all of the rules to find the best match. If no rules match, the framework will perform a default command, which is usually just to narrate the description of what was interacted with, or to move you to that location or take that item. If multiple rules match the current state of the world, the \"best\" choice will be selected based on the following weighting criteria:\n\n1. a `currentSceneIs` condition has the highest weight\n2. `with` has more weight than the broader `withAny*` matchers\n3. each additional condition adds more weight\n\nIn the case of a tie, the first candidate will be chosen, which is something you want to avoid, so design your rules carefully\n\n\n# Anatomy of a rule\n\n1. A matcher against what interactable story element id the user clicked on\n2. A list of conditions that all must match for the rule to match\n3. A list of changes to make if the rule matches\n\n rules =\n [ { interaction = with \"River\"\n , conditions =\n [ currentLocationIs \"Cottage\"\n , itemIsInInventory \"Cape\"\n , itemIsInInventory \"Basket of food\"\n ]\n , changes =\n [ moveTo \"River\"\n , moveCharacterToLocation \"Little Red Riding Hood\" \"River\"\n ]\n }\n -- etc\n ]\n\n\n@docs Rule, Rules, update\n\n### Interaction matchers\n\nThe following interaction matchers can be used in the `interaction` part of the rule record.\n\n@docs InteractionMatcher, with, withAnything, withAnyItem, withAnyLocation, withAnyCharacter\n\n\n### Conditions\n\nThe following condition matchers can be used in the `conditions` part of the rule record.\n\n@docs Condition, itemIsInInventory , characterIsInLocation , itemIsInLocation , currentLocationIs, itemIsNotInInventory , hasPreviouslyInteractedWith, hasNotPreviouslyInteractedWith, currentSceneIs, characterIsNotInLocation , itemIsNotInLocation , currentLocationIsNot\n\n\n### Changing the story world\n\nYou cannot change the story directly, but you can supply \"commands\" describing how the story state should change.\n\n@docs ChangeWorldCommand, moveTo, addLocation, removeLocation, moveItemToInventory, moveCharacterToLocation, moveCharacterOffScreen, moveItemToLocation, moveItemToLocationFixed, moveItemOffScreen, loadScene, endStory\n\n",
"aliases": [
{
"name": "ChangeWorldCommand",
"comment": " ",
"args": [],
"type": "Types.ChangeWorldCommand"
},
{
"name": "Condition",
"comment": " ",
"args": [],
"type": "Types.Condition"
},
{
"name": "InteractionMatcher",
"comment": " ",
"args": [],
"type": "Types.InteractionMatcher"
},
{
"name": "Rule",
"comment": " A declarative rule, describing how to advance your story and under what conditions.\n",
"args": [],
"type": "Types.Rule"
},
{
"name": "Rules",
"comment": " All the rules in your story.\n",
"args": [],
"type": "Types.Rules"
}
],
"types": [
{
"name": "Model",
"comment": " The opaque type that holds all of the \"world model\" state, such as where each item and character is, what the current location and scene are, etc.\n",
"args": [],
"cases": []
}
],
"values": [
{
"name": "addLocation",
"comment": " Adds a location to your list of known locations. Any location on this list is available for the player to click on at any time. This avoids clunky spatial navigation mechanics, but does mean that you will need to make rules to prevent against going to locations that are inaccessible (with appropriate narration).\n",
"type": "String -> Engine.ChangeWorldCommand"
},
{
"name": "changeWorld",
"comment": " A way to change the story world directly, rather than responding to a player's interaction.\n\nFor example, you could change the current location in the story based on browser geolocation events, or respond to a network event, etc. This is also used to set up any initial story state.\n\nIf you are simply responding to a player's interaction, use `update` instead.\n",
"type": "List Engine.ChangeWorldCommand -> Engine.Model -> Engine.Model"
},
{
"name": "characterIsInLocation",
"comment": " Will only match if the supplied character is in the supplied location.\n\nThe first String is a character id, the second is a location id.\n",
"type": "String -> String -> Engine.Condition"
},
{
"name": "characterIsNotInLocation",
"comment": " Will only match if the supplied character is *not* in the supplied location.\n\nThe first String is a character id, the second is a location id.\n",
"type": "String -> String -> Engine.Condition"
},
{
"name": "chooseFrom",
"comment": " Given a list of choices, this will return only the choice that matches the associated conditions, if any. Useful for conditional descriptions, for example, where an item has a different description depending on where it is.\n\nThis uses the same weighting scale as the rules (below), and likewise will return the first match if there is a tie, so specify your conditions carefully.\n",
"type": "Engine.Model -> List { a | conditions : List Engine.Condition } -> Maybe.Maybe { a | conditions : List Engine.Condition }"
},
{
"name": "currentLocationIs",
"comment": " Will only match when the supplied location is the current location.\n",
"type": "String -> Engine.Condition"
},
{
"name": "currentLocationIsNot",
"comment": " Will only match when the supplied location is *not* the current location.\n",
"type": "String -> Engine.Condition"
},
{
"name": "currentSceneIs",
"comment": " Will only match when the supplied location is *not* the current location.\n",
"type": "String -> Engine.Condition"
},
{
"name": "endStory",
"comment": " Sets a flag that the story has ended. The string you provide can be used to signify the \"type\" of story ending (\"good\", \"bad\", \"heroic\", etc), or how many moves it took to complete, or anything else you like. This has no effect on the framework, but you can use it in your client code how ever you like (change the view, calculate a score, etc).\n",
"type": "String -> Engine.ChangeWorldCommand"
},
{
"name": "getCharactersInCurrentLocation",
"comment": " Get a list of the characters in the current location to display\n",
"type": "Engine.Model -> List String"
},
{
"name": "getCurrentLocation",
"comment": " Get the current location to display\n",
"type": "Engine.Model -> String"
},
{
"name": "getCurrentScene",
"comment": " This gets the current scene to display\n",
"type": "Engine.Model -> String"
},
{
"name": "getEnding",
"comment": " Get the story ending, if it has ended. (Set with `EndStory`)\n",
"type": "Engine.Model -> Maybe.Maybe String"
},
{
"name": "getItemsInCurrentLocation",
"comment": " Get a list of the items in the current location to display\n",
"type": "Engine.Model -> List String"
},
{
"name": "getItemsInInventory",
"comment": " Get a list of the items in your inventory to display\n",
"type": "Engine.Model -> List String"
},
{
"name": "getLocations",
"comment": " Get a list of the known locations to display\n",
"type": "Engine.Model -> List String"
},
{
"name": "hasNotPreviouslyInteractedWith",
"comment": " Will only match if the supplied interactable has not already been interacted with.\n",
"type": "String -> Engine.Condition"
},
{
"name": "hasPreviouslyInteractedWith",
"comment": " Will only match if the supplied interactable has already been interacted with.\n",
"type": "String -> Engine.Condition"
},
{
"name": "init",
"comment": " Initialize the `Model` for use when embedding in your own app. Provide your \"manifest\" (a list of ids) of all of the items, characters, and locations in your story, and the rules that govern the story.\n\nYou will most likely want to call `changeWorld` immediately after `init` to setup your initial story state (the current scene, location, and any initial placements of items or characters and known locations).\n",
"type": "{ items : List String , locations : List String , characters : List String } -> Engine.Rules -> Engine.Model"
},
{
"name": "itemIsInInventory",
"comment": " Will only match if the supplied item is in the inventory.\n",
"type": "String -> Engine.Condition"
},
{
"name": "itemIsInLocation",
"comment": " Will only match if the supplied item is in the supplied location.\n\nThe first String is a item id, the second is a location id.\n",
"type": "String -> String -> Engine.Condition"
},
{
"name": "itemIsNotInInventory",
"comment": " Will only match if the supplied item is *not* in the inventory.\n",
"type": "String -> Engine.Condition"
},
{
"name": "itemIsNotInLocation",
"comment": " Will only match if the supplied item is *not* in the supplied location.\n\nThe first String is a item id, the second is a location id.\n",
"type": "String -> String -> Engine.Condition"
},
{
"name": "loadScene",
"comment": " Scenes are a way to further constrain rules. You could have a scene for each leg of your story to make sure only the rules for that scene will apply. Or you may start a scene at a turning point in your story to \"activate\" special rules that apply to that scene. This is how you start or switch to a new scene. Note that you can only have one scene active at at time.\n",
"type": "String -> Engine.ChangeWorldCommand"
},
{
"name": "moveCharacterOffScreen",
"comment": " Moves a character \"off-screen\". The character will not show up in any locations until you use `moveCharacterToLocation` again.\n",
"type": "String -> Engine.ChangeWorldCommand"
},
{
"name": "moveCharacterToLocation",
"comment": " Adds a character to a location, or moves a character to a different location (characters can only be in one location at a time, or off-screen). (Use moveTo to move yourself between locations.)\n\nThe first String is a character id, the second is a location id.\n",
"type": "String -> String -> Engine.ChangeWorldCommand"
},
{
"name": "moveItemOffScreen",
"comment": " Moves an item \"off-screen\" (either from a location or the inventory). The item will not show up in any locations or inventory until you use `placeItem` or `addInventory` again.\n",
"type": "String -> Engine.ChangeWorldCommand"
},
{
"name": "moveItemToInventory",
"comment": " Adds an item to your inventory (if it was previously in a location, it will be removed from there, as items can only be in one place at once). If the item is \"fixed\" this will not move it (if you want to \"unfix\" an item, use `moveItemOffScreen` or `MoveItemToLocation` first).\n",
"type": "String -> Engine.ChangeWorldCommand"
},
{
"name": "moveItemToLocation",
"comment": " Move an item to a location. If it was in another location or your inventory before, it will remove it from there, as items can only be in one place at once.\n\nThe first String is an item id, the second is a location id.\n",
"type": "String -> String -> Engine.ChangeWorldCommand"
},
{
"name": "moveItemToLocationFixed",
"comment": " Move an item to a location and set it as \"fixed.\" Fixed items are like scenery, they can be interacted with, but they cannot be added to inventory.\n\nIf it was in another location or your inventory before, it will remove it from there, as items can only be in one place at once.\n\nThe first String is an item id, the second is a location id.\n",
"type": "String -> String -> Engine.ChangeWorldCommand"
},
{
"name": "moveTo",
"comment": " Changes the current location.\n",
"type": "String -> Engine.ChangeWorldCommand"
},
{
"name": "removeLocation",
"comment": " Removes a location from your list of known locations. You probably don't need this since once you know about a location you would always know about it, and trying to go to a location that is inaccessible for some reason could just give some narration telling why. But maybe you will find a good reason to use it.\n",
"type": "String -> Engine.ChangeWorldCommand"
},
{
"name": "update",
"comment": " This is how you progress the story. Call it with the id of what ever was just \"interacted\" with. This will apply the best matching rule for the current context, or if it does not find a matching rule, it will perform some sensible default changes such as adding an item to inventory or moving to a location if no rules match. It also adds the interaction to the history (which is used for `hasPreviouslyInteractedWith`, save/load, and undo).\n\nThis will also return the id of the matching rule (if there was one). Normally the client would look up some associated narrative by this id to display, though it could respond in any other way as well.\n",
"type": "String -> Engine.Model -> ( Engine.Model, Maybe.Maybe String )"
},
{
"name": "with",
"comment": " Will only match the `interaction` part of a story rule if the player interacted with the specified entity id.\n",
"type": "String -> Engine.InteractionMatcher"
},
{
"name": "withAnyCharacter",
"comment": " Will match the `interaction` part of a story rule if the player interacted with any character (be careful about the conditions of your rules since this matcher is so broad).\n",
"type": "Engine.InteractionMatcher"
},
{
"name": "withAnyItem",
"comment": " Will match the `interaction` part of a story rule if the player interacted with any item (be careful about the conditions of your rules since this matcher is so broad).\n",
"type": "Engine.InteractionMatcher"
},
{
"name": "withAnyLocation",
"comment": " Will match the `interaction` part of a story rule if the player interacted with any location (be careful about the conditions of your rules since this matcher is so broad).\n",
"type": "Engine.InteractionMatcher"
},
{
"name": "withAnything",
"comment": " Will match the `interaction` part of a story rule every time (be careful about the conditions of your rules since this matcher is so broad).\n",
"type": "Engine.InteractionMatcher"
}
],
"generated-with-elm-version": "0.18.0"
}
]