J'ai codé des statistiques pour des démos de DOOM.

Doom 12 avr. 2022

Ce weekend, j’ai fait un petit projet totalement idiot, court mais intense… Non, ce n’est pas ce que vous pensez, mais j’ai décidé de recompiler Doom avec une fonctionnalité plutôt intéressante…

L’idée

En discutant assez longuement avec un ami, on avait voulu savoir plus de détails sur les statistiques de plusieurs de nos démos: notre taux de précision, le nombre de monstres tués pour chaque seconde, le nombre de tirs avec chaque arme. Autrement dit, obtenir beaucoup plus de détails et de statistiques sur une simple démo.

En vrai, l’idée était toute bête, mais depuis quelques temps, j’ai réalisé des statistiques et du monitoring sur mes serveurs, alors au final, quelques data de plus ou de moins, quelle importance! Et bien au contraire, ça m’entraine beaucoup la dessus, car c’est un domaine que je connais relativement peu. Une pierre deux coups, comme on dit 🙂

La réflexion

Pour pouvoir me lancer dedans, il me fallait récupérer les informations d’une démo. Initialement, j’aurais voulu le faire en Golang (un langage que j’apprends à utiliser avec tout l’amour que j’ai – et ce sans être développeur -), mais à ce jour aucun moyen ne permet de récupérer les statistiques en temps réel.

En effet, tout ce qui est enregistré dans ces démos ne sont que des boutons et actions pour chaque joueur ; le moteur du jeu fera tout le reste.

Donc, pour contrer cela, je dois trouver un autre moyen de faire le résultat espéré… Et pour cela, j’ai trouvé une idée bête: et si je m’inspirais des protocoles que j’ai analysé dans le passé pour faire mon propre protocole? Je pourrais ainsi les récupérer pour les traiter dans un second temps.

Le protocole que je vais utiliser

J’ai cherché ce que j’ai prévu de mettre dans mes statistiques, et comment la mettre en forme… Et après quelques instants, j’ai décidé de le faire de la sorte:

  • Numéro de tic
  • Nombre de Joueurs
  • Total de monstres tués
    • Monstres tués par joueur (1-4)
  • Total de Secrets trouvés
    • Secrets trouvés par joueur (1-4)
  • Total de tirs par joueur (1-4)
    • Total de coups de poings par joueur (1-4)
    • Total de coups de chainsaw par joueur (1-4)
    • Total de coups de pistolets par joueur (1-4)
    • Total de coups de Shotgun par joueur (1-4)
    • Total de coups de SSG par joueur (1-4)
    • Total de coups de Chaingun par joueur (1-4)
    • Total de coups de Roquettes par joueur (1-4)
    • Total de coups de Plasma par joueur (1-4)
    • Total de coups de BFG9000 par joueur (1-4)

Pfiou… Ça en fait des valeurs, pas vrai? D’ailleurs, vous remarquerez que j’ai écrit (1-4) sur plusieurs valeurs… Ça veut dire que cette liste sera itérable en fonction de nombre de joueurs.

Si je n’ai qu’un joueur, la boucle des tués, secrets ou tirs ne sera lancé qu’une seule fois. Si nous sommes 3, ça se lancera 3 fois, etc etc… Cela évite de coder des conditions beaucoup trop difficiles et inutile…

Développer le fork de Doom

Pour cette partie du projet, j’ai décidé de prendre Crispy-Doom comme base. J’aurais pu prendre DSDA-Doom étant donné qu’il est compatible avec d’autres protocoles, mais par souci de simplicité (et surtout que je ne fais pas vraiment de démo autre que dans les IWADs), j’ai décidé de ne pas l’utiliser (et surtout parce que DSDA-Doom est une véritable usine à gaz).

Je sais déjà comment Doom fonctionne: si vous me connaissez, j’ai déjà fait plusieurs maps, outils, mods, et j’ai même contribué à un port de Doom pendant plusieurs années. Nous savons que le jeu lance une boucle infinie de la logique du jeu, boucle qui s’appelle tic. Une seconde correspond par ailleurs à 35 tics. Pour récupérer ces statistiques, j’ai décidé de créer une fonction qui écrit dans un fichier les valeurs qu’on recherche à la fin de cette boucle.

Maintenant, plus qu’à obtenir ces valeurs. Pour les secrets et pour les monstres tués, le jeu récupère déjà ces statistiques. Pour les armes en revanche, rien n’est présent. Heureusement, rien de compliqué: une variable dans la structure du joueur plus tard, je n’ai qu’à incrémenter les valeurs par arme… Et le boulot est fait.

Histoire de gagner du temps, j’ai décidé d’incorporer un paramètre de lancement nommé -statdump dans la fonctionnalité déjà existante -timedemo. Cela fait en sorte que le jeu rende le plus d’images par seconde tout en les traitant. Le résultat: nous faire gagner beaucoup de temps lors du traitement des informations. Et un fichier txt est généré:

Alors oui, le résultat final est moche, très brut, mais ce n’était pas mon but de faire un protocole très poussé et ultra qualitatif. Au moins ces informations sont récupérés, c’est bien le principal, non?

Traiter ces informations avec du Golang.

Désormais, place à la partie du traitement d’infos avec un programme écrit en Golang.

Pour récupérer les informations, j’ai décidé de traiter les informations basées sur mon protocole. Le résultat est simple et efficace. Comme toutes les valeurs sont des integer, il a fallu les convertir pour pouvoir quantifier nos valeurs pour plus tard.

Concernant les graphiques, j’ai décidé d’utiliser la librairie go-echarts. C’est pas la librairie la plus parfaite, la documentation n’est pas vraiment existante, mais il y a au moins des exemples qui sont réutilisables, et ça fait le taf. Le reste m’importait peu ; mais si je me devais de réécrire mon programme, je prendrai surement une librairie plus complète.

Résultat, une fois compilé, on le lance, et nous voila avec notre magnifique page web générée qui nous donne nos jolies statistiques.

Pfiou, c’était long mais ça en valait la peine! Plus qu’à peaufiner le tout, mais ceci sera pour une autre fois…

Mots clés

Ch0wW

🌍 Entrez dans mon monde! Je poste du contenu en rapport avec les jeux retro, l'informatique, le modding et la réparation d'appareils... N'hésitez pas à me contacter pour toute question ou demande!