Skip to content

Commit

Permalink
Add READ_COUNT for explicit read counts, and to be able to get the re…
Browse files Browse the repository at this point in the history
…ad count of a variable divert target.
  • Loading branch information
joethephish committed Jun 6, 2017
1 parent ded0c8c commit 798f512
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 29 deletions.
6 changes: 6 additions & 0 deletions ink-engine-runtime/ControlCommand.cs
Expand Up @@ -19,6 +19,7 @@ public enum CommandType
NoOp,
ChoiceCount,
TurnsSince,
ReadCount,
Random,
SeedRandom,
VisitIndex,
Expand Down Expand Up @@ -104,6 +105,11 @@ internal override Object Copy()
return new ControlCommand(CommandType.TurnsSince);
}

public static ControlCommand ReadCount ()
{
return new ControlCommand (CommandType.ReadCount);
}

public static ControlCommand Random ()
{
return new ControlCommand (CommandType.Random);
Expand Down
1 change: 1 addition & 0 deletions ink-engine-runtime/JsonSerialisation.cs
Expand Up @@ -653,6 +653,7 @@ static Json()
_controlCommandNames [(int)ControlCommand.CommandType.NoOp] = "nop";
_controlCommandNames [(int)ControlCommand.CommandType.ChoiceCount] = "choiceCnt";
_controlCommandNames [(int)ControlCommand.CommandType.TurnsSince] = "turns";
_controlCommandNames [(int)ControlCommand.CommandType.ReadCount] = "readc";
_controlCommandNames [(int)ControlCommand.CommandType.Random] = "rnd";
_controlCommandNames [(int)ControlCommand.CommandType.SeedRandom] = "srnd";
_controlCommandNames [(int)ControlCommand.CommandType.VisitIndex] = "visit";
Expand Down
13 changes: 10 additions & 3 deletions ink-engine-runtime/Story.cs
Expand Up @@ -15,7 +15,7 @@ public class Story : Runtime.Object
/// <summary>
/// The current version of the ink story file format.
/// </summary>
public const int inkVersionCurrent = 16;
public const int inkVersionCurrent = 17;

// Version numbers are for engine itself and story file, rather
// than the story state save format (which is um, currently nonexistant)
Expand Down Expand Up @@ -853,6 +853,7 @@ bool PerformLogicAndFlowControl(Runtime.Object contentObj)
break;

case ControlCommand.CommandType.TurnsSince:
case ControlCommand.CommandType.ReadCount:
var target = state.PopEvaluationStack();
if( !(target is DivertTargetValue) ) {
string extraNote = "";
Expand All @@ -864,8 +865,14 @@ bool PerformLogicAndFlowControl(Runtime.Object contentObj)

var divertTarget = target as DivertTargetValue;
var container = ContentAtPath (divertTarget.targetPath) as Container;
int turnCount = TurnsSinceForContainer (container);
state.PushEvaluationStack (new IntValue (turnCount));

int eitherCount;
if (evalCommand.commandType == ControlCommand.CommandType.TurnsSince)
eitherCount = TurnsSinceForContainer (container);
else
eitherCount = VisitCountForContainer (container);

state.PushEvaluationStack (new IntValue (eitherCount));
break;

case ControlCommand.CommandType.Random:
Expand Down
2 changes: 1 addition & 1 deletion ink-engine-runtime/StoryState.cs
Expand Up @@ -17,7 +17,7 @@ public class StoryState
/// <summary>
/// The current version of the state save file JSON-based format.
/// </summary>
public const int kInkSaveStateVersion = 6;
public const int kInkSaveStateVersion = 7;
const int kMinCompatibleLoadVersion = 6;

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion inklecate/ParsedHierarchy/DivertTarget.cs
Expand Up @@ -50,7 +50,7 @@ public override void ResolveReferences (Story context)
}
else if( usageParent is FunctionCall ) {
var funcCall = usageParent as FunctionCall;
if( !funcCall.isTurnsSince ) {
if( !funcCall.isTurnsSince && !funcCall.isReadCount ) {
badUsage = true;
}
foundUsage = true;
Expand Down
56 changes: 32 additions & 24 deletions inklecate/ParsedHierarchy/FunctionCall.cs
Expand Up @@ -12,6 +12,7 @@ internal class FunctionCall : Expression
public bool isRandom { get { return name == "RANDOM"; } }
public bool isSeedRandom { get { return name == "SEED_RANDOM"; } }
public bool isListRange { get { return name == "LIST_RANGE"; } }
public bool isReadCount { get { return name == "READ_COUNT"; } }

public bool shouldPopReturnedValue;

Expand All @@ -33,34 +34,37 @@ public override void GenerateIntoContainer (Runtime.Container container)

container.AddContent (Runtime.ControlCommand.ChoiceCount ());

} else if (isTurnsSince) {
} else if (isTurnsSince || isReadCount) {

var divertTarget = arguments [0] as DivertTarget;
var variableDivertTarget = arguments [0] as VariableReference;

if (arguments.Count != 1 || (divertTarget == null && variableDivertTarget == null)) {
Error ("The TURNS_SINCE() function should take one argument: a divert target to the target knot, stitch, gather or choice you want to check. e.g. TURNS_SINCE(-> myKnot)");
Error ("The "+name+"() function should take one argument: a divert target to the target knot, stitch, gather or choice you want to check. e.g. TURNS_SINCE(-> myKnot)");
return;
}

if (divertTarget) {
_turnCountDivertTarget = divertTarget;
AddContent (_turnCountDivertTarget);
_divertTargetToCount = divertTarget;
AddContent (_divertTargetToCount);

_turnCountDivertTarget.GenerateIntoContainer (container);
_divertTargetToCount.GenerateIntoContainer (container);
} else {
_turnCountVariableReference = variableDivertTarget;
AddContent (_turnCountVariableReference);
_variableReferenceToCount = variableDivertTarget;
AddContent (_variableReferenceToCount);

_turnCountVariableReference.GenerateIntoContainer (container);
_variableReferenceToCount.GenerateIntoContainer (container);

if (!story.countAllVisits) {
Error ("Attempting to get TURNS_SINCE for a variable target without -c compiler option. You need the compiler switch turned on so that it can track turn counts for everything, not just those you directly reference.");
}
}


container.AddContent (Runtime.ControlCommand.TurnsSince ());
if (isTurnsSince)
container.AddContent (Runtime.ControlCommand.TurnsSince ());
else
container.AddContent (Runtime.ControlCommand.ReadCount ());

} else if (isRandom) {
if (arguments.Count != 2)
Error ("RANDOM should take 2 parameters: a minimum and a maximum integer");
Expand Down Expand Up @@ -103,7 +107,7 @@ public override void GenerateIntoContainer (Runtime.Container container)
// Don't attempt to resolve as a divert
content.Remove (_proxyDivert);

} else if (Runtime.NativeFunctionCall.CallExistsWithName(name)) {
} else if (Runtime.NativeFunctionCall.CallExistsWithName (name)) {

var nativeCall = Runtime.NativeFunctionCall.CallWithName (name);

Expand All @@ -121,8 +125,7 @@ public override void GenerateIntoContainer (Runtime.Container container)

// Don't attempt to resolve as a divert
content.Remove (_proxyDivert);
}
else if (foundList != null) {
} else if (foundList != null) {
if (arguments.Count > 1)
Error ("Can currently only construct a list from one integer (or an empty list from a given list definition)");

Expand All @@ -131,7 +134,7 @@ public override void GenerateIntoContainer (Runtime.Container container)
container.AddContent (new Runtime.StringValue (name));
arguments [0].GenerateIntoContainer (container);
container.AddContent (Runtime.ControlCommand.ListFromInt ());
}
}

// Empty list with given origin.
else {
Expand All @@ -144,8 +147,8 @@ public override void GenerateIntoContainer (Runtime.Container container)
content.Remove (_proxyDivert);
}

// Normal function call
else {
// Normal function call
else {
container.AddContent (_proxyDivert.runtimeObject);
}

Expand All @@ -170,8 +173,8 @@ public override void ResolveReferences (Story context)
arg.ResolveReferences (context);
}

if( _turnCountDivertTarget ) {
var divert = _turnCountDivertTarget.divert;
if( _divertTargetToCount ) {
var divert = _divertTargetToCount.divert;
var attemptingTurnCountOfVariableTarget = divert.runtimeDivert.variableDivertName != null;

if( attemptingTurnCountOfVariableTarget ) {
Expand All @@ -189,10 +192,10 @@ public override void ResolveReferences (Story context)
}
}

else if( _turnCountVariableReference ) {
var runtimeVarRef = _turnCountVariableReference.runtimeVarRef;
else if( _variableReferenceToCount ) {
var runtimeVarRef = _variableReferenceToCount.runtimeVarRef;
if( runtimeVarRef.pathForCount != null ) {
Error("Should be TURNS_SINCE(-> "+_turnCountVariableReference.name+"). Without the '->' it expects a variable target");
Error("Should be "+name+"(-> "+_variableReferenceToCount.name+"). Usage without the '->' only makes sense for variable targets.");
}
}
}
Expand All @@ -202,7 +205,12 @@ public static bool IsBuiltIn(string name)
if (Runtime.NativeFunctionCall.CallExistsWithName (name))
return true;

return name == "CHOICE_COUNT" || name == "TURNS_SINCE" || name == "RANDOM" || name == "SEED_RANDOM" || name == "LIST_VALUE";
return name == "CHOICE_COUNT"
|| name == "TURNS_SINCE"
|| name == "RANDOM"
|| name == "SEED_RANDOM"
|| name == "LIST_VALUE"
|| name == "READ_COUNT";
}

public override string ToString ()
Expand All @@ -212,8 +220,8 @@ public override string ToString ()
}

