inkle / inkle/ink

Threaded choice divert param retains original argument after loading StoryState JSON

Open
#321 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
4.9k
Forks
540
PR merge metrics
No merged PRs in 30d

Description

The divert parameter (e.g. `-> goback`) of a threaded choice is not stored correctly when converted to/from JSON.

The second time a choice inside the thread is chosen (with a different argument for `-> goback`), the Ink script incorrectly redirects to the original `-> goback` argument ... which should no longer exist!

**A failing C# NUnit test is included below** that passes only if the save/load StoryState JSON portion is commented out. This may be related to an earlier issue I originally reported via blade-ink (which was graciously resolved with a one-liner!): https://github.com/inkle/ink/issues/267

This issue is important because it prevents using the same thread in multiple knots.

**To reproduce:**

```
-> start

=== common_choices(-> goback) ===
+ No
Try again. <>
-> goback

=== start ===
Choice ONE?
<- common_choices(-> start) # First, select 'No'
+ Yes # Second, select 'Yes' then save/load StoryState JSON
-> asktwo

=== asktwo ===
Choice TWO?
<- common_choices(-> asktwo) # Third, select 'No'. It incorrectly diverts to 'start'!
+ Yes
You win!
-> END
```

Read the Ink script comments above to understand the issue most clearly, following the steps 1-3 when running the story. **If save/load to JSON is removed, the script works correctly.** This indicates the problem is with the save/load to JSON. If additional explanation is required, see the NUnit test below.

**C# Failing NUnit Test:**
```cs
[Test()]
public void TestThreadedChoiceParamJSON()
{
String inkStory = @"
-> start

=== common_choices(-> goback) ===
+ No
Try again. <>
-> goback

=== start ===
Choice ONE?
<- common_choices(-> start)
+ Yes
-> asktwo

=== asktwo ===
Choice TWO?
<- common_choices(-> asktwo)
+ Yes
You win!
-> END
";
Story story = CompileString(inkStory);

Assert.AreEqual("Choice ONE?\n", story.ContinueMaximally());

/** This threaded choice point must be visited twice for the error to occur (on the second visit).
* - Here, it correctly redirects back to 'start'.
* - Next time, it should redirect back to 'asktwo'. But, it incorrectly redirects to 'start' instead! **/
story.ChooseChoiceIndex(0); // start -> No (in thread)
Assert.AreEqual("No\nTry again. Choice ONE?\n", story.ContinueMaximally());

story.ChooseChoiceIndex(1); // start -> Yes (in knot)
Assert.AreEqual("Yes\nChoice TWO?\n", story.ContinueMaximally());

/** If these lines saving StoryState to/from JSON are commented out, the test passes as expected. **/
String savedStateJson = story.state.ToJson();
story = CompileString(inkStory);
story.state.LoadJson(savedStateJson);
/*******/

// ERROR If 0 - should redirect to 'asktwo', but it redirects back to 'start'! (only if state loaded from JSON)
// - #0 is a previously visited threaded choice
// NORMAL If 1 - always correctly ends the script
story.ChooseChoiceIndex(0); // asktwo -> No (in thread) ... should redirect back to asktwo
Assert.AreEqual("No\nTry again. Choice TWO?\n", story.ContinueMaximally());

Assert.IsFalse(story.hasError);
}
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.