class_name Story var hInterface: HInterface var insertionHooks: Variant var random: Random var ast: Array[Variant] var exprIndex: int var storyTree: StoryNode var viewCounts: Variant var nodeScopes: Array[StoryNode] var altInstances: Variant = haxe_ds_ObjectMap.new() var parser: HParser var embedMode: EmbedMode.EmbedMode = EmbedMode.EmbedMode.Tunnel var embeddedBlocks: Array[Story] = [] var parent: Variant = { "_index": 1 } var choicesTaken: Array[int] = [] var weaveDepth: int = 0 var storedFrame: Variant = { "_index": 1 } func _init(r: Random, p: HParser, ast2: Array[Variant], st: StoryNode, sc: Array[StoryNode], vc: Variant, hi: HInterface) -> void: self.insertionHooks = haxe_ds_StringMap.new() self.random = r self.parser = p self.ast = ast2 self.storyTree = st self.nodeScopes = sc self.viewCounts = vc self.hInterface = hi func currentFile() -> String: return self.ast[0].get("position").file func embeddedStory(h: String) -> Story: var ast2: Array[Variant] = self.parser.parseString(h) var story: Story = Story.new(self.random, self.parser, ast2, self.storyTree, self.nodeScopes, self.viewCounts, self.hInterface) story.exprIndex = 0 story.parent = { "_index": 0, "v": self } return story func storyFork(t: String, readonly: bool = false) -> Story: var tempMap if (readonly): tempMap = self.storyTree.createViewCounts() else: tempMap = self.viewCounts var story: Story = Story.new(self.random, self.parser, self.ast, self.storyTree, self.nodeScopes, tempMap, self.hInterface) if (self.embedMode == EmbedMode.EmbedMode.Thread): story.parent = { "_index": 0, "v": self } story.divertTo(t) return story func addVariable(name: String, val) -> void: self.hInterface.addVariable(name, val) func runRootIncludedHaxe(rootFile: String) -> void: var i: int = 0 while (i < ASTExtension.findFile(self.ast, rootFile)): var file: String = self.ast[i].get("position").file if true: var _g: Variant = self.ast[i].get("expr") match (_g._index): 7: var _g2: String = _g.haxe if true: var h: String = _g2 if true: self.hInterface.runEmbeddedHaxe(h, self.nodeScopes) i += 1 8: var _g2: String = _g.haxe if true: var h: String = _g2 if true: self.hInterface.runEmbeddedHaxe(h, self.nodeScopes) i += 1 _: i = ASTExtension.findEOF(self.ast, file) + 1 func nextFrame() -> Variant: if true: var _g: Variant = self.storedFrame if (_g._index == 0): var _g2: Variant = _g.v var f: Variant = _g2 self.storedFrame = { "_index": 1 } return f else: pass while (self.embeddedBlocks.size() > 0): if true: var _g: EmbedMode.EmbedMode = self.embedMode match (((_g as Variant) as int)): 0: var nf: Variant = self.embeddedBlocks[0].nextFrame() if (nf == { "_index": 2 }): var _this: Array[Story] = self.embeddedBlocks var x: Story = self.embeddedBlocks[0] var index: int = _this.find(x) if (index >= 0): _this.remove_at(index) true else: false else: return nf 1: var idx: int = 0 while (idx < self.embeddedBlocks.size()): var nf: Variant = self.embeddedBlocks[idx].nextFrame() match (nf._index): 1: var _g2: Array[String] = nf.choices var _g3: Array[Variant] = nf.tags idx += 1 continue 2: idx += 1 continue _: return nf break if (self.exprIndex >= self.ast.size()): if (self.embedMode == EmbedMode.EmbedMode.Thread): return self.nextChoiceFrame() return { "_index": 2 } var rootNf: Variant = self.processExpr(self.ast[self.exprIndex].get("expr")) if (self.embedMode == EmbedMode.EmbedMode.Thread): if (rootNf == { "_index": 2 }): return self.nextChoiceFrame() return rootNf func processExpr(expr: Variant) -> Variant: match (expr._index): 1: var _g: Output = expr.o var output: Output = _g self.exprIndex += 1 var text: String = StringTools.trim(output.format(self, self.hInterface, self.random, self.altInstances, self.nodeScopes, false)) if (self.exprIndex < self.ast.size()): var nextExpr: Variant = self.ast[self.exprIndex].get("expr") var nextIdx: int = self.exprIndex match (nextExpr._index): 2: var _g2: Array[String] = nextExpr.targets if true: var targets: Array[String] = _g2 nextIdx = self.indexOf(targets[0]) 3: var _g2: String = nextExpr.target if true: var target: String = _g2 nextIdx = self.indexOf(target) _: pass if (nextIdx < self.ast.size()): nextExpr = self.ast[nextIdx].get("expr") if (nextExpr._index == 9): var _g2: Variant = nextExpr.label var _g3: int = nextExpr.depth var _g4: Variant = nextExpr.expr var _exp: Variant = _g4 nextExpr = _exp else: pass if (nextExpr._index == 1): var _g2: Output = nextExpr.o var output2: Output = _g2 if (output2.startsWithGlue()): text = Output.appendNextText(self, text + " ", Output.GLUE_ERROR) else: pass return self.finalTextProcessing(text) 2: var _g: Array[String] = expr.targets if (_g.size() == 1): var _g2: String = _g[0] if (_g2 == ""): self.exprIndex += 1 else: var oneTarget: String = _g2 self.divertTo(oneTarget) return self.nextFrame() else: var targets: Array[String] = _g if true: var _g2 = targets.pop_back() if true: var target = _g2 if (target != ""): self.divertTo(target) else: if (_g2 == null): assert(false, str("No divert targets!")) else: if (_g2 == ""): self.exprIndex += 1 if true: var _g2: int = 0 while (_g2 < targets.size()): var target: String = targets[_g2] _g2 += 1 var fork: Story = self.storyFork(target, false) self.embeddedBlocks.push_back(fork) return self.nextFrame() 3: var _g: String = expr.target if true: var target: String = _g if true: self.exprIndex += 1 self.embedMode = EmbedMode.EmbedMode.Thread self.embeddedBlocks.push_back(self.storyFork(target, false)) var nf: Variant = self.nextFrame() return nf 7: var _g: String = expr.haxe if true: var h: String = _g if true: self.exprIndex += 1 self.hInterface.runEmbeddedHaxe(h, self.nodeScopes) return self.nextFrame() 8: var _g: String = expr.haxe if true: var h: String = _g if true: self.exprIndex += 1 self.hInterface.runEmbeddedHaxe(h, self.nodeScopes) return self.nextFrame() 9: var _g: Variant = expr.label var _g1: int = expr.depth var _g2: Variant = expr.expr if true: var label: Variant = _g var depth: int = _g1 var nextExpr: Variant = _g2 if true: match (label._index): 0: var _g3: String = label.v if true: var l: String = _g3 if true: var node: StoryNode = self.resolveNodeInScope(l, null)[0] if true: var _g4: StoryNode = node var _g5: Variant = self.viewCounts if true: var v: int = _g5.__get(_g4) + 1 _g5.__set(_g4, v) v 1: pass self.weaveDepth = depth self.exprIndex += 1 return self.nextFrame() 10: var _g: Variant = expr.c var choice: Variant = _g if (choice.get("depth") > self.weaveDepth): self.weaveDepth = choice.get("depth") else: if (choice.get("depth") < self.weaveDepth): self.gotoNextGather() return self.nextFrame() return self.nextChoiceFrame() _: haxe_Log.trace.call("" + str(expr) + " is not implemented", { "fileName": "../hank/Story.hx", "lineNumber": 336, "className": "hank.Story", "methodName": "processExpr" }) return { "_index": 2 } return { "_index": 2 } func nextChoiceFrame() -> Variant: var choices: Array[Variant] = self.availableChoices() var tempArray if true: var _g: Array[String] = ([] as Array[String]) if true: var _g1: int = 0 while (_g1 < choices.size()): var choiceInfo: Variant = choices[_g1] _g1 += 1 _g.push_back(choiceInfo.get("output").format(self, self.hInterface, self.random, self.altInstances, self.nodeScopes, false)) tempArray = _g var tempArray1 if true: var _g: Array[Variant] = ([] as Array[Variant]) if true: var _g1: int = 0 while (_g1 < choices.size()): var choiceInfo: Variant = choices[_g1] _g1 += 1 _g.push_back(choiceInfo.get("tags")) tempArray1 = _g var tags: Array[Variant] = tempArray1 if (tempArray.size() > 0): return self.finalChoiceProcessing(tempArray, tags) else: var fallback: Variant = self.fallbackChoice() if true: var _g: Variant = fallback.get("choiceInfo").get("divertTarget") if (_g._index == 0): var _g2: String = _g.v var t: String = _g2 if (t.length() > 0): var fallbackText: String = self.evaluateChoice(fallback.get("choiceInfo")) if (fallbackText.length() > 0): assert(false, str("For some reason a fallback choice evaluated to text!")) return self.nextFrame() else: self.exprIndex = fallback.get("index") + 1 self.weaveDepth = fallback.get("choiceInfo").get("depth") + 1 return self.nextFrame() else: self.exprIndex = fallback.get("index") + 1 self.weaveDepth = fallback.get("choiceInfo").get("depth") + 1 return self.nextFrame() return null func traceChoiceArray(choices: Array[Variant]) -> void: var _g: int = 0 while (_g < choices.size()): var choiceInfo: Variant = choices[_g] _g += 1 var tempRight var _this: Array[String] = choiceInfo.get("tags") var result: String = "" var len: int = _this.size() var _g2: int = 0 var _g1: int = len while (_g2 < _g1): var tempNumber _g2 += 1 tempNumber = _g2 - 1 var i: int = tempNumber var tempString if (i == len - 1): tempString = "" else: tempString = " #" result += str(_this[i]) + (tempString) tempRight = result haxe_Log.trace.call("" + ChoiceExtension.toString(choiceInfo) + ": #" + tempRight, { "fileName": "../hank/Story.hx", "lineNumber": 374, "className": "hank.Story", "methodName": "traceChoiceArray" }) haxe_Log.trace.call("---", { "fileName": "../hank/Story.hx", "lineNumber": 376, "className": "hank.Story", "methodName": "traceChoiceArray" }) func availableChoices() -> Array[Variant]: var choices: Array[Variant] = [] if (self.embedMode == EmbedMode.EmbedMode.Thread): var idx: int = 0 if true: var _g: int = 0 var _g1: Array[Story] = self.embeddedBlocks while (_g < _g1.size()): var thread: Story = _g1[_g] _g += 1 choices = (choices + thread.availableChoices()) idx += 1 var tempRight if true: var _g: Variant = self.ast[self.exprIndex].get("expr") if (_g._index == 10): var _g2: Variant = _g.c tempRight = true else: tempRight = false if (self.exprIndex < self.ast.size() && tempRight): var allChoiceInfo: Array[Variant] = ASTExtension.collectChoices(self.ast, self.exprIndex, self.weaveDepth).get("choices") if true: var _g: int = 0 while (_g < allChoiceInfo.size()): var choiceInfo: Variant = allChoiceInfo[_g] _g += 1 if (self.choicesTaken.find(choiceInfo.get("id")) == -1 || !choiceInfo.get("onceOnly")): if true: var _g2: Variant = choiceInfo.get("condition") match (_g2._index): 0: var _g3: String = _g2.v if true: var expr: String = _g3 if (!self.hInterface.cond(expr, self.nodeScopes)): continue 1: pass if (!choiceInfo.get("output").isEmpty()): choices.push_back(choiceInfo) return choices func fallbackChoice() -> Variant: var choiceInfo: Variant = ASTExtension.collectChoices(self.ast, self.exprIndex, self.weaveDepth) var lastChoice: Variant = choiceInfo.get("choices")[choiceInfo.get("choices").size() - 1] if (lastChoice.get("output").isEmpty()): return { "choiceInfo": lastChoice, "index": choiceInfo.get("fallbackIndex") } else: assert(false, str("there is no fallback choice!")) return null func gotoNextGather() -> void: var gatherIndex: int = ASTExtension.findNextGather(self.ast, self.currentFile(), self.exprIndex + 1, self.weaveDepth) if (gatherIndex == -1): assert(false, str("Ran out of choice content, and there is no gather")) self.exprIndex = gatherIndex func resolveNodeInScope(label: String, whichScope = null) -> Array[StoryNode]: if (whichScope == null): whichScope = self.nodeScopes var targetParts: Array[String] = Array(Array(label.split(".")), Variant.Type.TYPE_STRING, "", null) var newScopes: Array[StoryNode] = ([] as Array[StoryNode]) var _g: int = 0 var _g1: int = whichScope.size() while (_g < _g1): var tempNumber _g += 1 tempNumber = _g - 1 var i: int = tempNumber var scope: StoryNode = whichScope[i] if true: var _g2: Variant = scope.resolve(targetParts[0]) match (_g2._index): 0: var _g3: StoryNode = _g2.v var node: StoryNode = _g3 newScopes = whichScope.slice(i) newScopes.insert(0, node) null var _g4: int = 0 var _g5: Array[String] = targetParts.slice(1) while (_g4 < _g5.size()): var part: String = _g5[_g4] _g4 += 1 var scope2: StoryNode = newScopes[0] if true: var _g6: Variant = scope2.resolve(part) match (_g6._index): 0: var _g7: StoryNode = _g6.v var innerNode: StoryNode = _g7 newScopes.insert(0, innerNode) null 1: break break 1: pass return newScopes func resolveScopes(target: String) -> Array[StoryNode]: var tempArray if (StringTools.startsWith(target, "@")): var parts: Array[String] = Array(Array(target.split(".")), Variant.Type.TYPE_STRING, "", null) var root: Array[StoryNode] = self.hInterface.getVariable(parts[0].substr(1)) if (parts.size() > 1): var tempString var _this: Array[String] = parts.slice(1) var result: String = "" var len: int = _this.size() var _g: int = 0 var _g1: int = len while (_g < _g1): var tempNumber _g += 1 tempNumber = _g - 1 var i: int = tempNumber var tempString1 if (i == len - 1): tempString1 = "" else: tempString1 = "." result += str(_this[i]) + (tempString1) tempString = result var subTarget: String = tempString tempArray = self.resolveNodeInScope(subTarget, root) else: tempArray = root else: tempArray = self.resolveNodeInScope(target, null) if (tempArray == null || tempArray.size() == 0): assert(false, str("Divert target not found: " + target)) return tempArray func indexOf(target: String) -> int: var disposableFork: Story = self.storyFork(target, true) return disposableFork.exprIndex func divertTo(target: String) -> void: if (target.length() == 0): return if true: var _g: Variant = self.parent if (_g._index == 0): var _g2: Story = _g.v var p: Story = _g2 if (p.embedMode == EmbedMode.EmbedMode.Tunnel): p.embeddedBlocks = ([] as Array[Story]) p.divertTo(target) self.exprIndex = self.ast.size() return else: pass else: pass var newScopes: Array[StoryNode] = self.resolveScopes(target) var targetIdx: int = newScopes[0].astIndex self.exprIndex = targetIdx var target2: StoryNode = newScopes[0] self.weaveDepth = 0 if true: var _g: Variant = self.ast[self.exprIndex].get("expr") match (_g._index): 4: var _g2: String = _g.name if true: var _g3: StoryNode = target2 var _g1: Variant = self.viewCounts if true: var v: int = _g1.__get(_g3) + 1 _g1.__set(_g3, v) v self.exprIndex += 1 if true: var _g3: Variant = self.ast[self.exprIndex].get("expr") if (_g3._index == 5): var _g4: String = _g3.name var label: String = _g4 var firstStitch: StoryNode = self.resolveNodeInScope(label, newScopes)[0] if true: var _g5: StoryNode = firstStitch var _g1: Variant = self.viewCounts if true: var v: int = _g1.__get(_g5) + 1 _g1.__set(_g5, v) v self.exprIndex += 1 else: pass self.weaveDepth = 0 5: var _g2: String = _g.name if true: var _g3: StoryNode = target2 var _g1: Variant = self.viewCounts if true: var v: int = _g1.__get(_g3) + 1 _g1.__set(_g3, v) v var enclosingKnot: StoryNode = newScopes[1] if (self.nodeScopes.find(enclosingKnot) == -1): var _g3: StoryNode = enclosingKnot var _g1: Variant = self.viewCounts if true: var v: int = _g1.__get(_g3) + 1 _g1.__set(_g3, v) v self.exprIndex += 1 self.weaveDepth = 0 10: var _g2: Variant = _g.c var c: Variant = _g2 self.storedFrame = { "_index": 0, "v": self.finalTextProcessing(self.evaluateChoice(c)) } return _: pass self.nodeScopes = newScopes func choose(choiceIndex: int) -> String: var nf: Variant = self.nextFrame() var tempBool if (nf._index == 1): var _g: Array[String] = nf.choices var _g2: Array[Variant] = nf.tags tempBool = true else: tempBool = false if (!(tempBool)): assert(false, str("Trying to make a choice when next frame is " + str(nf))) if (self.embeddedBlocks.size() > 0 && self.embedMode == EmbedMode.EmbedMode.Tunnel): return self.embeddedBlocks[0].choose(choiceIndex) else: var output: String = self.evaluateChoice(self.availableChoices()[choiceIndex]) if (self.embedMode == EmbedMode.EmbedMode.Thread): self.embedMode = EmbedMode.EmbedMode.Tunnel self.embeddedBlocks = ([] as Array[Story]) return output func evaluateChoice(choice: Variant) -> String: if true: var _g: Variant = choice.get("label") match (_g._index): 0: var _g2: String = _g.v var l: String = _g2 var tempMaybeStoryNode if true: var _g3: Array[StoryNode] = self.resolveNodeInScope(l, null) if (_g3.size() == 0): tempMaybeStoryNode = self.storyTree.nodeForChoice(choice.get("id")) else: var nodePath: Array[StoryNode] = _g3 tempMaybeStoryNode = nodePath[0] var node = tempMaybeStoryNode if true: var _g3 = node var _g1: Variant = self.viewCounts if true: var v: int = _g1.__get(_g3) + 1 _g1.__set(_g3, v) v 1: pass self.weaveDepth = choice.get("depth") + 1 if (choice.get("onceOnly")): self.choicesTaken.push_back(choice.get("id")) if true: var _g: Variant = choice.get("divertTarget") match (_g._index): 0: var _g2: String = _g.v var t: String = _g2 self.divertTo(t) 1: self.exprIndex = ASTExtension.indexOfChoice(self.ast, choice.get("id")) + 1 var output: String = choice.get("output").format(self, self.hInterface, self.random, self.altInstances, self.nodeScopes, true) return self.finalChoiceOutputProcessing(output) func runEmbeddedHank(h: String) -> void: self.embedMode = EmbedMode.EmbedMode.Tunnel self.embeddedBlocks.push_back(self.embeddedStory(h)) func removeDoubleSpaces(t: String) -> String: var intermediate: String = t while (intermediate.find(" ") != -1): intermediate = StringTools.replace(intermediate, " ", " ") return intermediate func finalTextProcessing(t: String) -> Variant: if (t.length() > 0): return { "_index": 0, "text": StringTools.trim(self.removeDoubleSpaces(t)) } else: return self.nextFrame() func finalChoiceOutputProcessing(t: String) -> String: return StringTools.trim(self.removeDoubleSpaces(t)) func finalChoiceProcessing(choices: Array[String], tags: Array[Variant]) -> Variant: var _g: Array[String] = ([] as Array[String]) var _g1: int = 0 while (_g1 < choices.size()): var c: String = choices[_g1] _g1 += 1 _g.push_back(StringTools.trim(self.removeDoubleSpaces(c))) return { "_index": 1, "choices": _g, "tags": tags } func formatForInsertion(value) -> String: if (value == null): assert(false, str("Trying to format null for insertion!")) return str(value) func run(showText, showChoices, finish) -> void: var _gthis: Story = self var tempFunction if true: var _g: Story = self tempFunction = func() -> void: return _g.run(showText, showChoices, finish) if true: var _g: Variant = self.nextFrame() match (_g._index): 0: var _g2: String = _g.text var text: String = _g2 showText.call(text, func() -> void: tempFunction.call()) 1: var _g1: Array[String] = _g.choices var _g2: Array[Variant] = _g.tags var choices: Array[String] = _g1 var tags: Array[Variant] = _g2 showChoices.call(choices, tags, func(choiceIndex: int) -> void: _gthis.choose(choiceIndex) tempFunction.call()) 2: finish.call() static func FromAST(script: String, ast2: Array[Variant], randomSeed = null) -> Story: var random2: Random = Random.new(randomSeed) var storyTree2: StoryNode = StoryNode.FromAST(ast2) var nodeScopes2: Array[StoryNode] = ([storyTree2] as Array[StoryNode]) var viewCounts2: Variant = storyTree2.createViewCounts() var hInterface2: HInterface = HInterface.new(storyTree2, viewCounts2) var story: Story = Story.new(random2, HParser.new(), ast2, storyTree2, nodeScopes2, viewCounts2, hInterface2) hInterface2.setStory(story) hInterface2.addVariable("story", story) story.runRootIncludedHaxe(script) story.exprIndex = ASTExtension.findFile(ast2, script) return story static func FromFile(script: String, files = null, randomSeed = null) -> Story: var parser2: HParser = HParser.new() var ast2: Array[Variant] = parser2.parseFile(script, files, false) return Story.FromAST(script, ast2, randomSeed)