add PlaceShips message

This commit is contained in:
2026-10-27 17:31:41 +03:00
parent 31ef12b5f2
commit 6392c2ef03
7 changed files with 843 additions and 27 deletions
+62 -12
View File
@@ -27,12 +27,13 @@ JWT_SECRET=... PUBLIC_ADDR=ws://localhost:8081/ws ./server
Все сообщения — JSON-массивы, первый элемент — числовой опкод.
| Опкод | Направление | Название | Формат |
|-------|-------------|----------|--------|
| 1 | C -> S | JOIN | `[1, "<game_token>", "<user_token>"]` |
| 2 | S -> C | END | `[2, <seq>, <code>, "<reason>"]` |
| 3 | S -> C | STATE | `[3, <seq>, <state_code>]` |
| 4 | C <-> S | ACK | `[4, <seq>]` |
| Опкод | Направление | Название | Формат |
|-------|-------------|-------------|--------|
| 1 | C -> S | JOIN | `[1, "<game_token>", "<user_token>"]` |
| 2 | S -> C | END | `[2, <seq>, <code>, "<reason>"]` |
| 3 | S -> C | STATE | `[3, <seq>, <state_code>]` |
| 4 | C <-> S | ACK | `[4, <seq>]` |
| 5 | C -> S | PLACE_SHIPS | `[5, ship0_orientation, ship0_x, ship0_y, ...]` |
### JOIN (1)
@@ -85,8 +86,12 @@ JWT_SECRET=... PUBLIC_ADDR=ws://localhost:8081/ws ./server
| 4 | ваш ход |
| 5 | ожидайте ход соперника |
Сейчас рассылается только состояние `1` — при старте партии (когда оба
игрока впервые присоединились).
Смена состояний:
- Состояние `1` рассылается обоим игрокам при старте партии (когда оба игрока впервые присоединились).
- При получении расстановки кораблей от одного из игроков партия переходит в состояние ожидания соперника:
игрок, сдавший корабли, получает состояние `3` («ожидайте готовности соперника»), а его противник — состояние `2` («соперник готов»).
- Когда расстановку сдаёт второй игрок, игра переходит в фазу ходов: игрок, завершивший расстановку первым,
получает состояние `4` («ваш ход»), а второй игрок — состояние `5` («ожидайте ход соперника»).
### ACK (4)
@@ -103,6 +108,51 @@ JWT_SECRET=... PUBLIC_ADDR=ws://localhost:8081/ws ./server
Направление S->C зарезервировано для подтверждения будущих сообщений
клиента (у которых пока нет номеров).
### PLACE_SHIPS (5)
Сообщение расстановки кораблей от клиента серверу. Принимается только от игрока,
от которого ожидается расстановка в текущем состоянии партии (`StatePlacingShips` для
обоих игроков; `StatePlayer1Ready` — только для игрока 2; `StatePlayer2Ready` — только
для игрока 1). Повторные сообщения от уже расставившегося игрока или сообщения в фазе
ходов отклоняются.
Формат сообщения:
```json
[5, ship0_orientation, ship0_x, ship0_y, ship1_orientation, ship1_x, ship1_y, ..., ship9_orientation, ship9_x, ship9_y]
```
Сообщение содержит ровно 30 аргументов — по 3 аргумента на каждый из 10 кораблей
в порядке возрастания размера:
- 4 однопалубных корабля (размер 1, индексы 0..3)
- 3 двухпалубных корабля (размер 2, индексы 4..6)
- 2 трёхпалубных корабля (размер 3, индексы 7..8)
- 1 четырёхпалубный корабль (размер 4, индекс 9)
Каждый корабль описывается 3-кортежем `(orientation, x, y)`:
- `orientation` (boolean): `false` — горизонтальная ориентация (корабль продолжается
вправо по оси X от начальной клетки `(x, y)`: клетки `(x + i, y)` для `i = 0..size-1`),
`true` — вертикальная ориентация (корабль продолжается вниз по оси Y от начальной
клетки `(x, y)`: клетки `(x, y + i)` для `i = 0..size-1`). Для однопалубных кораблей
допустимо любое булево значение.
- `x` (integer): координата X начала корабля (`0 <= x <= 9`).
- `y` (integer): координата Y начала корабля (`0 <= y <= 9`).
Правила валидации расстановки:
1. Количество кораблей строго 10, размеры строго соответствуют схеме 4x1, 3x2, 2x3, 1x4.
2. Все клетки каждого корабля должны лежать строго в пределах игрового поля 10x10
(`0 <= x < 10` и `0 <= y < 10`).
3. Корабли не должны перекрываться и не должны соприкасаться сторонами или углами:
между любыми двумя различными кораблями во всех направлениях (включая диагонали)
всегда должен оставаться зазор минимум в 1 клетку.
При получении валидного сообщения сервер сохраняет расстановку в структуре матча
(в виде сетки 10x10 с идентификаторами кораблей и списка кораблей) и переводит партию
в следующее состояние:
- Если первым расстановку завершил игрок 1:
`StatePlacingShips` (1) -> `StatePlayer1Ready` (2) -> `StatePlayer1Turn` (4).
- Если первым расстановку завершил игрок 2:
`StatePlacingShips` (1) -> `StatePlayer2Ready` (3) -> `StatePlayer2Turn` (5).
## Коды закрытия соединения
| Код | Значение |
@@ -166,13 +216,13 @@ internal/ws/ — websocket-эндпоинт: апгрейд, JOIN,
go test -race ./...
```
Покрыты: валидация токенов, разбор/сборка сообщений, сценарии менеджера
(ожидание, старт, таймаут, повторный вход, замена соединения, ACK) и
сквозные интеграционные тесты через настоящий websocket.
Покрыты: валидация токенов, разбор/сборка сообщений (включая расстановку кораблей),
сценарии менеджера (ожидание, старт, таймаут, повторный вход, замена соединения, ACK,
расстановка кораблей с переходами состояний) и сквозные интеграционные тесты через настоящий websocket.
## TODO (следующие этапы)
- игровая логика (расстановка кораблей, ходы) и остальные состояния;
- игровая логика стрельбы/ходов (расстановка кораблей и переходы к фазе ходов уже реализованы);
- завершение партии по итогам игры с персонифицированными кодами
победы/поражения;
- репорт итогов партии на main-server (реестр завершённых партий уже