Minecraft-Console-Client/tools/tests/test_pathing_theory_matrix.py
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

126 lines
4.5 KiB
Python

import unittest
from pathlib import Path
from tools.pathing_theory.primitives import (
can_reach_gap,
can_reach_gap_with_side_wall,
get_landing,
)
from tools.pathing_theory.simulator import build_theory_cases
class PathingTheoryMatrixTests(unittest.TestCase):
def test_build_theory_cases_returns_first_wave_families(self) -> None:
cases = build_theory_cases()
families = {(case.family, case.subfamily) for case in cases}
self.assertIn(("linear", "flat"), families)
self.assertIn(("linear", "ascend"), families)
self.assertIn(("linear", "descend"), families)
self.assertIn(("neo", "neo"), families)
self.assertIn(("ceiling", "headhitter"), families)
self.assertIn(("sidewall", "flat"), families)
self.assertIn(("sidewall", "ascend"), families)
self.assertIn(("sidewall", "descend"), families)
linear_boundary = next(
case
for case in cases
if case.case_id == "linear-flat-sprint-mm12-gap5-dy0p0"
)
self.assertFalse(linear_boundary.expected_reachable)
self.assertTrue(
linear_boundary.margin is None or linear_boundary.margin < 0.0
)
def test_walk_momentum_does_not_turn_gap4_ascend_into_reachable(self) -> None:
ok, landing_x, needed_x = can_reach_gap(
gap_blocks=4,
dy=1.0,
sprint=False,
momentum_ticks=12,
)
self.assertFalse(ok)
self.assertTrue(landing_x is None or landing_x < needed_x)
def test_walk_momentum_can_reach_gap2_ascend_with_edge_takeoff_support(self) -> None:
ok, landing_x, needed_x = can_reach_gap(
gap_blocks=2,
dy=1.0,
sprint=False,
momentum_ticks=12,
)
self.assertTrue(ok)
self.assertIsNotNone(landing_x)
self.assertGreaterEqual(landing_x, needed_x)
def test_walk_gap3_ascend_does_not_snap_up_after_falling_below_platform(self) -> None:
landing = get_landing(
sprint=False,
target_y=1.0,
landing_x_start=3.5,
momentum_ticks=12,
)
self.assertIsNone(landing)
def test_sprint_with_run_up_still_treats_flat_gap5_as_unreachable(self) -> None:
ok, landing_x, needed_x = can_reach_gap(
gap_blocks=5,
dy=0.0,
sprint=True,
momentum_ticks=12,
)
self.assertFalse(ok)
self.assertTrue(landing_x is None or landing_x < needed_x)
def test_sidewall_wo0_margin_is_less_or_equal_to_linear(self) -> None:
"""Side wall should never make a jump easier than the open-air linear case."""
cases = build_theory_cases()
linear_by_key: dict[tuple, float | None] = {}
for c in cases:
if c.family == "linear":
key = (c.subfamily, c.movement_mode, c.momentum_ticks,
c.gap_blocks, c.delta_y)
linear_by_key[key] = c.margin
for c in cases:
if c.family != "sidewall" or c.wall_offset != 0:
continue
key = (c.subfamily, c.movement_mode, c.momentum_ticks,
c.gap_blocks, c.delta_y)
lin_margin = linear_by_key.get(key)
if lin_margin is None or c.margin is None:
continue
self.assertLessEqual(
c.margin, lin_margin + 1e-9,
f"sidewall margin {c.margin} > linear margin {lin_margin} "
f"for {c.case_id}",
)
def test_sidewall_walk_descend_gap3_mm0_is_unreachable_wo0(self) -> None:
"""The tight walk descend dy=-2 gap3 mm0 should flip to unreachable with wall."""
ok, _, _ = can_reach_gap_with_side_wall(
gap_blocks=3, dy=-2.0, wall_offset=0, sprint=False, momentum_ticks=0,
)
self.assertFalse(ok)
def test_sidewall_sprint_flat_gap4_mm12_is_still_reachable_wo0(self) -> None:
"""Sprint flat gap4 with plenty of margin should survive the wall penalty."""
ok, landing_x, needed_x = can_reach_gap_with_side_wall(
gap_blocks=4, dy=0.0, wall_offset=0, sprint=True, momentum_ticks=12,
)
self.assertTrue(ok)
self.assertIsNotNone(landing_x)
self.assertGreater(landing_x, needed_x)
def test_theory_markdown_mentions_canonical_live_coverage(self) -> None:
markdown = Path("tools/pathing_data/theory-matrix.md").read_text(encoding="utf-8")
self.assertIn("Canonical live coverage", markdown)
if __name__ == "__main__":
unittest.main()