Conditional options in cycling links?

Twine Version: 2.12.0

Hello all! I’m dipping my toe back into IF after a long hiatus to focus on my studies, and hoo boy am I rusty - apologies in advance if this is a really stupid question.

So what I’m attempting to do is to create a cycling link where the options available are conditional. Each possible link should include both a label and a value.

This is an example of what I naively assumed would work at first and didn’t - I guess if macros are ignored within cycle, because it just displayed all of the possible options irrespective of whether the condition was met or not.

<<cycle "$faveAnimal" autoselect>>
	<<if ($metDog is false) and ($metCat is false)>>
		<<option "I don't know what an animal is." 1>>
	<</if>>
	<<if $metDog is true>>
		<<option "Dogs are my favourite animal." 2>>
	<</if>>
	<<if $metCat is true>>
		<<option "Cats are my favourite animal." 3>>
	<</if>>
	<<if ($metDog is true) and ($metCat is true)>>
		<<option "I like dogs and cats equally." 4>>
	<</if>>
<</cycle>>

(This isn’t the actual use case of what I’m trying to implement, just an example of the logic - I really need the value as well as the label for what I have in mind.)

I’m certain there must be a way to do this elegantly with arrays/objects/maps and optionsfrom but I’ve been tooling around with those things for several hours and all I’ve succeeded in achieving is giving myself a headache. I am a writer first and a coder about seventeenth.

Any advice would be appreciated and thanks in advance!

Hrm. I think for that you’d have to populate an object or map with the options, yeah.

<<set $metDog to true>>
<<set $metCat to true>>

<<set _opts to {}>>
<<if ($metDog is false) and ($metCat is false)>>
  <<set _opts["I don't know what an animal is."] to 1>>
<</if>>
<<if $metDog is true>>
  <<set _opts["Dogs are my favourite animal."] to 2>>
<</if>>
<<if $metCat is true>>
  <<set _opts["Cats are my favourite animal."] to 3>>
<</if>>
<<if ($metDog is true) and ($metCat is true)>>
  <<set _opts["I like dogs and cats equally."] to  4>>
<</if>>

<<cycle "$faveAnimal" autoselect>>
  <<optionsfrom _opts>>
<</cycle>>
2 Likes

I tried a very similar solution to Josh’s, pasting it just in case the toggle links come handy for debugging.

Paste on a passage called Test
<<set _options to {}>>\
<<if ($metDog is false) and ($metCat is false)>>\
	<<set _options["I don't know what an animal is."] to 1 >>\
<</if>>\
<<if $metDog is true>>\
	<<set _options["Dogs are my favourite animal."] to 2 >>\
<</if>>\
<<if $metCat is true>>\
	<<set _options["Cats are my favourite animal."] to 3 >>\
<</if>>\
<<if ($metDog is true) and ($metCat is true) >>\
	<<set _options["I like dogs and cats equally."] to 4 >>\
<</if>>\
\
<<cycle "$faveAnimal" autoselect>>
	<<optionsfrom _options>>
<</cycle>>

metDog=<<print $metDog or false>> ([[Toggle->Test][$metDog = !$metDog]])
metCat=<<print $metCat or false>> ([[Toggle->Test][$metCat = !$metCat]])
1 Like

Thank you so much, that absolutely worked! Thanks @n-n too.

If you fancy another conundrum, I’ve now come across a secondary issue; ideally the options would be presented shuffled every time they are displayed. Is there any way to shuffle an object/map like you would an array?

Oh, that’s a pain. Convert to an array, shuffle, convert back? Ugh.

<<set _options to Object.entries(_options).shuffle().reduce((o,[k,v]) => { o[k] = v;  return o }, {})>>
1 Like

Thanks Josh, this is not the first time you’ve helped me out with something I was stuck on and I really do appreciate you taking the time!