Chapitre 13

L'alarme à noyade fonctionne parfaitement ; le geste de sauvetage, lui, ne sait pas où est la terre ferme

Prérequis : Chapitres 1 à 12 — dont la mémoire des lieux visités (attempt #12), dont la relecture des journaux révèle ici que 12 des 20 épisodes de son propre lot de confirmation se sont en fait terminés par une noyade.

Vue à la première personne dans Minecraft : après un bref passage dans une clairière herbeuse au crépuscule, l'agent descend dans une grotte souterraine et passe le reste de l'épisode à se déplacer dans des tunnels et couloirs de pierre et de gravier, sans jamais croiser d'eau à l'écran.
Le dernier des cinq épisodes du test en direct de l'attempt #13 — celui conservé dans ce GIF. Ici, le détecteur de noyade ne s'est jamais déclenché : pas d'eau visible à l'écran, seulement une descente dans une grotte. Cohérent avec le fait que 3 des 5 épisodes n'ont rien signalé et qu'un autre s'est terminé par une mort précoce sans lien avec la noyade. L'épisode le plus révélateur du lot — un déclenchement continu de plus de 260 instants, suivi d'une mort quand même — n'est pas celui montré ici : le mécanisme d'enregistrement ne garde que le dernier des cinq essais.

Piste débutant

Là où on en était

Le Chapitre 12 s'est terminé sur un vrai point positif : la mémoire des lieux déjà visités a

produit un deuxième succès réel (1 bûche coupée sur 20 essais), avec un comportement d'agent sain,

sans aucun signe de blocage sur un seul geste. Mais ce mécanisme avait lui-même une limite

signalée dès sa conception : quand il pousse l'agent à explorer une direction peu visitée, il ne

sait absolument rien des dangers qui pourraient se trouver sur son chemin.

En relisant, épisode par épisode, les journaux bruts de ce même lot de 20 essais — pas seulement

le chiffre final, mais ce que le jeu lui-même racontait pendant chaque partie — un fait s'est

révélé : sur les vingt épisodes, douze se sont terminés par un message du jeu confirmant que

l'agent s'était noyé. Pas une supposition, un vrai message du serveur Minecraft

(« MineRLAgent0 drowned »), retrouvé directement dans les journaux techniques de chaque partie.

Ce chapitre raconte la tentative construite directement en réponse à cette découverte, et ce

qu'elle apprend — un résultat qui, une fois de plus, n'est pas une victoire, mais qui referme la

question avec une précision inhabituelle.

Le problème : aucun capteur de vie n'existe dans ce jeu précis

Avant de construire quoi que ce soit, il fallait vérifier une chose simple : le jeu envoie-t-il à

l'agent une information du genre « ta barre de vie », « ton niveau d'air sous l'eau » ? La réponse,

vérifiée directement dans le code de l'environnement de jeu utilisé ici

(MineRLObtainIronPickaxeDense-v0) : non, rien de tout ça n'existe dans ce que le jeu transmet

au programme Python. Seules deux choses arrivent côté agent : l'image de la caméra, et le

contenu de l'inventaire. Pas de vie, pas de souffle, pas d'air. Il faut donc deviner « je suis en

train de me noyer » uniquement à partir de ce que l'écran montre.

L'idée : l'eau teinte l'écran d'une façon reconnaissable

Dans Minecraft, être sous l'eau donne à tout l'écran une teinte bleutée particulière : le rouge et

le vert de l'image deviennent presque égaux entre eux, pendant que le bleu grimpe nettement

au-dessus des deux. C'est un effet de brouillard coloré qui recouvre toute la vue, peu importe ce

qu'il y a devant l'agent. Un petit outil a donc été construit (mine_jepa/ebwm/hazard.py) qui lit,

image par image, la couleur moyenne de l'écran et compare le niveau de bleu à celui du rouge et du

vert — sans aucun apprentissage, juste un calcul de couleur.

Premier calibrage, raté à moitié : la nuit change tout

La première version comparait des différences brutes de couleur (« le bleu dépasse le rouge de

tant de points »), calée sur une vraie noyade observée en plein jour, confirmée par le message du

jeu à l'instant exact où elle s'est produite. Cette version fonctionnait bien pour cette noyade-là

— mais elle a complètement raté une deuxième vraie noyade, survenue de nuit. La raison est

simple une fois qu'on la voit : dans une scène sombre, le bleu monte proportionnellement tout

autant qu'en plein jour, mais sa valeur brute reste minuscule (tout est sombre), donc un seuil basé

sur des différences absolues ne se déclenche jamais.

La correction : comparer des rapports de couleur plutôt que des différences absolues — un

calcul qui reste vrai que la scène soit très claire ou très sombre, parce qu'il compare les

couleurs entre elles plutôt qu'à une valeur fixe.

Vérification sérieuse, deux fois

Cette nouvelle version a été repassée sur environ 5 900 vraies images, prises sur trois parties

entières qui se sont bien terminées (jour, crépuscule, forêt, ciel — des scènes très variées) plus

les deux vraies noyades déjà mentionnées. Résultat : aucune fausse alerte sur aucune des

images de parties normales, la noyade de jour est repérée à 100% de ses images, et la noyade

de nuit à environ 81%. Les 19% manqués sont des images d'un noir presque total, où les trois

couleurs s'effondrent toutes vers zéro en même temps — une vraie limite d'un outil basé sur la

couleur des pixels dans l'obscurité complète, pas un simple réglage de seuil mal ajusté.

Le geste de secours câblé

Quand le détecteur s'allume, il prend le contrôle : il alterne un saut (pour refaire surface et

respirer) avec un pas en arrière fixe, pendant un temps limité (jusqu'à 60 instants de jeu), avant

de rendre la main au fonctionnement normal.

Le test en vrai jeu, 5 parties

  • 3 parties sur 5 : rien à signaler, le détecteur ne s'est jamais déclenché.
  • 1 partie sur 5 : l'agent meurt tôt, mais le détecteur ne s'est jamais déclenché — cette

mort précise n'était donc pas une noyade. Une chute, un monstre, de la lave : le monde de

Minecraft peut simplement être dangereux sur un point de départ aléatoire, et cet outil n'a

jamais eu la prétention de couvrir ce genre de mort.

  • 1 partie sur 5, la plus intéressante : le détecteur s'est allumé sans interruption pendant

plus de 260 instants de jeu d'affilée (plus de 4 secondes réelles) — le geste de secours

(saut + pas en arrière) s'est bien déclenché à chaque instant, exactement comme prévu. Et

l'agent est mort à la fin de cette séquence quand même.

Le verdict : l'alarme marche, le sauvetage est aveugle

Le détecteur, en lui-même, fonctionne : il est précis, bien calibré, et il marche aussi bien de

jour que de nuit. Le vrai problème est plus loin dans la chaîne : le geste qui répond à l'alarme

ne sait absolument pas dans quelle direction se trouve la terre ferme. Alterner un saut et un

pas en arrière fixe n'a aucune idée de si ce pas en arrière mène vers le rivage ou plus profond

dans l'eau, ou juste le long d'une berge sans jamais s'en approcher. Si la direction tombe mal,

l'agent peut rester piégé indéfiniment — et une alarme qui sonne juste, sans jamais réussir à

sauver, ne sert à rien en pratique.

C'est exactement la même forme de leçon que ce projet avait déjà croisée une fois, pour un

mécanisme complètement différent (le réflexe « je suis perdu » du Chapitre 8) : un détecteur

bien calibré n'est pas, à lui seul, une solution, si le geste qui l'écoute ne peut pas résoudre la

vraie situation.

Et maintenant

Ce résultat n'est pas déployé tel quel : c'est un « non » honnête, pas un « presque oui » maquillé.

Une piste de suite est explorée séparément, sans résultat connu au moment d'écrire ces lignes :

diriger le geste de secours vers le dernier endroit où l'agent était connu comme étant hors de

l'eau, en réutilisant le même petit outil de repérage de position déjà construit pour la mémoire

des lieux visités (Chapitre 12) — pas de nouvel apprentissage, juste du comptage et de la

géométrie, comme pour cette mémoire elle-même.

Piste expert

Contexte

Le Chapitre 12 a laissé le mécanisme de frontière topologique (attempt #12) comme le point positif

de la campagne, avec une limite explicitement non traitée dès sa conception : la sélection de cap

ne comporte aucune notion de collision ou de danger. Ce chapitre couvre un diagnostic gratuit puis

l'attempt #13, tous deux issus d'une relecture des journaux du lot N=20 de l'attempt #12.

Diagnostic gratuit : la noyade comme cause dominante de terminaison précoce

Corrélation, épisode par épisode, entre le journal maître du batch et les journaux clients Malmo

(logs/mc*.log, un par sous-processus playminerl_multi.py), par horodatage de fichier.

12 des ~20 épisodes contiennent un message serveur explicite MineRLAgent0 drowned,

directement précédant les dernières lignes de l'épisode (mort réelle de fin d'épisode, pas un tick

de dégât transitoire survécu) — vérifié à nouveau directement sur les journaux bruts, pas

seulement repris d'un rapport antérieur. Les épisodes qui vont jusqu'au plafond de 3000 pas ne

contiennent aucun message de noyade — une coupure nette, bimodale, pas une tendance floue.

Conséquence pour la lecture du chiffre de tête de l'attempt #12 (1/20, 5%) : sur le

sous-ensemble d'épisodes qui survivent assez longtemps pour chercher dans des conditions

équitables (pas coupés court par une noyade), le taux de succès apparent est plus proche de 1 sur

7-8 que de 1 sur 20. Les deux lectures sont honnêtes ; le 1/20 brut reste le chiffre réellement

déployé, mais attribuer tout l'écart à un déficit de recherche/approche serait faux — une bonne

partie vient d'un problème de danger au spawn, explicitement hors périmètre de la conception de

FrontierTracker (aucune conscience de collision/danger dans la sélection de cap).

Attempt #13 — détecteur de noyade par pixels + geste d'échappement : NO-GO, mais diagnostic net

Cause du choix pixel plutôt que capteur d'état. Vérifié contre le code source de l'environnement

lui-même : MineRLObtainIronPickaxeDense-v0 ne transmet aucune observation de vie, de souffle ou

d'air côté Python — seulement l'image caméra et l'inventaire. Toute détection doit donc passer par

l'image.

Implémentation (mine_jepa/ebwm/hazard.py) : sous l'eau, Minecraft teinte tout l'écran d'un

brouillard bleuté achromatique (rouge ≈ vert, bleu élevé). Deux statistiques de couleur moyenne sur

la frame :

ratio  = mean(B) / max(mean(R), mean(G))
rel_rg = |mean(R) - mean(G)| / max(mean(R), mean(G))

Calibrage v1 (rejeté) — différences absolues. Calé sur une noyade réelle observée en plein

jour, confirmée par le message de mort du jeu exactement au pas 644 d'un épisode. Fonctionnait sur

cette noyade, ratait complètement une seconde noyade réelle survenue de nuit : dans une scène

sombre, l'élévation du bleu est proportionnellement aussi forte mais négligeable en valeur brute de

pixel — un seuil absolu ne se déclenche jamais.

Calibrage v2 (retenu) — ratios, invariants à la luminosité globale de la scène par

construction, remplaçant les différences absolues.

Validation sur ~5 900 frames réelles poolées depuis trois épisodes complets survécus (jour,

crépuscule, forêt, ciel) plus les deux vraies noyades : zéro faux positif sur toute frame

survivante ; 100% des frames de la noyade diurne correctement détectées ; ≈81% de la

noyade nocturne. Les 19% manqués correspondent à des frames de noir quasi total où les trois

canaux de couleur s'effondrent vers zéro simultanément et les ratios deviennent trop bruités pour

être lus — une vraie limite d'une heuristique de couleur pixel au fond de l'échelle de luminosité,

pas un problème de réglage de seuil supplémentaire.

Câblage : au déclenchement, le détecteur remplace la sortie du planificateur ou de la macro de

recherche en cours par une action d'échappement — alternance saut (pour refaire surface) / pas en

arrière fixe — pendant jusqu'à 60 instants de jeu par déclenchement, puis rend la main au contrôle

normal.

Test en direct, 5 épisodes réels :

ÉpisodeDéclenchement du détecteurIssue
3 épisodesjamais déclenchérien à signaler
1 épisodejamais déclenchémort précoce — cause non-noyade (chute, mob hostile, lave — hors périmètre du mécanisme par construction)
1 épisodedéclenché en continu >260 instants de jeu (>4 secondes réelles), échappement exécuté à chaque instant comme prévumort à la fin de la séquence malgré tout

Verdict. Le détecteur lui-même est fonctionnellement correct — précis, bien calibré,

invariant à la luminosité. L'échec est en aval : l'action d'échappement (saut + pas en arrière

fixe) n'a aucune information directionnelle sur où se trouve la terre ferme. Si le pas en arrière

