inkle / ink

inkle's open source scripting language for writing interactive narrative.
http://www.inklestudios.com/ink
MIT License
4.1k stars 490 forks source link

[Feature Request] Alternatives with conditional elements in the list #587

Open zacx-z opened 4 years ago

zacx-z commented 4 years ago

Is it possible to add a syntax so alternatives can have flexible number of elements?

For example:

{~Heads|Tails} can be like: {~Heads|{not john_cheat}Tails}

To complete the story logic that when someone cheated, the coin always show heads.

When the list gets long, this syntax can be very handy. I don't know other ways to do similar things.

EDIT: For example: I eat the {~!apple|{get_banana}banana|{get_chocolate}chocolate|{get_tomato}tomato|{get_cake}cake} in my pocket.

joningold commented 4 years ago

{cheated:Heads|{~Heads|Tails}}

Or

{cheated || RANDOM(0,1):Heads|Tails}

Or

~ temp result = cheated || RANDOM(0,1) {result:Heads|Tails}

Which is probably the most useful way to do it if the result has other consequences. -- Jazz, in Three-Four Time: A Novel http://www.amazon.co.uk/dp/B004K1EYIE

zacx-z commented 4 years ago

OK. Then think about this, when you get so many conditions like:

I eat the {~!apple|{get_banana}banana|{get_chocolate}chocolate|{get_tomato}tomato|{get_cake}cake} in my pocket.

It's gonna be crazy when you try to write in the ways shown above.

joningold commented 4 years ago

Sure. So if you’re tracking lots of picked up items I would absolutely use list items to do that rather than a large list of knot names. So have a list of fruit, put things in / out of it, pick one and say what it is - in short, model the fruit bowl. Shuffles are really intended for superficial text swapping since you can’t query the result.

If that’s all my you need, something like this can work

{~{got_bananas:bananas|kiwis}|apples}

You can engineer solutions that notice blank text and repick, like

...Which is closest to your original suggestion.

But we can’t readily extend the shuffle syntax in the way you describe because {got_banana} already has a meaning! -- Jazz, in Three-Four Time: A Novel http://www.amazon.co.uk/dp/B004K1EYIE

zacx-z commented 4 years ago

Hmm repicking would work, though I think it could be inefficient.

Here is what I wanted to do for prototyping:

I have 100 pieces of texts (logs).

When I click on "collect" option, I read a random log. Each log can be seen only once. So this can be done with shuffle once and tunneling, right?

The issue is, if I want to add dependencies of logs -- a log can be acquired only when another specific log is seen. It seems to be hard to do with that.

If I am using LIST, it seems not able to use knots as elements? I'll have to make a switch statement with 100 cases just to make the diverts -- to map the list elements to the knots of the logs.

So that's why I was hoping there can be conditional tests in alternatives. It will make everything much easier and I can quickly prototype the dependencies of logs.

joningold commented 4 years ago

That all makes sense but I would say; in practice I don’t think there’s as big a difference between the complexities of

{~ -> first_log|{first_log:-> follow_up_log}|...etc for a hundred items}

And

=== readlog (logPicked) // call this as a tunnel with the chosen log as a parameter {logPicked:

And the second is going to be less awful to come back to..!

So I’d really recommend it here even if the other syntax existed. We refer to this king of thing as a “pattern” and complex ink projects use this kind of idea a lot.

(And this particular pattern is exactly how we’re handling this kind of thing in our current game, and it has advantages, because now it’s easy to have an index of the logs their players seen; or query “is this log one from the list of logs that’s particularly rare” ... or whatever). -- Jazz, in Three-Four Time: A Novel http://www.amazon.co.uk/dp/B004K1EYIE

zacx-z commented 4 years ago

Thanks for the insights! Yeah, when you want to check the state somewhere else the second solution is the best one, although you have to write a lot more code when the list gets long.

This issue can be closed then, if this feature is considered unnecessary.