inkle / inky

An editor for ink: inkle's narrative scripting language
http://www.inklestudios.com/ink
2.41k stars 295 forks source link

How to stop accidental infinite loop in Inky #123

Open kbigdelysh opened 7 years ago

kbigdelysh commented 7 years ago

When writing a story, sometimes the inky gets into an infinite loop. How can I stop it? The only way I've found so far is to press Ctrl+Shift+Esc to bring up task manager and then ending its task. I would loose my work in these situations.

joningold commented 7 years ago

Yeah, this can be a problem. What I've done is to click Into the story script and hit { and then return -- it can take a while but inky usually manages to insert the { character, the return key forces a recompile, and an error, and so the player stops running.

Jon On Sun, 1 Oct 2017 at 6:11 am, Kamran Bigdely-Shamloo < notifications@github.com> wrote:

When writing a story, sometimes the inky gets into an infinite loop. How can I stop it? The only way I've found so far is to press Ctrl+Shift+Esc to bring up task manager and then ending its task. I'll loose my work in these situations.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/inkle/inky/issues/123, or mute the thread https://github.com/notifications/unsubscribe-auth/AA40ozLKREiYl40IGD3ir7YNzcMmry6Tks5snx8VgaJpZM4PpyVx .

amk1710 commented 4 years ago

Still having the same issue as of 02/2020. Inky suddenly stops accepting any sort of input and greedily consumes CPU resources.

inky-bug

It really makes it harder to write cyclical dialogue trees in Inky. My temporary fix was to insert an arbitrary choice so inky would actually stop and wait for input. Also, it doesn't help that Ink's official documentation treats this potencial usability issue very casually: image

I understand that such infinite loops are part of Ink's desired behaviour, but the Inky interface should have some sort of protection/hard-limit to how many times the same knot/content can be read. When this limit is reached, it should warn the user about a potentially undesired infinite loop.

Here's a little snippet of ink text (adapted from ink's documentation) that reproduces the issue:

-> round  
=== round ===  
and  
-> round  

ps: #214 has probably encountered the same problem, but gave way too little information

jeremydouglass commented 4 years ago

some sort of protection/hard-limit to how many times the same knot/content can be read

Inky could potentially keep a hashtable of knots/visits within one turn and have a default backstop value -- like 100, or 1000 -- that could be overridden set to 0 (infinite). If a table entry exceeds the limit, then execution halts. I'm not sure if anyone has already come up with a reason to visit a knot more than 100 times in a single turn, but if not then I'm sure that somebody eventually will....

Or antiloop could be a feature that can be enabled, and is off by default.

joningold commented 4 years ago

I’ve definitely used recursive ink functions that have gone thousands of levels deep - but a loop detection cut-off is a really good idea nonetheless. -- Jazz, in Three-Four Time: A Novel http://www.amazon.co.uk/dp/B004K1EYIE

amk1710 commented 4 years ago

Or antiloop could be a feature that can be enabled, and is off by default.

While I like the proposed solution, I'd still like to point out that infinite loop protection is not a "feature", and users should not be able to disable it at all. No settings menu should have an option that makes it possible for the program to crash.

Selsynn commented 4 years ago

You could have a sort of notation in front/before of your node that specifies that this node is infinite and to cut it after x times.

like

@RemoveWarning ( Warning.Recursive, 5)
===RecursiveNode
Youhou I'm a recursive node
->RecursiveNode

and Inky could stop on itself after the 5th time, and still display a warning for every other time it finds a infinite loop.

So antiloop is always enabled and you can disable for specifically a node you KNOW that it is recurrent. Because you should always know what you are doing when doing recurrent things.

I'm just not clear if two nodes that keep sending to the other will have the same pb.

===NodeA
hey, We are on NodeA
->NodeB

===NodeB
Hey, we are now on NodeB
->NodeA

Antiloop should be able to detect that, because i think it should crash it, right now.

jeremydouglass commented 4 years ago

infinite loop protection is not a "feature", and users should not be able to disable it at all

Maybe not "infinite", just "too deep". You can do static analysis to identify some simple loops as infinite if the paths are not conditional -- those can be disallowed in a way that can't be user-configured.

However as soon as you add variables and conditional paths to the mix you are heading into "halting problem" territory to predict whether a loop is infinite or not, and nobody is going to solve that in a general way anytime soon. Maybe the node will be revisited 1001 times and then the loop will terminate. Given that in many simple works any significant amount of recursion is probably unintentional, one general purpose approach would be to use runtime checking to notice when inky has visited the same node a great many times. I would have guessed 100 or 1000 was a reasonable maximum visit value, but users do need to the ability to override that limit if needed (if not disable it) -- as @joningold just pointed out, "a great many" might not be the same some advanced projects, so perhaps it should be configurable (even if it can't be completely disabled).