Документация Справочник
Квитанции и коды причин
Квитанция каждой команды содержит код статуса и код причины. На них опирается самокоррекция ботов и агентов: «почему не получилось» превращается в машиночитаемое число.
r = g.train(barracks, "hfoo")
bool(r) # False
r.status # 1 -> rejected
r.verdict # 3 -> не хватает пищи
r.reason # 'rejected(人口不够)' (= «не хватает пищи»)
r.exec_us # сколько микросекунд команда выполнялась в игровом потоке
if r: эквивалентно r.status == 0 (движок принял команду).
Код статуса status
| Код | Имя | Значение | Типичная причина |
|---|---|---|---|
| 0 | accepted | Движок принял команду | — (но «принята» ≠ «выполнена», см. ниже) |
| 1 | rejected | Движок отклонил команду | Смотрите verdict |
| 2 | bad_unit | Юнита нет или дескриптор не совпадает | Юнит уже погиб; использован устаревший объект юнита |
| 3 | not_owner | Это не ваш юнит | Командуете чужим юнитом от имени player |
| 4 | fault | Исключение при выполнении (рантайм его перехватил, игра не упадёт) | Сообщите нам, приложив шаги воспроизведения |
| 5 | bad_args | Неверные аргументы | Ошибка в координатах, номере ячейки или четырёхсимвольном коде |
| 6 | unsupported | Не поддерживается | В этой версии рантайма нет такой возможности |
| 7 | bad_target | Недопустимая цель | Цели уже нет; неподходящий тип цели |
| 8 | forbidden | Роль полосы этого не позволяет | Приказ от имени observer |
| 97 | cancelled | В блоке пачки возникло исключение, вся пачка не отправлена | Ошибка в коде внутри блока with g.batch(): |
| 98 | held | Юнита удерживает слой с более высоким приоритетом, команда не отправлена | Этого юнита держит рефлекторный слой эталонного мозга или ручной приказ из консоли |
| 99 | timeout | Тайм-аут | Игра на паузе или подвисла, и дедлайн истёк (просроченные команды уже не выполняются) |
Код причины verdict
При отклонении рантайм объясняет причину с помощью собственной проверки выполнимости движка. Можно и не отдавать приказ, а сначала спросить: g.can_do(юнит, код) возвращает те же коды.
| Код | Значение | Что делать |
|---|---|---|
| 0 / 220 | Можно | — |
| 3 | Не хватает пищи | Постройте здание для пищи; g.production(b).blocked покажет проблему заранее |
| 8 | Не хватает золота | Подождите; перед приказом проверяйте g.can_afford(code) |
| 9 | Не хватает древесины | Отправьте больше рабочих на лес |
| 32 | Очередь тренировки заполнена (7 мест) | Держите в очереди 1 юнит: ставьте следующего, когда g.queue(b) опустеет |
| 183 | Нет требуемой технологии / здания | Сначала постройте требуемое здание или перейдите на следующий тир |
| 185 | Здание занято | Алтарь воскрешает героя; главное здание нельзя улучшить, пока его очередь не пуста |
| 221 | Такого пункта нет / строится / улучшается / уже существует | Герой уже есть (погибшего нужно revive); этот магазин такое не продаёт |
| 89 | Товар ещё не поступил в магазин | В начале матча товары появляются по времени из таблицы предметов; у только что построенного магазина отсчёт идёт с момента завершения постройки |
| 1001 | Цель не видна | Цель в тумане войны или под чёрной маской; сделайте attack_move в её позицию |
«Принята» ≠ «выполнена»
Квитанция лишь сообщает, что «движок принял команду», и считывается в том же кадре. Что произойдёт потом, она не отражает:
| Команда | Что может сорваться уже после принятия | Как проверить |
|---|---|---|
| Строительство | Точку в лесу движок тоже сразу принимает, а срывается всё, когда рабочий дойдёт до места | Используйте build_near (он следит, появился ли фундамент) или ждите production.done |
| Применение способности | Прервали, не хватило маны | На следующем тике проверьте, ушла ли способность на перезарядку: g.cooldown(u, способность) |
| Тренировка | Встала в очередь, но пищи не хватает, и она не начинается | g.production(b).blocked |
| Движение / атака | Перебита другой логикой (или слоем с более высоким приоритетом) | g.current_target(u), g.order_of(u) |
Методы-запросы
Эти методы не отдают приказов, а только спрашивают движок; результат тоже кладётся в поле value квитанции (SDK возвращает само значение):
| Метод | Возвращает |
|---|---|
g.can_do(u, code) / g.can_do_many([(u, code), ...]) | Код причины из таблицы выше |
g.tech(code, player=None) / g.tech_many([...]) | Уровень исследования / число построенных зданий (с учётом цепочки улучшений) |
g.visible(x, y) | Видна ли эта точка нашей стороне |
g.gold_left(mine) | Сколько золота осталось в руднике |
g.enemy_ai_plan(вражеский_юнит) | Куда капитан компьютерного противника поведёт армию (работает только для компьютерного ИИ) |