+1 vote
by (2.2k points)
edited by

Pretty sure my code is correct

(if: (history:) contains "passage1" and not (history:) contains "passage2")

but I keep getting the error "I can only use 'not' to invert booleans, not an array" and I'm not sure what's wrong with it

Is there a way I can change the string into a Boolean or perhaps a variable?

1 Answer

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

Looks like you can sort this with some extra brackets to prevent ambiguity in the statement phrasing. Harlowe was trying to act on the array directly with the "not" operator, rather than the boolean returned by the "contains" condition.  I added brackets to both conditions for symmetry, even though the ones after "and not" were enough to clear the error.

(if: ((history:) contains "passage1") and not ((history:) contains "passage2"))


by (2.2k points)
edited by
I get the same error. Do you know a way I can change the string into a boolean? Or perhaps a variable?
by (159k points)

There is a natural (programmatic) order to the processing of a conditional expression like the one you are passing to the (if:) macro, the actual order can depend slightly on the programming language being used but mostly it is based on BOMDAS.

This order can also be influenced by the implementation of the parser that is converting the TwineScript you enter into a Passage into something that the story format's engine can execute.

Each sub-clause of a multi part conditional expression is evaluated separately to determine if it result (Boolean) is either true or false , those sub-clauses results are then combined based on the joiners (and, or, etc...) used to determine if the overall result is true or false.

If we break down your original example (based on the error message) with get :

a. (history:) contains "passage1"
b. not (history:)
c. ??? contains "passage2"

Which results in:
a. Boolean: true or false depending on if the Passage name was found or not.
b. Error: because (history:) returns an Array and the not operator doesn't know what to do with it.
c. Potential Error: I am not sure what is being evaluated in this case.

If you break down the example supplied by @geekdragon you get.
a. (history:) contains "passage1")
b. (history:) contains "passage2")
c. not B

Which results in:
a. Boolean: true or false.
b. Boolean: true or false.
c. Boolean: true or false.

by (2.2k points)
edited by

So the code isn't being understood, I getcha, but coding is the opposite of my forte and I don't understand how to make it work, could I put the not within brackets for the second history? like

(if: ((history:) contains "passage1") and ((history:) contains not "passage2"))

This just gives me an 'unexpected identifier' error

by (1.6k points)
edited by
Odd. I had tested the example I provided locally, and it seemed to behave as intended.
by (2.2k points)
Really? Could there be some error that comes with using the online version rather than the downloaded? Assuming you use the downloaded version that is.
by (2.2k points)
I made history a variable and now it works fine, I don't know what really happened there but thank you guys so much
by (1.6k points)

Just tested online without errors. I set up  "passage1" and "passage2", with both containing only a simple link to a third passage containing the following code:

(if: ((history:) contains "passage1") and not ((history:) contains "passage2"))[True](else:)[False]

Depending which passage is used as a starting point, "True" or "False" is displayed.

*edit* glad you got it working!