Harlowe : "commit" needed for datamaps?

Hi, all!

In my "Combat" demo I have a problem:

I have an object called "Vial" defined in this way:
(set: $Vial to (dm:
	"Name", "a vial full of elixir",
	"Room", "--",
	"Kind", "T",
))	

It is used in the datamap "Objects" like so:
(set: $Objects to (dm:
	"Goblin", $Goblin,
	"Fiole", $Vial, 
))

At some point in time I change its Room to "Player". If I check Vial directly, it is OK.
But if I check it in the Objects datamap via a (for:) macro, its Room  entry is still "--".

Is a kind of "commit" needed? Thanks in advance.

P.S : I use Twine 2.3.5 and harlowe 3.1.0.
1 Like

Please use the optional tags field of the New Topic screen to state which series of the Twine application and Story Format you are using, this saves needing to do so within the topic’s text.
I have altered the optional tags section of your topic to include this information.

Whenever you change the value of an existing DataMap (or an Array) the story format firsts clones (copies) the contents of that instance and then make the required change to the clone, and it is this changed clone which is assigned to the associated variable.
eg.

(set: $variable to (dm: "Name", "Aaaa"))  <!-- variable references original DataMap object -->
(set: $variable's Name to "Bbbb") <!-- variable now references a clone of original DataMap object -->

(note: A similar process occurs each time the Reader transitions between Passages)

This cloning process is what is causing the instance of the “Vial” object referenced by your $Vial variable to be a different instance of the “Vial” object than the one referenced by the “Fiole” property of the $Object variable’s DataMap.

This is why it is generally recommend to only have a single instance of any object you want to reference in multiple places, and to use the “key” or “index” of that single instance when referencing it such.
eg. Define your items in a single variable, this is likely done in your project’s startup tagged passage.

<!-- ex. Defining all 'properties' during variable initialisation, more efficient -->
(set: $items to (dm:
	"apple", (dm: "name", "Apple", "cost", 10),
	"pear", (dm: "name", "Pear", "cost", 12),
	"vial", (dm:
		"Name", "a vial full of elixir",
		"Room", "--",
		"Kind", "T"
	)
))

<!-- ex. Appending new 'properties' as needed, less efficient -->
(set: $creatures to (dm:))
(set: $creatures's "goblin" to (dm: "name", "Goblin", "health", 100))
(set: $creatures's "pixie" to (dm: "name", "Pixie", "health", 100))

You then store the “key” of any defined object as needed.

(set: $backpack to (a:))
(set: $backpack to it + (a: "apple")))
(set: $backpack to it + (a: "banana")))

(set: $Objects to (dm:
	"Goblin", "goblin,
	"Fiole", "vial" 
))

And when you need to update the ‘original’ object via a reference to its “key” , like the one stored in the $Objects variable, you would use a (set:) macro similar to the following.

(set: $items's ($Objects's "Fiole")'s "Room" to "Player")
1 Like

Thank you so much, Greyelf. I can restart, now.