fix(rules): require adjacency or pull the target when grappling

SRD 'Grapple': 'If you successfully grapple a creature that is not adjacent to you, move that creature to an adjacent open space (if no space is available, your grapple fails).' _maneuver_grapple now pulls a non-adjacent target to the nearest free anchor whose footprint is adjacent to the grappler (5-10-5 distance, (row,col) tie-break, new _nearest_anchor_adjacent_to helper) and fails outright when no adjacent open space exists. Three tests: pull, no-space failure, adjacent no-move.

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 14:45:55 +02:00
parent 25149c64ba
commit a989266747
3 changed files with 120 additions and 1 deletions
+8 -1
View File
@@ -1102,7 +1102,14 @@ Règles modélisées :
your attack exceeds your opponent's CMD you can push the target back an
additional 5 feet » — `1 + marge//5` cases, stoppées au premier obstacle
(un 20 naturel sous le CMD ne donne que la poussée de base) ;
grapple → `grappled`/`pinned` ; escape → **une** sauvegarde (bonus statique de la
grapple → `grappled`/`pinned` ; conformance L8 (SRD « Grapple ») : « If
you successfully grapple a creature that is not adjacent to you, move
that creature to an adjacent open space (if no space is available, your
grapple fails) » — une réussite à distance **tire la cible** sur la case
libre adjacente la plus proche (distance 5-10-5, départage (ligne,
colonne) ; journalisé `grapple pulls`), et **échoue** sans poser la
condition si aucune case adjacente libre n'existe (`FAILED (no adjacent
space)`) ; escape → **une** sauvegarde (bonus statique de la
compétence `escape_artist` ou CMB, + un d20) contre CMD — une seule tentative,
sans boucle multi-tour. Conformance L4 (SRD « Combat Maneuvers ») : le 20
naturel réussit **toujours** à l'escape d'un grapple (« Rolling a natural