# Пятнадцать правил

> Каждое выстрадано в реальных матчах. Сверяйтесь с ними, когда пишете бота, — это сэкономит большую часть времени на поиск ошибок.

Источник: https://war3ai.com/ru/docs/rules/

> **Совет**
>
> Отдайте эту страницу LLM вместе с [`api.json`](https://war3ai.com/ru/api.json) — бот, которого она напишет, обойдёт множество ловушек.

## Чтение состояния

### 1. Нет данных — это `None`, а не 0

`resources()`, `time_of_day()`, `production()`, `cooldown()` могут вернуть `None` (идёт загрузка, у юнита нет подробных данных, здание ничего не производит…). Сначала проверьте, потом используйте:

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

### 2. Узнавайте юнита по дескриптору, а не по адресу

Адреса переиспользуются: старый адрес может указывать на только что появившегося юнита. Чтобы помнить юнита между тиками, храните `u.handle` и находите его через `g.unit(handle)`.

### 3. Поток событий — глобальный

В `production.done` и `unit.died` попадают и события соперника, и крипов. Фильтруйте по `ev.owner` (или по дескриптору здания):

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

### 4. Рабочих внутри рудника нет в снимке

Рабочий, зашедший в золотой рудник, в этот момент исчезает из снимка (`unit.removed`, а не гибель). Чтобы знать, сколько рабочих на каждом руднике, **ведите учёт сами** и не урезайте его по снимку — иначе будете отправлять лишних в уже заполненный рудник.

## Отдача команд

### 5. «Принята» в квитанции ≠ «выполнена»

Точку строительства в лесу движок тоже сразу принимает, а срывается всё, когда рабочий дойдёт до места; способность могут прервать. Результат смотрите по снимку и событиям: для строительства используйте `build_near` (он следит, появился ли фундамент), для способностей проверяйте по `g.cooldown()`, началась ли перезарядка.

### 6. По невидимым целям бить нельзя

Целевой приказ по врагу в тумане войны будет отклонён с кодом причины **1001**. Чтобы преследовать врага в тумане, сделайте `attack_move` в место, где его видели последний раз.

### 7. Приказывайте только свободным юнитам

Если каждый тик повторять юниту один и тот же приказ, вы его сбиваете: бойцы дёргаются на месте, а у крестьянина обнуляется цикл добычи. Свободен ли юнит, проверяйте через `g.order_of(u)` (он учитывает и то, что вы приказали в этом тике), а не через `u.order` из снимка (снимок ещё не догнал).

### 8. Shift умеет только «вставить после текущего»

В движке нет «добавить в конец»: если подряд отправить B и C с `queue='after'`, получится A, C, B. Чтобы пройти цепочку точек по порядку, используйте `g.path(units, список_точек)`, чтобы один рабочий построил несколько зданий подряд — `g.build_queue(worker, план)`: они вставляют команды в обратном порядке и всё сделают за вас.

### 9. Команды одного тика — одной пачкой

Если отправлять десятки команд по одной, придётся десятки раз ждать игровой поток; внутри `with g.batch():` — только один раз.

## Экономика и производство

### 10. Не больше 5 рабочих на рудник

Больше — доход не растёт. Целевое число рабочих зависит от числа рудников: по 5 на золоте на каждый рудник плюс несколько на лесе.

### 11. В очереди тренировки — только 1 юнит

Заполненная очередь из 7 мест замораживает деньги (в тесте главное здание поставило в очередь 4 крестьян, 300 золота оказались заперты, и старт сильно затянулся). Ставьте следующего, когда `g.queue(b)` опустеет.

### 12. Упёрлись в пищу — смотрите таблицу производства

`g.production(b).blocked` = в очереди что-то есть, но производство не начинается; чаще всего не хватает пищи. Это на шаг раньше, чем «строить, когда пища почти кончилась»: потеряли в бою пачку юнитов, начали добирать, очередь встала — вы сразу это видите.

### 13. Герой уникален; главное здание не улучшить, пока его очередь не пуста

- Погибшего героя можно только воскресить через `g.revive(алтарь)`, повторная тренировка будет отклонена (221); воскрешение тоже требует пищи (герой занимает 5).
- Пока в очереди главного здания что-то есть, улучшить его нельзя (код причины 185, «здание занято»).

## Время и пространство

### 14. На скорости 2× не ждите по настенным часам

Чтобы подождать 3 игровые секунды, дождитесь, пока `g.clock()` вырастет на 3, а не делайте `sleep(1.5)`. На повышенной скорости часы движка идут быстрее настенных.

### 15. На островных и лесных картах не мерьте по прямой

Выбирайте лагеря крипов и места для второй базы через `g.path_distance(a, b)` (A* по земле в обход леса, обрывов и зданий); если дойти нельзя, вернётся `None`. Ближайшая по прямой точка может оказаться за морем.

## И ещё одно: пишите под честный режим

С `--fair` видны только юниты, предметы, производство и события в пределах обзора — именно по этим правилам играют на Арене. Пишите под честный режим уже сейчас, и при переходе на [Арену](https://war3ai.com/ru/arena/) ничего менять не придётся. Подробнее — в разделе [Честный режим](https://war3ai.com/ru/docs/fair-mode/).
