Inventory Systems

One of the most common problems in interactive fiction is one of containers. Frequently, you want to know what things hold other things and, from there, what can be done with them. Some common examples include things like picking up tools, "having" clues or knowledge, and holding pieces of puzzles. To approach this problem in Twine, there are several options. Two of the most common ones are the following: * Explicit: the user already "has" all of the things, but doesn't have knowledge of them until they are turned on (via true and false). * Implicit: the user somehow aquires things through actions, and they are added to the existing set. `(Note: these two options can be mixed, of course, and often deal more with the perception of the developer than the user herself.)` [[The Datamap]]On the other hand, in Harlowe we can also create a `(dataset:)`, a structure like an array of values we can test if something <em>is in</em> or if the set <em>contains</em> something. For example, if we wanted to know if the player had some string AND honey AND cat hair, we could test for that. (If we were playing <em>Gabriel Knight 3: Blood of the Sacred, Blood of the Damned</em>, such items would be very important.) {(set: $inventory to (dataset: "Honey", "String", "Cat Hair") ) (if: $inventory contains "Honey")[We have some honey!] (if: "String" is in $inventory)[We have some String!] (if: $inventory contains "Cat Hair")[We have Cat Hair!] (if: $inventory contains "Honey" and $inventory contains "String" and $inventory contains "Cat Hair")[We have all three!]} *`(set: $inventory to (dataset: "Honey", "String", "Cat Hair") ) (if: $inventory contains "Honey")[We have some honey!] (if: "String" is in $inventory)[We have some String!] (if: $inventory contains "Cat Hair")[We have Cat Hair!] (if: $inventory contains "Honey" and $inventory contains "String" and $inventory contains "Cat Hair")[We have all three!]`* [[Implicit approach]]In Harlowe, you can use the `(datamap:)` macro to create a JavaScript Map, a collection of key-value pairs. Thinking in terms of a inventory system, we can check if a user "has" certain things by testing for if something is true or not. For example, let's say you were playing a game similar to <em>Clue</em> (<em>Cluedo</em>). You would want to know what items you have. *`(set: $weapons to (datamap: "Candlestick", true, "Knife", false, "Leadpipe", false, "Revolver", false, "Rope", false, "Wrench", false) ) (set: $rooms to (datamap: "Ballroom", true, "Kitchen", false, "Conservatory", false, "DiningRoom", false, "BilliardRoom", false, "Library", false, "Hall", false, "Lounge", false, "Study", false) ) (set: $suspects to (datamap: "MissScarlett", true, "ProfessorPlum", false, "MrsPeacock", false, "MrGreen", false, "ColonelMustard", false, "MrsWhite", false) )`* {(set: $weapons to (datamap: "Candlestick", true, "Knife", false, "Leadpipe", false, "Revolver", false, "Rope", false, "Wrench", false) ) (set: $rooms to (datamap: "Ballroom", true, "Kitchen", false, "Conservatory", false, "DiningRoom", false, "BilliardRoom", false, "Library", false, "Hall", false, "Lounge", false, "Study", false) ) (set: $suspects to (datamap: "MissScarlett", true, "ProfessorPlum", false, "MrsPeacock", false, "MrGreen", false, "ColonelMustard", false, "MrsWhite", false) )} To test that knowledge, we can write things like the following: *`(if: $suspects's MissScarlett is true)[We know about Miss Scarlett!] (if: $weapons's Candlestick is true)[We know about the Candlestick!] (if: $rooms's Ballroom is true)[We know about the Ballroom!]`* (if: $suspects's MissScarlett is true)[We know about Miss Scarlett!] (if: $weapons's Candlestick is true)[We know about the Candlestick!] (if: $rooms's Ballroom is true)[We know about the Ballroom!] [[The Dataset]]So far, we have been dealing with the explicit approach. We give the user everything and then check against it. Of course, we can use a more implicit approach, too, only adding things as needed. For both `(datamap:)` and `(dataset:)`, we can "add" them using the same `(set:)` macro we've been using so far. *`(set: $weapons to (datamap: "Knife", true) + (datamap: "Wrench", true) ) (set: $clues to (dataset: "Miss Scarlett") + (dataset: "Mr. Green") ) (if: $weapons's Wrench is true)[We have the wrench!] (if: $clues contains "Mr. Green")[We have Mr. Green!]`* (set: $weapons to (datamap: "Knife", true) + (datamap: "Wrench", true) ) (set: $clues to (dataset: "Miss Scarlett") + (dataset: "Mr. Green") ) (if: $weapons's Wrench is true)[We have the wrench!] (if: $clues contains "Mr. Green")[We have Mr. Green!]