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 (PipBoy)
Gitea → 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.pyest 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
# 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 :
- PipBoy → Paramètres → STOP (attendre max 5 ticks)
- PipBoy → Paramètres → Reset Jour/Tick
- Relancer via terminal
Enrichissement lore
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_vstn'existe pas — c'estfallout_lore - 299 chunks avaient le champ
typeau lieu decategory— corrigé en juin 2026
Dashboard
- Le fichier actif est
/home/ubuntu/fallout-visu/app.py(monté Docker), pasdashboard/app.py - Toujours copier les deux après modification
Simulation
run.pyvé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)