# План: Тактический ИИ и Ролевая Логика (M4)

**Цель:** Реализовать роль Вратаря с логикой перекрытия углов и систему зонирования для нападающих и защитников.

**Архитектура:** 
- Введение `RoleGoalie` в перечисление ролей.
- Реализация специализированного метода `updateGoalieAI`, который вычисляет целевую точку на векторе «Центр ворот -> Шайба» с ограничением по радиусу.
- Внедрение системы зон (Защитная, Средняя, Атакующая) для динамического изменения агрессивности игроков.

**Стек:** Go

**Спека:** [docs/specs/2026-05-09-tactical-ai-design.md](../specs/2026-05-09-tactical-ai-design.md)

---

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

- `internal/entities/player.go` — добавление `RoleGoalie`.
- `internal/game/world.go` — константы зон, логика ИИ вратаря и зонирования.
- `internal/game/world_test.go` — тесты на поведение вратаря и смену зон.

---

## Задачи

### Задача 1: Расширение ролей и константы зон

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

- [ ] **Шаг 1: Добавить `RoleGoalie` в `PlayerRole`**
```go
type PlayerRole int
const (
    RoleStriker PlayerRole = iota
    RoleDefender
    RoleGoalie // Добавить это
)
```

- [ ] **Шаг 2: Добавить константы зон в `world.go`**
```go
const (
    ZoneWidth = WorldWidth / 3
    GoalieMaxDistance = 80.0 // Максимальный выход вратаря из ворот
)
```

- [ ] **Шаг 3: Коммит**
`git add internal/entities/player.go internal/game/world.go`
`git commit -m "feat(ai): add RoleGoalie and zone constants"`

### Задача 2: Реализация ИИ Вратаря (Перехватчик)

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

- [ ] **Шаг 1: Реализовать `updateGoalieAI`**
Логика:
1. Определить центр своих ворот (`GoalLeft` или `GoalRight`).
2. Вычислить вектор от центра ворот к шайбе.
3. Целевая точка = Центр ворот + (Нормализованный вектор * min(дистанция_до_шайбы, GoalieMaxDistance)).
4. Ограничить Y в пределах ворот (например, +/- 100 пикселей от центра).

```go
func (w *World) updateGoalieAI(p *entities.Player, puckPos entities.Vector2D) entities.Vector2D {
    goalPos := GoalLeft
    if p.Team == TeamRight {
        goalPos = GoalRight
    }

    // Вектор от ворот к шайбе
    dir := puckPos.Sub(goalPos)
    dist := dir.Len()
    
    // Ограничиваем выход из ворот
    moveDist := dist
    if moveDist > GoalieMaxDistance {
        moveDist = GoalieMaxDistance
    }
    
    target := goalPos.Add(dir.Normalize().Mul(moveDist))
    
    // Ограничение по Y (чтобы не уходил за пределы ворот)
    if target.Y < WorldCenterY-100 { target.Y = WorldCenterY-100 }
    if target.Y > WorldCenterY+100 { target.Y = WorldCenterY+100 }
    
    return target
}
```

- [ ] **Шаг 2: Интегрировать в `updatePlayerAI`**
```go
switch p.Role {
case entities.RoleGoalie:
    target = w.updateGoalieAI(p, puckPos)
// ... остальные роли
}
```

- [ ] **Шаг 3: Коммит**
`git commit -m "feat(ai): implement goalie interceptor logic"`

### Задача 3: Система зонирования для полевых игроков

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

- [ ] **Шаг 1: Реализовать определение зоны**
```go
func (w *World) getPlayerZone(p *entities.Player) int {
    // 0: Защитная, 1: Средняя, 2: Атакующая
    // Для TeamLeft: X < ZoneWidth (Защитная), X < 2*ZoneWidth (Средняя), else (Атакующая)
    // Для TeamRight: X > 2*ZoneWidth (Защитная), X > ZoneWidth (Средняя), else (Атакующая)
    if p.Team == TeamLeft {
        if p.Pos.X < ZoneWidth { return 0 }
        if p.Pos.X < 2*ZoneWidth { return 1 }
        return 2
    } else {
        if p.Pos.X > 2*ZoneWidth { return 0 }
        if p.Pos.X > ZoneWidth { return 1 }
        return 2
    }
}
```

- [ ] **Шаг 2: Обновить логику Striker и Defender с учетом зон**
- **Striker**: В зоне 0 (защитной) стремится к центру поля, в зоне 2 (атакующей) — агрессивно к шайбе.
- **Defender**: В зоне 0 — агрессивно к шайбе, в зоне 2 — возвращается к своим воротам.

- [ ] **Шаг 3: Коммит**
`git commit -m "feat(ai): implement player zoning logic"`

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

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

- [ ] **Шаг 1: Тест `TestWorld_GoaliePositioning`**
- Проверить, что вратарь TeamLeft при шайбе в центре поля стоит в районе `GoalLeft` и не уходит дальше `GoalieMaxDistance`.
- Проверить, что вратарь смещается вслед за шайбой по Y.

- [ ] **Шаг 2: Тест `TestWorld_ZoningBehavior`**
- Проверить, что защитник в атакующей зоне стремится вернуться назад.

- [ ] **Шаг 3: Запуск тестов**
`go test ./internal/game/ -v`

- [ ] **Шаг 4: Коммит**
`git commit -m "test(ai): add goalie and zoning tests"`
