Tunnels are in. Close #30
This commit is contained in:
40
examples/tunnels/main.hank
Normal file
40
examples/tunnels/main.hank
Normal file
@@ -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.
|
||||
13
examples/tunnels/test1.hlog
Normal file
13
examples/tunnels/test1.hlog
Normal file
@@ -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.
|
||||
@@ -10,7 +10,7 @@ enum ExprType {
|
||||
|
||||
EOutput(o: Output);
|
||||
|
||||
EDivert(target: String);
|
||||
EDivert(targets: Array<String>);
|
||||
EThread(target: String);
|
||||
EKnot(name: String);
|
||||
EStitch(name: String);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<StoryNode> = 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];
|
||||
|
||||
Reference in New Issue
Block a user