# План: Game Rules & Match Logic (M5)

**Цель:** Реализовать систему судейства, подсчёт голов, таймер матча и управление состояниями игры (Playing, GoalPause, MatchEnded).

**Архитектура:** Введение `MatchManager` в качестве верхнего уровня управления. Он владеет `World` и контролирует, когда физика и ИИ мира должны обновляться, а когда игра должна быть заморожена.

**Стек:** Go.

**Спека:** [docs/specs/2026-05-12-match-logic-design.md](../specs/2026-05-12-match-logic-design.md)

---

## Файловая структура

- `internal/game/world.go` — добавление методов для проверки гола и сброса позиций.
- `internal/game/match_manager.go` — новый файл с логикой управления матчем, счетом и таймерами.
- `cmd/game/main.go` — замена `World` на `MatchManager` в основном цикле игры.

---

## Задачи

### Задача 1: Методы управления состоянием мира

**Файлы:**
- Изменить: `internal/game/world.go`

- [ ] **Шаг 1: Реализовать `CheckGoal()`**
  - Метод должен проверять `Puck.Position.X`.
  - Если `X < 0` $\rightarrow$ возвращает `(entities.TeamBlue, true)`.
  - Если `X > WorldWidth` $\rightarrow$ возвращает `(entities.TeamRed, true)`.
  - Иначе $\rightarrow$ `(entities.TeamRed, false)`.

- [ ] **Шаг 2: Реализовать `ResetPositions()`**
  - Установить `Puck.Position` в центр поля, `Puck.Velocity = 0`.
  - Для каждого игрока в `Players` установить `Position = HomePosition` и `Velocity = 0`.

- [ ] **Шаг 3: Коммит**
  `git add internal/game/world.go && git commit -m "feat(game): add CheckGoal and ResetPositions to World"`

### Задача 2: Реализация MatchManager

**Файлы:**
- Создать: `internal/game/match_manager.go`

- [ ] **Шаг 1: Определить типы и структуру**
  - `GameState` (enum: `Playing`, `GoalPause`, `MatchEnded`).
  - `MatchManager` структура:
    - `World *World`
    - `State GameState`
    - `ScoreRed, ScoreBlue int`
    - `MatchDuration float64` (в секундах)
    - `CurrentTime float64`
    - `PauseDuration float64`
    - `PauseTimer float64`

- [ ] **Шаг 2: Реализовать `Update(dt float64)`**
  - Логика переключения состояний:
    - Если `Playing`:
      - Проверить `World.CheckGoal()`. Если гол $\rightarrow$ `State = GoalPause`, обновить счет, `PauseTimer = PauseDuration`.
      - Если не гол $\rightarrow$ вызвать `World.Update(dt)`.
      - Обновить `CurrentTime += dt`. Если `CurrentTime >= MatchDuration` $\rightarrow$ `State = MatchEnded`.
    - Если `GoalPause`:
      - `PauseTimer -= dt`.
      - Если `PauseTimer <= 0` $\rightarrow$ вызвать `World.ResetPositions()`, `State = Playing`.
    - Если `MatchEnded`:
      - Ничего не делать.

- [ ] **Шаг 3: Коммит**
  `git add internal/game/match_manager.go && git commit -m "feat(game): implement MatchManager for game rules"`

### Задача 3: Интеграция в Main Loop

**Файлы:**
- Изменить: `cmd/game/main.go`

- [ ] **Шаг 1: Обновить структуру `Game`**
  - Заменить `world *game.World` на `matchManager *game.MatchManager`.

- [ ] **Шаг 2: Обновить инициализацию в `NewGame()`**
  - Создать `world := game.NewWorld()`.
  - Создать `matchManager := game.NewMatchManager(world)`.

- [ ] **Шаг 3: Обновить `Update()` и `Draw()`**
  - В `Update()` вызывать `g.matchManager.Update(dt)`.
  - В `Draw()` передавать `g.matchManager.World` в функцию отрисовки.

- [ ] **Шаг 4: Коммит**
  `git add cmd/game/main.go && git commit -m "feat(game): integrate MatchManager into main loop"`

### Задача 4: Тестирование и верификация

- [ ] **Шаг 1: Проверка сценария "Гол"**
  - Запустить игру, забить гол.
  - Ожидание: Игра замирает, через несколько секунд все возвращаются в центр.

- [ ] **Шаг 2: Проверка сценария "Конец матча"**
  - Установить короткий `MatchDuration` (например, 10 сек).
  - Ожидание: Через 10 секунд игра замирает навсегда.

- [ ] **Шаг 3: Коммит**
  `git commit -m "test(game): verify match logic flow"`
