mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
pathing: align parkour contracts with live budgets
This commit is contained in:
parent
ce555da95e
commit
cf8bf349db
16 changed files with 3190 additions and 318 deletions
|
|
@ -150,6 +150,8 @@ public sealed class PathingContractStore
|
|||
throw new InvalidDataException($"Timing budget '{budget.ScenarioId}' must use zero totals when it has no segments.");
|
||||
|
||||
var normalizedSegments = new List<PathingSegmentTimingBudget>(budget.Segments.Count);
|
||||
int expectedSegmentTicksSum = 0;
|
||||
int maxSegmentTicksSum = 0;
|
||||
for (int i = 0; i < budget.Segments.Count; i++)
|
||||
{
|
||||
PathingSegmentTimingBudget segment = budget.Segments[i];
|
||||
|
|
@ -159,9 +161,23 @@ public sealed class PathingContractStore
|
|||
if (segment.ExpectedTicks > segment.MaxTicks)
|
||||
throw new InvalidDataException($"Timing budget '{budget.ScenarioId}' segment {i} has ExpectedTicks greater than MaxTicks.");
|
||||
|
||||
expectedSegmentTicksSum = checked(expectedSegmentTicksSum + segment.ExpectedTicks);
|
||||
maxSegmentTicksSum = checked(maxSegmentTicksSum + segment.MaxTicks);
|
||||
normalizedSegments.Add(segment);
|
||||
}
|
||||
|
||||
if (budget.ExpectedTotalTicks != expectedSegmentTicksSum)
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
$"Timing budget '{budget.ScenarioId}' ExpectedTotalTicks mismatch. Total={budget.ExpectedTotalTicks}, segmentSum={expectedSegmentTicksSum}.");
|
||||
}
|
||||
|
||||
if (budget.MaxTotalTicks != maxSegmentTicksSum)
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
$"Timing budget '{budget.ScenarioId}' MaxTotalTicks mismatch. Total={budget.MaxTotalTicks}, segmentSum={maxSegmentTicksSum}.");
|
||||
}
|
||||
|
||||
return budget with { Segments = normalizedSegments.AsReadOnly() };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using MinecraftClient.Pathing.Core;
|
|||
using MinecraftClient.Pathing.Execution;
|
||||
using MinecraftClient.Pathing.Execution.Templates;
|
||||
using MinecraftClient.Pathing.Goals;
|
||||
using MinecraftClient.Physics;
|
||||
using Xunit;
|
||||
|
||||
namespace MinecraftClient.Tests.Pathing.Execution;
|
||||
|
|
@ -35,6 +36,94 @@ public sealed class LivePathingRegressionTests
|
|||
Assert.Empty(PathSegmentBuilder.FromPath(result.Path));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AStar_RepeatedSingleGapParkourChain_PrefersTwoLongJumpsOverFourShortJumps()
|
||||
{
|
||||
World world = FlatWorldTestBuilder.CreateStoneFloor(min: 578, max: 590);
|
||||
FlatWorldTestBuilder.ClearBox(world, 578, 79, 578, 590, 90, 582);
|
||||
FlatWorldTestBuilder.SetSolid(world, 580, 79, 580);
|
||||
FlatWorldTestBuilder.SetSolid(world, 582, 79, 580);
|
||||
FlatWorldTestBuilder.SetSolid(world, 584, 79, 580);
|
||||
FlatWorldTestBuilder.SetSolid(world, 586, 79, 580);
|
||||
FlatWorldTestBuilder.SetSolid(world, 588, 79, 580);
|
||||
|
||||
var ctx = new CalculationContext(world, allowParkour: true, allowParkourAscend: true);
|
||||
var finder = new AStarPathFinder();
|
||||
|
||||
PathResult result = finder.Calculate(
|
||||
ctx,
|
||||
startX: 580,
|
||||
startY: 80,
|
||||
startZ: 580,
|
||||
new GoalBlock(588, 80, 580),
|
||||
CancellationToken.None,
|
||||
timeoutMs: 2000);
|
||||
|
||||
List<PathSegment> segments = PathSegmentBuilder.FromPath(result.Path);
|
||||
|
||||
Assert.Equal(PathStatus.Success, result.Status);
|
||||
Assert.Collection(
|
||||
segments,
|
||||
first =>
|
||||
{
|
||||
Assert.Equal(MoveType.Parkour, first.MoveType);
|
||||
Assert.Equal(new Location(580.5, 80, 580.5), first.Start);
|
||||
Assert.Equal(new Location(584.5, 80, 580.5), first.End);
|
||||
},
|
||||
second =>
|
||||
{
|
||||
Assert.Equal(MoveType.Parkour, second.MoveType);
|
||||
Assert.Equal(new Location(584.5, 80, 580.5), second.Start);
|
||||
Assert.Equal(new Location(588.5, 80, 580.5), second.End);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PathExecutor_RepeatedSingleGapParkourChain_TwoLongJumps_CompletesWithoutReplan()
|
||||
{
|
||||
World world = FlatWorldTestBuilder.CreateStoneFloor(min: 578, max: 590);
|
||||
FlatWorldTestBuilder.ClearBox(world, 578, 79, 578, 590, 90, 582);
|
||||
FlatWorldTestBuilder.SetSolid(world, 580, 79, 580);
|
||||
FlatWorldTestBuilder.SetSolid(world, 582, 79, 580);
|
||||
FlatWorldTestBuilder.SetSolid(world, 584, 79, 580);
|
||||
FlatWorldTestBuilder.SetSolid(world, 586, 79, 580);
|
||||
FlatWorldTestBuilder.SetSolid(world, 588, 79, 580);
|
||||
|
||||
var ctx = new CalculationContext(world, allowParkour: true, allowParkourAscend: true);
|
||||
var finder = new AStarPathFinder();
|
||||
PathResult result = finder.Calculate(
|
||||
ctx,
|
||||
startX: 580,
|
||||
startY: 80,
|
||||
startZ: 580,
|
||||
new GoalBlock(588, 80, 580),
|
||||
CancellationToken.None,
|
||||
timeoutMs: 2000);
|
||||
|
||||
var debugLogs = new List<string>();
|
||||
var infoLogs = new List<string>();
|
||||
var manager = new PathSegmentManager(debugLogs.Add, infoLogs.Add);
|
||||
var physics = TemplateSimulationRunner.CreateGroundedPhysics(new Location(580.5, 80, 580.5), yaw: 270f);
|
||||
var input = new MovementInput();
|
||||
|
||||
manager.StartNavigation(new GoalBlock(588, 80, 580), result);
|
||||
|
||||
for (int tick = 0; tick < 240 && manager.IsNavigating; tick++)
|
||||
{
|
||||
input.Reset();
|
||||
Location pos = new(physics.Position.X, physics.Position.Y, physics.Position.Z);
|
||||
manager.Tick(pos, physics, input, world);
|
||||
if (!manager.IsNavigating)
|
||||
break;
|
||||
|
||||
physics.ApplyInput(input);
|
||||
physics.Tick(world);
|
||||
}
|
||||
|
||||
Assert.True(!manager.IsNavigating && manager.ReplanCount == 0,
|
||||
$"replanCount={manager.ReplanCount}\ninfo={string.Join('\n', infoLogs)}\ndebug={string.Join('\n', debugLogs)}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SprintJumpTemplate_LandingRecoveryIntoTurn_CompletesInsideLandingBlock()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -86,6 +86,49 @@ public sealed class PathPlanningContractTests
|
|||
Assert.Contains("manager-accepted-ascend-chain", error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LoadFromJson_RejectsTimingBudget_WhenTotalsDoNotMatchSegments()
|
||||
{
|
||||
const string plannerJson = """
|
||||
[
|
||||
{
|
||||
"scenarioId": "totals-mismatch",
|
||||
"expectedStatus": "Success",
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"startBlock": { "x": 0, "y": 80, "z": 0 },
|
||||
"endBlock": { "x": 1, "y": 80, "z": 0 }
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"startBlock": { "x": 1, "y": 80, "z": 0 },
|
||||
"endBlock": { "x": 2, "y": 81, "z": 0 }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
""";
|
||||
const string timingJson = """
|
||||
[
|
||||
{
|
||||
"scenarioId": "totals-mismatch",
|
||||
"expectedTotalTicks": 1,
|
||||
"maxTotalTicks": 2,
|
||||
"segments": [
|
||||
{ "moveType": "Traverse", "expectedTicks": 2, "maxTicks": 3 },
|
||||
{ "moveType": "Ascend", "expectedTicks": 3, "maxTicks": 4 }
|
||||
]
|
||||
}
|
||||
]
|
||||
""";
|
||||
|
||||
InvalidDataException error = Assert.Throws<InvalidDataException>(
|
||||
() => PathingContractStore.LoadFromJson(plannerJson, timingJson));
|
||||
Assert.Contains("totals-mismatch", error.Message);
|
||||
Assert.Contains("ExpectedTotalTicks mismatch", error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LoadFromJson_Rejects_WhenPlannerAndTimingScenarioSetsMismatch()
|
||||
{
|
||||
|
|
@ -214,25 +257,26 @@ public sealed class PathPlanningContractTests
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("manager-accepted-ascend-chain")]
|
||||
[InlineData("same-move-ascend-staircase")]
|
||||
[InlineData("same-move-descend-staircase")]
|
||||
[InlineData("rejected-3x1-invalid-goal")]
|
||||
public void Scenario_PlannerMatchesContract(string scenarioId)
|
||||
{
|
||||
PathingExecutionScenario scenario = PathingExecutionScenarioCatalog.Get(scenarioId);
|
||||
PathResult planResult = PathingScenarioRunner.PlanOnly(scenario);
|
||||
PathingPlannerContract contract = PathingContractStore.LoadFromRepositoryRoot().GetPlanner(scenarioId);
|
||||
|
||||
PathingContractAssert.PlannerMatches(contract, PathSegmentBuilder.FromPath(planResult.Path), planResult);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("repeated-cardinal-parkour-chain")]
|
||||
[InlineData("repeated-diagonal-parkour-chain")]
|
||||
[InlineData("obstructed-parkour-l-turns")]
|
||||
[InlineData("vertical-jump-mix")]
|
||||
[InlineData("diagonal-vertical-mix")]
|
||||
public void JumpCombo_PlannerMatchesContract(string scenarioId)
|
||||
[InlineData("turn-density-alternating-traverse-diagonal-chain")]
|
||||
[InlineData("mixed-traverse-ascend-parkour-descend")]
|
||||
[InlineData("same-move-aligned-parkour-chain")]
|
||||
[InlineData("mixed-diagonal-ascend-traverse-descend")]
|
||||
[InlineData("speed-carry-repeated-traverse-ascend")]
|
||||
[InlineData("speed-carry-repeated-traverse-descend")]
|
||||
[InlineData("speed-carry-repeated-traverse-parkour")]
|
||||
[InlineData("same-move-diagonal-chain")]
|
||||
[InlineData("same-move-straight-traverse-chain")]
|
||||
[InlineData("mixed-traverse-turn-parkour-turn-traverse")]
|
||||
public void Scenario_PlannerMatchesContract(string scenarioId)
|
||||
{
|
||||
PathingExecutionScenario scenario = PathingExecutionScenarioCatalog.Get(scenarioId);
|
||||
PathResult planResult = PathingScenarioRunner.PlanOnly(scenario);
|
||||
|
|
|
|||
|
|
@ -62,9 +62,28 @@ internal static class PathingContractAssert
|
|||
sb.AppendLine($"seg[{i}] move={actual.MoveType} actual={actual.ElapsedTicks} expected={expected.ExpectedTicks} max={expected.MaxTicks}");
|
||||
}
|
||||
|
||||
if (result.InfoLogs.Count > 0)
|
||||
{
|
||||
sb.AppendLine("info tail:");
|
||||
AppendTail(sb, result.InfoLogs, maxLines: 8);
|
||||
}
|
||||
|
||||
if (result.DebugLogs.Count > 0)
|
||||
{
|
||||
sb.AppendLine("debug tail:");
|
||||
AppendTail(sb, result.DebugLogs, maxLines: 12);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static void AppendTail(StringBuilder sb, IReadOnlyList<string> lines, int maxLines)
|
||||
{
|
||||
int start = Math.Max(0, lines.Count - maxLines);
|
||||
for (int i = start; i < lines.Count; i++)
|
||||
sb.AppendLine(lines[i]);
|
||||
}
|
||||
|
||||
private static PathingBlock ToBlock(Location location) =>
|
||||
new((int)Math.Floor(location.X), (int)Math.Floor(location.Y), (int)Math.Floor(location.Z));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,26 @@ public sealed class MoveParkourTests
|
|||
Assert.Equal(2, result.DestX);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Accepts4x1JumpWithoutRearSupport_WhenTakeoffBlockProvidesRunway()
|
||||
{
|
||||
World world = FlatWorldTestBuilder.CreateStoneFloor(min: -2, max: 6);
|
||||
FlatWorldTestBuilder.ClearBox(world, -2, FloorY, -1, 6, FloorY + 4, 1);
|
||||
FlatWorldTestBuilder.SetSolid(world, 0, FloorY, 0);
|
||||
FlatWorldTestBuilder.SetSolid(world, 2, FloorY, 0);
|
||||
FlatWorldTestBuilder.SetSolid(world, 4, FloorY, 0);
|
||||
|
||||
var ctx = BuildContext(world);
|
||||
var move = new MoveParkour(4, 0);
|
||||
var result = default(MoveResult);
|
||||
|
||||
move.Calculate(ctx, 0, FloorY + 1, 0, ref result);
|
||||
|
||||
Assert.False(result.IsImpossible);
|
||||
Assert.Equal(4, result.DestX);
|
||||
Assert.Equal(0, result.DestZ);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rejects2x1WhenAdjacentBlockIsStillWalkable()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -215,19 +215,6 @@
|
|||
"y": 80,
|
||||
"z": 580
|
||||
},
|
||||
"endBlock": {
|
||||
"x": 582,
|
||||
"y": 80,
|
||||
"z": 580
|
||||
}
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": {
|
||||
"x": 582,
|
||||
"y": 80,
|
||||
"z": 580
|
||||
},
|
||||
"endBlock": {
|
||||
"x": 584,
|
||||
"y": 80,
|
||||
|
|
@ -241,19 +228,6 @@
|
|||
"y": 80,
|
||||
"z": 580
|
||||
},
|
||||
"endBlock": {
|
||||
"x": 586,
|
||||
"y": 80,
|
||||
"z": 580
|
||||
}
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": {
|
||||
"x": 586,
|
||||
"y": 80,
|
||||
"z": 580
|
||||
},
|
||||
"endBlock": {
|
||||
"x": 588,
|
||||
"y": 80,
|
||||
|
|
@ -370,25 +344,12 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"moveType": "Descend",
|
||||
"moveType": "Parkour",
|
||||
"startBlock": {
|
||||
"x": 642,
|
||||
"y": 81,
|
||||
"z": 620
|
||||
},
|
||||
"endBlock": {
|
||||
"x": 644,
|
||||
"y": 80,
|
||||
"z": 620
|
||||
}
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": {
|
||||
"x": 644,
|
||||
"y": 80,
|
||||
"z": 620
|
||||
},
|
||||
"endBlock": {
|
||||
"x": 646,
|
||||
"y": 81,
|
||||
|
|
@ -634,19 +595,6 @@
|
|||
"y": 80,
|
||||
"z": 380
|
||||
},
|
||||
"endBlock": {
|
||||
"x": 382,
|
||||
"y": 80,
|
||||
"z": 380
|
||||
}
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": {
|
||||
"x": 382,
|
||||
"y": 80,
|
||||
"z": 380
|
||||
},
|
||||
"endBlock": {
|
||||
"x": 384,
|
||||
"y": 80,
|
||||
|
|
@ -660,19 +608,6 @@
|
|||
"y": 80,
|
||||
"z": 380
|
||||
},
|
||||
"endBlock": {
|
||||
"x": 386,
|
||||
"y": 80,
|
||||
"z": 380
|
||||
}
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": {
|
||||
"x": 386,
|
||||
"y": 80,
|
||||
"z": 380
|
||||
},
|
||||
"endBlock": {
|
||||
"x": 388,
|
||||
"y": 80,
|
||||
|
|
|
|||
|
|
@ -38,55 +38,55 @@
|
|||
},
|
||||
{
|
||||
"scenarioId": "same-move-ascend-staircase",
|
||||
"expectedTotalTicks": 56,
|
||||
"maxTotalTicks": 68,
|
||||
"expectedTotalTicks": 60,
|
||||
"maxTotalTicks": 74,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 11,
|
||||
"maxTicks": 14
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 11,
|
||||
"maxTicks": 14
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 11,
|
||||
"maxTicks": 14
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 11,
|
||||
"maxTicks": 14
|
||||
"expectedTicks": 10,
|
||||
"maxTicks": 12
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 12,
|
||||
"maxTicks": 15
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 12,
|
||||
"maxTicks": 15
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 12,
|
||||
"maxTicks": 15
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 14,
|
||||
"maxTicks": 17
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "same-move-descend-staircase",
|
||||
"expectedTotalTicks": 61,
|
||||
"maxTotalTicks": 74,
|
||||
"expectedTotalTicks": 57,
|
||||
"maxTotalTicks": 70,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Descend",
|
||||
"expectedTicks": 24,
|
||||
"maxTicks": 29
|
||||
"expectedTicks": 23,
|
||||
"maxTicks": 28
|
||||
},
|
||||
{
|
||||
"moveType": "Descend",
|
||||
"expectedTicks": 25,
|
||||
"maxTicks": 30
|
||||
"expectedTicks": 23,
|
||||
"maxTicks": 28
|
||||
},
|
||||
{
|
||||
"moveType": "Descend",
|
||||
"expectedTicks": 12,
|
||||
"maxTicks": 15
|
||||
"expectedTicks": 11,
|
||||
"maxTicks": 14
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -98,79 +98,47 @@
|
|||
},
|
||||
{
|
||||
"scenarioId": "repeated-cardinal-parkour-chain",
|
||||
"expectedTotalTicks": 0,
|
||||
"maxTotalTicks": 2,
|
||||
"expectedTotalTicks": 37,
|
||||
"maxTotalTicks": 45,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 61,
|
||||
"maxTicks": 74
|
||||
"expectedTicks": 18,
|
||||
"maxTicks": 22
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 61,
|
||||
"maxTicks": 74
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 61,
|
||||
"maxTicks": 74
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 27,
|
||||
"maxTicks": 33
|
||||
"expectedTicks": 19,
|
||||
"maxTicks": 23
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "repeated-diagonal-parkour-chain",
|
||||
"expectedTotalTicks": 20,
|
||||
"maxTotalTicks": 24,
|
||||
"expectedTotalTicks": 67,
|
||||
"maxTotalTicks": 82,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 61,
|
||||
"maxTicks": 74
|
||||
"expectedTicks": 14,
|
||||
"maxTicks": 17
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 61,
|
||||
"maxTicks": 74
|
||||
"expectedTicks": 36,
|
||||
"maxTicks": 44
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 20,
|
||||
"maxTicks": 24
|
||||
"expectedTicks": 17,
|
||||
"maxTicks": 21
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "obstructed-parkour-l-turns",
|
||||
"expectedTotalTicks": 0,
|
||||
"maxTotalTicks": 2,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 27,
|
||||
"maxTicks": 33
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 27,
|
||||
"maxTicks": 33
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 27,
|
||||
"maxTicks": 33
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "vertical-jump-mix",
|
||||
"expectedTotalTicks": 33,
|
||||
"maxTotalTicks": 40,
|
||||
"expectedTotalTicks": 50,
|
||||
"maxTotalTicks": 62,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
|
|
@ -178,14 +146,53 @@
|
|||
"maxTicks": 16
|
||||
},
|
||||
{
|
||||
"moveType": "Descend",
|
||||
"expectedTicks": 201,
|
||||
"maxTicks": 242
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 21,
|
||||
"maxTicks": 26
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 19,
|
||||
"maxTicks": 23
|
||||
"expectedTicks": 16,
|
||||
"maxTicks": 20
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "vertical-jump-mix",
|
||||
"expectedTotalTicks": 41,
|
||||
"maxTotalTicks": 50,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 10,
|
||||
"maxTicks": 12
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 18,
|
||||
"maxTicks": 22
|
||||
},
|
||||
{
|
||||
"moveType": "Descend",
|
||||
"expectedTicks": 13,
|
||||
"maxTicks": 16
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "diagonal-vertical-mix",
|
||||
"expectedTotalTicks": 38,
|
||||
"maxTotalTicks": 46,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 10,
|
||||
"maxTicks": 12
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 14,
|
||||
"maxTicks": 17
|
||||
},
|
||||
{
|
||||
"moveType": "Descend",
|
||||
|
|
@ -194,32 +201,10 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "diagonal-vertical-mix",
|
||||
"expectedTotalTicks": 31,
|
||||
"maxTotalTicks": 38,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 81,
|
||||
"maxTicks": 98
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 16,
|
||||
"maxTicks": 20
|
||||
},
|
||||
{
|
||||
"moveType": "Descend",
|
||||
"expectedTicks": 15,
|
||||
"maxTicks": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "turn-density-alternating-traverse-diagonal-chain",
|
||||
"expectedTotalTicks": 47,
|
||||
"maxTotalTicks": 57,
|
||||
"maxTotalTicks": 59,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Diagonal",
|
||||
|
|
@ -255,72 +240,62 @@
|
|||
},
|
||||
{
|
||||
"scenarioId": "mixed-traverse-ascend-parkour-descend",
|
||||
"expectedTotalTicks": 40,
|
||||
"maxTotalTicks": 48,
|
||||
"expectedTotalTicks": 70,
|
||||
"maxTotalTicks": 88,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 6,
|
||||
"maxTicks": 8
|
||||
"expectedTicks": 5,
|
||||
"maxTicks": 7
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 11,
|
||||
"maxTicks": 14
|
||||
"expectedTicks": 12,
|
||||
"maxTicks": 15
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 11,
|
||||
"maxTicks": 14
|
||||
"expectedTicks": 13,
|
||||
"maxTicks": 16
|
||||
},
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 81,
|
||||
"maxTicks": 98
|
||||
"expectedTicks": 5,
|
||||
"maxTicks": 7
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 14,
|
||||
"maxTicks": 17
|
||||
},
|
||||
{
|
||||
"moveType": "Descend",
|
||||
"expectedTicks": 21,
|
||||
"maxTicks": 26
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "same-move-aligned-parkour-chain",
|
||||
"expectedTotalTicks": 37,
|
||||
"maxTotalTicks": 45,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 18,
|
||||
"maxTicks": 22
|
||||
},
|
||||
{
|
||||
"moveType": "Descend",
|
||||
"expectedTicks": 22,
|
||||
"maxTicks": 27
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "same-move-aligned-parkour-chain",
|
||||
"expectedTotalTicks": 0,
|
||||
"maxTotalTicks": 2,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 61,
|
||||
"maxTicks": 74
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 61,
|
||||
"maxTicks": 74
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 61,
|
||||
"maxTicks": 74
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 27,
|
||||
"maxTicks": 33
|
||||
"expectedTicks": 19,
|
||||
"maxTicks": 23
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "mixed-diagonal-ascend-traverse-descend",
|
||||
"expectedTotalTicks": 96,
|
||||
"maxTotalTicks": 116,
|
||||
"expectedTotalTicks": 76,
|
||||
"maxTotalTicks": 95,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Diagonal",
|
||||
|
|
@ -334,13 +309,13 @@
|
|||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 32,
|
||||
"maxTicks": 39
|
||||
"expectedTicks": 10,
|
||||
"maxTicks": 12
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 11,
|
||||
"maxTicks": 14
|
||||
"expectedTicks": 13,
|
||||
"maxTicks": 16
|
||||
},
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
|
|
@ -361,19 +336,9 @@
|
|||
},
|
||||
{
|
||||
"scenarioId": "speed-carry-repeated-traverse-ascend",
|
||||
"expectedTotalTicks": 66,
|
||||
"maxTotalTicks": 80,
|
||||
"expectedTotalTicks": 70,
|
||||
"maxTotalTicks": 90,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 6,
|
||||
"maxTicks": 8
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 11,
|
||||
"maxTicks": 14
|
||||
},
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 5,
|
||||
|
|
@ -381,18 +346,8 @@
|
|||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 11,
|
||||
"maxTicks": 14
|
||||
},
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 5,
|
||||
"maxTicks": 7
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 11,
|
||||
"maxTicks": 14
|
||||
"expectedTicks": 13,
|
||||
"maxTicks": 16
|
||||
},
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
|
|
@ -403,23 +358,43 @@
|
|||
"moveType": "Ascend",
|
||||
"expectedTicks": 12,
|
||||
"maxTicks": 15
|
||||
},
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 5,
|
||||
"maxTicks": 7
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 12,
|
||||
"maxTicks": 15
|
||||
},
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 5,
|
||||
"maxTicks": 7
|
||||
},
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"expectedTicks": 13,
|
||||
"maxTicks": 16
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "speed-carry-repeated-traverse-descend",
|
||||
"expectedTotalTicks": 41,
|
||||
"maxTotalTicks": 50,
|
||||
"expectedTotalTicks": 45,
|
||||
"maxTotalTicks": 57,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 81,
|
||||
"maxTicks": 98
|
||||
"expectedTicks": 5,
|
||||
"maxTicks": 7
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 22,
|
||||
"maxTicks": 27
|
||||
"expectedTicks": 21,
|
||||
"maxTicks": 26
|
||||
},
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
|
|
@ -435,45 +410,45 @@
|
|||
},
|
||||
{
|
||||
"scenarioId": "speed-carry-repeated-traverse-parkour",
|
||||
"expectedTotalTicks": 0,
|
||||
"maxTotalTicks": 2,
|
||||
"expectedTotalTicks": 58,
|
||||
"maxTotalTicks": 73,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 81,
|
||||
"maxTicks": 98
|
||||
"expectedTicks": 5,
|
||||
"maxTicks": 7
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 18,
|
||||
"maxTicks": 22
|
||||
"expectedTicks": 14,
|
||||
"maxTicks": 17
|
||||
},
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 81,
|
||||
"maxTicks": 98
|
||||
"expectedTicks": 5,
|
||||
"maxTicks": 7
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 14,
|
||||
"maxTicks": 17
|
||||
},
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 5,
|
||||
"maxTicks": 7
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 15,
|
||||
"maxTicks": 18
|
||||
},
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 81,
|
||||
"maxTicks": 98
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"expectedTicks": 29,
|
||||
"maxTicks": 35
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "same-move-diagonal-chain",
|
||||
"expectedTotalTicks": 55,
|
||||
"maxTotalTicks": 66,
|
||||
"maxTotalTicks": 69,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Diagonal",
|
||||
|
|
@ -515,7 +490,7 @@
|
|||
{
|
||||
"scenarioId": "same-move-straight-traverse-chain",
|
||||
"expectedTotalTicks": 70,
|
||||
"maxTotalTicks": 84,
|
||||
"maxTotalTicks": 94,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
|
|
@ -581,8 +556,8 @@
|
|||
},
|
||||
{
|
||||
"scenarioId": "mixed-traverse-turn-parkour-turn-traverse",
|
||||
"expectedTotalTicks": 46,
|
||||
"maxTotalTicks": 56,
|
||||
"expectedTotalTicks": 60,
|
||||
"maxTotalTicks": 75,
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
|
|
@ -591,8 +566,8 @@
|
|||
},
|
||||
{
|
||||
"moveType": "Diagonal",
|
||||
"expectedTicks": 81,
|
||||
"maxTicks": 98
|
||||
"expectedTicks": 6,
|
||||
"maxTicks": 8
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
|
|
@ -601,8 +576,8 @@
|
|||
},
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 7,
|
||||
"maxTicks": 9
|
||||
"expectedTicks": 8,
|
||||
"maxTicks": 10
|
||||
},
|
||||
{
|
||||
"moveType": "Diagonal",
|
||||
|
|
@ -616,8 +591,8 @@
|
|||
},
|
||||
{
|
||||
"moveType": "Traverse",
|
||||
"expectedTicks": 8,
|
||||
"maxTicks": 10
|
||||
"expectedTicks": 7,
|
||||
"maxTicks": 9
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue