Stories output transcripts. Closed #6
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
transcript.hanktest
|
||||
24
examples/tests/main2.hanktest
Normal file
24
examples/tests/main2.hanktest
Normal file
@@ -0,0 +1,24 @@
|
||||
This is a section of a Hank story. It's pretty much like a Knot in Ink.
|
||||
Line breaks define the chunks of this section that will eventually get sent to your game to process!
|
||||
Your Hank scripts will contain the static content of your game, but they can also insert dynamic content, even the result of complex haxe expressions!
|
||||
You can include choices for the player.
|
||||
* Door A looks promising!
|
||||
* Door B
|
||||
>>> 0
|
||||
Door A opens and there's nothing behind it.
|
||||
You can include choices for the player.
|
||||
* Door B
|
||||
* Choices can depend on logical conditions being truthy.
|
||||
>>> 0
|
||||
Door B opens but the room on the other side is identical!
|
||||
You can include choices for the player.
|
||||
* Door B
|
||||
* Choices can depend on logical conditions being truthy.
|
||||
>>> 1
|
||||
Choices can depend on logical conditions being truthy.
|
||||
* I don't think I'll use Hank for my games.
|
||||
* Hank sounds awesome, thanks!
|
||||
>>> 1
|
||||
Hank sounds awesome, thanks!
|
||||
That's the end of this example!
|
||||
This should say 'mouse': mouse
|
||||
@@ -18,7 +18,7 @@ class RunStoryDemo {
|
||||
}
|
||||
}
|
||||
|
||||
var story: Story = new Story(false);
|
||||
var story: Story = new Story(false, "transcript.hanktest");
|
||||
story.loadScript(path);
|
||||
var frame = StoryFrame.Finished;
|
||||
do {
|
||||
|
||||
59
src/Story.hx
59
src/Story.hx
@@ -1,5 +1,11 @@
|
||||
package src;
|
||||
|
||||
import haxe.ds.Option;
|
||||
import haxe.io.Bytes;
|
||||
|
||||
// TODO sys.io.File calls might not work on HTML5 targets
|
||||
import sys.io.FileOutput;
|
||||
|
||||
import hscript.Parser;
|
||||
import hscript.Interp;
|
||||
|
||||
@@ -40,6 +46,7 @@ class Story {
|
||||
private var interp = new Interp();
|
||||
// TODO use interp.set(name, value) to share things (i.e. modules) to script scope
|
||||
// TODO can objects be shared in/out of HScript?
|
||||
private var transcriptFile: Option<FileOutput> = None;
|
||||
|
||||
private var choiceDepth = 0;
|
||||
private var debugPrints: Bool;
|
||||
@@ -52,8 +59,48 @@ class Story {
|
||||
}
|
||||
}
|
||||
|
||||
public function new(debug: Bool = false) {
|
||||
private function closeTranscript() {
|
||||
switch (transcriptFile) {
|
||||
case Some(file):
|
||||
file.close();
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
private function logFrameToTranscript(frame: StoryFrame) {
|
||||
switch (frame) {
|
||||
case HasText(text):
|
||||
logToTranscript(text);
|
||||
case HasChoices(choices):
|
||||
for (choice in choices) {
|
||||
logToTranscript('* ${choice}');
|
||||
}
|
||||
case Error(message):
|
||||
logToTranscript('! ${message}');
|
||||
closeTranscript();
|
||||
case Finished:
|
||||
closeTranscript();
|
||||
}
|
||||
}
|
||||
|
||||
private function logToTranscript(line: String) {
|
||||
switch (transcriptFile) {
|
||||
case Some(file):
|
||||
file.write(Bytes.ofString(line + "\n"));
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Create a new Story processor.
|
||||
@param debug Whether to output debug information to stdout
|
||||
@param transcriptPath an optional filepath to output a transcript of the story playthrough
|
||||
**/
|
||||
public function new(debug: Bool = false, transcriptPath="") {
|
||||
debugPrints = debug;
|
||||
if (transcriptPath.length > 0) {
|
||||
transcriptFile = Some(sys.io.File.write(transcriptPath));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,10 +250,12 @@ class Story {
|
||||
}
|
||||
|
||||
public function nextFrame(): StoryFrame {
|
||||
return if (currentLine >= scriptLines.length) {
|
||||
Finished;
|
||||
if (currentLine >= scriptLines.length) {
|
||||
return Finished;
|
||||
} else {
|
||||
processNextLine();
|
||||
var frame = processNextLine();
|
||||
logFrameToTranscript(frame);
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,6 +432,8 @@ class Story {
|
||||
// Move to the line following this choice.
|
||||
stepLine();
|
||||
|
||||
logToTranscript('>>> ${index}');
|
||||
logToTranscript(choiceTaken.text);
|
||||
return choiceTaken.text;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,11 +68,15 @@ class StoryTest extends haxe.unit.TestCase {
|
||||
validateAgainstTranscript("examples/main.hank", "examples/tests/main1.hanktest");
|
||||
}
|
||||
|
||||
public function testRunFullSpec3() {
|
||||
validateAgainstTranscript("examples/main.hank", "examples/tests/main2.hanktest");
|
||||
}
|
||||
|
||||
/**
|
||||
Keep this clunky thing around to sanity check validateAgainstTranscript()
|
||||
**/
|
||||
public function testRunFullSpec1() {
|
||||
var story: Story = new Story(true);
|
||||
var story: Story = new Story(true, "transcript.hanktest");
|
||||
story.loadScript("examples/main.hank");
|
||||
var frame1 = Std.string(story.nextFrame());
|
||||
// This calls the INCLUDE statement. Ensure that all lines
|
||||
@@ -113,6 +117,9 @@ class StoryTest extends haxe.unit.TestCase {
|
||||
assertEquals("HasText(That's the end of this example!)", Std.string(story.nextFrame()));
|
||||
assertEquals("HasText(This should say 'mouse': mouse)", Std.string(story.nextFrame()));
|
||||
assertEquals(StoryFrame.Finished, story.nextFrame());
|
||||
|
||||
// Validate the transcript that was produced
|
||||
validateAgainstTranscript("examples/main.hank", "transcript.hanktest");
|
||||
}
|
||||
|
||||
public function testParseLine() {
|
||||
|
||||
Reference in New Issue
Block a user