From 0a07887579d6a1924b13763a608eafda8631b738 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Thu, 6 Jun 2019 21:33:29 -0600 Subject: [PATCH] Tunnels are in. Close #30 --- examples/tunnels/main.hank | 40 ++++++++++++++++++++ examples/tunnels/test1.hlog | 13 +++++++ hank/HankAST.hx | 2 +- hank/Parser.hx | 8 ++-- hank/Story.hx | 74 ++++++++++++++++++++++++++++++------- 5 files changed, 119 insertions(+), 18 deletions(-) create mode 100644 examples/tunnels/main.hank create mode 100644 examples/tunnels/test1.hlog diff --git a/examples/tunnels/main.hank b/examples/tunnels/main.hank new file mode 100644 index 0000000..7ad6a0a --- /dev/null +++ b/examples/tunnels/main.hank @@ -0,0 +1,40 @@ +// Based on https://github.com/inkle/ink/blob/01898140be43d29baac70c1cb6544bdb10164209/Documentation/WritingWithInk.md#tunnels-run-sub-stories + +// TODO this hack is because we don't have divert arguments yet. +~ var location = ->plains; + +-> @location +=== plains + += night_time + + The dark grass is soft under your feet. + + [Sleep] + -> sleep_here -> wake_here -> day_time += day_time + It is time to move on. + +=== wake_here + You wake as the sun rises. + + [Eat something] + -> eat_something -> @location.day_time + + [Make a move] -> @location.day_time + + +=== sleep_here + You lie down and try to close your eyes. + -> monster_attacks -> + Then it is time to sleep. + -> dream -> + +// I added these: + += monster_attacks + You get attacked by a monster! + += dream + You dream about even scarier monsters. + +=== eat_something + +You're out of food! Soon you will starve to death. \ No newline at end of file diff --git a/examples/tunnels/test1.hlog b/examples/tunnels/test1.hlog new file mode 100644 index 0000000..ebffdcb --- /dev/null +++ b/examples/tunnels/test1.hlog @@ -0,0 +1,13 @@ +The dark grass is soft under your feet. +* Sleep +> 1: +You lie down and try to close your eyes. +You get attacked by a monster! +Then it is time to sleep. +You dream about even scarier monsters. +You wake as the sun rises. +* Eat something +* Make a move +> 1: +You're out of food! Soon you will starve to death. +It is time to move on. diff --git a/hank/HankAST.hx b/hank/HankAST.hx index d5c1316..9486c0e 100644 --- a/hank/HankAST.hx +++ b/hank/HankAST.hx @@ -10,7 +10,7 @@ enum ExprType { EOutput(o: Output); - EDivert(target: String); + EDivert(targets: Array); EThread(target: String); EKnot(name: String); EStitch(name: String); diff --git a/hank/Parser.hx b/hank/Parser.hx index 433f2ee..6640228 100644 --- a/hank/Parser.hx +++ b/hank/Parser.hx @@ -142,10 +142,10 @@ class Parser { } static function divert(buffer: HankBuffer, position: HankBuffer.Position) : ExprType { - buffer.drop('->'); - buffer.skipWhitespace(); - var tokens = lineTokens(buffer, 1, position, true, true); - return EDivert(tokens[0]); + var line = buffer.takeLine().unwrap(); + var targets = [for(t in line.split('->')) t.trim()].slice(1); + + return EDivert(targets); } static function thread(buffer: HankBuffer, position: HankBuffer.Position) : ExprType { diff --git a/hank/Story.hx b/hank/Story.hx index 2296cfe..07b02c2 100644 --- a/hank/Story.hx +++ b/hank/Story.hx @@ -101,7 +101,8 @@ class Story { function storyFork(t: String): Story { // Everything is the same as when embedding blocks, but a fork uses the same AST as its parent -- simply starting after a hypothetical divert var story = new Story(random, parser, this.ast, storyTree, nodeScopes, viewCounts, hInterface); - story.parent = Some(this); + // Just trust me that in Tunneling mode, the embedded stories don't need a parent. This is because I was too lazy to disambiguate tunnel mode from embedded mode. + if (embedMode == Thread) story.parent = Some(this); // trace('story parent: ${story.parent.match(Some(_))}'); story.divertTo(t); return story; @@ -224,16 +225,43 @@ class Story { exprIndex += 1; hInterface.runEmbeddedHaxe(h, nodeScopes); return nextFrame(); - case EDivert(target): - // Fallback choices simply advance flow using divert syntax - if (target.length == 0) { + // Fallback choices simply advance flow using divert syntax by not specifying a target + case EDivert([""]): + exprIndex += 1; - } - // All other diverts: - else { - divertTo(target); - } + + // The most common form of divert is to one other location. + case EDivert([oneTarget]): + divertTo(oneTarget); + return nextFrame(); + + // Tunneling statements! + case EDivert(targets): + switch (targets.pop()) { + case target if (target != ''): + // If the last target isn't empty, we want to fork the main story to start at that point once the tunnels are done. + // trace('this divert'); + divertTo(target); + case '': + exprIndex++; + case null: + throw 'No divert targets!'; + } + + // Spawn the rest of the forks in tunneling mode + for (target in targets) { + // trace('embedded $target'); + var fork = storyFork(target); + // trace(fork != null); + embeddedBlocks.push(fork); + // trace(embeddedBlocks.length); + } + + // trace(embeddedBlocks.length); + + return nextFrame(); + case EThread(target): // The thread only needs to be added once exprIndex++; @@ -410,14 +438,34 @@ class Story { // trace('diverting to $target'); - var newScopes = if (target.startsWith("@")) hInterface.getVariable(target.substr(1)) else resolveNodeInScope(target); + var newScopes = if (target.startsWith("@")) { + + var parts = target.split('.'); + + var root: Array = hInterface.getVariable(parts[0].substr(1)); + if (parts.length > 1) { + var subTarget = parts.slice(1).join('.'); + //trace(subTarget); + resolveNodeInScope(subTarget, root); + } else { + root; + }; + } + else resolveNodeInScope(target); // trace('$target is $newScopes'); + if (newScopes == null // happens when a divert target variable doesn't exist + || newScopes.length == 0) // happens when target can't be resolved + throw 'Divert target not found: $target'; + var targetIdx = newScopes[0].astIndex; - if (targetIdx == -1) { - throw 'Divert target not found: $target'; - } + if (targetIdx == null) { + throw 'Divert target not found: $target'; + +} + //trace(targetIdx); + // update the expression index exprIndex = targetIdx; var target = newScopes[0];