Docs Concepts clés

Les quinze règles

Chacune a été apprise dans de vraies parties. Relisez-les en écrivant un Bot : vous économiserez l’essentiel du temps de débogage.

Donnez cette page au LLM avec api.json : le Bot qu’il écrira s’épargnera bien des détours.

Lire l’état

1. Une valeur illisible vaut None, pas 0

resources(), time_of_day(), production() et cooldown() peuvent tous renvoyer None (chargement en cours, unité sans détails, bâtiment qui ne produit rien…). Vérifiez avant d’utiliser la valeur :

res = g.resources()
if res is None:
    return

2. Identifiez les unités par leur handle, pas par leur adresse

Les adresses sont réutilisées par de nouvelles unités : une ancienne adresse peut pointer vers une unité qui vient d’apparaître. Pour suivre une unité d’un tick à l’autre, stockez u.handle et retrouvez-la avec g.unit(handle).

3. Le flux d’événements est global

production.done et unit.died concernent aussi l’adversaire et les creeps. Filtrez par ev.owner (ou par le handle du bâtiment) :

if ev.kind == "production.done" and ev.owner == g.me():
    ...

4. Les ouvriers dans une mine d’or ne sont pas dans l’instantané

Au moment où un ouvrier entre dans la mine, il disparaît de l’instantané (unit.removed, il n’est pas mort). Pour savoir combien d’ouvriers travaillent sur chaque mine, tenez vos propres comptes au lieu de les corriger d’après l’instantané — sinon vous enverrez trop d’ouvriers dans une mine déjà pleine.

Donner des ordres

5. Accusé « accepté » ≠ réussi

Le moteur accepte sur le moment même un point de construction en pleine forêt ; l’échec ne survient qu’à l’arrivée de l’ouvrier. Un sort peut être interrompu. Jugez de l’effet d’après l’instantané et les événements : pour construire, utilisez build_near (qui vérifie que les fondations apparaissent) ; pour un sort, vérifiez que g.cooldown() est bien en recharge.

6. Impossible d’attaquer une cible invisible

Un ordre ciblant un ennemi dans le brouillard de guerre est rejeté avec le code de raison 1001. Pour poursuivre un ennemi dans le brouillard, faites un attack_move vers sa dernière position connue.

7. Ne donnez d’ordres qu’aux unités inactives

Redonner le même ordre à la même unité à chaque tick l’interrompt : les soldats tressautent sur place, le cycle de récolte des paysans repart de zéro. Pour savoir si une unité est « inactive », utilisez g.order_of(u) (qui inclut ce que vous venez d’ordonner pendant ce tick), et non u.order de l’instantané (qui n’est pas encore à jour).

8. Shift ne sait qu’« insérer après l’ordre en cours »

Le moteur n’a pas d’« ajout en fin de file » : envoyer B puis C avec queue='after' donne A, C, B. Pour parcourir une série de points dans l’ordre, utilisez g.path(units, liste_de_points) ; pour qu’un ouvrier enchaîne plusieurs constructions, g.build_queue(worker, plan) — ces méthodes insèrent en ordre inverse et règlent le problème pour vous.

9. Envoyez les commandes d’un tick en un seul lot

Envoyer des dizaines de commandes une par une, c’est attendre des dizaines de fois le thread du jeu ; regroupées dans with g.batch():, elles n’attendent qu’une fois.

Économie et production

10. 5 ouvriers au maximum par mine

Au-delà, le revenu n’augmente plus. L’objectif d’ouvriers suit le nombre de mines : 5 à l’or par mine, plus quelques bûcherons.

11. Une seule unité en file d’entraînement

Remplir les 7 places immobilise l’argent dans la file (mesuré : 4 paysans en file au bâtiment principal, 300 d’or bloqués, un début de partie nettement plus lent). N’ajoutez l’unité suivante que lorsque g.queue(b) est vide.

12. Nourriture bloquée : regardez la table de production

g.production(b).blocked = une unité est en file mais n’a pas démarré, le plus souvent faute de nourriture. Vous avez ainsi un coup d’avance sur « construire quand la nourriture est presque au maximum » : si vous perdez une partie de l’armée au combat et que la file bloque au moment de la reconstituer, vous le savez tout de suite.

13. Les héros sont uniques ; pas de montée de tier tant que la file du bâtiment principal n’est pas vide

  • Un héros mort ne peut qu’être ressuscité avec g.revive(autel) ; essayer de l’entraîner de nouveau est rejeté (221). La résurrection consomme aussi de la nourriture (un héros en occupe 5).
  • Impossible d’améliorer le bâtiment principal tant que sa file contient quelque chose (code de raison 185, « bâtiment occupé »).

Temps et espace

14. En vitesse 2×, n’attendez pas selon l’horloge murale

Pour attendre 3 secondes de jeu, attendez que g.clock() ait avancé de 3, et non sleep(1.5). Quand le jeu est accéléré, l’horloge du moteur avance plus vite que l’horloge murale.

15. Sur les cartes à îles ou très boisées, oubliez la distance à vol d’oiseau

Pour choisir un camp de creeps ou une expansion, utilisez g.path_distance(a, b) (A* au sol, qui contourne forêts, falaises et bâtiments) ; il renvoie None si le point est inaccessible. Le point le plus proche à vol d’oiseau se trouve peut-être de l’autre côté de la mer.

Une de plus : écrivez en mode équitable

Avec --fair, vous ne voyez que les unités, objets, productions et événements situés dans votre champ de vision : c’est la règle de l’arène. Écrivez dès maintenant en mode équitable et vous n’aurez rien à changer pour passer sur l’Arène. Voir Mode équitable.