feat(runner): Monte Carlo runner, closed-form metrics and balance CLI
Adds the S6 layer on top of the deterministic combat engine: - metrics.py: closed-form binomial statistics (win rate, standard error, 3-sigma confidence band) with clamped degenerate proportions. - runner.py: EncounterSpec/Side definitions, per-run SeededRng streams, global duplicate-id disambiguation, attrition averages per combatant. - cli.py: pf1e-sim entry point producing a French balance report with win rates, 3-sigma bands, draws, rounds, and attrition. - Movement fix: greedy straight-line heuristic could oscillate at walls; _step_toward now follows the true shortest path via an unbounded Dijkstra cost field from the target (Grid.reachable budget=None). - Regression tests: melee unit routes around a wall and engages; grid unbounded-budget coverage.
This commit is contained in:
@@ -112,3 +112,9 @@ def test_reachable_cannot_enter_wall_squares() -> None:
|
||||
grid = make_grid(["..", ".C"])
|
||||
reached = grid.reachable((0, 0), 9, frozenset())
|
||||
assert (1, 1) not in reached
|
||||
|
||||
|
||||
def test_reachable_unbounded_budget_covers_whole_map() -> None:
|
||||
grid = make_grid([".#.", "..."])
|
||||
reached = grid.reachable((0, 0), None, frozenset())
|
||||
assert reached == {(0, 0): 0, (1, 0): 1, (1, 1): 2, (1, 2): 3, (0, 2): 4}
|
||||
|
||||
Reference in New Issue
Block a user