fix(rules): constrain a run to a straight line
SRD Full-Round Actions - Run: 'you can move up to four times your speed in a straight line'. _execute_run reused the Dijkstra move machinery, so it turned corners around walls. It now walks the straight Bresenham line (_run_line_path) and stops at the first obstacle (impassable terrain, difficult terrain, or a blocking creature), mirroring the charge clear-path logic. Keeps the 4x budget, step-by-step AoO provocation, moved_this_turn and the running/Dex-loss flag; a destination the straight line cannot honour is rejected (unreachable_destination). Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -814,27 +814,34 @@ Règles modélisées :
|
||||
une politique personnalisée).
|
||||
- Course (`Action(kind="run")`, action à round complet, U5e) : le combattant
|
||||
se déplace jusqu'à **4× sa vitesse** vers `target_id` (auto-dirigé,
|
||||
s'arrête adjacent à la cible) ou vers une `destination` explicite (U5c), en
|
||||
réutilisant exactement la mécanique de `move` (descente du champ de coût
|
||||
Dijkstra, pas à pas avec provocation d'AoO — courir ne protège pas des
|
||||
AoO), **sauf que la course ne traverse pas le terrain difficile**
|
||||
(conformance R2 — CRB « Movement, Position and Distance — Difficult
|
||||
Terrain » : « You can't run or charge across difficult terrain ») : la
|
||||
descente refuse tout pas dont le footprint toucherait une case de coût > 1
|
||||
(mécanisme `avoid_difficult` de `_descend_path`, symétrique du refus de la
|
||||
charge dans `_charge_path_clear`) ; le combattant **avance jusqu'à
|
||||
l'obstacle et s'y arrête** (comportement déterministe, retenu plutôt que
|
||||
le rejet de l'action) **quand la course est auto-dirigée**. À l'achèvement, le combattant est `running` jusqu'au
|
||||
début de son prochain tour : il **perd son bonus de Dextérité à la CA**
|
||||
(résolu par le même chemin flat-footed/`denies_dex_to_ac` que les
|
||||
conditions). Une `destination` hors budget 4× (ou invalide) est rejetée
|
||||
(`unreachable_destination`) ; une `destination` joignable uniquement en
|
||||
traversant le terrain difficile est **aussi rejetée** — le test de
|
||||
portée (`_destination_reachable`) applique la même contrainte
|
||||
`avoid_difficult` que la descente, donc le verdict et le chemin parcouru
|
||||
sont cohérents (pas d'arrêt silencieux avant la destination) ; sans cible ni destination, rejet
|
||||
(`missing_target`). `default_policy` ne choisit pas la course (disponible
|
||||
via une politique personnalisée).
|
||||
s'arrête adjacent à la cible) ou vers une `destination` explicite (U5c).
|
||||
**S4a — la course est une ligne droite** (SRD « Full-Round Actions — Run » :
|
||||
« When you run, you can move up to four times your speed **in a straight
|
||||
line** ») : contrairement à `move` (descente Dijkstra qui contourne les
|
||||
obstacles), la course suit la **ligne de Bresenham** entre la position
|
||||
courante et la cible/destination, et **s'arrête au premier obstacle** —
|
||||
terrain infranchissable, terrain difficile, ou créature bloquante — en
|
||||
miroir de la logique de ligne dégagée de la charge (`_run_line_path`,
|
||||
`_charge_path_clear`). Le déplacement reste pas à pas avec **provocation
|
||||
d'AoO** (courir ne protège pas des AoO), et conserve le budget 4×, le
|
||||
drapeau `moved_this_turn` et l'exclusivité avec les autres mouvements.
|
||||
Comme pour `move`, la course **traverse les cases des alliés** sans jamais
|
||||
y **finir** (SRD « Movement », conformance L5 — la queue du chemin est
|
||||
tronquée) ; une créature hostile (la cible incluse) arrête la course une
|
||||
case avant, donc la course auto-dirigée **s'arrête adjacent à la cible**.
|
||||
La course **ne traverse pas le terrain difficile** (conformance R2 — CRB
|
||||
« Difficult Terrain » : « You can't run or charge across difficult
|
||||
terrain ») : elle avance jusqu'à l'obstacle et s'y arrête **quand elle est
|
||||
auto-dirigée**. À l'achèvement, le combattant est `running` jusqu'au début
|
||||
de son prochain tour : il **perd son bonus de Dextérité à la CA** (résolu
|
||||
par le même chemin flat-footed/`denies_dex_to_ac` que les conditions). Une
|
||||
`destination` que la ligne droite ne peut pas honorer dans le budget 4×
|
||||
(hors portée, bloquée par un obstacle/une créature, ou joignable uniquement
|
||||
en tournant un coin ou en traversant le terrain difficile) est **rejetée**
|
||||
(`unreachable_destination`) — le verdict et le chemin parcouru sont
|
||||
cohérents (pas de contournement silencieux) ; sans cible ni destination,
|
||||
rejet (`missing_target`). `default_policy` ne choisit pas la course
|
||||
(disponible via une politique personnalisée).
|
||||
- Pas de placement (5-foot step) : action libre qui déplace le combattant d'une
|
||||
case vers l'ennemi le plus proche sans provoquer d'AoO. Exclusivité mutuelle
|
||||
avec tout autre mouvement (move, charge, retraite) dans le même tour —
|
||||
|
||||
Reference in New Issue
Block a user