# 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.

Source: https://war3ai.com/fr/docs/rules/

> **Astuce**
>
> Donnez cette page au LLM avec [`api.json`](https://war3ai.com/fr/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 :

```python
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) :

```python
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](https://war3ai.com/fr/arena/). Voir [Mode équitable](https://war3ai.com/fr/docs/fair-mode/).
