206 lines
9.1 KiB
Markdown
206 lines
9.1 KiB
Markdown
# HEXO
|
||
|
||
Учебный проект. Игра, клон [DiceWars](https://www.gamedesign.jp/games/dicewars/)
|
||
|
||
## Запуск игры
|
||
|
||
```bash
|
||
npm run serve # Запустить веб-сервер (http://localhost:8080)
|
||
npm test # Запустить тесты (88 тестов)
|
||
npm start # Консольная версия карты
|
||
```
|
||
|
||
## Экран запуска
|
||
|
||
При запуске игры открывается экран настройки:
|
||
|
||
1. **Выберите количество игроков**: 2, 3 или 4
|
||
2. **Выберите размер карты**:
|
||
- **Small (10×10)** — Быстрая игра на маленькой карте
|
||
- **Medium (15×15)** — Сбалансированный размер
|
||
- **Large (20×20)** — Стандартный размер (по умолчанию)
|
||
- **Extra Large (25×25)** — Большая карта для длительных игр
|
||
3. **Настройте тип каждого игрока**:
|
||
- **Human** — управление человеком (клики мышью)
|
||
- **AI Bot** — управление компьютером
|
||
4. Нажмите **Start Game** для начала игры
|
||
|
||
### Комбинации игроков
|
||
|
||
Можно создавать любые комбинации:
|
||
- Все игроки — люди (Hotseat)
|
||
- Все игроки — AI боты (наблюдение за игрой ИИ)
|
||
- Смешанный режим (например, P1-Human, P2-AI, P3-Human, P4-AI)
|
||
|
||
## Цвета игроков
|
||
|
||
| Игрок | Цвет | HEX |
|
||
|-------|------|-----|
|
||
| P1 | 🟢 Зелёный | `#4ecca3` |
|
||
| P2 | 🔴 Красный | `#e94560` |
|
||
| P3 | 🟡 Жёлтый | `#f9ed69` |
|
||
| P4 | 🔵 Бирюзовый | `#00adb5` |
|
||
|
||
## AI Bot
|
||
|
||
### Как работает
|
||
|
||
AI бот автоматически играет за выбранного игрока:
|
||
|
||
1. **Анализ поля** — бот оценивает все возможные ходы
|
||
2. **Приоритеты ходов**:
|
||
- 🎯 Атака слабого противника (высокий шанс победы) — приоритет 100+
|
||
- 📈 Захват пустых клеток (расширение территории) — приоритет 50+
|
||
- 💪 Укрепление позиций (перемещение к сильным клеткам)
|
||
3. **Задержка мышления** — 1000 мс перед каждым ходом для естественности геймплея
|
||
4. **Несколько ходов за turn** — AI делает все возможные ходы подряд, затем завершает ход
|
||
|
||
### Индикаторы AI
|
||
|
||
- В карточке игрока отображается метка **(AI)**
|
||
- Во время хода AI в панели действий показано: *"AI is thinking..."*
|
||
- Кнопки управления отключены во время хода AI
|
||
|
||
### Логика принятия решений
|
||
|
||
```javascript
|
||
movePriority(move) {
|
||
let priority = 0;
|
||
|
||
// Атака слабого врага (высший приоритет)
|
||
if (move.type === 'attack') {
|
||
if (move.attackStrength > move.defenseStrength) {
|
||
priority += 100; // Высокий шанс победы
|
||
priority += move.attackStrength - move.defenseStrength;
|
||
} else {
|
||
priority -= 50; // Рискованная атака
|
||
}
|
||
}
|
||
|
||
// Расширение на пустые клетки (средний приоритет)
|
||
if (move.type === 'expand') {
|
||
priority += 50;
|
||
priority += move.attackStrength;
|
||
}
|
||
|
||
// Бонус за сильную позицию
|
||
priority += move.attackStrength * 0.5;
|
||
|
||
return priority;
|
||
}
|
||
```
|
||
|
||
## Правила игры
|
||
|
||
### 1. Карта
|
||
|
||
- Гексагональная сетка **10×10**, **15×15**, **20×20** или **25×25** ячеек
|
||
- Каждая ячейка может быть:
|
||
- **Проходима** (пустая или принадлежит игроку)
|
||
- **Непроходима** (заблокирована, серый цвет, ~15% карты)
|
||
|
||
### 2. Игровые единицы
|
||
|
||
- **Кубик**: 6-гранный, значения 1-6
|
||
- На поле может быть до **8 кубиков** на клетку
|
||
- **Сила юнита**: `F = (cnt-1) × 6 + current_dice`
|
||
- `cnt` — количество кубиков
|
||
- `current_dice` — значение верхнего кубика
|
||
|
||
**Примеры расчёта силы:**
|
||
| Кубики | Сила |
|
||
|--------|------|
|
||
| [4] | 4 |
|
||
| [6] | 6 |
|
||
| [6, 1] | 7 |
|
||
| [6, 6, 2] | 14 |
|
||
| [6, 6, 6, 6, 6, 6, 6, 6] | 48 (максимум) |
|
||
|
||
### 3. Ход игры
|
||
|
||
#### Перемещение/Атака
|
||
|
||
- Можно ходить, если **сила > 1**
|
||
- На целевую клетку переходит `сила-1`, на исходной остаётся **1**
|
||
- При атаке оба игрока бросают кости:
|
||
- **Атакующий**: `attack_roll = rnd(1..сила-1)`
|
||
- **Защищающийся**: `defense_roll = rnd(1..сила)`
|
||
|
||
#### Результат боя
|
||
|
||
| Условие | Результат |
|
||
|---------|-----------|
|
||
| `attack_roll > defense_roll` | Атакующий побеждает, занимает клетку с `attack_roll-1`. На исходной клетке остаётся **1** |
|
||
| `attack_roll <= defense_roll` | Атака отбита. Атакующий уменьшается до **1**. Защитник остаётся с `defense_roll - attack_roll` (мин. **1**) |
|
||
|
||
#### Снабжение
|
||
|
||
После хода игрок получает снабжение:
|
||
|
||
- **Снабжение = размер наибольшей непрерывной территории**
|
||
- **Непрерывная территория** — связанные между собой клетки игрока
|
||
- Если территория разорвана врагом — считается только наибольший кусок
|
||
- Снабжение распределяется по **1 единице** случайным клеткам (не максимальным)
|
||
- **Максимум на клетке**: 48 (8 кубиков × 6)
|
||
|
||
### 4. Победа
|
||
|
||
**Последний игрок**, оставшийся с клетками на карте, побеждает.
|
||
|
||
## Управление
|
||
|
||
| Действие | Управление |
|
||
|----------|------------|
|
||
| Выбрать клетку | Клик на свою клетку с кубиками |
|
||
| Атаковать | Клик на соседнюю вражескую/пустую клетку |
|
||
| Отменить выбор | Кнопка **Cancel** или клик на ту же клетку |
|
||
| Завершить ход | Кнопка **End Turn** |
|
||
| Вернуться в меню | Кнопка **Main Menu** |
|
||
|
||
### Индикаторы на экране
|
||
|
||
- **Выделенная клетка** — красная подсветка
|
||
- **Доступные цели** — зелёная подсветка соседних клеток
|
||
- **Лог боёв** — правая панель с историей действий
|
||
- **Инфо о клетке** — сила и количество кубиков выбранной клетки
|
||
|
||
## Настройки игры
|
||
|
||
Игра поддерживает:
|
||
- **2-4 игрока** (любая комбинация людей и AI)
|
||
- **4 размера карты**: 10×10, 15×15, 20×20, 25×25
|
||
- **Случайная генерация карты** при каждом запуске
|
||
- **Случайные стартовые позиции** для игроков
|
||
|
||
## Стартовые позиции
|
||
|
||
Игроки размещаются в углах карты (позиции масштабируются с размером карты):
|
||
|
||
| Игрок | Позиция | Описание |
|
||
|-------|---------|----------|
|
||
| P1 | (offset, offset) | Верхний-левый угол |
|
||
| P2 | (size-1-offset, size-1-offset) | Нижний-правый угол |
|
||
| P3 | (offset, size-1-offset) | Нижний-левый угол |
|
||
| P4 | (size-1-offset, offset) | Верхний-правый угол |
|
||
|
||
`offset = max(1, floor(size / 10))`
|
||
|
||
Каждый игрок начинает с **силой 8** на своей стартовой позиции.
|
||
|
||
## Тестирование
|
||
|
||
Проект покрыт **88 тестами**, проверяющими:
|
||
|
||
- **Динамические размеры карт** (10×10, 15×15, 20×20, 25×25)
|
||
- **HexCell**: создание, расчёт силы, максимальная сила, добавление кубиков
|
||
- **HexMap**: генерация, соседи, снабжение, владение
|
||
- **Логика выбора целей**: атака врагов, захват пустых клеток, блокировка своих клеток
|
||
- **AIBot**: поиск ходов, приоритеты, выполнение ходов, завершение хода
|
||
- **Интеграционные тесты**: 4 AI бота одновременно, разные размеры карт
|
||
|
||
```bash
|
||
npm test
|
||
```
|
||
|
||
Все тесты проходят успешно ✅
|