Parsed.Divert _proxyDivert;
Parsed.DivertTarget _turnCountDivertTarget;
Parsed.VariableReference _turnCountVariableReference;
Parsed.DivertTarget _divertTargetToCount;
Parsed.VariableReference _variableReferenceToCount;
}
}

28 changes: 28 additions & 0 deletions tests/Tests.cs
Expand Up @@ -2889,6 +2889,34 @@ public void TestTunnelOnwardsWithParamDefaultChoice ()
Assert.AreEqual ("8\n", story.ContinueMaximally ());
}


[Test ()]
public void TestReadCountVariableTarget ()
{
var storyStr =
@"
VAR x = ->knot
Count start: {READ_COUNT (x)} {READ_COUNT (-> knot)} {knot}
-> x (1) ->
-> x (2) ->
-> x (3) ->
Count end: {READ_COUNT (x)} {READ_COUNT (-> knot)} {knot}
-> END
== knot (a) ==
{a}
->->
";

var story = CompileString (storyStr, countAllVisits:true);
Assert.AreEqual ("Count start: 0 0 0\n1\n2\n3\nCount end: 3 3 3\n", story.ContinueMaximally ());
}


[Test ()]
public void TestDivertTargetsWithParameters ()
{
Expand Down

0 comments on commit 798f512

Please sign in to comment.