# Questions ouvertes — toutes sources confondues Liste consolidée de tout ce qui n'est **pas encore tranché**. Découpée en trois groupes : ce qui reste vraiment à décider, ce qui est **volontairement reporté** (décision de principe déjà prise de le traiter plus tard, pas un oubli), et ce qui a été **explicitement abandonné** (pour ne pas être reproposé plus tard sans savoir que c'est déjà passé en revue). > Les **valeurs numériques** non chiffrées ne sont plus listées ici : elles sont regroupées > dans [`valeurs.md`](valeurs.md), qui est la table de chiffrage du jeu. ## Décision ajoutée le 2026-09-06 - **Choix des modèles et bâtiments dans l’atelier : décidé et implémenté** (`pieces.md` §8). Catégories Unités/Bâtiments, catalogue par faction/rôle, version retenue et historique. L’œil donne un aperçu 3D direct, avec lecture complète du mouvement choisi, pause, ralenti, progression et répétition facultative. Les paquets animés complets peuvent désormais être activés pour les nouvelles parties ; les douze unités et vingt bâtiments sont raccordés. Les bâtiments ont leur paquet statique contrôlé, leur échelle uniforme adaptée à l’emprise et une révélation progressive du chantier sans déformation (§4 et §8). - **Pièces importées en jeu : autorisées** (`pieces.md` §2 et §6), à la demande d’intégrer le démon animé. Sources et paquets conservés, contrôle des animations distinct du coût d’affichage. Mode d’essai détaillé explicite ; optimisation pour une armée et une ville, zone de couleur d’équipe peinte et nœuds animés des moulins restent à réaliser. - **Chargement progressif des pièces : décidé** (`pieces.md` §8), après le blocage au téléchargement des 32 modèles. Le manifeste reste figé par partie ; les paquets arrivent à la demande. Le provisoire n’empêche ni les ordres ni la simulation, et son remplacement respecte l’état visuel courant. - **Taille et géographie des références du monde : décidées le 2026-09-06** (`monde.md`) — 288×288 cellules par territoire, 25 bases distinctes tirées d'un paysage continu. À sa demande suivante, les bases sont copiées dans les quatre factions : 100 cartes actives avec le même relief, sans spécialisation des gisements pour l'instant. Atlas interactif et parties utilisent ces documents. Relief v3 adouci après le nouveau retour : plaines ondulées, massifs courbés et espacés, piémonts, cols et volcan plus bas ; suppression des parois et du bruit de relief répété de la v2. Ressources réduites en huit petites poches de pierre et douze bosquets d’expansion, en plus du bois de départ ; roche nue distincte du gisement. L’équilibrage des durées et de cette nouvelle répartition reste à mesurer. ## À trancher - **Atlas de texture partagé pour les pièces ?** (`pieces.md` §6) — la couleur par sommet plafonne le détail. Un atlas unique pour tout le jeu ne coûterait ni appel de dessin ni shader de plus. Le modèle importé du 2026-08-13 (planche « Modèle importé (.glb) ») arrive justement avec une texture UV unique et rend mieux : l'argument est là, la décision reste à prendre — notamment sur la façon de produire l'atlas sans asset externe. - **Outils fondus dans la peau, ou objets rapportés sur une ancre ?** (`pieces.md` §9) — un ouvrier tient son outil ; faut-il le fondre dans la peau (ce qu'on fait aujourd'hui, lié à l'os de la main) ou poser des poses génériques et y accrocher pioche/hache/seau ? Piste actuelle : mutualiser la **source** des outils (une fonction `pic()` appelée par toutes les races), fondre la **fusion** — et réserver le nœud rapporté à la **charge transportée**, qui varie en cours de partie. Depuis le passage au squelette, la fusion n'a plus lieu qu'**une fois** par créature et non dans chacune des dix poses : la question est moins chère. - **Bâtiment ou technologie qui recharge le « seau »** (`terraformation.md`) — le principe est acté (pas de temporisateur, quelque chose à débloquer), le *quoi* ne l'est pas. *Une version du code avait tranché pour le bâtiment d'énergie ; ça n'avait jamais été décidé au design, et c'est retiré.* - **Rendre l'obsidienne moins rare** — le modèle actuel (une seule source par carte) fait qu'une partie sans joueur Homme ni Démon n'en produit aucune. C'est **accepté en l'état, le gameplay ne change pas** ; reste à imaginer, plus tard, une autre façon d'en créer ou d'en trouver. *(`terraformation.md`)* - **Existence des remparts** — le tracé libre est abandonné (voir plus bas). Reste à décider s'il faut malgré tout un bâtiment de fortification à empreinte fixe, ou si creuser suffit comme geste défensif. *(`economie.md`)* - **Franchissement de la lave** — pour l'instant infranchissable (`valeurs.md`), et c'est ce que le pathfinding implémente. Elle infligerait peut-être mieux des dégâts qu'un blocage pur : à rejuger en playtest. **Ce n'est plus bloquant pour personne** : le coût de passage est branché sur `LAVA_IMPASSABLE`, changer d'avis ne coûtera qu'une valeur. · Tranché au passage : on peut toujours **sortir** d'une cellule de lave, sinon une unité rattrapée par une coulée serait murée sur place. - **Nombre de champs de flux vivants** (`MAX_FLOW_FIELDS`, `valeurs.md`) — 24 pour l'instant. Au-delà, les unités surnuméraires se guident à vue : elles respectent les falaises mais ne contournent plus un grand obstacle. À rejuger si des parties à 4 joueurs très morcelées le montrent. *(`architecture.md` §6)* ## Volontairement reportées à plus tard Décision explicite : ces points seront tranchés plus tard (playtest, session dédiée), ce ne sont pas des oublis. - **Contre-unités** (« la lance bat le cavalier ») et **noms définitifs** des unités — réservés à une session dédiée aux unités. *(`economie.md`, `combat.md`)* · Ce qui est **fixé depuis le contrat de pièces** (`client/pieces/`) : les **emplacements** existent et sont nommés — un `worker`, un `melee`, un `ranged` et cinq bâtiments par race, identifiants `_`, avec leur silhouette provisoire et leur échelle (`valeurs.md`). · Ce qui est **chiffré depuis** (🟡, à ajuster en playtest) : **PV et coûts** par l'Agent 4, **vitesses** par l'Agent 3, **dégâts, portée et cadence** par l'Agent 7 — table complète dans `valeurs.md` § « Unités et combat ». Il ne reste donc plus, ici, que les contre-unités et les noms. · Tranché au passage : **il n'y a aucune table de contre-unités**, et les deux seuls modificateurs de dégâts sont le **bonus de hauteur** et le **bonus contre les bâtiments**. Mêmes nombres pour les 4 races : la faction change la silhouette, pas les statistiques. · 2026-09-06 : le joueur demande une famille visuelle complète depuis les ouvriers approuvés. `?planches=unites-factions` propose huit combattants et conserve les quatre ouvriers. Noms et armes proposés ne créent aucune classe ni statistique ; le joueur valide ensuite les combattants et demande leurs animations et leur mise en jeu. Les douze unités sont activées le même jour. - **Optimisation des formes détaillées en jeu** — le gréement et le raccord des quatre ouvriers et des huit combattants sont livrés et activés sur demande du joueur le 2026-09-06. Restent le budget d’une armée, l’optimisation fidèle des détails et le masque peint de couleur d’équipe. Chaque rôle garde son repli indépendant. *(`pieces.md` §6 et §8)* - **🔴 La partie qui ne finit jamais — CHIFFRÉE le 2026-08-16, et c'est pire qu'on ne le pensait.** Ce n'était plus une crainte théorique : **150 parties IA contre IA**, 96², variantes réparties sur les 4 races, plafond d'**une heure de jeu** — | | | |---|---| | **terminées** | **43 / 150 (29 %)**, toutes par élimination | | **atteignent le plafond sans vainqueur** | **107 / 150 (71 %)** | | par **Monument** | **0** | | durée de celles qui finissent | médiane **10 min 31 s** (quartiles 8 min 52 – 12 min 01) | **Sept parties sur dix ne se terminent pas.** Ce nombre ne clôt pas la question — il la chiffre, et c'est le premier qu'on ait. 🔴 **ET LA MOITIÉ DE CE PROBLÈME EST DANS LES RÈGLES, PAS DANS L'IA** (mesuré le 2026-08-16). Sur 24 parties à 4 joueurs, 9 n'aboutissent pas — et **5 de ces 9 (56 %) sont déjà DÉCIDÉES** : un camp encore officiellement en jeu, **sans un seul soldat et sans un seul bâtiment capable d'en produire**. La partie ne peut plus basculer ; elle ne peut simplement pas **se conclure**. La cause est dans `sim/victory.ts#holdsGround` — `unitCount > 0 || buildingCount > 0`, **sans aucune notion de « capable de produire »**, alors que `combat.md` promet « tant qu'il lui reste de quoi produire ». **Un ouvrier caché dans le brouillard garde un joueur en jeu indéfiniment**, et le vainqueur doit le retrouver sur 9 216 cellules. **La question n'est donc pas « faut-il éliminer plus vite » mais « qu'est-ce qui tient un joueur en jeu ».** Trois sorties, aucune tranchée : compter la **capacité de production** plutôt que la simple présence ; une **reddition** (automatique ou offerte) ; ou une **limite de durée** avec départage. La troisième est la seule qui ferme aussi le cas du joueur inatteignable ci-dessous. ✅ **Et une bonne nouvelle mesurée le même jour : la coupure de terrain N'ARRIVE PAS en partie réelle.** Relevé de connexité entre bases toutes les 300 ticks, sur `stepAllowed` : **0 coupure sur 104 parties** (40 à deux joueurs, 64 à quatre, 96²). ⚠️ Ça dit que **ça n'arrive pas**, pas que **c'est impossible** — aucune IA n'essaie. Voir l'entrée suivante. 🔴 **Le Monument ne fait PAS finir les parties — l'A/B l'a réfuté** (2026-08-16, 40 graines, mêmes factions, une seule variable) : | | terminées | par Monument | médiane | |---|---|---|---| | sans Monument | 22/40 (55 %) | 0 | 10 min 42 s | | avec Monument | 25/40 (63 %) | **13** | 11 min 33 s | **z = 0,68 — l'écart ne tient pas.** ⚠️ Le « 32 % → 63 % » annoncé quelques heures plus tôt était **confondu** (graines et code changés ensemble) ; son auteur l'avait signalé comme tel, et l'A/B propre l'a réfuté. La prédiction écrite avant le code **est fausse**, et c'est un bon résultat : elle était réfutable, et elle a été réfutée. **Ce qui est réel : 0 → 13 victoires par Monument, à taux de conclusion constant.** Et le mécanisme est daté — le Monument est posé **1 930 à 6 400 ticks après que le perdant a perdu son dernier soldat**. > **Le Monument n'est donc pas une seconde voie de victoire concurrente de la voie militaire : > c'est la façon dont le vainqueur militaire CLÔT une partie que `holdsGround` refuse de > terminer.** Les 13 sont exactement la population des « décidées mais pas terminées ». ⚠️ **Ne présente donc jamais « 93 % des victoires sont par Monument » comme un déplacement de la voie militaire** — les deux ne sont pas en concurrence, la seconde répare ce que la première ne peut pas conclure. Et ça **renforce** le point ci-dessus : le vrai défaut est bien dans la condition d'élimination, pas dans l'appétit des joueurs pour le Monument. ⚠️ Un troisième bras (l'IA répond militairement à un Monument ennemi) a rendu **des hachages identiques sur les 40 graines** : ce code ne s'exécute **jamais**, faute de Monument ennemi visible tant que l'adversaire est vivant. *Un hachage identique n'est pas « l'effet est petit », c'est « rien n'a changé ».* ⚠️ **Trois garde-fous, à citer avec le chiffre.** (1) C'est mesuré **contre cette IA-là**, qui ne joue ni la spécialité énergie ni le bonus de ferme (mesuré par C2 : énergie finale 80 pour les quatre races, 0 ferme bonifiée sur 7) — un adversaire qui joue mieux finirait peut-être. (2) **`abandon` est hors de portée de ce banc** : il n'y a ni réseau ni déconnexion, donc « 0 abandon » n'est pas un résultat. (3) N = 150 et non 300, faute de temps machine — IC 95 % de ±5,7 points, ce qui suffit à départager « la moitié » de « la quasi-totalité ». ⚠️ Et **ce n'est plus seulement un choix des joueurs** : on sait depuis le même jour qu'un joueur peut se rendre **inatteignable** pour ~24 coups de pelle — voir l'entrée suivante. *(`combat.md`, `sim/victory.ts`, `server/match.ts`)* - **❓ L'emplacement 0 gagne toutes les égalités** — et c'est **structurel**, pas un réglage. Vérifié dans le code le 2026-08-16, deux mécanismes qui vont dans le même sens : · `compareOrders` (`sim/orders.ts`) trie sur `(tick, player, seq)` — **à tick égal, le plus petit emplacement passe d'abord** ; · `createMatchWorld` crée les joueurs par emplacement croissant, donc les entités de l'emplacement 0 portent **les index les plus bas** — et tous les systèmes parcourent les entités dans l'ordre des index. **Ce n'est pas un bug** : le tri total des ordres est une **exigence de déterminisme** (`architecture.md` §3), il doit être identique sur toutes les machines, et n'importe quel départage convient tant qu'il est total. La question est qu'il **va toujours au même joueur**. Mesuré par l'arène : **28 victoires sur 38 pour l'emplacement 0** (74 %, P = 0,0026), à race et à case identiques. ⚠️ **Le garde-fou doit voyager avec le chiffre**, et il est de C8 : deux IA identiques à la même cadence décident **exactement aux mêmes ticks**, donc sont à égalité en permanence. **Deux humains ne le seraient jamais.** Le dispositif *maximise* l'effet ; les 74 % ne se transposent pas. Ce qui se transpose, c'est que **le départage est systématique et va toujours au même siège**. 🔴 **La mesure a été faite le 2026-08-16, et elle désigne le SECOND mécanisme, pas le premier.** Deux IA de même race et même difficulté, cadences **10 et 11** — elles ne coïncident plus qu'un tick sur 110 au lieu d'un sur un —, jouées dans les deux sens : | | emplacement 0 | |---|---| | référence, simultané | **68 %** | | cadences brisées, cumulé | **66 %** (25/38, P = 0,037) | **L'effet ne bouge quasiment pas, et l'emplacement 0 gagne même quand il décide 10 % MOINS souvent que son adversaire.** Ce n'est donc **pas** le tri des ordres : si c'était `compareOrders`, l'effet se serait effondré en passant d'une égalité permanente à une égalité tous les 110 ticks. **C'est l'ordre d'itération des entités**, et c'est beaucoup plus cher à corriger. Vérifié : **onze boucles `0 → entityTop`** dans `combat.ts` (1), `economy.ts` (1), `move.ts` (5) et `buildings.ts` (4). Les entités de l'emplacement 0 étant créées en premier, elles portent les index les plus bas et **agissent avant celles de l'adversaire à chaque tick, dans chaque système** — ce qui ne dépend d'aucune égalité, donc ne pouvait pas disparaître avec la simultanéité. **Rien n'est décidé, et `sim/` n'est pas touché.** L'ordre d'itération des entités est la clé de voûte du déterminisme (`architecture.md` §4) ; y toucher demanderait un ordre tournant dérivé de la graine du match, appliqué aux onze boucles, et coûterait le hachage de rejeu et tous les instantanés de référence. **Ce n'est pas le sujet le plus urgent** : 71 % des parties ne finissent pas, ce qui pèse plus lourd que 66 contre 34. ⚠️ **Deux réserves, de C8 lui-même** : son bras à cadences 10/11 confond encore « briser la simultanéité » et « changer la vitesse » (10 % de décisions en plus) — les deux sens le rendent lisible puisque **le lent gagne aussi**, mais un bras 11/11 serait plus propre et n'a pas été fait ; et 38 parties décisives à P = 0,037, **c'est significatif, ce n'est pas écrasant**. ⚠️ **Une troisième cause existait, dans le jeu réel et pas dans le banc** : le pilote d'IA posait `phase = slot % periodeTicks`, donc l'emplacement 0 décidait **un tick avant, à chaque période, sur 200 graines sur 200**. Corrigée par C2 le 2026-08-16 (phase tirée de `(graine, emplacement)`, 43 % au lieu de 100 %). **Le banc était propre ; c'est la partie jouée qui était pire.** ⚠️ **Et l'enjeu n'est pas que sportif** : une partie décide de la possession d'une case du monde partagé (`monde.md`). Un biais systématique de siège est un biais sur la carte du monde. Ouverte le 2026-08-16. *(`architecture.md` §3, `sim/orders.ts`, `shared/protocol.ts`)* - **❓ Un joueur qu'on ne peut plus atteindre** — le terrain se creuse, donc un joueur peut se retrancher derrière une douve qui n'a plus d'entrée : **24 cellules de pelle en médiane à 96×96** (coupe minimale de sommets, mesurée le 2026-08-16 sur 25 cartes, sur le vrai graphe de `stepAllowed`), **une seule** sur les cartes qui portent un goulet. Il n'est alors ni éliminable (`combat.md` : plus aucune unité *et* plus aucun bâtiment) ni contestable, et **rien ne termine la partie** — `Match.checkEnd` (`server/match.ts`) n'a ni limite de ticks ni horloge, la seule du dépôt appartient à l'arène IA. Ça contredit deux promesses déjà écrites : `combat.md` (« un Monument invulnérable […] rendrait la victoire par Monument **imparable**, ce que ce fichier interdit ») et le chiffrage du Monument dans `valeurs.md` (« assez tard pour que l'adversaire ait le temps de venir le renverser »). ⚠️ **La réponse ne se cherche pas du côté du terrain**, et c'est le résultat le plus utile de l'instruction. Interdire de creuser là où ça couperait demanderait un contrôle de connexité que le joueur **ne peut pas voir** (mesuré : le mur se rouvre d'un seul coup de pelle dans 13 cas sur 13, mais seules 5 à 9 cellules sur ~3 100 le permettent, la plus proche à **28 cellules du mur en médiane**, sous le brouillard) ; ça renverserait quatre décisions ✅ — la douve qui bloque, la douve qui coupe une armée, l'empreinte qui bloque le passage, l'abandon des remparts — et **ça ne fermerait rien**, les 24 cellules restant creusables une à une. Ce qui manque est une **condition de fin de partie**. À mesurer d'abord dans l'arène : combien de parties atteignent la limite sans vainqueur, et un pilote qui s'emmure volontairement gagne-t-il ? Ouverte le 2026-08-16. *(`combat.md`, `sim/victory.ts`, `server/match.ts`)* - **Obsidienne comme méga-ressource** pour fabriquer des super-unités — idée retenue, à concevoir plus tard. *(`terraformation.md`)* - **Simulation dans un Web Worker** côté client — reporté au profilage, voir `architecture.md`. Le thread principal suffit au départ. - **Cap de population / limite d'unités** — non abordé. - **Usage de la monnaie meta** (XP / argent) — on accumule, on ne dépense pas encore. Le chiffrage du pillage est posé (100 XP / 50 pièces, × 1,5 en raid) et n'engage à rien tant que rien ne se dépense. *(`progression.md`)* - **Mode spectateur et rejeu en jeu** — le journal d'ordres de chaque match est conservé et rejouable (vérifié en test), mais aucune interface ne s'en sert. *(`architecture.md` §9)* - **La partie qui ne finit jamais, vue du serveur** — le serveur ne clôt une instance que si la simulation déclare un vainqueur ou s'il ne reste au plus qu'un joueur non éliminé. Deux joueurs retranchés bloquent donc bien une case, comme annoncé dans `combat.md`. - **Équipes fixes (2v2)** — le MVP est en chacun pour soi. *(`matchmaking.md`)* ## Tranchées depuis (pour mémoire) - **Direction des fantassins de la reprise** — ✅ retour explicite du joueur, **2026-09-06** : personnages de jeu vidéo stylisés et vivants, plutôt que vraies figurines de bois. Joues rapportées et gardes droites rejetées ; davantage de finesse géométrique, appuis fléchis, bustes tournés et mouvement. Le terrain boisé est conservé (`pieces.md` §1). Cela fixe une direction, pas une validation des propositions de modèles ni une modification des budgets du moteur. Le même jour, le joueur choisit l’ouvrier démon généré comme référence de qualité pour la reprise : anatomie et détails reconnaissables, au-delà du nombre de polygones. Après rejet du résultat procédural, il autorise explicitement un essai imagegen puis API 3D, avec brut et retouché comparables sur la même planche. Le choix final du modèle pour le combat reste ouvert ; le budget moteur et le besoin de gréement ne changent pas. Le joueur apprécie l’essai Trellis 2 puis demande une comparaison de la même image dans Trellis 1, brut et retouché sur la même planche. Le 2026-09-06, les images des ouvriers elfe, nain et humain sont validées : le joueur autorise Trellis 2 et les retouches, puis demande les quatre ouvriers réunis avec son démon existant. La planche sert à leur examen ; budgets moteur, apprêt et gréement restent applicables avant intégration au jeu. Le joueur apprécie cette famille puis demande de refaire aussi le démon ouvrier dans Trellis 2 et d’animer les quatre. L’atelier les présente sur quatre planches, avec les dix clés du contrat et leurs lectures interpolées : repos, marche, récolte, construction, mort. Cela autorise cette préparation et cet examen ; le raccord au moteur et le budget de production restent distincts. Retour suivant du joueur : les surfaces animées doivent conserver la propreté des modèles fixes, y compris au repos. La simplification visible qui introduisait des facettes parasites est retirée des quatre planches ; le budget moteur reste distinct. - **Ce que couvre la garantie de connexité** — ✅ **le tick 0, et rien d'autre.** Tranché le 2026-08-16 après instruction mesurée. La carte engendrée ne coupe jamais un joueur (0 sur 400 cartes, 4 tailles) ; ce que les joueurs creusent ensuite a le droit de couper. **Ni interdiction côté fluide, ni élargissement des cols** — les trois termes de la crainte d'origine (« un seul seau de lave emmure définitivement ») sont faux, et chacun a été réfuté sur les 159 cellules fatales relevées : · **le seau n'est pas le vecteur** — on ne verse que dans un **lit** (`pourAllowed`), et **0 goulet sur 159** en est un à la génération : il faut toujours creuser d'abord ; · **le seau d'eau ne mure rien** — l'eau est franchissable, seule la lave bloque. Le seau n'ajoute donc des cas que chez les **Démons** ; · **un mur de lave n'est pas de l'obsidienne** — celle-ci exige que les **deux** fluides se rencontrent, donc rien n'est « définitif » ; · **et il n'y a pas besoin de goulet** : se couper soi-même coûte **24 cellules de pelle** en médiane à 96×96, sans aucun seau, pour les quatre races. Le goulet n'est que le cas à *une* cellule d'une capacité que `terraformation.md` **enseigne**. ⚠️ Ce qui reste ouvert n'est donc pas le terrain mais la **fin de partie** — voir « Un joueur qu'on ne peut plus atteindre » plus haut. *(`monde.md`, `terraformation.md`, `valeurs.md`)* - **Poses cuites ou vrai squelette ?** — ✅ **VRAI SQUELETTE** (voie C), tranché le 2026-08-13. Une créature livre **une géométrie et un squelette** ; une pose est une liste d'angles d'os, et le moteur **interpole** entre deux poses. C'est un **renversement** : `pieces.md` §2 disait l'inverse, et le disait depuis une décision prise **avant qu'aucune pièce ait un squelette**. · Ce que sont devenues ses trois raisons : « **la peau reste fermée** » ❌ **fausse** — un habillage déplace des sommets, il ne change pas la topologie (mesuré : 20 poses sur 20 sans une arête de bord) ; « **ça s'instancie** » ✅ **vraie, et c'est le prix à payer** — le `SkinnedMesh` de three.js ne s'instancie pas, il faudra écrire un **habillage instancié** (texture d'os + attribut d'instance), qui reste à faire ; « **c'est la bonne matière** » — **arbitrage du joueur, il veut du fluide**. · Ce qui a emporté la décision, en poids téléchargé : une pose pèse **324 octets** d'angles contre **63 Ko** de géométrie cuite (**×199**) ; **~200 Ko** livrés par créature contre 700 Ko à 1,6 Mo ; à 100 types d'unités, **~17 Mo** contre ~90 Mo. · ⚠️ Coût caché à ne pas oublier : le **recalage au sol par pose** (4 octets, calculé à l'apprêt). Sans lui, une bête qui meurt s'enfonce de **49 cm** dans le sol. · ⚠️ Vocabulaire : ce qui est abandonné, c'est la **cuisson des POSES**. **L'apprêt du modèle** (échelle, origine, décimation, texture, étanchéité) reste, et compte davantage qu'avant puisqu'il n'y a plus qu'une géométrie. *(`pieces.md` §2, `mockups/rig.js`, planches `glb-pantin` / `glb-rig` / `glb-skin` de l'atelier)* - **Brouillard de guerre** — ✅ **il y en a un, et il est écrit** (2026-08-12). Trois états (inexploré / souvenir / en vue), rayons de vision chiffrés dans `valeurs.md` § « Vision », et **le ciblage suit la vision** : on n'acquiert et on n'attaque que ce qu'on voit. `sim/world.ts` a été rouvert pour deux champs — `terrain.explored` (cumulatif, donc de l'état) et `ent.sight` — tandis que « en vue en ce moment » reste du **dérivé**. La limite est connue et assumée : la simulation étant répliquée, **ce brouillard est cosmétique** (un client modifié voit tout), exactement comme dans tous les STR à simulation répliquée. *(`brouillard.md`, `sim/vision.ts`)* · Reste ouvert, et c'est de l'affichage seul : **le relief sous le voile du souvenir est le relief courant**, pas celui qu'on a laissé ; et **un bâtiment vu de mémoire est affiché à pleine lumière** au lieu d'être terni. - **Un chantier est-il attaquable ?** — ✅ **oui**. `placeBuilding` pose `ENT_UNTARGETABLE` sur un chantier ; le combat lit ce drapeau comme « **pas encore dans le monde** » (une unité en cours de production), pas comme « invulnérable ». Un chantier occupe le sol et ses PV montent avec l'avancement — et le laisser intouchable rendrait la **victoire par Monument imparable**, ce que `combat.md` interdit. *(`combat.md`, `sim/combat.ts`)* - **Un ordre de déplacement rend-il agressif ?** — ✅ **non**, seul l'ordre d'attaque engage, et une unité militaire **au repos** acquiert d'elle-même. Une armée en marche traverse donc une ligne ennemie sans se faire happer ; c'est le comportement d'un Age of Empires. *(`combat.md`)* - **Abandon et victoire militaire** — ✅ **une seule issue : un abandon est une victoire militaire.** Le partant est éliminé sur-le-champ et ce qu'il laisse sur la carte cesse de compter ; s'il ne reste qu'un joueur, `sim/victory.ts` déclare `WonByElimination` au même tick et la case change de main comme après n'importe quelle conquête. *(Une version antérieure distinguait `abandon` et `elimination` et refusait la conquête tant que la base du partant tenait debout : c'est annulé. Le chemin `victory: abandon` du serveur n'est plus qu'un garde-fou de processus.)* *(`combat.md`, `architecture.md` §8)* - **Modèle réseau** — ✅ **serveur autoritaire exécutant une simulation déterministe à tick fixe (10 Hz), avec relais des ordres** aux clients, qui rejouent la même simulation. Conséquence structurante : arithmétique en **virgule fixe**, aucune donnée de simulation en flottant. Détail dans `architecture.md`. - **Pile technique** — ✅ **TypeScript sur Bun**, Three.js pour le rendu, `bun:sqlite` pour la persistance, HUD en DOM sans framework. Détail dans `architecture.md` §2. - **Pathfinding** — ✅ **champs de flux par destination**, recalculés par chunk quand le terrain change, **écrit et livré** (`sim/path.ts`, `sim/move.ts`). La réparation incrémentale rend bit à bit le champ d'un recalcul complet — sans quoi un client passé par un instantané divergerait. Détail dans `architecture.md` §6. - **Pente maximale franchissable** — ✅ **1 niveau** entre cellules voisines ; 2 niveaux ou plus forment une falaise. D'où *creuser une fois ralentit, creuser deux fois bloque*. Valeur de départ, révisable — `terraformation.md` et `valeurs.md`. - **Ce qui persiste d'un match au suivant** — ✅ **le Monument, et lui seul.** Trous, canaux, obsidienne, bâtiments et ruines disparaissent ; la case repart de sa variante propre. La mémoire du monde est dans la possession des cases et les Monuments, pas dans le terrain. *(`architecture.md` §9)* - **Persistance** — ✅ une carte est stockée comme une **graine de génération + des deltas**, jamais comme un terrain complet. Le **journal d'ordres** de chaque match est conservé, ce qui donne le rejeu et le mode spectateur gratuitement. Détail dans `architecture.md` §9. - **Comptes et sessions** — ✅ pseudo + mot de passe en **argon2id** (`Bun.password`), session par **cookie signé** (HMAC-SHA256), sans table de sessions. Pas d'OAuth, pas de dépendance de crypto. *(`architecture.md` §8)* - **Choix de faction et démarrage d'une partie** — ✅ chacun choisit sa faction, doublons autorisés, pas de bouton « prêt » : la partie démarre dès que le dernier siège est pris. *(`matchmaking.md`)* - **Variante active de la case neutre** — ✅ celle des Hommes, pour qu'elle ait de l'eau et non de la lave. *(`monde.md`)* - **Lissage du terrain contre lisibilité d'un trou** — ✅ **lissage sélectif**. On ne lisse pas la même chose de la même façon : le relief naturel généreusement (aucune case visible), les falaises de 2 niveaux beaucoup moins (elles doivent se lire comme infranchissables), **le creusage du joueur pas du tout** (arête franche sur un tiers de cellule) — plus deux signaux de shader, terre fraîche non peinte et ombre portée. Un trou d'une cellule se voit à 70 unités de recul, vérifié sur capture. Conséquence assumée : une saignée en diagonale montre ses cellules, et c'est voulu — le joueur doit lire quelles cellules sont creusées. *(`terrain.md` §5)* - **Comment on voit où récolter, si le terrain n'a pas le droit de montrer une case** — ✅ **par des pièces posées dessus, et seulement sur les gisements** : un arbre sur chaque `Surface.Forest` à `resource > 0`, un rocher sur chaque `Surface.Rock` à `resource > 0`, **rien ailleurs** (le massif nain a 2 200 cellules de roche et 250 de carrière : seules les 250 en portent). Un gisement épuisé perd sa pièce dans la même image. Aucun décor d'ambiance : une pièce qui ne veut rien dire, le joueur apprend à ne plus la regarder. Le décentrage dans la cellule reste sous une demi-cellule (le pied ne sort jamais de la cellule désignée) sans descendre vers zéro (sinon la forêt devient un damier) : **0,32**. *(`terrain.md` §5 bis, `client/render/props.js`)* - **Modèle de terrain** — ✅ **une seule couche**. Le relief visible est le relief simulé ; creuser abaisse une cellule d'un niveau et en fait un lit ; les fluides descendent et ne remontent jamais. Remplace le modèle de profondeur binaire 0 / -1. *(`terraformation.md`)* - **Vitesse de propagation d'un fluide** — ✅ **une cellule tous les 2 ticks**, comptée en ticks entiers. *(`terraformation.md`, `valeurs.md`)* - **Ce que « volume fini » veut dire pour le seau** — ✅ le versement **mouille d'un coup** jusqu'à `BUCKET_CELLS` cellules de lit sans remonter la pente, et la poche obéit ensuite à la gravité. La différence avec la source n'est pas une quantité qui s'épuise, c'est qu'il n'y a **plus rien derrière**. *(`terraformation.md`)* - **Ce qui n'est pas creusable** — ✅ le critère est le **gisement** (`resource` non nul), pas la surface : une roche nue se creuse, une carrière non. Sans quoi le massif nain serait le seul terrain du jeu où les Nains ne pourraient pas terraformer. *(`terraformation.md`)* - **L'obsidienne est-elle franchissable** — ✅ **non**, et elle n'est plus un lit : elle bouche définitivement le canal qui l'a fait naître. *(`terraformation.md`)* - **Génération de carte** — ✅ quatre quadrants, deux lits creusés, une vasque centrale plus basse que les deux bouches, quatre départs aux coins. Entièrement déterministe et en entiers. *(`monde.md`)* - **Ce qu'un départ doit avoir à portée** — ✅ **du bois et de la pierre à 8 cellules ou moins**, à pied. Les biomes sont par quadrant : aucun choix de position ne peut donner les deux aux Hommes ni aux Démons, puisqu'il n'y a chez eux ni forêt ni roche. La génération **pose** donc ce qui manque autour de la base retenue, plutôt que de déplacer la base vers ce qui n'existe pas. Sans cette garantie, la victoire par Monument était intestable. *(`monde.md`, `valeurs.md`)* - **Ce que la génération garantit, et ce qu'elle refuse** — ✅ elle **garantit** quatre bases posables (au besoin en terrassant), reliées entre elles (au besoin en taillant un col), et pourvues ; elle **refuse** explicitement une carte de moins de 32 cellules de côté. Une carte injouable rendue en silence a coûté au chantier des mois de tests serveur sur des mondes vides. *(`monde.md`, `valeurs.md`)* - **Charge utile des événements** — ✅ documentée par émetteur dans `architecture.md` §6 ; les quatre événements de terraformation y sont. *(dette levée)* - **Conditions d'élimination et déconnexion** — ✅ dernier debout ; un joueur est éliminé quand il n'a plus ni unité ni bâtiment ; 2 minutes pour se reconnecter avant défaite par abandon. *(`combat.md`)* - **Chiffrages d'équilibrage** — ✅ regroupés dans `valeurs.md`, destinés à vivre à terme dans une table en base de données. Le bloc **économie** (récolte, coûts, chantiers, production, spécialisations) y est chiffré depuis l'Agent 4 ; il reste 🟡, donc à éprouver en playtest, mais plus rien n'y est ❓. - **Comment se gagnent la nourriture et l'énergie** — ✅ **la ferme et le bâtiment d'énergie les produisent seuls**, sans personne dessus, à cadence régulière une fois terminés. Les gisements (forêt, carrière) restent le domaine des ouvriers : deux façons de gagner une ressource, et deux seulement. *(Une version du code en avait fait des « sites de travail » où l'ouvrier venait produire ; c'était un raccourci d'écriture, jamais une décision de design, et c'est abandonné.)* *(`economie.md`, `valeurs.md`)* ## Explicitement abandonnées Propositions reconsidérées puis écartées — pour mémoire, à ne pas reproposer sans savoir qu'elles ont déjà été tranchées. - **Remparts tracés à la main** — abandonné. Le geste (dessiner librement une ligne de défense que les ouvriers viennent bâtir) était le plus coûteux à implémenter de tout le jeu pour un apport jugé faible. **Creuser** devient le geste défensif du jeu. *(`economie.md`)* - **La ferme et le bâtiment d'énergie comme « sites de travail »** — abandonné. On y envoyait un ouvrier produire par cycle, comme sur une forêt, avec un nombre de places par site. C'était une décision prise à l'écriture du code pour n'avoir qu'une boucle d'ouvrier à équilibrer, jamais une décision de design : elle effaçait la seule vraie asymétrie de l'économie. **Un bâtiment de production produit seul.** *(`economie.md`, `valeurs.md`)* - **Le bâtiment d'énergie comme rechargeur de seau** — abandonné pour la même raison : le code avait tranché, le design non. La question est **rouverte**, voir « À trancher » plus haut. *(`factions.md`, `terraformation.md`)* - **Entropie inverse** (tick d'érosion/régénération du monde entre les parties) — abandonnée : le système des 4 variantes figées par case (`monde.md`) répond déjà au problème du monde qui se dégrade sans force de réparation, et cumuler les deux mécanismes rendrait l'équilibrage illisible. - **Cycle de dépendance entre races** (chaque race dépend d'une ressource qui n'est pas la sienne) — abandonné : la spécialisation économique + les bonus de terrain (`factions.md`) suffisent pour l'instant. - **Granularité en escouades** (~8 unités par bannière plutôt qu'individuelles) — abandonnée : les unités restent individuelles, cohérent avec la référence Age of Empires classique (`economie.md`). - **Profondeur binaire 0 / -1 sur terrain plat** — remplacée par le modèle à une seule couche (`terraformation.md`), qui garde le relief et le rend jouable. - **Automate cellulaire de fluide continu** (concept d'origine) — trop coûteux, remplacé par l'écoulement gravitaire de cellule à cellule.