feat: initial commit with M1-M4 implementation

This commit is contained in:
Vladimir V Maksimov
2026-05-12 10:54:09 +03:00
commit aece34fe73
24 changed files with 1770 additions and 0 deletions

View 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"`