Le blog d’Ata Kuyumcu est statique. Quelque part dessous, il y a pourtant un donjon multijoueur avec des slimes, des coffres, des cris spatialisés et un maître du donjon élu entre les navigateurs.
Il n’y a pas de serveur de jeu.1
Le projet vaut surtout pour cette contrainte. Kuyumcu voulait cacher un petit dungeon crawler sous chaque page de son blog sans transformer un site léger en backend permanent pour une blague que la majorité des visiteurs ne découvrira jamais.
Il a donc construit le jeu autour de deux idées : les navigateurs peuvent se parler directement, et ils n’ont pas besoin de s’envoyer un monde qu’ils savent déjà reconstruire eux-mêmes.
Le blog n’a pas besoin de son propre serveur de signalement
Le multijoueur utilise WebRTC à travers Trystero.1 2
WebRTC permet aux navigateurs d’ouvrir un canal de données pair à pair, mais ils ont d’abord besoin d’un moyen de se trouver et d’échanger les informations nécessaires à la connexion. Trystero utilise pour cette phase des infrastructures publiques existantes, notamment des relais Nostr, des trackers BitTorrent ou des brokers MQTT selon la stratégie choisie.2
Dans le donjon, les visiteurs du même jour rejoignent une salle identifiée par la date UTC. Une fois la poignée de main terminée, le trafic du jeu passe directement entre les pairs.1
Kuyumcu décrit son empreinte côté serveur comme une seule adaptation de la Content-Security-Policy du blog pour autoriser les WebSockets nécessaires aux relais.1
Ce n’est pas « zéro infrastructure » au sens littéral. Les pairs ont besoin d’infrastructures publiques pour se découvrir. Ce qui disparaît est le serveur de jeu que l’auteur doit maintenir.
Tout le monde obtient le même donjon sans le télécharger
La carte utilise une génération déterministe.
Chaque navigateur prend la date du jour, la transforme en graine et alimente le même générateur pseudo-aléatoire. Même graine, mêmes salles, mêmes couloirs et mêmes monstres initiaux.1
Les niveaux plus profonds dérivent à leur tour une nouvelle graine depuis la date et la profondeur.
Personne n’a donc besoin d’envoyer la géométrie complète du donjon aux autres. Elle est implicite dans la règle de génération.
Le réseau transporte surtout ce qui change pendant la partie : positions, points de vie et événements comme l’ouverture d’un coffre. Kuyumcu affirme qu’une mise à jour complète reste sous les cent octets dans son implémentation.1
C’est une vieille idée des systèmes distribués rendue très visible par un petit jeu : si deux machines connaissent la même fonction et la même entrée, envoyer le résultat entier est parfois du gaspillage.
Mais les monstres doivent obéir à quelqu’un
Le déterminisme règle l’état initial. Il ne règle pas le slime qui décide de tourner à gauche deux secondes plus tard.
Deux joueurs doivent voir le même monstre au même endroit. Sans autorité centrale, le jeu en élit donc une.1
Sur chaque étage, le pair dont l’identifiant est le plus petit dans l’ordre lexicographique devient l’autorité. Il met à jour les monstres toutes les 400 ms, résout leurs actions et diffuse l’état aux autres.1
Si ce navigateur ferme son onglet, le suivant prend la relève depuis le dernier état reçu. Chaque client conservait déjà une copie.
En solo, la démocratie est plus rapide : vous êtes automatiquement le plus petit identifiant de la pièce.
Le système n’essaie pas de résoudre tous les problèmes d’un MMO compétitif. Il fabrique juste assez de consensus pour que deux inconnus puissent voir le même mimic mordre la même personne.
1 057 octets avant d’ouvrir la porte
Le blog paie très peu tant que personne ne découvre le jeu.
Kuyumcu mesure 1 057 octets pour le script chargé sur toutes les pages. Il écoute uniquement la séquence qui ouvre le passage. Le vrai jeu est importé dynamiquement ensuite : 94 Ko de bundle, Trystero compris, et environ 10 Ko de tileset.1
Les tuiles viennent des packs Tiny Dungeon et Tiny Town de Kenney, publiés sous CC0.3 4
Même les sons ne sont pas des fichiers. Le navigateur les synthétise avec Web Audio à partir d’oscillateurs et d’enveloppes de gain.1
Ce choix donne une règle assez élégante pour les easter eggs : le poids du secret doit être payé par les gens qui le trouvent, pas par tous ceux qui passent devant.
L’IA écrit le réseau, l’humain remarque les briques
Kuyumcu raconte avoir construit l’essentiel avec Claude Opus en une soirée d’allers-retours.1
Le modèle a écrit le netcode puis lancé deux navigateurs headless qui se sont trouvés via de vrais relais publics et ont produit des captures montrant qu’ils se voyaient mutuellement.1
La partie humaine est presque plus amusante : Kuyumcu a remarqué que les murs avaient l’air faux.
Le tileset de Kenney contient une grammaire visuelle. Certaines briques portent des ombres pour une orientation précise. Le premier rendu les plaçait comme de simples variantes décoratives. Kuyumcu a ouvert la carte d’exemple Tiled fournie avec les assets pour comprendre comment les pièces étaient censées s’assembler, puis le renderer a été corrigé.1
C’est un bon exemple de ce que l’évaluation automatique détecte mal. Deux bots peuvent prouver qu’un canal WebRTC fonctionne. Ils ne savent pas forcément que le mur « sent mauvais » visuellement.
Le cri est plus intéressant qu’un minimap
Le jeu contient enfin une fonction de cri.
Un joueur diffuse sa position. Les autres entendent un appel panoramiqué à gauche ou à droite selon la direction, atténué avec la distance. Si la personne se trouve à un autre étage, la hauteur du son change pour indiquer si elle est au-dessus ou en dessous.1
Kuyumcu dit que c’est sa fonction préférée.
Je comprends pourquoi. Le jeu pouvait afficher une flèche ou un petit radar. Il choisit à la place une information qui appartient au monde : quelqu’un crie dans un donjon, et vos oreilles indiquent où chercher.
Le petit projet accumule ce genre de décisions cohérentes. Le monde commun vient d’une graine plutôt que d’un téléchargement. L’autorité vient d’un pair plutôt que d’un serveur. Le son vient du navigateur plutôt que de fichiers. Le code du jeu n’arrive qu’après avoir trouvé l’entrée.
Un blog statique reste un blog statique.
Il a juste un sous-sol beaucoup trop élaboré.