docs(rules): document skill checks, Acrobatics Tumbling and Stealth in README (rule list, observation schema hidden_from, out-of-scope updates, test count 1970)

This commit is contained in:
2026-09-20 21:48:02 +02:00
parent 2c40994610
commit 1257bb3849
+96 -6
View File
@@ -1139,6 +1139,92 @@ Règles modélisées :
modificateurs d'effets (`StatModifier` avec `target` correspondant) sont modificateurs d'effets (`StatModifier` avec `target` correspondant) sont
appliqués via `resolve_modifiers` (mêmes règles d'empilement que les appliqués via `resolve_modifiers` (mêmes règles d'empilement que les
attaques). Renvoie un `SaveResult` (success, roll, total, dc). attaques). Renvoie un `SaveResult` (success, roll, total, dc).
- Compétences : `skill_check(state, skill, *, extra_mods=())` — jet de
compétence générique `d20 + rangs + mod de caractéristique + 3 si compétence
de classe avec rangs investis + pénalité d'armure` (SRD « Skill Checks »,
Table 4-2 « Trained Class Skill » : le bonus de classe +3 n'est accordé que
si la compétence est de classe ET a au moins 1 rang). **Aucune réussite ou
échec automatique sur 1/20 naturel** (SRD « Skill Checks » : « Unlike attack
rolls and saving throws, a natural roll of 20 on the d20 is not an automatic
success, and a natural roll of 1 is not an automatic failure »). Renvoie un
`SkillCheckResult` (roll, total). `resolve_skill` (bonus statique de
compétence, utilisé par l'escape par compétence) délègue désormais au même
calcul. Compétences de combat modélisées : **Acrobatics — Tumbling** et
**Stealth** (voir ci-dessous) ; les autres compétences (Climb, Swim,
Diplomacy, Disable Device…) restent hors périmètre (voir « Limites hors
périmètre »).
- Acrobatics — Tumbling (SRD « Acrobatics », KB
`rules/pathfinder-unchained/acrobatics-dex-armor-check-penalty.md` ;
« Moving Through a Square », KB
`rules/prpg-core-rulebook/moving-through-a-square.md`) :
`Action(kind="move", tumble=True)` (opt-in, comme `weapon_id`/
`destination` — `default_policy` ne tumbling jamais) fait tenter au
déplaceur un jet d'Acrobatics **par adversaire menaçant** avant de quitter
une case menacée et avant d'entrer dans la case d'un ennemi. DD = **CMD de
l'adversaire** (SRD : « The DC of this check is your opponent's CMD ») ;
entrer dans la case d'un ennemi : DD = **CMD + 5** (SRD « Move Through an
Enemy's Space » : « A trained character can attempt to use Acrobatics to
move through a square occupied by an opponent. The DC is 5 + the opponent's
CMD » — la clause « +5 si l'opposant est plus grand que vous » du cahier des
charges est couverte par cette entrée de case) ; **+2 par adversaire
supplémentaire déjà testé** dans le même déplacement (SRD : « If you attempt
to move through an enemy's space and fail, you lose the move action and
provoke an attack of opportunity from that enemy » ; « +2 to the DC for each
additional opponent you attempt to tumble past in the same round »). Le
tumbling est **réservé aux entraînés** (SRD : « A character can attempt to
use Acrobatics to move through a square occupied by an opponent only if she
is trained in the skill » — sans rang, l'action est rejetée
`untrained_tumble`). Le déplacement se fait à **moitié vitesse** (SRD :
« You can move through a threatened square at half speed »). **Échec** :
le mouvement s'arrête immédiatement et l'adversaire porte une AoO (SRD :
« If you fail this check, you provoke an attack of opportunity from that
enemy »). Le jet d'Acrobatics est un jet de compétence : pas de réussite/
échec automatique sur 20/1 naturel.
- Stealth (SRD « Stealth », KB `rules/ultimate-intrigue/perception-and-stealth.md`,
`rules/pathfinder-unchained/perception-wis.md`) :
`Action(kind="hide")` (action de mouvement, opt-in) fait tenter au
combattant un jet de Stealth **opposé à la Perception de chaque ennemi**
(SRD : « Your Stealth check is opposed by the Perception check of anyone who
might notice you »). Le jet de Stealth vaut `d20 + rangs + mod de Dextérité
+ 3 de classe + pénalité d'armure + modificateur de taille` (SRD Table 4-2 :
Small +4, Medium 0, Large −4, Tiny +8, Diminutive +12, Fine +16) ; la
Perception de l'observateur subit **−1 par 10 ft de distance** (SRD
« Perception » : « +1 to the DC for every 10 feet of distance between you
and the target » — le moteur applique le modificateur au jet de Perception
de l'observateur). Un observateur qui **voit directement** le combattant
(ligne d'effet, sans couvert ni dissimulation, non aveuglé) ne peut pas être
battu : la dissimulation contre lui est impossible (SRD « Being Observed » :
« If people are observing you, you can't use Stealth »). Un observateur qui
**échoue à battre** le total de Stealth (opposition résolue par la règle
générale des jets opposés — CRB « Skill Checks » : « the attempt is
successful if your check result exceeds the result of the target ») ne
perçoit plus le combattant : il est ajouté à `hidden_from` et le traite
comme **invisible** (SRD : « Creatures that fail to beat your Stealth check
are not aware of you and treat you as if you had total concealment ») —
dissimulation totale 50 % contre ses attaques, **+2 aux attaques** du
combattant caché contre lui et **perte de son bonus de Dextérité à la CA**
(même chemin `denies_dex_to_ac` que l'invisible), et **aucune AoO** contre
un déplacement caché (SRD « Concealment » : « You can't execute an attack of
opportunity against an opponent with total concealment relative to you »).
**Briser la dissimulation** (SRD « Breaking Stealth ») : attaquer (ou
incanter un sort de contact) révèle le combattant à tous ses observateurs
(`hidden_from` vidé) ; **courir ou charger** brise aussi la dissimulation
(SRD : « If you run or charge, you lose Stealth ») ; **se déplacer** (move,
retraite) ou **faire un pas de placement** tout en restant caché re-joue
l'opposition avec **−5** (SRD : « You can move up to half your normal speed
and use Stealth at no penalty. When moving at a speed greater than half but
not more than your normal speed, you take a −5 penalty » — le moteur
applique le −5 à tout déplacement, simplification documentée : la vitesse
exacte du déplacement n'est pas distinguée) ; un observateur qui voit
directement la nouvelle position retire le combattant de sa liste
(journalisé `no longer hidden from X (observed)`). Le snapshot d'observation
expose l'état via la clé `hidden_from` (tuple trié des ids d'observateurs
qui ne perçoivent pas le combattant). Hors périmètre (documenté) : le
**sniping** (−20 au jet de Stealth pour attaquer puis rester caché), la
**création de diversion** (Bluff), le modificateur « distrait » (+5 au DD
de Perception — le moteur n'a pas d'état « distrait » et aucune règle SRD
ne rend les observateurs en combat automatiquement distraits), et la
distinction vitesse moitié/vitesse normale du −5 (voir ci-dessus).
- Modificateurs conditionnés : un `StatModifier` avec `condition=` n'est appliqué - Modificateurs conditionnés : un `StatModifier` avec `condition=` n'est appliqué
que si la condition tient au moment de la résolution (`_modifier_condition_holds`) : que si la condition tient au moment de la résolution (`_modifier_condition_holds`) :
`target_within_30ft_ranged` (arme à distance à ≤ 30 ft), `axe` (arme dont le nom `target_within_30ft_ranged` (arme à distance à ≤ 30 ft), `axe` (arme dont le nom
@@ -1906,7 +1992,10 @@ Règles modélisées :
pas ; V5b ; `bleeding`/`confused` sont visibles via `conditions`), pas ; V5b ; `bleeding`/`confused` sont visibles via `conditions`),
recurring_damage (S2c — liste des sources de dégâts récurrents de sort recurring_damage (S2c — liste des sources de dégâts récurrents de sort
actives, chacune `{formula, types, rounds_left}` ; tick au début du tour, actives, chacune `{formula, types, rounds_left}` ; tick au début du tour,
réduit par résistance énergétique, jamais par la RD). réduit par résistance énergétique, jamais par la RD),
hidden_from (tuple trié des ids d'observateurs ennemis qui ne perçoivent
pas le combattant — état de dissimulation par observateur, voir
« Stealth » ; vide = tout le monde le voit).
- Par paire combattant actif × cible : target_index, distance_ft, weapon_for, - Par paire combattant actif × cible : target_index, distance_ft, weapon_for,
range_penalty, can_charge, can_step5_to_attack, has_line_of_effect, range_penalty, can_charge, can_step5_to_attack, has_line_of_effect,
flanking, movement_cost_ft, target_threatens_me, enemies_threatening_me, flanking, movement_cost_ft, target_threatens_me, enemies_threatening_me,
@@ -1990,10 +2079,11 @@ plutôt que bricolées) :
son footprint ne rentre pas ; ni le squeeze payant, ni la réduction de son footprint ne rentre pas ; ni le squeeze payant, ni la réduction de
footprint dans les couloirs ne sont modélisés. footprint dans les couloirs ne sont modélisés.
- **Passage à travers une créature (3 catégories d'écart) — approximations** : - **Passage à travers une créature (3 catégories d'écart) — approximations** :
la règle est modélisée (traversée + AoO d'entrée, voir « Mouvement ») ; la règle est modélisée (traversée + AoO d'entrée, voir « Mouvement ») et le
restent hors périmètre le test d'Acrobatics « Tumbling » (« A trained test d'Acrobatics « Tumbling » est désormais modélisé (voir « Acrobatics —
character can attempt to use Acrobatics to move through a square occupied Tumbling » : opt-in `tumble=True`, DD = CMD, +5 pour entrer dans la case
by an opponent » — la compétence n'existe pas dans le moteur) et la clause d'un ennemi, +2 par adversaire supplémentaire, moitié vitesse, échec = AoO
+ mouvement arrêté) ; reste hors périmètre la clause
des très grosses créatures inertes (« Some creatures, particularly very des très grosses créatures inertes (« Some creatures, particularly very
large ones, may present an obstacle even when helpless. In such cases, each large ones, may present an obstacle even when helpless. In such cases, each
square you move through counts as 2 squares » — les cases d'une créature square you move through counts as 2 squares » — les cases d'une créature
@@ -2183,7 +2273,7 @@ Limites de sorts (conformance D6-D9, documentées plutôt que bricolées) :
La gate de validation complète (tests + lint + types) : La gate de validation complète (tests + lint + types) :
```bash ```bash
uv run pytest -q # 1900 tests uv run pytest -q # 1970 tests
uv run ruff check src tests uv run ruff check src tests
uv run basedpyright src # mode strict uv run basedpyright src # mode strict
``` ```