+1 vote
by (170 points)

Hi,

I'm using Twine 2.1.3 and Harlowe 2.0.1.

I have a dataset that contains datamaps. This represents a itemlist (dataset) with items (datamaps) that have some characteristics. So for example:

(set: $itemlist to (ds:
  (dm: "name", "item1", "value", 0, "useable", false),
  (dm: "name", "item2", "value", 0, "useable", false)
))

While playing several items can be added or subtracted from the $itemlist.

Now I want to make a link for every item in $itemlist. Once the player clicks on the link the corresponding item has to be stored in a variable. So I tried:

(for: each _item , ...$itemlist)[
  (link: _item's name)[
    (set: $youritem to _item)
    (go-to: "SomePage")
  ]
]

But if you click the link it gives the error "There isn't a temp variable named _item in this place".
I think _item is destroyed before clicking on the link. So I think this isn't the way. But..

How can this be accomplished?

PS: In SugarCube v2, I think this can be solved by enclosing the link in the <<capture variable_list>> macro.

<<for etc _item etc>>
<<capture _item>>
  link
<</capture>>
<</for>>

 But I don't want to switch from Harlowe ^^.

Hope the question is clear enough and that someone can help me. Thanks!

1 Answer

+1 vote
by (143k points)
selected by
 
Best answer

1. The temporary variable used within the (for:) macro only exists within the scope of the macro's associated hook, and that hook no longer exists after the (for:) macro is finished creating your links, and this is why you are getting that error message.

Using a story variable instead of a temporary variable would not solve this issue because variables contained within the associated hook of macros that require end-user interaction (like the (link:) macro does) are not evaluated until after the interaction occurs, and at the time of that interaction the variable will equal whatever it did at the end of the (for:) macro's looping.

To get around this issue you generally use a (print:) macro to dynamically create the macro & associated hook you need to include the value in.

(set: $array to (array: 1,2,3,4,5))

(for: each _item, ...$array)[
	(print: "(link: 'item: " + (text: _item) + "')[(set: $var to " + (text: _item) + ")(goto: 'Next')]")
]

 

2. The (set:) macro is assigning a clone of the original data-map object to the $youritem variable, so the object referenced in the $itemlist variable and the object referenced in the $youritem are no longer the same object even though the two objects have the 'same' value. Cloning of an object also occurs when (set:) is used to modify a property/element of an object.

The following example demonstrate this cloning process and the disassociation of the two copies of the original data-map object:

{
(set: $itemlist to (ds:
  (dm: "name", "item1", "value", 0, "useable", false),
  (dm: "name", "item2", "value", 0, "useable", false)
))

(for: each _item , ...$itemlist)[
	(if: _item's name is "item1")[
		(set: $youritem to _item)
	]
]
}

(set: $youritem's value to 1)

itemlist: (print: $itemlist)
youritem value: (print: $youritem's value)

To get around this issue I suggest that instead of assign an object reference to the $youritem variable that you assign an identifier to the original data-map stored within the $itemlist variable, this will require you to change the data-type of the collection object being used within $itemlist from a data-set to one that allows referencing it's contents via either an index or a property name. (eg. an Array or a (Data-)Map)

by (170 points)

Thank you for the respons, it was really helpful! I managed to accomplish it using the 'print-trick' and using the find macro to identify the item like this:

{(for: each _item , ...$itemlist)[
	(print: 
		"(link: '" + _item's name + "')[
			(set: $youritem to 1st of (find: _item2 where _item2's name is '" + _item's name + "', ... $itemlist))(go-to: 'Next')
		]"
	)
]}

The identification using the name works since no two items have the same name in my case. And the cloning isn´t a problem for me either.. This allows me to alter ´$youritem´ and get a new one from the ´$itemlist´. Not very elegant that you have to search trough the whole dataset again.. but it works..
Thanks for the print-trick!

by (120 points)
this somehow does not work with strings, any idea?
by (143k points)

@lasse

this somehow does not work with strings, any idea?

Without seeing your code it is difficult to guess why a piece of code doesn't work as you want it to.

Also because the site's software doesn't notify people when an old question is added to, I suggest you create a new question and include an example of your existing code within it.

Welcome to Twine Q&A, where you can ask questions and receive answers from other members of the community.

You can also find hints and information on Twine on the official wiki and the old forums archive.

See a spam question? Flag it instead of downvoting. A question flagged enough times will automatically be hidden while moderators review it.
...