# Format de carte (YAML) Chaque couche est un bloc ASCII de mêmes dimensions ; un caractère = une case de `square_size_ft` pieds. Seule `terrain` est obligatoire. ```yaml name: "Arène d'essai" square_size_ft: 5 terrain: | # couche obligatoire #################### #......######......# #..C...######...C..# #......~..~........# #..TT..~..~...TT...# #......~..~........# #..C............C..# #################### legend: # un caractère = un type de terrain "#": { type: wall, move_cost: null, blocks_los: true } # bloque déplacement + LoS ".": { type: floor, move_cost: 1 } "T": { type: rubble, move_cost: 2 } # terrain difficile "~": { type: water, move_cost: 2 } "C": { type: pillar, move_cost: null, cover: true } # bloque le pas, couvert (+4) "W": { type: ruin, move_cost: null, cover_bonus: 2 } # couvert partiel (+2) ; 4 = standard, 8 = amélioré elevation: | # optionnel : chiffres = hauteur (appliqué : coût de pas + high ground) .................... ..1111.............. ..1111.............. .................... zones: | # optionnel : lettres de zone de déploiement .................... .AAAA..........BBBB. .AAAA..........BBBB. .................... markers: # optionnel : points nommés (validés, pas encore utilisés) autel: [1, 16] deployment: # obligatoire si zones : nom de camp -> lettre de zone players: A monsters: B ``` ## Détail des champs ### `square_size_ft` Taille d'une case en pieds (entier > 0). Par défaut 5 ft (1,5 m). ### `terrain` (obligatoire) Bloc ASCII représentant le terrain. Chaque ligne = une rangée de cases. ### `legend` Dictionnaire associant chaque caractère du terrain à ses propriétés : - `type` : identificateur du type de terrain - `move_cost` : entier > 0 pour terrain praticable, `null` pour infranchissable (mur, pilier) - `blocks_los` : booléen, bloque la ligne d'effet - `cover` : booléen, couvert standard (+4) - `cover_bonus` : optionnel, niveau de couvert (2 = partiel, 4 = standard, 8 = amélioré) **Important** : omettre `move_cost` équivaut à `null` (infranchissable). Un terrain praticable doit **toujours** déclarer explicitement son coût. ### `elevation` (optionnel) Chiffres = hauteur de sol (marche). Monter d'un niveau coûte +1 case de mouvement par niveau ; la descente est gratuite. Une créature plus haute que sa cible gagne +1 aux jets d'attaque de mêlée et à la confirmation de critique (high ground). La ligne d'effet reste 2D. ### `zones` (optionnel) Lettres de zone de déploiement. Chaque lettre = une zone distincte. ### `markers` (optionnel) Points nommés (validés à la lecture, pas encore utilisés en jeu). ### `deployment` (obligatoire si `zones` présent) Mapping nom de camp -> lettre de zone. Chaque camp du déploiement doit être fourni via `--side`, et toutes les zones doivent être couvertes. Deux camps ne peuvent pas partager la même lettre de zone. ## Sémantique de `blocks_los` **Ligne d'effet, non ligne de vision** (SRD « Aiming a Spell — Line of Effect ») : > « A line of effect is a straight, unblocked path that indicates what a spell can affect. A line of effect is canceled by a solid barrier. It's like line of sight for ranged weapons, except that it's not blocked by fog, darkness, and other factors that limit normal sight. » Le drapeau encode donc une **barrière solide** ; un terrain qui ne limite que la vision normale (brouillard, obscurité, dissimulation) n'est pas modélisé — le moteur n'a qu'un seul drapeau, et la dissimulation passe par les conditions (`miss_chance`), pas par la carte. ## Vol et terrain Une créature **aérienne** (vol ≥ sol) ignore les coûts de `move_cost` > 1 et **enjambe** les cases `move_cost: null` qui ne portent **pas** `blocks_los` (fosses, eau, gravats, piliers non bloquants). Une case `blocks_los` (barrière solide, hauteur supposée pleine) l'arrête aussi. La règle des coins suit la même vue : un aérien peut passer en diagonale au ras d'une fosse mais pas au ras d'un coin de mur.