mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
test: add jump combo planner and timing contracts
This commit is contained in:
parent
ba1dc32ccb
commit
eb9d6ce356
7 changed files with 328 additions and 1 deletions
|
|
@ -225,4 +225,21 @@ public sealed class PathPlanningContractTests
|
|||
|
||||
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)
|
||||
{
|
||||
PathingExecutionScenario scenario = PathingExecutionScenarioCatalog.Get(scenarioId);
|
||||
PathResult planResult = PathingScenarioRunner.PlanOnly(scenario);
|
||||
|
||||
PathingContractAssert.PlannerMatches(
|
||||
PathingContractStore.LoadFromRepositoryRoot().GetPlanner(scenarioId),
|
||||
PathSegmentBuilder.FromPath(planResult.Path),
|
||||
planResult);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,4 +29,19 @@ public sealed class PathTimingContractTests
|
|||
|
||||
PathingContractAssert.TimingMatches(budget, result);
|
||||
}
|
||||
|
||||
[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_ExecutionStaysWithinBudget(string scenarioId)
|
||||
{
|
||||
PathingExecutionScenario scenario = PathingExecutionScenarioCatalog.Get(scenarioId);
|
||||
PathingTimingBudget budget = PathingContractStore.LoadFromRepositoryRoot().GetTiming(scenarioId);
|
||||
PathingScenarioResult result = PathingScenarioRunner.RunAccepted(scenario);
|
||||
|
||||
PathingContractAssert.TimingMatches(budget, result);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,4 +23,20 @@ public sealed class PathingContractBootstrapTests
|
|||
if (planResult.Status == PathStatus.Success)
|
||||
_output.WriteLine(PathingContractBootstrapWriter.WriteTimingFragment(scenarioId, PathingScenarioRunner.RunAccepted(scenario)));
|
||||
}
|
||||
|
||||
[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 PrintJumpComboContractFragments(string scenarioId)
|
||||
{
|
||||
PathingExecutionScenario scenario = PathingExecutionScenarioCatalog.Get(scenarioId);
|
||||
PathResult planResult = PathingScenarioRunner.PlanOnly(scenario);
|
||||
|
||||
_output.WriteLine(PathingContractBootstrapWriter.WritePlannerFragment(scenarioId, planResult));
|
||||
if (planResult.Status == PathStatus.Success)
|
||||
_output.WriteLine(PathingContractBootstrapWriter.WriteTimingFragment(scenarioId, PathingScenarioRunner.RunAccepted(scenario)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,51 @@ internal static class PathingExecutionScenarioCatalog
|
|||
StartYaw = 270f,
|
||||
MaxExecutionTicks = 80
|
||||
},
|
||||
"repeated-cardinal-parkour-chain" => new PathingExecutionScenario
|
||||
{
|
||||
Id = scenarioId,
|
||||
BuildWorld = BuildRepeatedCardinalParkourChain,
|
||||
Start = new Location(580.5, 80, 580.5),
|
||||
Goal = new GoalBlock(588, 80, 580),
|
||||
StartYaw = 270f,
|
||||
MaxExecutionTicks = 420
|
||||
},
|
||||
"repeated-diagonal-parkour-chain" => new PathingExecutionScenario
|
||||
{
|
||||
Id = scenarioId,
|
||||
BuildWorld = BuildRepeatedDiagonalParkourChain,
|
||||
Start = new Location(600.5, 80, 600.5),
|
||||
Goal = new GoalBlock(606, 80, 606),
|
||||
StartYaw = 315f,
|
||||
MaxExecutionTicks = 420
|
||||
},
|
||||
"obstructed-parkour-l-turns" => new PathingExecutionScenario
|
||||
{
|
||||
Id = scenarioId,
|
||||
BuildWorld = BuildObstructedParkourLTurns,
|
||||
Start = new Location(620.5, 80, 620.5),
|
||||
Goal = new GoalBlock(626, 80, 622),
|
||||
StartYaw = 270f,
|
||||
MaxExecutionTicks = 420
|
||||
},
|
||||
"vertical-jump-mix" => new PathingExecutionScenario
|
||||
{
|
||||
Id = scenarioId,
|
||||
BuildWorld = BuildVerticalJumpMix,
|
||||
Start = new Location(640.5, 80, 620.5),
|
||||
Goal = new GoalBlock(648, 80, 620),
|
||||
StartYaw = 270f,
|
||||
MaxExecutionTicks = 420
|
||||
},
|
||||
"diagonal-vertical-mix" => new PathingExecutionScenario
|
||||
{
|
||||
Id = scenarioId,
|
||||
BuildWorld = BuildDiagonalVerticalMix,
|
||||
Start = new Location(680.5, 80, 620.5),
|
||||
Goal = new GoalBlock(684, 80, 624),
|
||||
StartYaw = 315f,
|
||||
MaxExecutionTicks = 420
|
||||
},
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(scenarioId), scenarioId, null)
|
||||
};
|
||||
|
||||
|
|
@ -88,4 +133,70 @@ internal static class PathingExecutionScenarioCatalog
|
|||
FlatWorldTestBuilder.SetSolid(world, 143, 80, 138);
|
||||
return world;
|
||||
}
|
||||
|
||||
private static World BuildRepeatedCardinalParkourChain()
|
||||
{
|
||||
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);
|
||||
return world;
|
||||
}
|
||||
|
||||
private static World BuildRepeatedDiagonalParkourChain()
|
||||
{
|
||||
World world = FlatWorldTestBuilder.CreateStoneFloor(min: 598, max: 608);
|
||||
FlatWorldTestBuilder.ClearBox(world, 598, 79, 598, 608, 90, 608);
|
||||
FlatWorldTestBuilder.SetSolid(world, 600, 79, 600);
|
||||
FlatWorldTestBuilder.SetSolid(world, 602, 79, 602);
|
||||
FlatWorldTestBuilder.SetSolid(world, 604, 79, 604);
|
||||
FlatWorldTestBuilder.SetSolid(world, 606, 79, 606);
|
||||
return world;
|
||||
}
|
||||
|
||||
private static World BuildObstructedParkourLTurns()
|
||||
{
|
||||
World world = FlatWorldTestBuilder.CreateStoneFloor(min: 618, max: 628);
|
||||
FlatWorldTestBuilder.ClearBox(world, 618, 79, 618, 628, 90, 624);
|
||||
FlatWorldTestBuilder.SetSolid(world, 620, 79, 620);
|
||||
FlatWorldTestBuilder.SetSolid(world, 622, 79, 620);
|
||||
FlatWorldTestBuilder.SetSolid(world, 622, 79, 621);
|
||||
FlatWorldTestBuilder.SetSolid(world, 624, 79, 621);
|
||||
FlatWorldTestBuilder.SetSolid(world, 624, 79, 622);
|
||||
FlatWorldTestBuilder.SetSolid(world, 626, 79, 622);
|
||||
FlatWorldTestBuilder.SetSolid(world, 620, 80, 621);
|
||||
FlatWorldTestBuilder.SetSolid(world, 620, 81, 621);
|
||||
FlatWorldTestBuilder.SetSolid(world, 622, 80, 622);
|
||||
FlatWorldTestBuilder.SetSolid(world, 622, 81, 622);
|
||||
return world;
|
||||
}
|
||||
|
||||
private static World BuildVerticalJumpMix()
|
||||
{
|
||||
World world = FlatWorldTestBuilder.CreateStoneFloor(min: 618, max: 650);
|
||||
FlatWorldTestBuilder.ClearBox(world, 638, 79, 618, 650, 80, 622);
|
||||
FlatWorldTestBuilder.ClearBox(world, 638, 81, 618, 650, 92, 622);
|
||||
FlatWorldTestBuilder.SetSolid(world, 640, 79, 620);
|
||||
FlatWorldTestBuilder.SetSolid(world, 642, 80, 620);
|
||||
FlatWorldTestBuilder.SetSolid(world, 644, 79, 620);
|
||||
FlatWorldTestBuilder.SetSolid(world, 646, 80, 620);
|
||||
FlatWorldTestBuilder.SetSolid(world, 648, 79, 620);
|
||||
return world;
|
||||
}
|
||||
|
||||
private static World BuildDiagonalVerticalMix()
|
||||
{
|
||||
World world = FlatWorldTestBuilder.CreateStoneFloor(min: 618, max: 686);
|
||||
FlatWorldTestBuilder.ClearBox(world, 678, 79, 618, 686, 80, 626);
|
||||
FlatWorldTestBuilder.ClearBox(world, 678, 81, 618, 686, 92, 626);
|
||||
FlatWorldTestBuilder.SetSolid(world, 680, 79, 620);
|
||||
FlatWorldTestBuilder.SetSolid(world, 681, 80, 621);
|
||||
FlatWorldTestBuilder.SetSolid(world, 682, 79, 622);
|
||||
FlatWorldTestBuilder.SetSolid(world, 683, 80, 623);
|
||||
FlatWorldTestBuilder.SetSolid(world, 684, 79, 624);
|
||||
return world;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ internal static class PathingContractAssert
|
|||
internal static void TimingMatches(PathingTimingBudget budget, PathingScenarioResult result)
|
||||
{
|
||||
if (!result.Completed)
|
||||
throw new XunitException("navigation did not complete");
|
||||
throw new XunitException($"navigation did not complete\n{Format(result, budget)}");
|
||||
|
||||
if (result.ReplanCount != 0)
|
||||
throw new XunitException($"expected 0 replans, saw {result.ReplanCount}\n{Format(result, budget)}");
|
||||
|
|
@ -53,6 +53,7 @@ internal static class PathingContractAssert
|
|||
private static string Format(PathingScenarioResult result, PathingTimingBudget budget)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"completed={result.Completed} replans={result.ReplanCount}");
|
||||
sb.AppendLine($"route actual={result.TotalTicks} expected={budget.ExpectedTotalTicks} max={budget.MaxTotalTicks}");
|
||||
for (int i = 0; i < result.SegmentRuns.Count; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -91,5 +91,120 @@
|
|||
"scenarioId": "rejected-3x1-invalid-goal",
|
||||
"expectedStatus": "Failed",
|
||||
"segments": []
|
||||
},
|
||||
{
|
||||
"scenarioId": "repeated-cardinal-parkour-chain",
|
||||
"expectedStatus": "Success",
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": { "x": 580, "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, "z": 580 }
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": { "x": 584, "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, "z": 580 }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "repeated-diagonal-parkour-chain",
|
||||
"expectedStatus": "Success",
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": { "x": 600, "y": 80, "z": 600 },
|
||||
"endBlock": { "x": 602, "y": 80, "z": 602 }
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": { "x": 602, "y": 80, "z": 602 },
|
||||
"endBlock": { "x": 604, "y": 80, "z": 604 }
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": { "x": 604, "y": 80, "z": 604 },
|
||||
"endBlock": { "x": 606, "y": 80, "z": 606 }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "obstructed-parkour-l-turns",
|
||||
"expectedStatus": "Success",
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": { "x": 620, "y": 80, "z": 620 },
|
||||
"endBlock": { "x": 622, "y": 80, "z": 620 }
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": { "x": 622, "y": 80, "z": 620 },
|
||||
"endBlock": { "x": 624, "y": 80, "z": 621 }
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": { "x": 624, "y": 80, "z": 621 },
|
||||
"endBlock": { "x": 626, "y": 80, "z": 622 }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "vertical-jump-mix",
|
||||
"expectedStatus": "Success",
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": { "x": 640, "y": 80, "z": 620 },
|
||||
"endBlock": { "x": 642, "y": 81, "z": 620 }
|
||||
},
|
||||
{
|
||||
"moveType": "Descend",
|
||||
"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, "z": 620 }
|
||||
},
|
||||
{
|
||||
"moveType": "Descend",
|
||||
"startBlock": { "x": 646, "y": 81, "z": 620 },
|
||||
"endBlock": { "x": 648, "y": 80, "z": 620 }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "diagonal-vertical-mix",
|
||||
"expectedStatus": "Success",
|
||||
"segments": [
|
||||
{
|
||||
"moveType": "Ascend",
|
||||
"startBlock": { "x": 680, "y": 80, "z": 620 },
|
||||
"endBlock": { "x": 681, "y": 81, "z": 621 }
|
||||
},
|
||||
{
|
||||
"moveType": "Parkour",
|
||||
"startBlock": { "x": 681, "y": 81, "z": 621 },
|
||||
"endBlock": { "x": 683, "y": 81, "z": 623 }
|
||||
},
|
||||
{
|
||||
"moveType": "Descend",
|
||||
"startBlock": { "x": 683, "y": 81, "z": 623 },
|
||||
"endBlock": { "x": 684, "y": 80, "z": 624 }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -39,5 +39,57 @@
|
|||
"expectedTotalTicks": 0,
|
||||
"maxTotalTicks": 0,
|
||||
"segments": []
|
||||
},
|
||||
{
|
||||
"scenarioId": "repeated-cardinal-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 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenarioId": "repeated-diagonal-parkour-chain",
|
||||
"expectedTotalTicks": 20,
|
||||
"maxTotalTicks": 24,
|
||||
"segments": [
|
||||
{ "moveType": "Parkour", "expectedTicks": 61, "maxTicks": 74 },
|
||||
{ "moveType": "Parkour", "expectedTicks": 61, "maxTicks": 74 },
|
||||
{ "moveType": "Parkour", "expectedTicks": 20, "maxTicks": 24 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"segments": [
|
||||
{ "moveType": "Parkour", "expectedTicks": 13, "maxTicks": 16 },
|
||||
{ "moveType": "Descend", "expectedTicks": 201, "maxTicks": 242 },
|
||||
{ "moveType": "Parkour", "expectedTicks": 19, "maxTicks": 23 },
|
||||
{ "moveType": "Descend", "expectedTicks": 14, "maxTicks": 17 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"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 }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue