implement game turn logic
This commit is contained in:
+47
-5
@@ -34,6 +34,8 @@ JWT_SECRET=... PUBLIC_ADDR=ws://localhost:8081/ws ./server
|
||||
| 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, ...]` |
|
||||
| 6 | C -> S | FIRE | `[6, <x>, <y>]` |
|
||||
| 7 | S -> C | FIRE_RESULT | `[7, <seq>, <result_code>]` |
|
||||
|
||||
### JOIN (1)
|
||||
|
||||
@@ -67,11 +69,15 @@ JWT_SECRET=... PUBLIC_ADDR=ws://localhost:8081/ws ./server
|
||||
|
||||
Партия завершена. Формат: `[2, <seq>, <code>, "<reason>"]`.
|
||||
|
||||
Коды завершения:
|
||||
Коды завершения (отсылаются с точки зрения получателя):
|
||||
|
||||
| Код | Причина |
|
||||
|-----|---------|
|
||||
| -1 | `join timeout exceeded` — второй игрок не присоединился вовремя |
|
||||
| Код | Причина | Описание |
|
||||
|-----|---------|----------|
|
||||
| -1 | `join timeout exceeded` | второй игрок не присоединился вовремя |
|
||||
| 1 | `victory` | победа (все корабли соперника уничтожены) |
|
||||
| 2 | `defeat` | поражение (все корабли игрока уничтожены) |
|
||||
|
||||
После отправки сообщения END сервер сразу закрывает WebSocket-соединение с кодом 1000 (нормальное завершение). Сохранённое сообщение END хранится в реестре завершённых партий и автоматически воспроизводится игроку при повторном подключении перед закрытием соединения.
|
||||
|
||||
### STATE (3)
|
||||
|
||||
@@ -92,10 +98,13 @@ JWT_SECRET=... PUBLIC_ADDR=ws://localhost:8081/ws ./server
|
||||
игрок, сдавший корабли, получает состояние `3` («ожидайте готовности соперника»), а его противник — состояние `2` («соперник готов»).
|
||||
- Когда расстановку сдаёт второй игрок, игра переходит в фазу ходов: игрок, завершивший расстановку первым,
|
||||
получает состояние `4` («ваш ход»), а второй игрок — состояние `5` («ожидайте ход соперника»).
|
||||
- При промахе ход переходит к противнику: стрелявший игрок получает состояние `5` («ожидайте ход соперника»), а противник — состояние `4` («ваш ход»).
|
||||
- При попадании или потоплении корабля ход остаётся у текущего стрелка (состояние матча не изменяется).
|
||||
- При уничтожении всех кораблей одного из игроков игра завершается победой: партия не переходит в новые состояния STATE — вместо этого обоим игрокам рассылается сообщение END (победителю — с кодом 1 victory, проигравшему — с кодом 2 defeat), после чего соединение сразу закрывается.
|
||||
|
||||
### ACK (4)
|
||||
|
||||
Каждое изменяющее состояние сообщение S->C (END, STATE) несёт `seq` —
|
||||
Каждое изменяющее состояние сообщение S->C (END, STATE, FIRE_RESULT) несёт `seq` —
|
||||
монотонно возрастающий номер в рамках пары (партия, игрок). Клиент
|
||||
подтверждает доставку сообщением `[4, <seq>]`; ACK кумулятивен
|
||||
(подтверждает все сообщения с `seq` <= указанного).
|
||||
@@ -153,6 +162,39 @@ JWT_SECRET=... PUBLIC_ADDR=ws://localhost:8081/ws ./server
|
||||
- Если первым расстановку завершил игрок 2:
|
||||
`StatePlacingShips` (1) -> `StatePlayer2Ready` (3) -> `StatePlayer2Turn` (5).
|
||||
|
||||
### FIRE (6)
|
||||
|
||||
Сообщение выстрела от клиента к серверу. Содержит координаты клетки на поле соперника:
|
||||
```json
|
||||
[6, x, y]
|
||||
```
|
||||
- `x` (integer): координата X (колонка, `0 <= x <= 9`).
|
||||
- `y` (integer): координата Y (строка, `0 <= y <= 9`).
|
||||
|
||||
Обработка сообщения сервером:
|
||||
- Сообщение принимается только от игрока, чей сейчас ход (`StateYourTurn` / серверное состояние `StatePlayer1Turn` или `StatePlayer2Turn`). Сообщения от игрока не в свой ход, во время фазы расстановки или после завершения партии игнорируются без ответа.
|
||||
- Если координаты выходят за границы игрового поля (`x < 0` или `x >= 10`, `y < 0` или `y >= 10`) либо клетка уже была поражена ранее (выстрелом, попаданием или окаймлением потопленного корабля), сервер возвращает стрелявшему игроку результат `4` (`неверная позиция`). Право хода остаётся у текущего игрока.
|
||||
- Если выстрел произведён в валидную ещё не поражённую клетку:
|
||||
- При промахе (клетка с водой) клетка помечается поражённой, игроку отправляется результат `1` (`промах`), а ход переходит противнику (рассылается `STATE` 5 и 4).
|
||||
- При попадании в корабль, если корабль ещё не уничтожен полностью, клетка помечается поражённой, игроку отправляется результат `2` (`простое попадание`). Стрелявший игрок продолжает свой ход.
|
||||
- Если корабль уничтожен полностью, все клетки корабля и все соседние с ним клетки (включая диагональные) помечаются поражёнными, а игроку отправляется результат `3` (`корабль потоплен`). Если после этого у противника не осталось непотопленных кораблей, партия завершается: сервер отправляет обоим игрокам сообщение END (`1` victory победителю и `2` defeat проигравшему) и сразу закрывает соединения. Если у противника ещё остались корабли, стрелявший игрок продолжает ход.
|
||||
|
||||
### FIRE_RESULT (7)
|
||||
|
||||
Результат выстрела, отправляемый сервером стрелявшему игроку в ответ на выстрел. Содержит порядковый номер сообщения `seq` для подтверждения через ACK и числовой код результата:
|
||||
```json
|
||||
[7, <seq>, <result_code>]
|
||||
```
|
||||
|
||||
Коды результатов выстрела:
|
||||
|
||||
| Код | Результат | Описание |
|
||||
|-----|-----------|----------|
|
||||
| 1 | `miss` (промах) | Выстрел в пустую клетку поля соперника. Клетка помечается как поражённая, ход переходит сопернику. |
|
||||
| 2 | `hit` (простое попадание) | Попадание в палубу корабля соперника, но корабль ещё имеет уцелевшие палубы. Клетка помечается как поражённая, право хода остаётся у стрелявшего игрока. |
|
||||
| 3 | `sunk` (корабль потоплен) | Корабль полностью уничтожен последним выстрелом. Все палубы корабля и все окружающие его клетки (включая диагональные) помечаются как поражённые. Если все корабли соперника уничтожены, партия завершается победой (рассылается сообщение END и соединение сразу закрывается). В противном случае право хода остаётся у стрелявшего игрока. |
|
||||
| 4 | `invalid_position` (неверная позиция) | Координаты выходят за пределы поля `10x10` либо указанная клетка уже была поражена ранее. Право хода остаётся у игрока. |
|
||||
|
||||
## Коды закрытия соединения
|
||||
|
||||
| Код | Значение |
|
||||
|
||||
Reference in New Issue
Block a user