Écrit par GuillaumeTechnoProjet Deep Core
Deep Core, partie 1 : d'un prototype HTML à LÖVE
D'où vient mon jeu incrémental de minage : un prototype d'une seule page, un portage en Lua vérifié chiffre par chiffre, et les premiers changements qui sont allés plus loin.

Deep Core est mon jeu incrémental de minage. On frappe une roche à la main, on achète des foreuses qui creusent un puits, on nourrit une raffinerie avec le minerai, et quand la partie ralentit, on effondre la mine pour repartir plus fort. Cette série raconte son histoire à partir du journal des modifications, de l’historique des commits et de captures du jeu. Cette première partie couvre le prototype, le portage en Lua et les choix des premiers jours. Les captures montrent le jeu en octobre 2026, avant sa refonte.
Table des matières
- Le prototype
- Un portage, pas une réécriture
- Le prouver
- Une mise en page, tous les écrans
- Le temps d’absence
- Au-delà du prototype
- En chiffres
- L’histoire de Deep Core
Le prototype
Deep Core est parti d’une seule page HTML faite avec React. Tout le jeu y tenait, en quatre onglets : Mine, Refinery, Field Perks et Legacy. Le puits faisait 50 niveaux, avec sept sols, du Topsoil et son charbon jusqu’au Core et son Aetherium. Six bâtiments de raffinerie transformaient le minerai en biens, du Kiln, qui fait du coke avec le charbon, jusqu’au Gem Cutter. Les atouts de terrain, achetés avec des géodes, comptaient une racine, trois branches de cinq atouts et un atout final, 17 en tout. Les atouts d’héritage, achetés avec des éclats de noyau, en comptaient 18, disposés de la même façon. L’un d’eux, Night Crews, faisait travailler la mine jusqu’à 8 heures pendant que la page était fermée.
La boucle fonctionnait, mais dans un navigateur. Je voulais le jeu sur Steam et sur téléphone. J’ai choisi LÖVE parce que je l’utilise déjà pour Skyfall, et qu’un fichier .love s’empaquette pour Windows, macOS, Linux, Android et iOS. Deep Core n’a besoin ni de réseau ni de module natif, alors une version Steam n’a qu’à lancer le jeu empaqueté.
Un portage, pas une réécriture
La première règle du portage était de ne rien changer. Tous les chiffres d’équilibrage du prototype sont allés dans un seul fichier Lua, data.lua. La logique du jeu, une seule classe JavaScript dans le prototype, est devenue state.lua, portée ligne par ligne : foreuses, puits, emplacements, bâtiments, atouts et effondrement. Dans un jeu incrémental, les coûts et les revenus croissent de façon exponentielle, alors un petit écart dans une formule devient un gros écart après quelques heures de jeu. Un portage qui « a l’air correct » peut quand même se jouer autrement.

