Minecraft-Console-Client/MinecraftClient/Pathing/Moves/ParkourFeasibility.cs
BruceChen 418f17b4a1 pathing: add side-wall theory, full-coverage parkour test suite, and live test fixes
Theory simulator:
- Add 2D side-wall jump physics with yaw sweep for worst-case margin
- Generate sidewall theory cases (flat/ascend/descend, wall_offset 0/1)
- Add momentum-capabilities.json with band compression and max_reach
- Extend models, capabilities, canonical, and renderers for sidewall

Full-coverage parkour test suite (tools/test-parkour.py):
- Derive test matrix from momentum-capabilities.json
- Build linear/neo/ceiling courses via RCON with 7-block clear margin
- Use /goto for pathfinding, parse A* and PathMgr log output
- Stop-at-first-failure per (family, subfamily, dy, ceil, wo) group
- Hierarchical --filter (e.g. linear/flat, ceiling/headhitter/ceil2.5)
- Exclude sidewall from default matrix (identical max_reach to linear)

Pathing execution fixes:
- Align parkour contracts and timing budgets with live test results
- Fix jump-entry yaw snapping for grounded handoffs
- Template helper and sprint jump template refinements

Made-with: Cursor
2026-04-15 17:52:47 +00:00

104 lines
2.6 KiB
C#

using System;
using MinecraftClient.Pathing.Core;
namespace MinecraftClient.Pathing.Moves;
internal static class ParkourFeasibility
{
public static bool HasRunUp(
CalculationContext ctx,
int x,
int y,
int z,
int xOffset,
int zOffset,
int yDelta)
{
double horiz = Math.Sqrt(xOffset * xOffset + zOffset * zOffset);
double threshold = yDelta > 0 ? 2.5 : 3.5;
if (horiz < threshold)
return true;
int backX = x - Math.Sign(xOffset);
int backZ = z - Math.Sign(zOffset);
if (!ctx.CanWalkOn(backX, y - 1, backZ))
return false;
return IsColumnPassable(ctx, backX, y, backZ);
}
public static bool HasDiagonalShoulderClearance(
CalculationContext ctx,
int x,
int y,
int z,
int xOffset,
int zOffset)
{
if (xOffset == 0 || zOffset == 0)
return true;
return IsColumnPassable(ctx, x + Math.Sign(xOffset), y, z)
&& IsColumnPassable(ctx, x, y, z + Math.Sign(zOffset));
}
public static bool HasLandingOvershootClearance(
CalculationContext ctx,
int destX,
int destY,
int destZ,
int xSign,
int zSign)
{
if (xSign == 0 && zSign == 0)
return true;
return IsColumnPassable(ctx, destX + xSign, destY, destZ + zSign);
}
public static bool HasCardinalSideClearance(
CalculationContext ctx,
int x,
int y,
int z,
int xOffset,
int zOffset)
{
if ((xOffset == 0) == (zOffset == 0))
return true;
if (xOffset != 0)
{
int xSign = Math.Sign(xOffset);
for (int step = 1; step <= Math.Abs(xOffset); step++)
{
int gx = x + xSign * step;
if (!IsColumnPassable(ctx, gx, y, z - 1)
|| !IsColumnPassable(ctx, gx, y, z + 1))
{
return false;
}
}
return true;
}
int zSign = Math.Sign(zOffset);
for (int step = 1; step <= Math.Abs(zOffset); step++)
{
int gz = z + zSign * step;
if (!IsColumnPassable(ctx, x - 1, y, gz)
|| !IsColumnPassable(ctx, x + 1, y, gz))
{
return false;
}
}
return true;
}
private static bool IsColumnPassable(CalculationContext ctx, int x, int y, int z)
{
return ctx.CanWalkThrough(x, y, z)
&& ctx.CanWalkThrough(x, y + 1, z);
}
}