fix(rules): allow movement through friendly squares

PF1e (SRD Movement, Position and Distance): "You can move through a square occupied by a friendly character, unless you are charging." The move and run descents now route their Dijkstra cost field and greedy steps over hostile-only blocking (_blocked_hostile), so allies' squares are passable; a friendly square may only be entered when a free cell descends from it and the path tail is trimmed, so movement never ENDS on an occupied cell. Charge, withdraw, the auto 5-foot step and the Observation cost fields keep full blocking (documented). Corridor tests added; the Combat Reflexes multi-AoO transcript is unchanged. README updated.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-09-12 09:18:29 +02:00
parent faa8a72a86
commit 2f00d76ecc
3 changed files with 192 additions and 17 deletions
+14 -5
View File
@@ -584,11 +584,20 @@ Règles modélisées :
allonge naturelle`, la dead zone vaut donc 5 ft pour un porteur
Small/Medium et 10 ft pour un porteur Large. Une arme ordinaire sans
allonge menace les cases adjacentes (disque de 5 ft).
Mouvement : un déplacement parcourt jusqu'à la
vitesse du combattant en cases le long du plus court chemin réel (champ de
coût Dijkstra depuis la cible, diagonales 5-10-5), en s'arrêtant adjacent à
l'ennemi le plus proche — les combattants contournent les murs au lieu
d'osciller contre eux.
Mouvement : un déplacement parcourt jusqu'à la
vitesse du combattant en cases le long du plus court chemin réel (champ de
coût Dijkstra depuis la cible, diagonales 5-10-5), en s'arrêtant adjacent à
l'ennemi le plus proche — les combattants contournent les murs au lieu
d'osciller contre eux. Conformance L5 (SRD « Movement, Position and
Distance ») : « You can move through a square occupied by a friendly
character, unless you are charging » — `move` et `run` **traversent** les
cases des alliés (les ennemis bloquent toujours le chemin), mais ne
peuvent jamais **finir** sur une case occupée : entrer sur une case alliée
exige un prolongement libre (règle du « pass-through »), et la queue du
chemin est tronquée si le budget s'épuise sur une case alliée. La charge
reste bloquée par les créatures (ligne droite dégagée), comme la retraite
(limite documentée : le passage à travers les alliés n'est pas modélisé
pour `withdraw` et le pas de placement auto-dirigé).
Vitesse de déplacement (V4) : le budget de tout mouvement (déplacement,
charge 2×, retraite 2×, course 4×) est le **meilleur entre la vitesse au
sol (`speed_land_ft`) et la vitesse de vol (`speed_fly_ft`)** — une créature