Architecture modulaire du jeu

Le client Android de Block Blast, version 10.8.2, se compose d’une petite couche Java et d’une bibliothèque native Cocos. L’analyse avec jadx et Ghidra montre que le binaire ne contient que quelques dizaines de classes. La logique du jeu repose sur des traits, chaque trait possédant plusieurs arms. Au lancement, le serveur transmet un fichier de configuration contenant environ 700 traits ; l’installation étudiée a sélectionné 254 d’entre eux, dont 101 ont été téléchargés sous forme de JavaScript chiffré. Cette architecture permet de modifier le comportement du jeu sans mise à jour de l’application, car le serveur peut activer ou désactiver des arms à la volée.

Mécanisme du trait publicitaire à haute valeur

Le trait nommé RewardHighValueAdHarvestTrait s’active uniquement lorsque trois conditions sont réunies. Premièrement, le tableau interne rewardedAds doit contenir trois valeurs true, indiquant que les trois dernières publicités récompensées ont été visionnées jusqu’à la fin. Cette information provient du callback onUserRewarded d’AppLovin MAX dans la couche Java ; une fermeture prématurée laisse la valeur à false.

if (rewardedAds[0] && rewardedAds[1] && rewardedAds[2]) { … }

Deuxièmement, le jeu compare le eCPM de la publicité prête à être affichée avec celui de la dernière publicité récompensée. La fonction native NativeAd.callNativeGetMaxEcpmNumber("2") renvoie le revenu maximal parmi les slots prêts, multiplié par 1 000. Le même facteur 1 000 s’applique à la valeur de la dernière publicité, ce qui rend la comparaison directe :

let currentEcpm = NativeAd.callNativeGetMaxEcpmNumber("2");
let lastEcpm = lastRewardedEcpm * 1000;
if (currentEcpm >= 3.5 * lastEcpm) { … }

Troisièmement, le score du joueur doit dépasser son meilleur score enregistré de scoreDeltaStep points. Le fichier de configuration fournit trois valeurs possibles : 500, 750 ou 1 000. Dans l’exemple étudié, la valeur était 1 000, ce qui place la barre de déclenchement à 1 000 points au‑dessus du record.

Lorsque les trois critères sont remplis, le moteur de jeu invoque la fonction deathAlgorithm, qui génère le « puzzle mortel » décrit ci‑dessous.

Puzzle mortel et modèle de décision

Le puzzle mortel correspond à l’algorithme 24001, présent à la fois dans le script JavaScript et dans la bibliothèque native C++. La fonction func_death_blcok recherche un ensemble de trois pièces où deux s’emboîtent immédiatement et la troisième ne peut être placée sans créer une ligne complète. Un test exhaustif sur le tableau fourni montre qu’aucune des 171 permutations possibles ne résout le puzzle, confirmant son caractère impossible.

Outre le trait publicitaire, le jeu possède d’autres déclencheurs, comme PersonalMarginBreakTrait, qui demande le même puzzle dans 20 % des parties dès que le score dépasse de 10 % le record. Ces appels supplémentaires illustrent que le puzzle n’est pas dédié uniquement à la monétisation.

La localisation du puzzle dans le niveau est déterminée par un modèle XGBoost de 500 arbres, stocké sous le nom predict_travel_difficulty_dead. Le modèle accepte 52 variables liées à la progression du joueur (niveau actuel, nombre d’essais, temps d’utilisation, etc.) et renvoie la configuration de difficulté la plus probable. Le jeu sélectionne parmi trois variantes de paramètres sw_process et applique celle qui obtient le score maximal du classificateur.

En combinant un système de traits téléchargeables, un contrôle strict des publicités récompensées et un modèle prédictif, Block Blast crée un mécanisme d’acquisition d’utilisateurs qui maximise les revenus publicitaires tout en conservant la capacité d’ajuster le gameplay à distance.