Документация Основные понятия

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

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

Отдайте эту страницу LLM вместе с api.json — бот, которого она напишет, обойдёт множество ловушек.

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

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

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

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

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

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

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

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

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 видны только юниты, предметы, производство и события в пределах обзора — именно по этим правилам играют на Арене. Пишите под честный режим уже сейчас, и при переходе на Арену ничего менять не придётся. Подробнее — в разделе Честный режим.