s'oriente vers de l'eau plus profonde, ou longe une berge sans s'en rapprocher, l'agent peut rester

piégé indéfiniment sans que l'alarme, correctement déclenchée, ne se convertisse jamais en

sauvetage réel.

Leçon : même forme que l'attempt #5 (Chapitre 8), sur un mécanisme entièrement différent.

Un détecteur « quelque chose ne va pas » correctement câblé et calibré n'est pas, à lui seul, un

correctif si l'action qui le consomme ne peut pas résoudre la situation réelle. Là, c'était le

réflexe de recherche face à un score plat ; ici, c'est un échappement sans direction face à un

danger réel et correctement détecté. Le point commun : détecter n'est pas agir efficacement, et

aucun de ces deux mécanismes ne peut se corriger lui-même une fois câblé sur une action de

réponse aveugle.

Statut livré : NO-GO, non déployé tel quel. Piste de suite explorée séparément, résultat

inconnu au moment de la rédaction : orienter l'échappement vers la dernière position connue hors de

l'eau, en réutilisant le même outil léger de suivi de position par calcul mort déjà construit pour

FrontierTracker (attempt #12) — aucun apprentissage, seulement du comptage et de la géométrie,

cohérent avec le choix de conception déjà fait pour ce même mécanisme.

Où ça laisse la campagne

Le diagnostic de noyade et l'attempt #13 ne changent pas le verdict du Chapitre 11 sur le mur

principal (recherche/approche pour trouver le premier arbre) — ils isolent une source de mortalité

distincte et partiellement responsable de la faiblesse du chiffre de tête de l'attempt #12, sans

la corriger complètement. ebwm.pt et craftwmv4.pt restent intacts : l'attempt #13 n'introduit

aucun paramètre appris, uniquement une heuristique de couleur pixel et un réflexe d'échappement

câblé à la main.

Références

Ce chapitre ne s'appuie sur aucune référence bibliographique nouvelle : le détecteur de noyade de

l'attempt #13 est une heuristique de couleur pixel construite et calibrée directement sur les

données de ce projet, pas l'application d'une méthode publiée — conformément à la règle du projet

de ne citer que des identifiants arXiv déjà vérifiés dans docs/references/index.md, aucun n'est

invoqué ici faute de pertinence directe.