1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
using Godosa.Core.Runs.Scripts;
using Xunit;
using static Godosa.Core.Tests.Runs.Scripts.ScriptRunnerTests;
namespace Godosa.Core.Tests.Runs.Scripts;
public class ScriptRunnerStructureTests
{
[Fact]
public void Output_DefaultLabels_StepsLevelShowsEveryStep()
{
var (_, labels) = Run("format 1\nmode player\nstep a:\n key R\n log \"hi\"\nkey Q", new FakeGame());
Assert.Equal(["hi", "[main.steps:3 a] done f=2 (+2)", "digest 2 0.033 0000000000000002"], labels);
var (_, steps) = Run("format 1\nmode player\noutput steps\nstep a:\n key R\nkey Q", new FakeGame());
Assert.Equal(["[main.steps:5 a] key R done f=2 (+2)", "[main.steps:4 a] done f=2 (+2)", "digest 2 0.033 0000000000000002", "[main.steps:6] key Q done f=4 (+2)"], steps);
}
[Fact]
public void Output_ScopedToIncludedFile()
{
var (_, output) = Run("format 1\nmode player\ninclude loud.steps\nkey Q", new FakeGame(),
files: new() { ["loud.steps"] = "format 1\noutput steps\nkey R" });
Assert.Equal(["[loud.steps:3] key R done f=2 (+2)"], output); // key Q at labels level: silent
}
[Fact]
public void Output_FloorCannotBeLowered()
{
var (_, output) = Run("format 1\nmode player\noutput quiet\nkey R", new FakeGame(), new ScriptRunOptions { Floor = OutputLevel.Steps });
Assert.Equal(["[main.steps:4] key R done f=2 (+2)"], output);
}
[Fact]
public void DefCall_BindsParams_ParamUnknownOutside()
{
var g = new FakeGame();
var a = new FakeAction(VerbKind.Debug, _ => new ActionStart(Status: StepStatus.Done), min: 1, max: 3);
g.ActionTable["cheat"] = a;
var (ok, _) = Run("format 1\nmode debug\ndef d(x):\n set local = in\n cheat ${x} ${local}\ncall d(gold)", g);
Assert.Equal(RunOutcome.Passed, ok.Outcome);
Assert.Equal(["gold", "in"], a.Begun[0]);
var (bad, output) = Run("format 1\nmode debug\ndef d(x):\n cheat ${x}\ncall d(gold)\ncheat ${x}", g);
Assert.Equal(RunOutcome.Invalid, bad.Outcome);
Assert.Contains(output, l => l == "main.steps:6: unresolved variable ${x}");
}
[Fact]
public void Try_FaultInsideContinuesAfterTheBlock_NonDeterministic()
{
var g = new FakeGame();
g.ProbeFns["never"] = _ => RunValue.Of(false);
var (r, output) = Run("format 1\nmode player\ntry:\n wait never 3\n key A\nkey B", g, new ScriptRunOptions { Deterministic = false });
Assert.Equal(RunOutcome.Passed, r.Outcome);
Assert.Contains(output, l => l == "try failed at main.steps:4: timeout after 3 frames: never (never=0)");
Assert.DoesNotContain(g.Sent, s => s.Event.Key == "A");
Assert.Contains(g.Sent, s => s.Event.Key == "B");
}
// Review focus 1: a fault while a button is down releases it.
[Fact]
public void Fault_ReleasesHeldButtonAndKey()
{
var g = new FakeGame();
g.ProbeFns["never"] = _ => RunValue.Of(false);
g.ActionTable["walk-to"] = new FakeAction(VerbKind.Player,
_ => new ActionStart(new InputPlan([new PlannedInput(0, new InputEvent(InputKind.KeyDown, Key: "Shift")), new PlannedInput(0, new InputEvent(InputKind.Down, 9, 9)),
new PlannedInput(5, new InputEvent(InputKind.Up, 9, 9)), new PlannedInput(5, new InputEvent(InputKind.KeyUp, Key: "Shift"))])),
polls => StepStatus.Running, 1, 1);
g.OnAdvance = f => { if (f == 2) throw new InvalidOperationException("crash"); };
var (r, _) = Run("format 1\nmode player\nwalk-to 9,9", g);
Assert.Equal(RunOutcome.Failed, r.Outcome);
Assert.Contains(g.Sent, s => s.Event == new InputEvent(InputKind.Up, 9, 9));
Assert.Contains(g.Sent, s => s.Event == new InputEvent(InputKind.KeyUp, Key: "Shift"));
}
[Fact]
public void Setup_RunsFirstAtFrameZero()
{
var g = new FakeGame();
var order = new List<string>();
g.ActionTable["cheat"] = new FakeAction(VerbKind.Debug, a => { order.Add($"cheat@{g.Frame}"); return new ActionStart(Status: StepStatus.Done); }, min: 1, max: 3);
Run("format 1\nmode player\nsetup:\n cheat stats max\nkey R", g);
Assert.Equal(["cheat@0"], order);
}
}
|