232 lines
9.9 KiB
Markdown
232 lines
9.9 KiB
Markdown
# Fallout: Venice of Wasteland — Moteur de simulation JDR
|
||
|
||
Simulation autonome d'un univers **Fallout 2D20** situé en Louisiane post-nucléaire.
|
||
Le moteur simule des PNJ, des factions, des rencontres et une économie — sans MJ humain permanent.
|
||
Un LLM joue le rôle de MJ narrateur, un second LLM anime les PNJ.
|
||
|
||
**Dashboard** → [fallout.coyoteos.ovh](https://fallout.coyoteos.ovh) (PipBoy)
|
||
**Gitea** → [git.coyoteos.ovh](https://git.coyoteos.ovh) — repo `Corback/fallout-venice`
|
||
|
||
> ⚠️ Les informations de connexion (IPs, credentials, clés SSH) sont dans `INFRA_PRIVATE.md` (local uniquement, non commité).
|
||
|
||
---
|
||
|
||
## Architecture générale
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ AMPÈRE (Oracle ARM) │
|
||
│ │
|
||
│ ┌──────────────┐ ┌───────────────┐ ┌────────────┐ │
|
||
│ │ run.py S1 │ │ run.py S2 │ │ PipBoy │ │
|
||
│ │ (sim engine)│ │ (sim engine) │ │ Flask │ │
|
||
│ └──────┬───────┘ └───────┬───────┘ └─────┬──────┘ │
|
||
│ │ │ │ │
|
||
│ ┌──────▼───────────────────▼────────────────▼──────┐ │
|
||
│ │ Ollama (localhost:11434) │ │
|
||
│ │ qwen2.5:14b (MJ) + qwen2.5:7b (PNJ) │ │
|
||
│ └───────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ ChromaDB :8800 — collection fallout_lore │ │
|
||
│ │ 1403 chunks : règles 2D20, lore canon, ambiance │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
└────────────────────────┬────────────────────────────────┘
|
||
│ SSH tunnel :15432
|
||
┌────────────────────────▼────────────────────────────────┐
|
||
│ VIGILE (OVH) │
|
||
│ PostgreSQL — base "fallout" │
|
||
└─────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Stack technique
|
||
|
||
| Composant | Technologie | Détail |
|
||
|-----------|------------|--------|
|
||
| Moteur sim | Python 3.11 | `src/engine/` |
|
||
| Dashboard | Flask + Jinja2 | Docker `fallout-visu` |
|
||
| LLM MJ | qwen2.5:14b via Ollama | ~30s/réponse warm |
|
||
| LLM PNJ | qwen2.5:7b via Ollama | ~5s/réponse warm |
|
||
| Base de données | PostgreSQL 15 (Vigile) | SSH tunnel depuis Ampère |
|
||
| RAG | ChromaDB v1.0.0 (API v2) | collection `fallout_lore` |
|
||
| Proxy | nginx-proxy-manager | SSL Let's Encrypt auto |
|
||
| Gitea | git.coyoteos.ovh:2222 | repo Corback/fallout-venice |
|
||
|
||
---
|
||
|
||
## Structure du projet
|
||
|
||
```
|
||
fallout-venice/
|
||
├── src/
|
||
│ ├── engine/
|
||
│ │ ├── run.py # Lanceur principal (hot-reload config, status check loop)
|
||
│ │ ├── tick.py # Orchestration d'un tick
|
||
│ │ ├── encounter.py # Rencontres (safe zones, raids, commerce PNJ)
|
||
│ │ ├── combat_engine.py # Résolution combats 2D20
|
||
│ │ ├── sim_config.py # Chargement + deep-merge config JSON
|
||
│ │ ├── init_pnj.py # Initialisation PNJ en DB
|
||
│ │ ├── lore_enricher.py # Enrichissement lore via LLM + RAG Chroma
|
||
│ │ └── db.py # Accès PostgreSQL
|
||
│ ├── config/
|
||
│ │ ├── sim_001.json # Config session 1 (référence des 5 modes)
|
||
│ │ ├── sim_002.json # Config session 2
|
||
│ │ └── crash_results.json # Résultats derniers tests LLM (lu par PipBoy)
|
||
│ └── data/
|
||
│ └── encounter_tables.json # Tables rencontres, zones sûres, pools entités
|
||
├── dashboard/
|
||
│ └── app.py # Source PipBoy — copier dans /home/ubuntu/fallout-visu/
|
||
├── tools/
|
||
│ ├── llm_crash_test.py # Stress test LLM (modes: simultane/decale/solo)
|
||
│ └── capacity_test.py # Test capacité N joueurs simultanés
|
||
├── README.md
|
||
└── ROADMAP.md
|
||
```
|
||
|
||
> ⚠️ Le dashboard actif est `/home/ubuntu/fallout-visu/app.py` (monté dans Docker).
|
||
> `dashboard/app.py` est la source de vérité — toujours synchroniser les deux après modification.
|
||
|
||
---
|
||
|
||
## Système de PNJ — 4 tiers
|
||
|
||
| Tier | Label | Comportement | LLM actuel |
|
||
|------|-------|-------------|-----------|
|
||
| 0 | BOSS | Immortel, chef de faction | Non (prévu 14b) |
|
||
| 1 | ACTIFS SIM | Simulés chaque tick, mémoire persistante | Non (prévu 7b) |
|
||
| 2 | PNJ+ | Réagissent aux événements importants | Non (prévu 7b) |
|
||
| 3 | PASSAGE | Décor narratif | Jamais |
|
||
|
||
Actuellement tous les PNJ sont animés par le **moteur Python seul**.
|
||
Le LLM PNJ sera déclenché uniquement sur **interaction joueur directe** (Phase 5).
|
||
|
||
---
|
||
|
||
## Zones sûres
|
||
|
||
`independance` | `nola_vieux_carre` | `baton_rouge` | `laplace`
|
||
|
||
Règles : pas de rencontres lambda/groupe. Seuls les raids de faction (faible probabilité) et le commerce PNJ-à-PNJ sont possibles.
|
||
|
||
---
|
||
|
||
## Modes de simulation
|
||
|
||
Configurables depuis le PipBoy — prise en compte au **prochain jour** (hot-reload).
|
||
|
||
| Mode | Rencontres | Drain | Économie | Usage |
|
||
|------|-----------|-------|---------|-------|
|
||
| `pacifiste` | ×0.4 | ×0.7 | normal | Test/debug |
|
||
| `politique` | ×0.6 | ×1.0 | normal | Intrigues factions |
|
||
| `guerre_commerciale` | ×1.2 | ×1.5 | ×1.5 caps | Blocus, routes coupées |
|
||
| `guerre` | ×2.0 | ×1.8 | pénurie | Front de guerre actif |
|
||
| `survie_extreme` | ×1.8 | ×2.5 | ×0.3 | Stress test pur |
|
||
|
||
---
|
||
|
||
## ChromaDB — collection `fallout_lore`
|
||
|
||
**1403 chunks** — source de vérité en lecture seule.
|
||
|
||
| Catégorie | Chunks | Contenu |
|
||
|-----------|--------|---------|
|
||
| `regles_core` | ~934 | Règles 2D20 Fallout |
|
||
| `regles_supplement` | 279 | Suppléments et extensions |
|
||
| `lore_inspiration` | 86 | Inspiration univers Fallout |
|
||
| `ambiance` | 43 | Descriptions atmosphériques |
|
||
| `aventure` | 29 | Scénarios de référence |
|
||
| `lore_canon` | 32 | **Bible Venice of Wasteland v1.1 & v2.0** |
|
||
|
||
`fallout_lore_enriched` → reçoit les propositions lore **acceptées** depuis le PipBoy.
|
||
|
||
---
|
||
|
||
## Performances LLM mesurées (Ampère ARM)
|
||
|
||
| Joueurs simultanés | Tick complet | Actions/heure | Viable tick 10min |
|
||
|-------------------|-------------|---------------|-----------------|
|
||
| 1 | 35s | 103 | ✓ |
|
||
| 5 | 57s | 62 | ✓ |
|
||
| 10 | 1m17 | 46 | ✓ |
|
||
| 50 | 3m32 | 16 | ✓ (8 timeouts) |
|
||
|
||
**Plafond recommandé V1 : 10-15 joueurs actifs simultanés.**
|
||
|
||
---
|
||
|
||
## Lancement des simulations
|
||
|
||
```bash
|
||
# SSH sur Ampère (voir INFRA_PRIVATE.md pour la clé et l'IP)
|
||
cd /home/ubuntu/fallout-venice/src/engine
|
||
|
||
# Session 1
|
||
nohup env SESSION_ID=1 TICK_SLEEP_SEC=60 PYTHONUNBUFFERED=1 \
|
||
python3 -u run.py > ~/fallout_sim_s1.log 2>&1 &
|
||
|
||
# Session 2
|
||
nohup env SESSION_ID=2 TICK_SLEEP_SEC=60 PYTHONUNBUFFERED=1 \
|
||
python3 -u run.py > ~/fallout_sim_s2.log 2>&1 &
|
||
|
||
tail -f ~/fallout_sim_s1.log
|
||
```
|
||
|
||
**Reset propre d'une session :**
|
||
1. PipBoy → Paramètres → **STOP** (attendre max 5 ticks)
|
||
2. PipBoy → Paramètres → **Reset Jour/Tick**
|
||
3. Relancer via terminal
|
||
|
||
---
|
||
|
||
## Enrichissement lore
|
||
|
||
```bash
|
||
cd /home/ubuntu/fallout-venice/src/engine
|
||
|
||
python3 lore_enricher.py --faction grand_krewe # une faction
|
||
python3 lore_enricher.py --faction all # toutes
|
||
python3 lore_enricher.py --list-factions # liste
|
||
```
|
||
|
||
Valider les propositions → PipBoy onglet **ENRICHISSEMENT**
|
||
|
||
---
|
||
|
||
## Variables d'environnement clés
|
||
|
||
| Variable | Défaut | Description |
|
||
|----------|--------|-------------|
|
||
| `SESSION_ID` | 1 | Session simulée |
|
||
| `TICK_SLEEP_SEC` | 60 | Durée d'un tick (secondes) |
|
||
| `PYTHONUNBUFFERED` | — | `1` pour logs temps réel |
|
||
| `OLLAMA_URL` | `http://localhost:11434` | Endpoint Ollama |
|
||
| `MODEL_MJ` | `qwen2.5:14b` | Modèle MJ narrateur |
|
||
| `MODEL_PNJ` | `qwen2.5:7b` | Modèle animation PNJ |
|
||
| `DB_HOST` / `DB_PORT` | voir INFRA_PRIVATE.md | PostgreSQL via tunnel SSH |
|
||
|
||
---
|
||
|
||
## ⚠️ Points critiques — à ne jamais oublier
|
||
|
||
**ChromaDB**
|
||
- API v2 uniquement — `/api/v1/` retourne `{"error":"Unimplemented"}`
|
||
- La collection `fallout_vst` **n'existe pas** — c'est `fallout_lore`
|
||
- 299 chunks avaient le champ `type` au lieu de `category` — corrigé en juin 2026
|
||
|
||
**Dashboard**
|
||
- Le fichier actif est `/home/ubuntu/fallout-visu/app.py` (monté Docker), pas `dashboard/app.py`
|
||
- Toujours copier les deux après modification
|
||
|
||
**Simulation**
|
||
- `run.py` vérifie le statut DB toutes les **5 ticks** — STOP depuis PipBoy n'est pas instantané
|
||
- Hot-reload config JSON au **début de chaque jour** (tick 0), pas immédiatement
|
||
|
||
**Réseau Docker**
|
||
- Le container PipBoy accède à Ollama via `host.docker.internal:11434`
|
||
- Une règle iptables autorise le subnet Docker → port 11434. Voir INFRA_PRIVATE.md si disparaît après reboot.
|
||
|
||
**Infos de connexion**
|
||
- Voir `INFRA_PRIVATE.md` (local uniquement, dans `.gitignore`)
|