Протокол используется как для web-приложения, так и для отдельных клиентов. Запрос к серверу — обычный POST-запрос в кодировке UTF-8. Ответ сервера — объект, сериализованный в JSON.
Для идентификации пользователя используется идентификатор сессии. Отдельные клиенты получают сессию при авторизации. В случае с web-клиентом код сессии может внедряться в код клиента — в этом случае он не должен совпадать с кодом обычной сессии, хранящейся в куках, что служит защитой от CSRF-атак.
Версия протокола, разумеется, не последняя, в будущем наверняка появятся новые. Чтобы упростить жизнь игрокам и разработчикам клиентов, сервер, реализующий протокола версии N, обязан поддерживать работу с клиентами, реализущими версию N-1. Также желательно поддерживать и более ранние версии.
Новый сервер совместим с клиентом, использующим старую версию протокола, если:
Две версии протокола совместимы, если в новой версии имеются только следующие отличия от старой:
Для совместимости клиенты должны выполнять следующие требования:
Тип в JavaScript | Тип в POST-запросе |
---|---|
null | пустая строка |
boolean | «0» (ложь) или «1» (истина) |
number | строковое представление числа |
string | строка |
В случае с массивами и объектами генерируется отдельное поле запроса для каждого скалярного элемента или поля всех уровней вложенности. Имя такого поля имеет форму имя_объекта[ключ_или_индекс1][ключ_или_индекс2]… Например, год[2012][декабрь][21].
Для задания времени используется число, представляющее метку времени UNIX.
Массив, отсортированный по убыванию времени окончания боя. Формат элемента:
Ключ | Значение |
---|---|
FightId | идентификатор боя |
FightType | тип боя: «train» (тренировочный) или «challenge» (рейтинговый) |
FightTime | время окончания боя |
TurnLimit | лимит ходов на бой |
TurnCount | длительность боя |
PlayerId | идентификатор игрока, «заказавшего» бой |
PlayerName | имя игрока, «заказавшего» бой |
Snakes | список из 4 змей (null для отсутствующих), участвующих в бою; см. поле Snakes |
Массив, содержащий от 1 до 9 карт программы. Карта представлена в виде объекта:
Поле | Описание |
---|---|
Description | текстовое описание карты |
HeadX | координата x головы своей змеи (0 – 6) |
HeadY | координата y головы своей змеи (0 – 6) |
Lines | массив из описаний строк карты |
Голова змеи всегда смотрит вверх. Описание строк карты является объектом:
Поле | Описание |
---|---|
X | координата x начала линии (0 – 6) |
Y | координата y начала линии (0 – 6) |
Line | описание линии карты |
Линия карты длиной n клеток задается строкой из 2×n символов. Первый символ пары задает набор элементов:
Символ | Значение |
---|---|
- | шаблон не определен либо в данной клетке находится голова своей змеи |
A – D | пользовательские наборы элементов 1 – 4 |
S | тело змеи игрока |
T | хвост змеи игрока |
V | пустая клетка |
W | граница поля |
X | голова змеи противника |
Y | тело змеи противника |
Z | хвост змеи противника |
Соответствующие символы в нижнем регистре обозначают инвертированные наборы элементов; так, например, символ «t» означает «все, кроме хвоста своей змеи». Второй символ пары задает группу, к которой принадлежит шаблон:
Символ | Значение |
---|---|
- | шаблон не определен либо в данной клетке находится голова своей змеи |
0 – 3 | И-группа 1 – 4 |
4 – 7 | ИЛИ-группа 1 – 4 |
Строка описывает часть линии карты слева направо с координаты (X; Y). Если длина строки слишком велика, то остаток строки переносится на следующую линию с координаты (0; Y + 1). Например, объект {X: 6, Y: 2, Line: «A1B2C3»} описывает клетки с координатами (6; 2), (0; 3), (1; 3). «Переполнение» последней линии карты является ошибкой.
Массив. Формат элемента:
Ключ | Значение |
---|---|
PlayerId | идентификатор игрока |
PlayerName | имя игрока |
Rating | текущий рейтинг; null, если не участвует |
Массив. Формат элемента:
Ключ | Значение |
---|---|
SnakeId | идентификатор змеи |
SnakeName | имя змеи |
SnakeType | тип змеи: «B» (бот) или «N» (обычная) |
SkinId | идентификатор окраски |
Массив. Формат элемента:
Ключ | Значение |
---|---|
PlayerId | идентификатор игрока |
PlayerName | имя игрока |
Rating | текущий рейтинг игрока |
SnakeId | идентификатор бойца |
SnakeName | имя бойца |
SkinId | идентификатор окраски бойца |
Массив, осортирован по названию окраски. Формат элемента:
Ключ | Значение |
---|---|
SkinId | идентификатор окраски |
SkinName | название окраски |
Массив из 10 элементов, null для отсутствующих. Формат элемента:
Ключ | Значение |
---|---|
SlotName | имя сохраненного боя |
FightId | идентификатор боя |
FightType | тип боя |
FightTime | время окончания боя |
Массив. Формат элемента:
Ключ | Значение |
---|---|
SnakeId | идентификатор змеи |
SnakeName | имя змеи |
SnakeType | тип змеи: «B» (бот) или «N» (обычная) |
SkinId | идентификатор окраски |
PlayerId | идентификатор владельца |
PlayerName | имя владельца |
Массив из 4 элементов, содержащих описания змей, null для отсутствующих. Элемент является объектом:
Ключ | Значение |
---|---|
SnakeId | идентификатор змеи, null для временной |
SnakeName | имя змеи |
SnakeType | тип змеи: «B» (бот) или «N» (обычная) |
SkinId | идентификатор окраски |
PlayerId | идентификатор владельца |
PlayerName | имя владельца |
Массив из 4 элементов, содержащих информацию о змеях, участвовавших в бою, null для отсутствующих. Элемент является объектом:
Ключ | Значение | |
---|---|---|
Status | состояние змеи на последнем ходу боя: | |
«free» | змея сделала шаг | |
«blocked» | не смогла сделать шаг (заблокирована) | |
«eaten» | змея съедена | |
FinalLength | итоговая длина змеи | |
InitialRating | рейтинг владельца перед началом боя; отсутствует для тренировочных боев | |
FinalRating | рейтинг владельца по итогам боя; отсутствует для тренировочных боев | |
ProgramDescription | описание программы (отсутствует для чужих обычных змей) | |
Templates | пользовательские шаблоны (отсутствует для чужих обычных змей); см. Templates | |
Maps | карты программы (отсутствует для чужих обычных змей); см. Maps | |
DebugData | отладочная информация (отсутствует для чужих обычных змей) |
DebugData является строкой, кодирующей последовательность решений змеи на каждом ходу. Каждый символ кодирует число в диапазоне 1 – 79, равное ASCII-коду символа минус 32 («!» – «o»). Число состоит из двух или трех полей:
Если используется карта:
Биты | Описание | |
---|---|---|
0 – 1 | ориентация карты: | |
0 | оригинал | |
1 | по часовой стрелке | |
2 | перевернута | |
3 | против часовой стрелки | |
2 | отражение карты по вертикальной оси оригинала (0: нет, 1: есть) | |
3 – 6 | номер карты (1 – 9) |
Если карта не используется:
Биты | Описание | |
---|---|---|
0 – 1 | причина: | |
1 | нет возможных ходов, пропуск хода | |
2 | только один возможный ход | |
3 | нет подходящей карты | |
2 – 6 | 0 |
В случае, если отладочная информация для змеи недоступна (чужая обычная змея или в бою участвуют меньше 4 змей), то соответствующий элемент массива содержит null.
Массив из 4 строк длиной от 1 до 6 различных символов. Каждая строка задает пользовательский набор элементов. Элементы кодируются следующими символами:
Символ | Значение |
---|---|
S | тело змеи игрока |
T | хвост змеи игрока |
V | пустая клетка |
W | граница поля |
X | голова змеи противника |
Y | тело змеи противника |
Z | хвост змеи противника |
Другие символы недопустимы. Порядок символов не имеет значения.
Массив из 1 – 1000 чисел, кодирующих очередность и направления шагов. Формат:
Биты | Значение |
---|---|
0 – 1 | первый номер змеи (0 – 3) |
2 – 3 | второй номер змеи (0 – 3) |
4 – 5 | третий номер змеи (0 – 3) |
6 – 7 | направление движения первой змеи |
8 – 9 | направление движения второй змеи |
10 – 11 | направление движения третьей змеи |
12 – 13 | направление движения четвертой змеи |
Все номера змей различны. Четвертый номер однозначно выводится из первых трех. Порядок всегда генерируется для четырех змей. Если змея с указанным номером отсутствует, то при расчете/отображении боя она пропускается.
Направление движения змеи:
Число | Значение |
---|---|
0 | не движется (нет ходов, съедена или не участвует) |
1 | налево |
2 | прямо |
3 | направо |
Поле | Описание |
---|---|
Compatible | минимальный номер версии клиента, совместимого с текущим |
Count | количество запрашиваемых записей |
Error | текстовое описание ошибки; может содержать данные, вызвавшие ошибку, в т. ч. имя поля в формате «поле.элемент.подэлемент» |
ErrorCode | числовой код ошибки |
FightId | идентификатор боя |
FightList | отсортированный список боев, см. выше |
FightListType | тип списка боев: «ordered» (заказанные) или «challenged» (рейтинговые, заказанные другими) |
FightResult | результат боя: «limit» (лимит ходов), «eaten» (съедены все змеи, кроме одной) или «blocked» (нет возможных ходов) |
FightTime | дата и время окончания боя |
FightType | тип боя, «train» (обычный) или «challenge» (рейтинговый) |
FirstIndex | индекс первого элемента списка |
Hash | хэш: SHA1(SHA1(SHA1(логин «:» пароль) соль) штамп); соль выдается сервером в ответе «login data» |
Lifetime | время жизни сессии после последнего запроса к серверу, в секундах |
Login | логин пользователя, в нижнем регистре |
OtherSnakeIds | массив из 3 идентификаторов змей, null для отсутствующих |
PlayerId | идентификатор игрока |
PlayerIds | массив из 3 различных идентификаторов игроков, участвующих рейтинге, кроме текущего игрока |
PlayerList | отсортированный список игроков, см. выше |
PlayerName | имя пользователя |
PlayerSnakes | список змей игрока, см. выше |
ProgramDescription | описание программы |
Rating | числовой рейтинг игрока |
Ratings | отсортированная таблица рейтингов, см. выше |
Request | тип запроса |
RequestId | клиентский идентификатор запроса, любой тип |
Response | тип ответа |
Salt | соль, используемая для генерации хэша при авторизации |
Sid | идентификатор сессии |
SkinId | идентификатор окраски змеи, целое неотрицательное число |
SkinList | список вариантов окраски змей, см. выше |
SlotIndex | номер сохраненного боя (0 – 9) |
SlotList | отсортированный список сохраненных боев, см. выше |
SlotName | описание сохраненного боя |
SnakeId | идентификатор змеи, null для временной |
SnakeIds | массив из 4 идентификаторов змей, null для отсутствующих |
SnakeList | отсортированный список змей, см. выше |
SnakeName | имя змеи |
Snakes | массив из 4 описаний змей, null для отсутствующих, см. выше |
SnakeStats | массив из 4 элементов, содержащих результаты боя для каждой змеи, null для отсутствующих, см. выше |
SnakeType | тип змеи: «B» (бот) или «N» (обычная) |
SnakeTypes | строка из 1 – 2 символов типов змей |
SortBy | список вида [<имя_поля/>имя_поля*], задающий имена полей для сортировки и порядок их сортировки («<» — по возрастанию, «>» — по убыванию) |
Templates | пользовательские шаблоны для программы, см. выше |
Timestamp | метка времени; не должна отличаться от метки времени сервера больше, чем на 3 минуты |
TotalCount | общее количество объектов (игроков, змей) |
TurnLimit | максимальное количество ходов для боя, 1 — 1000 |
Turns | информация о ходах, см. выше |
Version | текущий номер версии протокола |
Все имена полей и их содержимое регистрозависимы. Поля, которые не могут входить в данный запрос, игнорируются.
Все поля, перечисленные в описании запроса, обязательны (если в описании явно не указано иное). Помимо перечисленных полей запрос должен содержать поле Sid (если в описании запроса не указано иное). Также запрос может содержать необязательное поле RequestId. В этом случае ответ сервера будет содержать одноименное поле, содержимое которого совпадает с этим полем запроса.
В случае успешного выполнения запроса сервер выдает ответ, указанный в описании запроса. В случае неудачи возвращается один из следующих ответов:
relogin
, если время жизни сессии истекло либо данные авторизации были изменены;nack
, если в запросе есть ошибки;error
, если произошла внутренняя ошибка сервера.При авторизации используется хэш-функция SHA1, ее реализацию для JavaScript можно найти, например, здесь. На входе функции — строка в кодировке UTF-8, на выходе — шестнадцатиричное текстовое представление хэша в нижнем регистре (40 символов 0 – 9, a – f). Примеры:
SHA1(SHA1(«hello»)) == «9cf5caf6c36f5cccde8c73fad8894c958f4983da»
SHA1(SHA1(«привет»)) == «60a72cfc2aa27af4b1bda6d18cf50a27046914c4»
получение информации о сервере
Request
: «info»
Sid
: не требуется (игнорируется)
ответ: «info»
получение информации о текущем пользователе
Request
: «whoami»
ответ: «whoami»
получение данных (соль, штамп сервера) для авторизации
Request
: «login data»
Sid
: не требуется (игнорируется)
Login
:
ответ: «login data»
авторизация и открытие сессии
Request
: «login»
Sid
: не требуется (игнорируется)
Login
:
Timestamp
:
Hash
:
ответ: «login»
выход и закрытие сессии
Request
: «logout»
ответ: «ack»
таблица рейтингов игроков
Request
: «ratings»
FirstIndex
: необязательно, по умолчанию 0
Count
: необязательно, 1 – 50, по умолчанию 30
SortBy
: необязательно, возможные ключи: PlayerName или Rating, по умолчанию [«>Rating»]
ответ: «ratings»
список игроков, отсортированный по имени
Request
: «player list»
FirstIndex
: необязательно, по умолчанию 0
Count
: необязательно, 1 – 50, по умолчанию 30
SortBy
: необязательно, возможные ключи: PlayerName, по умолчанию [«<PlayerName»]
ответ: «player list»
информация об игроке
Request
: «player info»
PlayerId
:
ответ: «player info»
список всех змей
Request
: «snake list»
SnakeTypes
: необязательно, по умолчанию «BN»
FirstIndex
: необязательно, по умолчанию 0
Count
: необязательно, 1 – 50, по умолчанию 30
SortBy
: необязательно, возможные ключи: SnakeName или PlayerName, по умолчанию [«<SnakeName», «<PlayerName»]
ответ: «snake list»
получение списка вариантов окраски змей
Request
: «skin list»
ответ: «skin list»
информация о змее
Request
: «snake info»
SnakeId
:
ответ: «snake info»
создание новой змеи
Request
: «snake new»
SnakeName
:
SnakeType
:
SkinId
:
ProgramDescription
:
Templates
:
Maps
:
ответ: «snake new»
удаление своей змеи
Request
: «snake delete»
SnakeId
:
ответ: «ack»
редактирование змеи
Request
: «snake edit»
SnakeId
:
SnakeName
: необязательно
SnakeType
: необязательно
SkinId
: необязательно
ProgramDescription
: необязательно
Templates
: необязательно
Maps
: необязательно
ответ: «ack»
назначение своей обычной змеи бойцом
Request
: «snake assign»
SnakeId
:
ответ: «ack»
список боев игрока
Request
: «fight list»
FightListType
:
ответ: «fight list»
информация о бое
Request
: «fight info»
FightId
:
ответ: «fight info», «fight delayed»
начать бой со временной змеей; временная змея будет первой
Request
: «fight test»
TurnLimit
: необязательно
SnakeName
:
SkinId
:
ProgramDescription
:
Templates
:
Maps
:
OtherSnakeIds
:
ответ: «fight info», «fight delayed»
начать обычный бой
Request
: «fight train»
TurnLimit
: необязательно
SnakeIds
:
ответ: «fight info», «fight delayed»
начать рейтинговый бой
Request
: «fight challenge»
PlayerIds
:
ответ: «fight info», «fight delayed»
отменить бой
Request
: «fight cancel»
ответ: «ack»
список сохраненных боев
Request
: «slot list»
ответ: «slot list»
загрузить информацию о сохраненном бое
Request
: «slot view»
SlotIndex
:
ответ: «slot view»
сохранить информацию о бое
Request
: «slot save»
SlotIndex
:
SlotName
:
FightId
:
ответ: «ack»
изменение описания сохраненного боя
Request
: «slot rename»
SlotIndex
:
SlotName
:
ответ: «ack»
очистить сохраненный бой
Request
: «slot delete»
SlotIndex
:
ответ: «ack»
обновление сессии
Request
: «ping»
ответ: «ack»
Все поля, перечисленные в описании ответа, обязательны (если в описании явно не указано иное). Если в запросе было поле RequestId, то ответ также содержит это поле с тем же значением. В будущих версиях протокола могут появиться дополнительные поля ответов; старые версии клиентов должны игнорировать такие поля.
Сообщение об ошибке может быть выдано в ответ на любой запрос.
требуется заново авторизоваться (истекло время жизни сессии, изменились данные авторизации или просто указан неверный идентификатор сессии)
Response
: «relogin»
ошибка в запросе
Response
: «nack»
ErrorCode
:
Error
:
внутренняя ошибка
Response
: «error»
ErrorCode
:
Error
:
подтверждение выполнения запроса
Response
: «ack»
информация о сервере
Response
: «info»
Version
:
Compatible
:
Lifetime
:
информация о текущем игроке
Response
: «whoami»
PlayerId
:
PlayerName
:
FightId
: текущий отложенный бой (null, если отложенных боев нет)
Rating
: отсутствует, если игрок не участвует в рейтинге
SnakeId
: ид бойца; отсутствует, если игрок не участвует в рейтинге
SnakeName
: имя бойца; отсутствует, если игрок не участвует в рейтинге
SkinId
: окраска бойца; отсутствует, если игрок не участвует в рейтинге
данные для авторизации; если в запросе «login data» указан неизвестный логин, это не считается ошибкой
Response
: «login data»
Login
:
Salt
:
Timestamp
:
успешная авторизация
Response
: «login»
PlayerId
:
PlayerName
:
Sid
:
таблица рейтингов
Response
: «ratings»
FirstIndex
:
SortBy
:
TotalCount
:
Ratings
:
список игроков
Response
: «player list»
FirstIndex
:
SortBy
:
TotalCount
:
PlayerList
:
информация об игроке
Response
: «player info»
PlayerId
:
PlayerName
:
Rating
:
SnakeId
: идентификатор бойца или null
PlayerSnakes
:
список змей
Response
: «snake list»
SnakeTypes
:
FirstIndex
:
SortBy
:
TotalCount
:
SnakeList
:
список вариантов окраски
Response
: «skin list»
SkinList
:
информация о змее
Response
: «snake info»
SnakeId
:
SnakeName
:
SnakeType
:
SkinId
:
PlayerId
:
PlayerName
:
ProgramDescription
: необязательно, выдается только для ботов и своих змей
Templates
: необязательно, выдается только для ботов и своих змей
Maps
: необязательно, выдается только для ботов и своих змей
создана новая змея
Response
: «snake new»
SnakeId
:
список боев
Response
: «fight list»
FightListType
:
FightList
:
информация о бое
Response
: «fight info»
FightId
:
FightType
:
FightTime
:
FightResult
:
TurnLimit
:
Turns
:
Snakes
:
SnakeStats
:
расчет боя не завершен
Response
: «fight delayed»
FightId
:
список сохраненных боев
Response
: «slot list»
SlotList
:
информация о сохраненном бое
Response
: «slot view»
SlotIndex
:
SlotName
:
FightType
:
FightTime
:
FightResult
:
TurnLimit
:
Turns
:
Snakes
:
SnakeStats
:
Код | Описание | Текст ошибки содержит: |
---|---|---|
0 | сервер временно недоступен | причина |
1 | неизвестное имя запроса | содержимое поля Request |
2 | неизвестное имя поля | имя поля |
3 | отсутствует необходимое поле | имя поля |
4 | некорректное значение поля | имя поля, содержимое поля |
5 | слишком длинная строка | имя поля, максимальная длина |
6 | неизвестный логин или неверный хэш | |
7 | неизвестный идентификатор игрока | идентификатор |
8 | неизвестный идентификатор змеи | идентификатор |
9 | неизвестный идентификатор боя | идентификатор |
10 | игрок не участвует в рейтинге | идентификатор |
11 | некорректный формат поля | имя поля, содержимое поля |
12 | невозможно удалить бойца или сменить его тип | идентификатор змеи |
13 | некорректная окраска змеи | идентификатор змеи, указанная окраска |
14 | невозможно назначить бойцом бота | идентификатор змеи |
15 | сохраненный бой с указанным индексом отсутствует | индекс |
16 | чужая змея | идентификатор |
17 | невозможно «заказать» бой, поскольку есть незавершенный бой | идентификатор боя |
18 | у игрока уже максимально допустимое количество змей | количество |
19 | некорректные данные в запросе | описание |
20 | некорректное описание линии карты | номер карты, номер линии, линия |
В будущих версиях протокола могут появиться новые (более специфические) коды ошибок.