feat(data): transpose Foundry PC sheets into data/pcs
All 8 sheets from fiches_personnages/ converted to the strict Combatant
JSON schema (data/monsters convention) so the CLI can run PCs directly:
--side players data/pcs/esha.json
- id derived from the file stem; source field points at the original sheet
- oni: placeholder attacks without encoded damage ('une Pioche', 'Weapon')
left out, documented in notes (pick stats ambiguous light/heavy in the
rules KB; no identification possible for 'Weapon')
- README: PC section now documents data/pcs usage
- tests: parametrized load check + golden spots for the 8 PC files
This commit is contained in:
@@ -232,12 +232,24 @@ Champ `range_increment_ft` (optionnel, uniquement pour `kind: ranged`) : portée
|
||||
maximale de tir — au-delà, l'arme n'est pas utilisable. `damage_bonus` et `dr`
|
||||
sont optionnels. Deux monstres d'exemple sont fournis : gobelin et orc.
|
||||
|
||||
### Fiches de personnages
|
||||
### Fiches de personnages (PJ)
|
||||
|
||||
`fiches_personnages/` contient 8 fiches de PJ au format Foundry VTT
|
||||
(`pf1-sheet/v1`) ; le chargeur `loaders/foundry.py` sait les lire. Les
|
||||
rencontres CLI se construisent pour l'instant avec des monstres JSON — les
|
||||
fiches Foundry alimenteront la couche PJ dans une phase ultérieure.
|
||||
`fiches_personnages/` contient les 8 fiches de PJ au format Foundry VTT
|
||||
(`pf1-sheet/v1`) ; le chargeur `loaders/foundry.py` sait les lire. Elles sont
|
||||
transposées en JSON au schéma `Combatant` dans `data/pcs/` (`esha.json`,
|
||||
`harvie.json`, `ierlieth.json`, `jeanne.json`, `misty.json`, `nairda.json`,
|
||||
`oni.json`, `tammara.json`) et se passent directement à la CLI comme les
|
||||
monstres :
|
||||
|
||||
```bash
|
||||
uv run pf1e-sim --map data/maps/sample_arena.yaml \
|
||||
--side players data/pcs/oni.json \
|
||||
--side monsters data/pcs/tammara.json --runs 200
|
||||
```
|
||||
|
||||
Les armes placeholder des fiches sans dégâts encodés sont omises (notées
|
||||
dans `notes` le cas échéant) ; le champ `source` de chaque fichier pointe
|
||||
vers la fiche Foundry d'origine.
|
||||
|
||||
## Règles implémentées et limites de la Phase 0
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"name": "Esha Randu",
|
||||
"level": 4,
|
||||
"size": "Medium",
|
||||
"abilities": {
|
||||
"str_score": 14,
|
||||
"dex_score": 18,
|
||||
"con_score": 14,
|
||||
"int_score": 16,
|
||||
"wis_score": 12,
|
||||
"cha_score": 9
|
||||
},
|
||||
"hp_max": 32,
|
||||
"ac": {
|
||||
"total": 19,
|
||||
"touch": 15,
|
||||
"flat_footed": 14
|
||||
},
|
||||
"bab": 4,
|
||||
"initiative_mod": 5,
|
||||
"speed_land_ft": 25,
|
||||
"saves": {
|
||||
"fort": 6,
|
||||
"ref": 10,
|
||||
"will": 5
|
||||
},
|
||||
"attacks": [
|
||||
{
|
||||
"name": "Lance",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 7,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d8",
|
||||
"types": [
|
||||
"piercing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 4,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 3,
|
||||
"reach_ft": 10,
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"name": "Composite Shortbow +3",
|
||||
"kind": "ranged",
|
||||
"attack_bonus": 9,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d6",
|
||||
"types": [
|
||||
"piercing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 3,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 3,
|
||||
"reach_ft": 5,
|
||||
"count": 1,
|
||||
"range_increment_ft": 70
|
||||
},
|
||||
{
|
||||
"name": "Earth Breaker",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 8,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "2d6",
|
||||
"types": [
|
||||
"bludgeoning"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 4,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 3,
|
||||
"reach_ft": 5,
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"source": "fiches_personnages/esha_sheet.json"
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "Harvie",
|
||||
"level": 2,
|
||||
"size": "Small",
|
||||
"abilities": {
|
||||
"str_score": 10,
|
||||
"dex_score": 15,
|
||||
"con_score": 12,
|
||||
"int_score": 2,
|
||||
"wis_score": 14,
|
||||
"cha_score": 6
|
||||
},
|
||||
"hp_max": 15,
|
||||
"ac": {
|
||||
"total": 14,
|
||||
"touch": 13,
|
||||
"flat_footed": 12
|
||||
},
|
||||
"bab": 1,
|
||||
"initiative_mod": 2,
|
||||
"speed_land_ft": 10,
|
||||
"saves": {
|
||||
"fort": 4,
|
||||
"ref": 5,
|
||||
"will": 2
|
||||
},
|
||||
"attacks": [
|
||||
{
|
||||
"name": "Talons (attaque naturelle)",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 2,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d4",
|
||||
"types": [
|
||||
"slashing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 0,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"name": "Bite (attaque naturelle)",
|
||||
"kind": "melee",
|
||||
"attack_bonus": -3,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d4",
|
||||
"types": [
|
||||
"piercing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 0,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"source": "fiches_personnages/harvie_sheet.json",
|
||||
"speed_fly_ft": 80
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"name": "Ierlieth",
|
||||
"level": 4,
|
||||
"size": "Tiny",
|
||||
"abilities": {
|
||||
"str_score": 8,
|
||||
"dex_score": 17,
|
||||
"con_score": 11,
|
||||
"int_score": 10,
|
||||
"wis_score": 10,
|
||||
"cha_score": 9
|
||||
},
|
||||
"hp_max": 29,
|
||||
"ac": {
|
||||
"total": 17,
|
||||
"touch": 15,
|
||||
"flat_footed": 14
|
||||
},
|
||||
"bab": 3,
|
||||
"initiative_mod": 3,
|
||||
"speed_land_ft": 15,
|
||||
"saves": {
|
||||
"fort": 3,
|
||||
"ref": 6,
|
||||
"will": 3
|
||||
},
|
||||
"attacks": [
|
||||
{
|
||||
"name": "Bite (attaque naturelle)",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 4,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d4",
|
||||
"types": [
|
||||
"piercing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": -1,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"name": "Tail (attaque naturelle)",
|
||||
"kind": "melee",
|
||||
"attack_bonus": -1,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d4",
|
||||
"types": [
|
||||
"bludgeoning"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 0,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"source": "fiches_personnages/ierlieth_sheet.json"
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"name": "Jeanne",
|
||||
"level": 4,
|
||||
"size": "Large",
|
||||
"abilities": {
|
||||
"str_score": 18,
|
||||
"dex_score": 14,
|
||||
"con_score": 15,
|
||||
"int_score": 2,
|
||||
"wis_score": 12,
|
||||
"cha_score": 6
|
||||
},
|
||||
"hp_max": 31,
|
||||
"ac": {
|
||||
"total": 23,
|
||||
"touch": 11,
|
||||
"flat_footed": 21
|
||||
},
|
||||
"bab": 3,
|
||||
"initiative_mod": 2,
|
||||
"speed_land_ft": 40,
|
||||
"saves": {
|
||||
"fort": 6,
|
||||
"ref": 6,
|
||||
"will": 2
|
||||
},
|
||||
"attacks": [
|
||||
{
|
||||
"name": "Hooves (attaque naturelle)",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 8,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d4",
|
||||
"types": [
|
||||
"bludgeoning"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 4,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"name": "Bite (attaque naturelle)",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 3,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d3",
|
||||
"types": [
|
||||
"piercing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 2,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"source": "fiches_personnages/jeanne_sheet.json"
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
{
|
||||
"name": "Misty",
|
||||
"level": 4,
|
||||
"size": "Medium",
|
||||
"abilities": {
|
||||
"str_score": 12,
|
||||
"dex_score": 19,
|
||||
"con_score": 14,
|
||||
"int_score": 16,
|
||||
"wis_score": 7,
|
||||
"cha_score": 18
|
||||
},
|
||||
"hp_max": 31,
|
||||
"ac": {
|
||||
"total": 20,
|
||||
"touch": 14,
|
||||
"flat_footed": 16
|
||||
},
|
||||
"bab": 3,
|
||||
"initiative_mod": 4,
|
||||
"speed_land_ft": 30,
|
||||
"saves": {
|
||||
"fort": 7,
|
||||
"ref": 9,
|
||||
"will": 3
|
||||
},
|
||||
"attacks": [
|
||||
{
|
||||
"name": "MWK Rapier",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 8,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d6",
|
||||
"types": [
|
||||
"piercing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 1,
|
||||
"crit_range": 18,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"name": "Dagger",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 7,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d4",
|
||||
"types": [
|
||||
"piercing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 1,
|
||||
"crit_range": 19,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1,
|
||||
"range_increment_ft": 10
|
||||
},
|
||||
{
|
||||
"name": "Talons (attaque naturelle)",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 4,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d4",
|
||||
"types": [
|
||||
"slashing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 1,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"name": "Bite (attaque naturelle)",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 4,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d4",
|
||||
"types": [
|
||||
"piercing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 1,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"name": "Unarmed Strike",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 4,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d3",
|
||||
"types": [
|
||||
"bludgeoning"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 1,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"source": "fiches_personnages/misty_sheet.json"
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "Nairda Guisenda",
|
||||
"level": 4,
|
||||
"size": "Medium",
|
||||
"abilities": {
|
||||
"str_score": 9,
|
||||
"dex_score": 16,
|
||||
"con_score": 14,
|
||||
"int_score": 21,
|
||||
"wis_score": 14,
|
||||
"cha_score": 12
|
||||
},
|
||||
"hp_max": 31,
|
||||
"ac": {
|
||||
"total": 13,
|
||||
"touch": 13,
|
||||
"flat_footed": 10
|
||||
},
|
||||
"bab": 3,
|
||||
"initiative_mod": 3,
|
||||
"speed_land_ft": 30,
|
||||
"saves": {
|
||||
"fort": 4,
|
||||
"ref": 5,
|
||||
"will": 7
|
||||
},
|
||||
"attacks": [
|
||||
{
|
||||
"name": "Coup à mains nues (aucune arme encodée)",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 2,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d3",
|
||||
"types": [
|
||||
"bludgeoning"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": -1,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"name": "Attaque à distance (aucune arme encodée)",
|
||||
"kind": "ranged",
|
||||
"attack_bonus": 6,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d4",
|
||||
"types": [
|
||||
"piercing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 0,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1,
|
||||
"range_increment_ft": 10
|
||||
}
|
||||
],
|
||||
"source": "fiches_personnages/nairda_sheet.json"
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"name": "Oni Triumvir",
|
||||
"level": 4,
|
||||
"size": "Medium",
|
||||
"abilities": {
|
||||
"str_score": 12,
|
||||
"dex_score": 14,
|
||||
"con_score": 14,
|
||||
"int_score": 12,
|
||||
"wis_score": 18,
|
||||
"cha_score": 16
|
||||
},
|
||||
"hp_max": 36,
|
||||
"ac": {
|
||||
"total": 19,
|
||||
"touch": 18,
|
||||
"flat_footed": 17
|
||||
},
|
||||
"bab": 4,
|
||||
"initiative_mod": 2,
|
||||
"speed_land_ft": 30,
|
||||
"saves": {
|
||||
"fort": 7,
|
||||
"ref": 7,
|
||||
"will": 9
|
||||
},
|
||||
"attacks": [
|
||||
{
|
||||
"name": "Longbow",
|
||||
"kind": "ranged",
|
||||
"attack_bonus": 6,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d8",
|
||||
"types": [
|
||||
"piercing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 0,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 3,
|
||||
"reach_ft": 5,
|
||||
"count": 1,
|
||||
"range_increment_ft": 100
|
||||
},
|
||||
{
|
||||
"name": "Alchemist's Fire",
|
||||
"kind": "touch",
|
||||
"attack_bonus": 6,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d6",
|
||||
"types": [
|
||||
"fire"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 0,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1,
|
||||
"range_increment_ft": 10
|
||||
},
|
||||
{
|
||||
"name": "Attaques naturelles (Shifter Claws / formes fées)",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 5,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d6",
|
||||
"types": [
|
||||
"slashing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 1,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"source": "fiches_personnages/oni_sheet.json",
|
||||
"notes": "Armes placeholder Foundry sans dégâts encodés omises : 'une Pioche' (non maîtrisée) et 'Weapon' (à remplacer par la vraie arme)."
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"name": "Tammara Cailean",
|
||||
"level": 4,
|
||||
"size": "Medium",
|
||||
"abilities": {
|
||||
"str_score": 14,
|
||||
"dex_score": 20,
|
||||
"con_score": 14,
|
||||
"int_score": 9,
|
||||
"wis_score": 17,
|
||||
"cha_score": 12
|
||||
},
|
||||
"hp_max": 36,
|
||||
"ac": {
|
||||
"total": 20,
|
||||
"touch": 16,
|
||||
"flat_footed": 14
|
||||
},
|
||||
"bab": 4,
|
||||
"initiative_mod": 7,
|
||||
"speed_land_ft": 30,
|
||||
"saves": {
|
||||
"fort": 7,
|
||||
"ref": 10,
|
||||
"will": 8
|
||||
},
|
||||
"attacks": [
|
||||
{
|
||||
"name": "Rapier (masterwork)",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 7,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d6",
|
||||
"types": [
|
||||
"piercing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 2,
|
||||
"crit_range": 18,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"name": "Braises d'Automne (pistolet ?)",
|
||||
"kind": "ranged",
|
||||
"attack_bonus": 9,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d8",
|
||||
"types": [
|
||||
"piercing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 0,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 4,
|
||||
"reach_ft": 5,
|
||||
"count": 1,
|
||||
"range_increment_ft": 20
|
||||
},
|
||||
{
|
||||
"name": "Adieux du Printemps (pistolet, masterwork)",
|
||||
"kind": "ranged",
|
||||
"attack_bonus": 10,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d8",
|
||||
"types": [
|
||||
"piercing"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 0,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 4,
|
||||
"reach_ft": 5,
|
||||
"count": 1,
|
||||
"range_increment_ft": 20
|
||||
},
|
||||
{
|
||||
"name": "Alchemist's Fire",
|
||||
"kind": "touch",
|
||||
"attack_bonus": 9,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d6",
|
||||
"types": [
|
||||
"fire"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 0,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1,
|
||||
"range_increment_ft": 10
|
||||
},
|
||||
{
|
||||
"name": "Unarmed Strike",
|
||||
"kind": "melee",
|
||||
"attack_bonus": 6,
|
||||
"damage": [
|
||||
{
|
||||
"formula": "1d3",
|
||||
"types": [
|
||||
"bludgeoning"
|
||||
]
|
||||
}
|
||||
],
|
||||
"damage_bonus": 2,
|
||||
"crit_range": 20,
|
||||
"crit_mult": 2,
|
||||
"reach_ft": 5,
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"source": "fiches_personnages/tammara_sheet.json"
|
||||
}
|
||||
@@ -11,6 +11,43 @@ from pf1e_simulator.dice import DiceExpr
|
||||
from pf1e_simulator.loaders.monster import MonsterLoadError, load_monster
|
||||
|
||||
MONSTERS_DIR = Path(__file__).resolve().parents[1] / "data" / "monsters"
|
||||
PCS_DIR = Path(__file__).resolve().parents[1] / "data" / "pcs"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"stem",
|
||||
["esha", "harvie", "ierlieth", "jeanne", "misty", "nairda", "oni", "tammara"],
|
||||
)
|
||||
def test_pc_sheet_loads(stem: str) -> None:
|
||||
"""Every transposed PC sheet loads through the strict monster JSON path."""
|
||||
combatant = load_monster(PCS_DIR / f"{stem}.json")
|
||||
assert combatant.attacks
|
||||
assert combatant.hp_max >= 1
|
||||
assert combatant.ac.total >= 10
|
||||
assert combatant.speed_land_ft >= 0
|
||||
|
||||
|
||||
def test_pc_sheets_golden_spots() -> None:
|
||||
esha = load_monster(PCS_DIR / "esha.json")
|
||||
assert esha.name == "Esha Randu"
|
||||
assert [a.name for a in esha.attacks] == [
|
||||
"Lance",
|
||||
"Composite Shortbow +3",
|
||||
"Earth Breaker",
|
||||
]
|
||||
assert esha.attacks[0].reach_ft == 10
|
||||
assert esha.attacks[1].range_increment_ft == 70
|
||||
|
||||
harvie = load_monster(PCS_DIR / "harvie.json")
|
||||
assert harvie.size == "Small"
|
||||
assert harvie.speed_fly_ft == 80
|
||||
|
||||
oni = load_monster(PCS_DIR / "oni.json")
|
||||
assert "Pioche" in oni.notes
|
||||
assert "Weapon" in oni.notes
|
||||
|
||||
tammara = load_monster(PCS_DIR / "tammara.json")
|
||||
assert tammara.initiative_mod == 7
|
||||
|
||||
|
||||
def _write(tmp_path: Path, payload: dict[str, object]) -> Path:
|
||||
|
||||
Reference in New Issue
Block a user