Looking for a solution to compounding if statements from long choice chains

Twine: 2.5.1.0
Working with Sugarcube 2.36.1

So wasn’t sure exactly what to make the tile for this. And what I’m looking to try and do might be a bit complex and I’m still learning.

I am attempting to make a ‘Home’ passage, with the idea that there will be other characters present within the ‘Home’. I had the idea of using the include macro to handle extra passages with the side characters, that will have links to various conversations with them.

So what I am looking to do, is allow the player to say talk to Abby. Then I want the choice to talk to Abby about that subject to disappear, and perhaps be replaced by another two choices about something that came up during the conversation. And then perhaps speak to some other character, say Jeff about the same subject. And speaking with Jeff then will allow for another choice with Abby.

And the reason that I’m not doing this in a linear way with progressive passages and if statements is that I intend for the player to be able to leave the ‘Home’ and go do other things, then return with the ability to then discuss with these characters what the player has learned.

So ultimately, what I’m looking for is a more elegant way to evaluate what the player has learned and where the player is in relationship to the conversation with the side characters. Without an absolute mess of if statements and variables. I’ve been trying to figure out how I could maybe make an array or object per character to hold these variables (or just the macro links themselves), and use that to pick which links/buttons should be shown.

Hopefully that all makes sense so far, below I’ll show the sort of idea in code that I’m looking to alleviate.

'Home' Passage

The house is quiet for now.

<<if $abbyHome is true>>
You see Abby reading a book by the fireplace.
   <<include "abbyHandler">>
<</if>>
<<if $jeffHome is true>>
   <<include "jeffHandler">>
<</if>>

abbyHandler Passage

<<nobr>>
<<if $abbyConvo1 is false>>
   <<button "Talk to Abby" "abbyConvo1">><<set $abbyConvo1 to true>><</button>>
<<elseif $abbyConvo1 is true and $abbyAskCar1 is false>>
   <<button "Ask Abby about the car" "abbyCar">><<set $abbyAskCar1 to true>><</button>>
<<elseif $abbyConvo1 is true and $abbyBrother1 is false>>
   <<button "Ask Abby about her brother" "abbyBro">><<set $abbyBrother1 to true>><</button>>
<<elseif $abbyQuestioned is true and $jeffTalk is true>>
   <<button "Ask Abby about Jeff" "abbyRel">><<set $abby2 to true>><</button>>
<</if>>
<</nobr>>

Hopefully that conveys what I’m trying to do, if anyone could help me find a less cumbersome way to do all that I’d appreciate it.

idk if you want to go full storylets, but you could possibly check out my library for that. And if the conversations are a simple branching path for each character you can even get the link arrows to show up in Twine…

Happy to talk more about this if it looks promising to you. It’s not actually less complex than the if-statements, but it can put the conditions and content for each conversation piece together in their own passage instead of lumping all the conditions together separately from the content, if you like that better…

As mentioned by @JoshGrams, you may to consider using “Storylets” as a means to implement what you want. But even if you don’t, there is one improvement you can do now that will help either way…

You shouldn’t use is true or is false when evaluating the current value of a Boolean variable, as it just adds an additional unnecessary step to the evaluation process.

eg. To check if a variable equals true, or a Truthy value…

<<if $hasLamp>>You have the Lamp<</if>>

<<if $hasLamp and $lampOn>>
	Your lamp lights up the room.
<<else>>
	The area is to dark to see anything.
<</if>>

eg. To check if a variable equals false, or a Falsy value…

<<if not $hasLamp>>You need the Lamp to processed<</if>>

<<if ! $hasLamp or ! $lampOn>>The area is to dark to see anything.<</if>>

notes:

  1. You can use either the not keyword or the ! mathematical symbol, as both can be used to flip a true evaluation to false , and vice versa.
  2. You can also use the <<else>> macro when evaluating false, I just didn’t include an example of that.

Based on the above your own example could be shorten a little like so…

'Home' Passage

The house is quiet for now.

<<if $abbyHome>>
You see Abby reading a book by the fireplace.
   <<include "abbyHandler">>
<</if>>
<<if $jeffHome>>
   <<include "jeffHandler">>
<</if>>

abbyHandler Passage

<<nobr>>
<<if not $abbyConvo1>>
   <<button "Talk to Abby" "abbyConvo1">><<set $abbyConvo1 to true>><</button>>
<<elseif $abbyConvo1 and not $abbyAskCar1>>
   <<button "Ask Abby about the car" "abbyCar">><<set $abbyAskCar1 to true>><</button>>
<<elseif $abbyConvo1 and not $abbyBrother1>>
   <<button "Ask Abby about her brother" "abbyBro">><<set $abbyBrother1 to true>><</button>>
<<elseif $abbyQuestioned and $jeffTalk>>
   <<button "Ask Abby about Jeff" "abbyRel">><<set $abby2 to true>><</button>>
<</if>>
<</nobr>>

Something else that you can simplify is the logic in your <<if>> macro. If your first condition checks if $abbyConvo1 is false, then the following conditions don’t need to check if it’s true, since they will only be evaluated if the first condition doesn’t apply:

<<if not $abbyConvo1>>
   <<button "Talk to Abby" "abbyConvo1">><<set $abbyConvo1 to true>><</button>>
<<elseif not $abbyAskCar1>>
   <<button "Ask Abby about the car" "abbyCar">><<set $abbyAskCar1 to true>><</button>>
<<elseif not $abbyBrother1>>
   <<button "Ask Abby about her brother" "abbyBro">><<set $abbyBrother1 to true>><</button>>
<<elseif $abbyQuestioned and $jeffTalk>>
   <<button "Ask Abby about Jeff" "abbyRel">><<set $abby2 to true>><</button>>
<</if>>

Another thing you might want to consider is using the hasVisited() function instead setting variables:

<<if not hasVisited("abbyConvo1")>>
   <<button "Talk to Abby" "abbyConvo1">><</button>>
<<elseif not hasVisited("abbyCar")>>
   <<button "Ask Abby about the car" "abbyCar">><</button>>
<<elseif not hasVisited("abbyBro")>>
   <<button "Ask Abby about her brother" "abbyBro">><</button>>
<<elseif hasVisited("abbyQuestioned") and hasVisited("jeffTalk")>>
   <<button "Ask Abby about Jeff" "abbyRel">><</button>>
<</if>>
<</nobr>>

This has the limitation that you won’t be able to set the variables back to false if you want to revisit a conversation option, but if you don’t need to do that it’s more efficient.

Thanks for the info it’s very helpful!

I spent some time looking over the library @JoshGrams and followed the tutorial you’ve put there. And I think this is almost exactly what I was looking for. Like you said I don’t know that I would call it less complex overall. But it’s way more versatile and manageable. I think I can easily fit what I’m trying to do into a storylet system. So thank you for sharing that! I am going to make use of it in my game.

Might hit some bumps along the road, but I think I understand it fairly well from the tutorial.

As well @Greyelf and @svlin that’s very useful info thank you! Definitely going to help me cut down on the bulk while trying to code everything out.