feat: initial commit with M1-M4 implementation
This commit is contained in:
151
docs/plans/2026-05-09-tactical-ai.md
Normal file
151
docs/plans/2026-05-09-tactical-ai.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# План: Тактический ИИ и Ролевая Логика (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"`
|
||||
Reference in New Issue
Block a user