Débogage et performances
Pourquoi un tick est lent, pourquoi une commande reste sans effet, pourquoi le jeu ne bouge pas. Diagnostiquez à partir du symptôme, puis confirmez avec les scripts de vérification en jeu fournis.
Lire les accusés de réception
L’accusé de réception de chaque commande est l’indice de première main :
r = g.cast(hero, "blizzard", x=tx, y=ty)
if not r:
print(r.reason, r.verdict) # rejected(…) et le code de raison
print(r.exec_us, r.engine_us) # durée d'exécution sur le thread du jeu, en µs / dont la fonction d'ordre du moteur elle-même
En temps normal, une commande prend de quelques microsecondes à quelques centaines de microsecondes sur le thread du jeu. À la fin d’un bloc de lot, g.last_receipts contient l’accusé de réception de chaque commande du lot.
Observer dans le jeu
g.say(unit, "Repli") # une bulle de dialogue au-dessus de l'unité (sans effet sur le jeu)
g.message("Début du creeping") # une ligne dans la zone de messages en bas à gauche (visible seulement en local)
Ce que vous passez à print s’affiche dans le terminal qui exécute le Bot. Afficher les décisions clés de chaque tick, en plus des bulles de dialogue, est bien plus rapide que de relire le code.
Un tick est lent
Vérifiez d’abord s’il s’agit de l’un de ces cas :
| Cause | Correction |
|---|---|
| Commandes envoyées une par une, chacune attend une frame | Les regrouper dans with g.batch(): : des dizaines de commandes, une seule attente |
Appels à g.visible() / g.can_do() un par un (chacun passe par la voie rapide et attend une frame) | Visibilité : u.visible_to() de l’instantané ; faisabilité : g.can_do_many([...]) en un seul lot |
sleep ou attente dans on_tick | Notez l’heure de jeu et vérifiez au tick suivant |
| Recalcul coûteux à chaque tick (recherche de chemin, balayage de toute la carte) | Mettez le résultat en cache et recalculez-le tous les quelques ticks. g.grid() a un cache intégré de 2 secondes ; les niveaux de technologie de g.stats() sont mis en cache 5 secondes |
Le jeu ne bouge pas / le Bot n’entre jamais en partie
| Symptôme | Cause probable |
|---|---|
| Toujours « en attente de la partie » | Mauvais numéro d’instance ; ou la fenêtre du jeu est réduite — tant qu’elle est réduite, la simulation est à l’arrêt (l’horloge n’avance pas) |
| Le jeu tourne, mais les ordres du Bot restent sans effet | Ordres donnés aux unités d’un autre joueur (accusé not_owner) ; ou le Bot est connecté en tant qu’observer (forbidden) |
Commande held | Cette unité est tenue par une couche plus prioritaire (couche réflexe du cerveau de référence, ordre manuel de la console) : la commande n’a pas été envoyée |
| Les commandes passent encore pendant la pause | Normal : en pause, l’horloge du moteur s’arrête, mais la distribution des événements continue et les commandes s’exécutent normalement |
Se connecter pour voir l’état
python -m openwar3 status --inst 5
Affiche l’état de la connexion : pid du jeu, période de publication du monde et durée de chaque capture, compteurs de la voie rapide, en partie ou non, nombre d’unités, horloge du jeu.
Scripts de vérification en jeu
Lancez une instance de test et vérifiez point par point que les capacités du SDK fonctionnent sur votre machine :
python tools/sdk_live_check.py --inst 20 # tout
python tools/sdk_live_check.py --inst 20 --only prod # une seule section
Sections : lots, temps, production, ordres en file, caractéristiques de combat, recherche de chemin, mode équitable. Chaque section donne des ordres dans une vraie partie, relit l’effet obtenu et affiche le nombre de vérifications réussies.
Les tests hors ligne ne demandent pas de lancer le jeu :
python tools/run_tests.py
Les faux bugs fréquents
- Construction acceptée, mais pas de fondations : le moteur accepte sur le moment même un point en pleine forêt ; l’échec ne survient qu’à l’arrivée de l’ouvrier. Utilisez
build_near, qui suit la construction et met temporairement sur liste noire les points en échec. - Sort accepté, mais jamais lancé : il a été interrompu, ou le mana manquait. Au tick suivant, vérifiez que
g.cooldown()est bien en recharge. - Attaque acceptée, mais les soldats frappent autre chose : pour attaquer une cible précise, utilisez
g.attack(soldats, ennemi)(sémantique du clic droit). L’ordre d’attaque brut sur une cible ne fait que changer l’ordre sans mémoriser la cible : les unités attaquent autre chose à proximité. - Le nombre d’ouvriers ne tombe pas juste : les ouvriers entrés dans une mine d’or ne sont pas dans l’instantané.
- Impossible d’entraîner un héros mort : un héros est unique, il faut
g.revive(autel); la résurrection consomme de la nourriture et n’est possible qu’environ 3 secondes de jeu après la mort.