# План: Тактический ИИ и Ролевая Логика (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"`