Как играть: руководство автора бота
Здесь описано, как зарегистрировать команду, подключиться к арене и написать клиент, который управляет коврами и собирает золото. Поля игрового запроса и ответа с полными примерами приведены в [справочнике игрового API](api.md); на сайте Hub эти страницы доступны в разделе «Документация».
1. Создать команду и получить токен
1. Откройте страницу Hub и перейдите в `/register`.
2. Введите уникальное имя команды (1–48 печатных символов). Сравнение уникальности не зависит от регистра: `MyBot` и `mybot` считаются одинаковыми.
3. Hub создаст случайный токен и покажет его один раз. Сохраните его в безопасном месте, например в переменной окружения или локальном файле, который исключён из Git.
4. Используйте этот токен в заголовке `X-Auth-Token` каждого запроса к игровой арене.
Токен не выбирается игроком и не является именем команды. Это секретный ключ доступа и стабильный идентификатор команды между разными аренами. Потерянный токен нельзя восстановить из сайта; зарегистрируйте новую команду, если секрет утерян. Имя можно изменить с помощью уже выданного токена, но смена имени не меняет сам токен или статистическую идентичность команды.
Не передавайте токен в URL, не коммитьте его, не печатайте в логах и не отдавайте браузерному JavaScript. В публичной среде используйте HTTPS. API отклоняет отсутствие токена и токен, которого нет в реестре, ответом `401 Unauthorized`.
Пример безопасной локальной настройки:
export DATS_PLAYER_TOKEN='сюда-вставьте-выданный-токен'
2. Найти арену и начать игру
На главной странице Hub показаны текущий мир и адрес активной арены. Арена меняется после завершения запуска; перед началом новой сессии проверяйте актуальный URL. Подключение — обычный HTTP POST к единственному игровому endpoint:
POST http://<адрес-активной-арены>/play/magcarp/player/move
X-Auth-Token: <выданный-токен>
Content-Type: application/json
Первый запрос токена создаёт команду и её флот. Чтобы запросить начальное состояние без команды, можно отправить `{"transports":[]}`. После этого возьмите ID ковров из `transports` ответа. ID непрозрачные и стабильные при респавне; не выводите их из имени или токена самостоятельно.
Игровой API объединяет наблюдение и управление: каждый POST принимает один пакет ускорений и возвращает полный актуальный снимок мира для вашей команды. Отдельного игрового GET нет. В ответе нет номера тика, поэтому планируйте частоту по серверному шагу 200 мс. Для пакета с хотя бы одной командой сервер принимает не более одного запроса на команду за игровой тик; лишний запрос получит `429`. Не делайте немедленный retry на `429` — дождитесь следующего интервала.
Удобный цикл бота:
1. Прочитать из ответа размеры мира, параметры ковров и список сущностей.
2. Для каждого живого ковра выбрать управляющий вектор.
3. Отправить один JSON-пакет со всеми рассчитанными командами.
4. Использовать возвращённый снимок как вход следующего цикла; обрабатывать сетевые ошибки и смену арены.
Короткий пример вызова из Python (пакет `requests`):
import os
import requests
arena = "http://127.0.0.1:8080" # брать актуальный адрес из Hub
token = os.environ["DATS_PLAYER_TOKEN"]
headers = {"X-Auth-Token": token, "Content-Type": "application/json"}
state = requests.post(
arena + "/play/magcarp/player/move",
headers=headers,
json={"transports": []}, # первый вызов: создать флот и получить ID
timeout=2,
).json()
commands = [
{"id": carpet["id"], "acceleration": {"x": 0, "y": 0}}
for carpet in state["transports"] if carpet["status"] == "alive"
]
state = requests.post(
arena + "/play/magcarp/player/move",
headers=headers,
json={"transports": commands},
timeout=2,
).json()
Пример показывает только формат обмена и не задаёт стратегию управления. Серверный тик равен 200 мс; ограничение частоты и обработку ошибок см. выше.
3. Команда и ковры
Команда — игрок, идентифицируемый выданным токеном. Её флот содержит число ковров, заданное конфигурацией мира (обычно 5, в отдельных режимах 1 или 10). Новый токен создаёт новый флот. В ответе поле `name` — публичное имя команды, `points` — её текущий общий счёт, а `transports` содержит каждый отдельный ковер.
Поля собственного ковра:
| Поле | Смысл |
|---|---|
| `id` | Стабильный ID, используемый в командах; сохраняется при респавне. |
| `x`, `y` | Текущая позиция центра в координатах арены. |
| `velocity: {x, y}` | Вектор скорости. Длина вектора — скорость, направление — курс движения. |
| `selfAcceleration: {x, y}` | Последнее эффективное ускорение, заданное командой и ограниченное максимумом. |
| `anomalyAcceleration: {x, y}` | Суммарная сила аномалий в текущей точке; это внешнее воздействие, а не команда вашего бота. |
| `maxAccel`, `maxSpeed` | Лимиты приходят на верхнем уровне ответа и действуют на каждый ковер. |
| `status` | `alive` или `dead`. |
| `health` | Сейчас только индикатор жизни: 100 у живого, 0 у погибшего; убывающей шкалы HP нет. |
| `deathCount` | Сколько раз этот ковер погиб в текущем запуске арены. |
Положение — это `x,y`; три полезных вектора динамики — `velocity`, `selfAcceleration` и `anomalyAcceleration`. Модуль вектора ускорения ограничивается `maxAccel`, а модуль скорости после физического шага — `maxSpeed`. Команда задаёт ускорение, а не мгновенную скорость или координату назначения.
Если в запросе пропустить ковер либо его `acceleration`, сервер продолжит применять последнюю принятую команду. Для явного прекращения управляющей тяги отправьте нулевой вектор. Нулевая команда не означает мгновенную остановку: сохранённая скорость и внешние силы продолжают двигать ковер.
4. Мир и его сущности
Координаты и карта
`mapSize.x` и `mapSize.y` задают размеры арены. Начало координат `(0,0)` — нижний левый угол; `x` растёт вправо, `y` вверх. Все расстояния и скорости заданы в условных игровых единицах. Тик всегда равен 0,2 секунды. Активные профили и подробные настройки можно посмотреть на странице Hub `/worlds`; полный список профилей хранится в `assets/worlds.json`.
За пределами прямоугольника `0 ≤ x ≤ mapSize.x`, `0 ≤ y ≤ mapSize.y` ковер погибает. Проверяется координата центра. Граница сама по себе ещё не смерть; выход за неё — смерть.
Монеты (`bounties`)
Каждая монета сообщает `x`, `y` и `points`. При пересечении пути ковра с зоной сбора монета засчитывается, даже если центр ковра не совпал с центром монеты: сервер проверяет расстояние от центра монеты до всего отрезка движения ковра за тик. Порог в текущей настройке равен `2 × transportRadius`; для стандартного радиуса 5 это 10 игровых единиц.
Собранная монета удаляется из текущего снимка. Если у мира включён генератор пополнения, сервер создаёт новую, чтобы поддерживать заданную квоту; точка и ценность новой монеты могут отличаться. Плотность зависит от мира. Лидерборд отдельно показывает золото, собранное за попытку, остаток золота, потери ковров и расстояние.
Аномалии (`anomalies`)
Аномалия движется с постоянным на данный момент вектором `velocity`. Её параметры:
- `x`, `y` — центр;
- `effectiveRadius` — радиус внешней зоны влияния;
- `radius` — радиус смертельного ядра;
- `strength` — знаковая величина силы: `> 0` притягивает к центру, `< 0` отталкивает от центра;
- `velocity` — перемещение центра за секунду.
Внутри `effectiveRadius` аномалия добавляет силу к общей внешней силе ковра. Несколько воздействий векторно складываются. Модуль силы конкретной аномалии постоянен внутри зоны, а направление радиальное; результирующая сила меняется при движении относительно центра и других аномалий. Синяя/отталкивающая аномалия имеет отрицательный `strength`, красная/притягивающая — положительный.
Касание ядра уничтожает ковер; условие учитывает радиус ковра. Область действия силы шире смертельного ядра и сама по себе не означает гибель.
Противники (`enemies`)
`enemies` — плоский массив чужих ковров, а не массив команд. Элемент содержит координаты `x`,`y`, `velocity`, `status`, `health` и совместимые поля `killBounty`,`shieldLeftMs`. В текущей модели атаки и щиты не исполняются игровым API; не рассчитывайте на бой или защиту этими механизмами.
5. Физика, сбор золота и гибель
Для каждого тика сервер применяет схему Эйлера. В упрощённой записи:
V_next = clamp_length(V_now × friction + (A_command + W_anomalies) × 0.2, maxSpeed)
P_next = P_now + V_next × 0.2
`friction` зависит от профиля мира и не возвращается в игровом ответе. Значение меньше 1 уменьшает скорость на каждом тике; ближе к 1 — дольше сохраняет инерцию. Сервер сначала ограничивает командный вектор до `maxAccel`, складывает его с силами аномалий, обновляет и ограничивает скорость, затем позицию.
Ковер может погибнуть из-за любого из условий:
- касание смертельного ядра аномалии;
- выход за границу карты;
- столкновение с другим ковром; собственные ковры команды тоже могут сталкиваться друг с другом.
При гибели теряется заданный миром процент личного золота погибшего ковра; общий счёт уменьшается на ту же сумму. При включённом `enable_respawn` сервер возрождает ковер в безопасной случайной точке, сбрасывает скорость и ускорение, но сохраняет его ID и счётчик гибелей. При отключённом респавне ковер остаётся `dead`; если погиб весь флот, API вернёт `400 player_destroyed` и этот токен не сможет продолжить текущий запуск. В мирах с респавном первый спавн всё равно создаётся.
6. Технический цикл клиента
- Один запрос может содержать команды для нескольких ковров команды; ID ковров берутся из ответа API.
- Для одного токена сервер принимает не более одного непустого пакета команд за тик. Параллельные запросы могут столкнуться с лимитом `429`.
- Статус, позиция, скорость, лимиты, аномалии, монеты и противники передаются в каждом ответе; собственного номера тика в контракте нет.
- Отсутствие команды не останавливает ковер: сервер сохраняет последнее принятое ускорение. Нулевое ускорение также не отменяет инерцию скорости.
- Если включён респавн, ID ковра сохраняется. В ответе его `status` снова станет `alive`; `deathCount` показывает накопленные гибели.
- Разбирайте `401`, `429`, `400` и сетевые ошибки отдельно. При смене арены проверьте актуальный URL на странице Hub.
7. Формат и реальные ограничения
У запроса есть поля `id`, `acceleration`, а также совместимые `activateShield` и `attack`. Последние два поля сейчас не реализованы и игнорируются. Ответ содержит ряд исторических настроек боя и щита, однако наличие этих полей не означает наличия соответствующей механики. Единственное активное действие текущего игрового API — управляющее ускорение ковров.
Полный JSON-контракт, таблица кодов HTTP и copy-paste `curl` находятся на странице [Игровой API](api.md). Веб-приложение Hub также публикует эти два руководства в меню «Документация».