From 6fbba748e9574d3771949c8ef31502100e71f4f3 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Wed, 29 Oct 2025 19:01:32 -0500 Subject: [PATCH] put tags in choices --- hank/Choice.hx | 7 +++---- hank/HankAST.hx | 15 +++++---------- hank/Parser.hx | 12 ++++++++++-- hank/Story.hx | 37 +++++++++++++++++-------------------- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/hank/Choice.hx b/hank/Choice.hx index 655f638..a538d95 100644 --- a/hank/Choice.hx +++ b/hank/Choice.hx @@ -2,10 +2,9 @@ package hank; import haxe.ds.Option; -typedef Choice = {id:Int, onceOnly:Bool, label:Option, condition:Option, depth:Int, output:Output, divertTarget:Option}; -typedef ChoiceInfo = {choice: Choice, tags: Array}; -typedef ChoicePointInfo = {choices:Array, fallbackIndex:Int}; -typedef FallbackChoiceInfo = {choiceInfo:ChoiceInfo, index:Int}; +typedef Choice = {id:Int, onceOnly:Bool, label:Option, condition:Option, depth:Int, output:Output, divertTarget:Option, tags:Array}; +typedef ChoicePointInfo = {choices:Array, fallbackIndex:Int}; +typedef FallbackChoiceInfo = {choiceInfo:Choice, index:Int}; class ChoiceExtension { public static function toString(choice:Choice):String { diff --git a/hank/HankAST.hx b/hank/HankAST.hx index e886eb2..61a2ff7 100644 --- a/hank/HankAST.hx +++ b/hank/HankAST.hx @@ -2,7 +2,6 @@ package hank; import haxe.ds.Option; import hank.Alt.AltInstance; -import hank.Choice.ChoiceInfo; import hank.Choice.ChoicePointInfo; enum ExprType { @@ -19,8 +18,6 @@ enum ExprType { EGather(label:Option, depth:Int, expr:ExprType); // Hank pre-tag-implementation: Choices are the most complicated expressions EChoice(c:Choice); - // Tags: Hold my beer - ETagged(e: ExprType, tags:Array); } typedef HankExpr = { @@ -56,9 +53,9 @@ class ASTExtension { return -1; } - static function tryAddFunc(choices: Array, expectedDepth: Int, c: Choice, tags: Array) { + static function tryAddFunc(choices: Array, expectedDepth: Int, c: Choice, tags: Array) { var valid = (c.depth == expectedDepth); - if (valid) choices.push({choice:c,tags:tags}); + if (valid) choices.push(c); return valid; } @@ -66,7 +63,7 @@ class ASTExtension { Collect every choice in the choice point starting at the given index. **/ public static function collectChoices(ast:HankAST, startingIndex:Int, depth:Int):ChoicePointInfo { - var choices = new Array(); + var choices = new Array(); var lastChoiceIndex = 0; var tryAdd = tryAddFunc.bind(choices, depth); if (startingIndex > ast.length || startingIndex < 0) { @@ -79,8 +76,6 @@ class ASTExtension { // Gather choices of the current depth case EChoice(choice) if (tryAdd(choice, [])): lastChoiceIndex = i; - case ETagged(EChoice(choice), tags) if (tryAdd(choice, tags)): - lastChoiceIndex = i; // Stop at the next gather of this depth case EGather(_, d, _) if (d == depth): break; @@ -97,7 +92,7 @@ class ASTExtension { public static function findNextGather(ast:HankAST, path:String, startingIndex:Int, maxDepth:Int):Int { for (i in startingIndex...findEOF(ast, path)) { switch (ast[i].expr) { - case EGather(_, depth, _) | ETagged(EGather(_, depth, _), _): + case EGather(_, depth, _): if (depth <= maxDepth) return i; default: @@ -111,7 +106,7 @@ class ASTExtension { for (i in 0...ast.length) { var expr = ast[i].expr; switch (expr) { - case EChoice(c) | ETagged(EChoice(c), _) | EGather(_, _, EChoice(c)): + case EChoice(c): if (c.id == id) return i; default: diff --git a/hank/Parser.hx b/hank/Parser.hx index fcbf2fa..6fa6bb1 100644 --- a/hank/Parser.hx +++ b/hank/Parser.hx @@ -216,7 +216,8 @@ class Parser { condition: condition, depth: depth, output: output, - divertTarget: divertTarget + divertTarget: divertTarget, + tags: [] }); } @@ -224,7 +225,14 @@ class Parser { buffer.drop('#'); var tagLine = buffer.takeLine('lr').unwrap(); var tags = tagLine.tokenize(); - return ETagged(parseExpr(buffer, position), tags); + var expr = parseExpr(buffer, position); + switch (expr) { + case EChoice(c): + c.tags = tags; + default: + trace("Warning! Can't apply tags to " + expr); + } + return expr; } static function haxeBlock(buffer:HankBuffer, position:HankBuffer.Position):ExprType { diff --git a/hank/Story.hx b/hank/Story.hx index 64ca74b..39d00db 100644 --- a/hank/Story.hx +++ b/hank/Story.hx @@ -12,7 +12,6 @@ using hank.Extensions; using HankAST.ASTExtension; import hank.Choice; -import hank.Choice.ChoiceInfo; import hank.Choice.FallbackChoiceInfo; using Choice.ChoiceExtension; @@ -239,12 +238,12 @@ class Story { nextExpr = ast[nextIdx].expr; // trace(nextExpr); switch (nextExpr) { - case EGather(_, _, exp) | ETagged(EGather(_,_,exp), _): + case EGather(_, _, exp): nextExpr = exp; default: } switch (nextExpr) { - case EOutput(output) | ETagged(EOutput(output), _): + case EOutput(output): if (output.startsWithGlue()) text = Output.appendNextText(this, text + " ", Output.GLUE_ERROR); default: @@ -322,7 +321,7 @@ class Story { ++exprIndex; return nextFrame(); - case EChoice(choice) | ETagged(EChoice(choice), _): + case EChoice(choice): if (choice.depth > weaveDepth) { weaveDepth = choice.depth; } else if (choice.depth < weaveDepth) { @@ -343,7 +342,7 @@ class Story { var choices = availableChoices(); var optionsText = [ for (choiceInfo in choices) - choiceInfo.choice.output.format(this, hInterface, random, altInstances, nodeScopes, false) + choiceInfo.output.format(this, hInterface, random, altInstances, nodeScopes, false) ]; var tags = [ for (choiceInfo in choices) @@ -353,30 +352,30 @@ class Story { return finalChoiceProcessing(optionsText, tags); } else { var fallback = fallbackChoice(); - switch (fallback.choiceInfo.choice.divertTarget) { + switch (fallback.choiceInfo.divertTarget) { case Some(t) if (t.length > 0): - var fallbackText = evaluateChoice(fallback.choiceInfo.choice); + var fallbackText = evaluateChoice(fallback.choiceInfo); if (fallbackText.length > 0) { throw 'For some reason a fallback choice evaluated to text!'; } return nextFrame(); default: exprIndex = fallback.index + 1; - weaveDepth = fallback.choiceInfo.choice.depth + 1; + weaveDepth = fallback.choiceInfo.depth + 1; return nextFrame(); } } } - private function traceChoiceArray(choices:Array) { + private function traceChoiceArray(choices:Array) { for (choiceInfo in choices) { - trace('${choiceInfo.choice.toString()}: #${choiceInfo.tags.join(" #")}'); + trace('${choiceInfo.toString()}: #${choiceInfo.tags.join(" #")}'); } trace('---'); } - private function availableChoices():Array { - var choices = new Array(); + private function availableChoices():Array { + var choices = new Array(); // If we're threading, collect all the childrens' choices, too. if (embedMode == Thread) { @@ -389,20 +388,18 @@ class Story { } } - if (exprIndex < ast.length && - (ast[exprIndex].expr.match(EChoice(_)) - || ast[exprIndex].expr.match(ETagged(EChoice(_), _)))) { + if (exprIndex < ast.length && ast[exprIndex].expr.match(EChoice(_))) { var allChoiceInfo = ast.collectChoices(exprIndex, weaveDepth).choices; for (choiceInfo in allChoiceInfo) { - if (choicesTaken.indexOf(choiceInfo.choice.id) == -1 || !choiceInfo.choice.onceOnly) { - switch (choiceInfo.choice.condition) { + if (choicesTaken.indexOf(choiceInfo.id) == -1 || !choiceInfo.onceOnly) { + switch (choiceInfo.condition) { case Some(expr): if (!hInterface.cond(expr, nodeScopes)) { continue; } case None: } - if (!choiceInfo.choice.output.isEmpty()) { + if (!choiceInfo.output.isEmpty()) { choices.push(choiceInfo); } } @@ -418,7 +415,7 @@ class Story { private function fallbackChoice():FallbackChoiceInfo { var choiceInfo = ast.collectChoices(exprIndex, weaveDepth); var lastChoice = choiceInfo.choices[choiceInfo.choices.length - 1]; - if (lastChoice.choice.output.isEmpty()) { + if (lastChoice.output.isEmpty()) { return {choiceInfo: lastChoice, index: choiceInfo.fallbackIndex}; } else { throw 'there is no fallback choice!'; @@ -574,7 +571,7 @@ class Story { return embeddedBlocks[0].choose(choiceIndex); } else { // if not embedded, actually make the choice. availableChoices() accounts for aggregating threaded choices - var output = evaluateChoice(availableChoices()[choiceIndex].choice); + var output = evaluateChoice(availableChoices()[choiceIndex]); if (embedMode == Thread) { embedMode = Tunnel; embeddedBlocks = [];