How to get Bitwise Flags to work with multiple if statements and nesting if statements, and toggleLink widgets

Twine version : 2.12.0.0 / SugarCube 2.37.3

~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

I am creating a template for my future IF (where each choice is supposed to have an effect on the story). To cut down the number of passages, I decided to mark each choice link with a $variable, and use IF statements to check with parts of the story should be visible at what time. Then to cut down the number of variables, I decided to only have one $variable per passage for choice links, and then add the link choices beneath it using Bitwise Flags (after learning such things existed). (If I can get them to work, I’ll probably use them elsewhere too, but right now, I want to focus on this.) …based on the information I have, Bitwise Flags should work on SugarCube… ?

I may know more than the average person, but I am far from being proficient in coding (or using Twine and SucarCube), at best, I merely dabble…and right now I am at my wits end.

~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

“StoryInit” Passage

Question : Can the “Value option” name be the same for multiple Flags? Or do they have to be unique?

So is this ok?

<<set $passage111name = 0>>
<<set setup.Choice01 = Math.pow(2, 0)>>
<<set setup.Choice02 = Math.pow(2, 1)>>
<<set setup.Choice03 = Math.pow(2, 2)>>
<<set setup.Choice04 = Math.pow(2, 3)>>

<<set $passage222name = 0>>
<<set setup.Choice01 = Math.pow(2, 0)>>
<<set setup.Choice02 = Math.pow(2, 1)>>
<<set setup.Choice03 = Math.pow(2, 2)>>
<<set setup.Choice04 = Math.pow(2, 3)>>

Or is this how it is suppose to be?

<<set $passage111name = 0>>
<<set setup.P111Choice01 = Math.pow(2, 0)>>
<<set setup.P111Choice02 = Math.pow(2, 1)>>
<<set setup.P111Choice03 = Math.pow(2, 2)>>
<<set setup.P111Choice04 = Math.pow(2, 3)>>

