fix(rules): charge clear-path tests the whole footprint for difficult terrain (SRD movement-position-and-distance-2.md: 'You can't run or charge across difficult terrain' + 'you can move only as fast as the most difficult terrain you occupy') - _charge_path_clear priced only the anchor cell, so a 2x2 creature with one trailing square in rubble charged freely; the move-descent footprint pricing is deferred (would rewrite the anchor-based Dijkstra cost field)

This commit is contained in:
2026-09-19 15:51:15 +02:00
parent 5e478bfd27
commit 9086038bfb
2 changed files with 146 additions and 4 deletions
+7 -4
View File
@@ -3999,14 +3999,17 @@ class CombatEngine:
blocks movement, slows movement, or contains a creature (even an
ally), you can't charge" - the straight Bresenham anchor line is the
engine's model of that path, walked under the full-footprint gates
below.
below. Difficult terrain is tested over the WHOLE footprint, not
just the anchor cell (SRD "Movement, Position and Distance": "You
can't run or charge across difficult terrain" - a 2x2 creature with
one trailing square in rubble cannot charge).
"""
prev = state.pos
for pos in path:
if not self._cells_free(self._footprint_at(pos, state), state):
footprint = self._footprint_at(pos, state)
if not self._cells_free(footprint, state):
return False
terrain = self._grid.terrain_at(pos)
if terrain.move_cost is not None and terrain.move_cost > 1:
if self._footprint_touches_difficult(footprint):
return False
if (
prev[0] != pos[0]