Le prouver
Pour vérifier le portage, j’ai écrit un banc de parité dès le premier jour. tools/parity extrait la classe du jeu du fichier HTML du prototype et la fait tourner dans Node. Il fait tourner le portage Lua dans un interpréteur lua ordinaire. Les deux passent par le même scénario de 782 étapes, d’un départ à zéro jusqu’au fond des 50 niveaux, avec chaque atout acheté et quatre effondrements. Le banc compare 5 310 valeurs de chaque partie : soldes, inventaires, prix, état des foreuses et des bâtiments, coûts, libellés des atouts et journal du contremaître. Le premier jour, les deux concordaient au bit près.
Ce banc a façonné le code. state.lua et data.lua ne touchent pas du tout à LÖVE, et c’est ce qui leur permet de tourner sous Lua tout court. Quand je change l’équilibrage exprès, le changement va dans une liste DEVIATIONS, et le banc l’applique au prototype avant de comparer. Tout ce qui est hors de cette liste reste comparé exactement. Le banc tourne encore aujourd’hui, sur 8 502 valeurs par instantané. Le plus grand écart relatif est de 2e-16, à cause du logarithme dans la formule des éclats.
Une mise en page, tous les écrans
Le prototype était conçu en 1440×960. Le portage dessine en unités logiques à cette taille et applique un seul facteur d’échelle par image, si bien que sur ordinateur, il est identique au prototype. Sous environ 980 unités logiques de large, la mise en page s’empile. La barre latérale avec la roche et le stock devient son propre onglet, Camp, les quatre compteurs passent en grille de 2×2 et la rangée d’onglets passe à la ligne. Le jeu rend le texte à la vraie résolution de l’écran, pour qu’il reste net à toutes les échelles. Quand un téléphone pivote en pleine partie, le jeu prend la nouvelle taille à l’image suivante.
La même nuit, un téléphone à l’horizontale en 932×430 zoomait au-delà de ce qui tenait à l’écran. Le correctif tient compte de la hauteur pour choisir l’échelle. Sous 560 unités logiques de haut, l’en-tête met le titre et les onglets sur une ligne et les compteurs en dessous, ce qui le fait passer de 180 à 110 unités.
Pour attraper le reste, le portage a eu un test de fumée. love . --smoke dessine 93 combinaisons de mise en page, puis envoie environ 41 000 clics synthétiques sur une grille dans chaque onglet et vérifie que les 14 effets de l’interface se produisent vraiment : frapper, vendre, acheter, changer d’onglet, effondrer la mine, et le reste. Un bouton qui s’affiche bien mais ne fait rien passe facilement inaperçu dans une taille de fenêtre que je n’essaie jamais à la main.
Le temps d’absence
Un jeu incrémental doit continuer pendant qu’il est fermé. Chaque sauvegarde note l’heure réelle. Au chargement, le jeu rejoue l’écart avec la même étape de simulation que le jeu en direct, si bien qu’une heure d’absence donne exactement ce qu’une heure de jeu aurait donné. Le rythme du jeu suit aussi l’horloge réelle plutôt que les images affichées. Une fenêtre réduite ou un téléphone verrouillé rattrape donc son retard à l’image suivante, plafonné à une heure par pas, comme dans le prototype.
La sauvegarde elle-même est une table Lua, chargée dans un bac à sable vide. Un fichier corrompu ou modifié à la main donne une nouvelle partie au lieu d’exécuter quoi que ce soit.
L’après-midi du 30 septembre, le jeu a eu sa fenêtre « While you were away ». Elle s’ouvre au lancement et liste l’argent et les géodes que l’absence a rapportés, et les éclats de noyau en plus qu’un effondrement rapporterait maintenant. Night Crews est aussi passé au premier nœud de la branche Fortune, pour 2 éclats. C’était la première entrée de la liste DEVIATIONS.
Au-delà du prototype
Le 3 octobre, le portage a commencé à aller plus loin que l’original.
- Des chiffres plus fluides. La simulation avance toutes les 0,2 seconde, alors les barres de forage et de géodes bougeaient par à-coups visibles. Elles extrapolent maintenant entre deux pas, sans toucher à l’état du jeu. L’argent, le stock et les statistiques roulent vers leur nouvelle valeur, la molette glisse vers sa cible et la fenêtre d’absence compte ses totaux à partir de zéro.
- 500 niveaux. Le prototype s’arrête au niveau 50. Le portage ajoute huit minerais profonds au-delà, du Voidstone au niveau 51 jusqu’au Singularium au 443. Chacun débloque un bâtiment profond qu’il faut inventer. Pour ça, son minerai doit être atteint et les bâtiments qui fabriquent ses ingrédients doivent déjà exister. La limite de profondeur s’ouvre 10 niveaux à la fois.
- Du stock gardé pour les bâtiments. La vente automatique ne gardait que les ingrédients des bâtiments profonds, alors le Coke était vendu avant que la Foundry, qui en a besoin pour l’acier, puisse s’en servir. La vente automatique et « Sell all » gardent maintenant ce dont chaque bâtiment en marche a besoin.
- Plus de foreuses. Les emplacements de foreuse étaient limités à 8. Maintenant, une percée qui dépasse le milieu d’une couche sans atteindre un nouveau sol ouvre un emplacement de plus, au prix de 1,5 fois la foreuse précédente. La vue du puits s’adapte jusqu’à 28 foreuses.
- Night Crew et la branche Crews. Night Crew est devenu un atout de terrain, le deuxième de la branche Trade, pour 5 géodes, avec une fenêtre de 12 heures. Une quatrième branche d’héritage, Crews, a reçu dix atouts qui doublent chacun cette fenêtre. Les sauvegardes qui avaient l’ancien Night Crews ont récupéré leurs 2 éclats.
- Seed Money. L’atout d’héritage qui fixe l’argent de départ d’une partie est passé de 25 K$ à 250 M$.
- Des toiles d’atouts. Les listes d’atouts sont devenues des toiles, dans le style d’un arbre de compétences passives. Les atouts de terrain et d’héritage comptent maintenant 84 nœuds chacun, autour d’un nœud de départ gratuit. Quatre bras partent du départ, chacun avec ses branches secondaires, reliés par des nœuds de liaison et un anneau extérieur qui porte quatre atouts clés. Chaque atout du prototype a gardé son identifiant, son coût et son effet, alors le banc de parité les vérifie encore. Les nouveaux nœuds, mineurs, notables et clés, ajoutent des bonus de statistiques. On déplace la toile en glissant, on zoome avec la molette ou en pinçant, et on survole un nœud pour voir ce qu’il donne.


Puis plus rien pendant trois semaines. Le commit suivant, le 24 octobre, a remplacé toute l’interface.
En chiffres
- 22 commits entre le 30 septembre et le 3 octobre.
- Environ 4 000 lignes de Lua à la fin du 30 septembre, et 5 100 le 3 octobre.
- 782 étapes et 5 310 valeurs comparées dans le premier scénario de parité.
L’histoire de Deep Core
- D’un prototype HTML à LÖVE (cet article)
- Du pixel art, une équipe et une gare de triage