<<set $passage222name =0>>
<<set setup.P222Choice01 = Math.pow(2, 0>>
<<set setup.P222Choice02 = Math.pow(2, 1)>>
<<set setup.P222Choice03 = Math.pow(2, 2)>>
<<set setup.P222Choice04 = Math.pow(2, 3)>>

Question : Just to make sure, that is how the code is supposed to look, right?

~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

Passage containing the Flag

<<link "Choice01" "passage222name">><<set $passage111name |= setup.Choice01>><</link>>
<<link "Choice02" "passage222name">><<set $passage111name |= setup.Choice02>><</link>>
<<link "Choice03" "passage222name">><<set $passage111name |= setup.Choice03>><</link>>
<<link "Choice04" "passage222name">><<set $passage111name |= setup.Choice04>><</link>>

That is how it is suppose to look like when using with a link…I think.

~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

Question : How to make it (and other variables) work with ToggleLink (widget) ?

Passage : toggle-link Tags: widget nobr

<<widget "toggleLink">>
<<if ndef _tlink>>
<<set _tlink = 1>>
<<else>>
<<set _tlink++>>
<</if>>
<<set _linkStr = "$('.togglelink[id!=\\'tlink" + _tlink + "\\']')">>
<span @id="'tlink' + _tlink" class="togglelink"
@onmouseenter="_linkStr + '.addClass(\'disabled\')'"
@onmouseleave="_linkStr + '.removeClass(\'disabled\')'">
<<link $args[0] $args[1]>><</link>>
</span>
<</widget>>

Passage containing the Flag

<<toggleLink "Choice 1" "Chapter 1">>
<<toggleLink "Choice 2" "Chapter 1">>
<<toggleLink "Choice 3" "Chapter 1">>
<<toggleLink "Choice 4" "Chapter 1">>

It doesn’t have <> so where I am suppose to put the <<set $variables>> ? Can it even be done ?

This is really not “a must”…but I do kinda fancy the effect it has on the choice links. It would be nice to get the IF not only working smoothly but also looking good.

~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

Passage checking for the Flag

When using the regular choice links, I can get this far :

<<if ($passage111name & setup.Choice01)>>
Flag 1 is set.
<<elseif ($passage111name & setup.Choice02)>>
Flag 2 is set.
<<elseif ($passage111name & setup.Choice03)>>
Flag 3 is set.
<<elseif ($passage111name & setup.Choice04)>>
Flag 4 is set.
<</if>>

: and it works. So, I assume it is correct…?

But when I try to check for multiple Flags, it stops working…

<<if (($passage111name & setup.Choice01) & (($passage222name & setup.Choice01))>>
Flag 111 choice01 and Flag 222 choice01

<<elseif (($passage111name & setup.Choice02) & (($passage222name & setup.Choice02))>>
Flag 111 choice02 and Flag 222 choice02

<<elseif (($passage111name & setup.Choice03) & (($passage222name & setup.Choice03))>>
Flag 111 choice03 and Flag 222 choice03

<<elseif (($passage111name & setup.Choice04) & (($passage222name & setup.Choice04))>>
Flag 111 choice04 and Flag 222 choice04

<</if>>

…regardless of which StoryInit version I use…

<<if (($passage111name & setup.P111Choice01) & (($passage222name & setup.P222Choice01))>>
Flag 111 choice01 and Flag 222 choice01

<<elseif (($passage111name & setup.P111Choice02) & (($passage222name & setup.P222Choice02))>>
Flag 111 choice02 and Flag 222 choice02

<<elseif (($passage111name & setup.P111Choice03) & (($passage222name & setup.P222Choice03))>>
Flag 111 choice03 and Flag 222 choice03

<<elseif (($passage111name & setup.P111Choice04) & (($passage222name & setup.P222Choice04))>>
Flag 111 choice04 and Flag 222 choice04

<</if>>

…and regardless of whether I use the “&” or “and” between the two $variables :

<<if (($passage111name & setup.P111Choice01) & ($passage222name & setup.P222Choice01))>>

<<if (($passage111name & setup.P111Choice01) and ($passage222name & setup.P222Choice01))>>

Any help and / or clarification is welcomed with open arms!

~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

Your first option here is setting the same values twice: setup.Choice01 is the same name each time. But if your Choice01 are always 1, Choice03 is always 8, then there’s no need to have a separate set of bit flags for each passage, you can just reuse one set of names (just make it big enough for the max number of choices that you’re giong to have).

On the other hand, if you’re not going to name them specifically instead of just numbering them (not Choice01 but TurnLeft or TakePurpleCrayon) then you may want separate names, and in that case you probably DO want to use the passage name as a prefix to avoid naming conflicts.


When using a link… That looks OK, I think? You can also use the Setter Link syntax that SugarCube has (SugarCube v2 Documentation)

[[Choice01|passagea222name][$passage111name |= setup.Choice01]]

toggleLink: I’m being too lazy to be sure I’m reading this code correctly, but I think you’d add a <<set State.variables[_args[2]] |= setup[_args[3]]>> in the widget and call it with <<toggleLink "Choice 1" "Chapter 1" "Chapter01" "Choice01">> or something like that?


Checking multiple flags:

<<if (($passage111name & setup.Choice01) & (($passage222name & setup.Choice01))>>
Flag 111 choice01 and Flag 222 choice01

You need a double ampersand (or the word and) between the two: a single & is a bitwise AND (which bits are set in both numbers?), the double && or and is a logical AND (are both these conditions true?).

But since you’re checking the same bit in each, I would expect your code to accidentally work here. Are you sure you have both variables set correctly?

My honest first reaction is, don’t do this.

You aren’t going to run out of variables. In any reasonable game, you can have as many boolean variables set as you like, and it won’t affect performance. i.e. you are over-optimising something that doesn’t need optimising.

And what’s more, I think you are actively making things harder for yourself. $passage111name & setup.P111Choice01 is so much harder to track and remember for you, the author, than $events.passage111.tookKey that you will drive yourself mad trying to make sense of it after a small number of choices.

And even more than that, there’s pretty much no need to economise on the number of passages either, and SugaeCube already tracks all the passages you have visited for you. You could just make all these choices passages and use visited() and track no variables at all.

So … don’t do this.

If you do do this, then the answer to the <<toggeLink>> widget is to make it a container, so it acts like <<link>> does.

<<widget "toggleLink" container>>
<<if ndef _tlink>>
<<set _tlink = 1>>
<<else>>
<<set _tlink++>>
<</if>>
<<set _linkStr = "$('.togglelink[id!=\\'tlink" + _tlink + "\\']')">>
<span @id="'tlink' + _tlink" class="togglelink"
@onmouseenter="_linkStr + '.addClass(\'disabled\')'"
@onmouseleave="_linkStr + '.removeClass(\'disabled\')'">
<<link $args[0] $args[1]>>_contents<</link>>
</span>
<</widget>>

I opted out on using the regular SugarCube linking system, because 1) I dislike the arrows it creates to show the path between linked passages, 2) the code harder for me to read (could be a dyslexia thing ??). When I do happen use the SugarCube version, I useually prefer the [[passagea222name->Choice01][$passage111name |= setup.Choice01]] way of writing it.

For some reason using AND (and) between the two $variables does not work…or at least, I can’t get it to work in this case (maybe it has something to do with the Bitwise Flag??). However :

<<if (($page111name& setup.Choice01) && ($page222name & setup.Choice011))>>
this is page111 choice01 and page222 choice011

: using the double ambersand (&&), as shown above, worked like a charm! So thank very very much! You saved me from a ton tears and extra gray hair!

I think that’s the opposite of what you are trying to do, though. The single & is logical AND, the double && is the bitwise and. You are trying to compare bitwise properties inside the parens, and then logically combine them afterwards, so you should be doing:

<<if ($page111name && setup.Choice01) & ($page222name && setup.Choice01)>>

I totally understand where you coming when saying, “…,don’t do this.”

One of the main reasons why I’m leaning on doing things this way, is my innate hatered for messy Story Boards. I detest tracking down passages and jumping from one passage to another. It is not enough for me to make the game look good from a player’s point of view…but the Twine file need to tidy and well organized as well. My neurodivergent brain just won’t have it in any other way without having a meltdown.

Also this is just for the “Link Choices”, things that do not really give anything. For everything else, such as obtaining a key, I will be using good old regular $variables.

If I did not do this, I would end up with an approximately one and a half million passages and four times that “Link Choice” $variables. I mean, if each choice open to a new passage and each new passage had four choices to choose from.

However, your answer was a life savior.

The code you provided worked perfectly and I could not be happier with the results! So thank you very very much!

I not sure how to explain this…I hope this makes sense.

I was not trying to check whether or not $passage111name was setup.Choice01. Nor was I trying to check whether or not $passage222 was setup.Choice011.

…what I did want to check was whether both statements :

$passage111name = setup.Choice01 AND $passage222name = setup.Choice011

: are simultaneously true. And I think I managed to do that :

: with this…

Right, I get it. Ignore what I said before then :smiley:

Make sure that your $passageXXX variables are always powers of 2, because & can return a truthy value without your flags being set as you exepct if it isn’t. e.g. 11 & 2 is truthy, even if you can’t get 11 from your flags.

Yeah, I think after I get a section to work, I’ll just be copy+pasting it, in order to minimize the likely hood of errors :upside_down_face:

Thank you so much for taking your time to help out! It is much appreciated!