Add AI bot tests and update documentation

This commit is contained in:
sokol
2026-02-21 20:34:42 +03:00
parent a0f6276e5d
commit afebcbca1a
3 changed files with 1178 additions and 90 deletions

220
QWEN.md
View File

@@ -2,7 +2,7 @@
## Project Overview
**hexo** is an educational game project - a clone of [DiceWars](https://www.gamedesign.jp/games/dicewars/).
**hexo** is an educational game project a clone of [DiceWars](https://www.gamedesign.jp/games/dicewars/).
### Game Concept
@@ -11,45 +11,11 @@ A strategy dice game played on a hexagonal grid where players command armies of
### Features
- **2-4 Players**: Support for multiple human and/or AI players
- **AI Bots**: Computer-controlled players with smart move selection
- **AI Bots**: Computer-controlled players with smart move selection and thinking delay
- **Hexagonal Grid**: 20×20 map with proper adjacency
- **Dice Combat**: Roll-based battle system
- **Solid Territory Supply**: Supply = size of largest connected territory
### Core Game Mechanics
#### Map System
- Generatable hexagonal grid map (20x20 cells)
- Each cell can be passable or blocked/impassable
- Each field can hold up to 8 dice
- Cells are connected to 6 neighbors (hexagonal adjacency)
#### Dice System
- Standard 6-sided dice
- Unit strength calculation formula:
```
F = (cnt-1) * full_dice + current_dice
```
Where:
- `cnt` = number of dice on the field
- `full_dice` = maximum die value (6)
- `current_dice` = top die current value (1-6)
#### Game Rules
1. **Setup**: Each player starts with dice on their starting position
2. **Movement**: Can move if strength > 1
- Source cell left with 1, target receives strength-1
3. **Combat**: Both sides roll dice (1 to their strength)
- **Attacker wins**: Takes cell with attack_roll-1, source becomes 1
- **Defender wins**: Attacker reduced to 1, defender keeps defense_roll-attack_roll (min 1)
4. **Supply**: After turn ends, player receives supply = largest connected territory size
- Distributed 1 by 1 to random non-max cells
- Max per cell: 48 (8 dice × 6)
#### AI Bot Logic
- Evaluates all possible moves
- Prioritizes: winning attacks > expansion to empty > reinforcement
- Includes thinking delay for natural gameplay
- **Flexible Setup**: Any combination of human/AI players (hotseat, full AI, or mixed)
## Directory Structure
@@ -62,13 +28,14 @@ hexo/
├── .gitignore # Git ignore rules
├── jsdom-pkg/ # Local jsdom library copy
├── public/ # All application files
│ ├── index.html # Main HTML page with start screen
│ ├── index.html # Main HTML page with start screen and game UI
│ ├── styles.css # Game UI styles
│ ├── game.js # Main game logic and rendering
│ ├── map.js # HexMap module
│ ├── game.js # Main game logic and canvas rendering
│ ├── map.js # HexMap module (map generation, cells, supply)
│ └── ai-bot.js # AI bot player logic
└── test/ # Unit tests
── map.test.js # Map and cell tests
── map.test.js # Map and cell tests
└── ai-bot.test.js # AI bot tests
```
## Technology Stack
@@ -98,29 +65,170 @@ npm test
- Map module exports both ES and CommonJS for compatibility
- Tests use Node.js built-in `node:test` module
> **TODO**: Coding standards and testing practices are not yet established.
## Core Game Mechanics
### Inferred Practices (based on jsdom usage)
- JavaScript/TypeScript expected for implementation
- DOM-based rendering likely planned (given jsdom inclusion)
- Game logic will need to implement:
- Hexagonal grid generation
- Dice mechanics and randomization
- Turn-based combat system
- Player state management
### Map System
- Generatable hexagonal grid map (20×20 cells)
- Each cell can be passable or blocked/impassable
- Each field can hold up to 8 dice
- Cells are connected to 6 neighbors (hexagonal adjacency)
### Dice System
- Standard 6-sided dice
- Unit strength calculation formula:
```
F = (cnt - 1) × full_dice + current_dice
```
Where:
- `cnt` = number of dice on the field
- `full_dice` = maximum die value (6)
- `current_dice` = top die current value (1-6)
### Game Rules
1. **Setup**: Each player starts with dice on their starting position
2. **Movement**: Can move if strength > 1
- Source cell left with 1, target receives strength-1
3. **Combat**: Both sides roll dice (1 to their strength)
- **Attacker wins**: Takes cell with `attack_roll - 1`, source becomes 1
- **Defender wins**: Attacker reduced to 1, defender keeps `defense_roll - attack_roll` (min 1)
4. **Supply**: After turn ends, player receives supply = largest connected territory size
- Distributed 1 by 1 to random non-max cells
- Max per cell: 48 (8 dice × 6)
### Player Configuration
| Player | Color | HEX Code |
|--------|-------|----------|
| P1 | Green | `#4ecca3` |
| P2 | Red | `#e94560` |
| P3 | Yellow | `#f9ed69` |
| P4 | Cyan | `#a8e6cf` |
### Starting Positions
Players are placed at fixed positions on the map:
- **P1**: Top area (q: 2, r: 2)
- **P2**: Bottom area (q: MAP_SIZE-3, r: MAP_SIZE-3)
- **P3**: Bottom-left (q: 2, r: MAP_SIZE-3)
- **P4**: Top-right (q: MAP_SIZE-3, r: 2)
Each player starts with strength 8 at their starting position.
## AI Bot Logic
### Implementation Details (`ai-bot.js`)
The AI bot is implemented in the `AIBot` class with the following behavior:
#### Thinking Delay
- **Delay**: 1000ms between moves
- **Purpose**: Creates natural gameplay feel, allows human players to follow AI actions
#### Move Evaluation
The AI evaluates all possible moves using a priority system:
```javascript
movePriority(move) {
let priority = 0;
// Attack weak enemies (highest priority)
if (move.type === 'attack') {
if (move.attackStrength > move.defenseStrength) {
priority += 100; // Likely to win
priority += move.attackStrength - move.defenseStrength;
} else {
priority -= 50; // Risky attack
}
}
// Expand to empty cells (medium priority)
if (move.type === 'expand') {
priority += 50;
priority += move.attackStrength; // Stronger placement = better
}
// Prefer moves that create strong positions
priority += move.attackStrength * 0.5;
return priority;
}
```
#### Move Types
| Type | Priority | Description |
|------|----------|-------------|
| **Attack (favorable)** | 100+ | Attack enemy with higher strength |
| **Expand** | 50+ | Capture empty cells |
| **Attack (risky)** | -50 | Attack enemy with equal/higher strength |
#### Turn Flow
1. Get all player cells
2. Find all possible moves (neighbors that are not own cells)
3. Sort moves by priority
4. Wait for thinking delay (1000ms)
5. Execute best move
6. Repeat until no moves available, then end turn
### Integration with Game UI
The AI bot integrates with the main game through:
- **`gameUI.selectedCell`** / **`gameUI.currentTarget`**: Set before executing moves
- **`gameUI.executeAttack()`**: Called to perform the actual attack
- **`gameUI.endTurn()`**: Called when AI has no more moves
- **`gameUI.isAIThinking`**: Flag to prevent user interaction during AI turn
## Key Implementation Areas
When development begins, focus on these components:
### 1. Map Generator (`map.js`)
1. **Map Generator**: Hexagonal grid creation with passable/impassable cells
2. **Dice Engine**: Randomization and strength calculation
3. **Combat System**: Attack/defense resolution logic
4. **Game State**: Player turns, unit positions, victory conditions
5. **UI/Rendering**: Visual representation of the game board
- Hexagonal grid creation with passable/impassable cells
- Cell ownership tracking
- Neighbor calculation (6 directions)
- Supply calculation (largest connected territory)
### 2. Dice Engine (`game.js`)
- Randomization for combat rolls
- Strength calculation
- Dice distribution during supply phase
### 3. Combat System (`game.js`)
- Attack/defense resolution logic
- Victory/defeat outcomes
- Cell ownership transfer
### 4. Game State (`game.js`)
- Player turns management
- Unit positions tracking
- Victory conditions (last player standing)
### 5. UI/Rendering (`game.js`)
- HTML5 Canvas rendering
- Hexagon drawing with proper coordinates
- Player color indicators
- Dice visualization
- Battle log
### 6. AI Bot (`ai-bot.js`)
- Move evaluation and prioritization
- Thinking delay for natural gameplay
- Integration with game UI for move execution
## Notes
- The `.gitignore` file appears to be a Python template and may need to be updated for a JavaScript project
- The `jsdom-pkg` directory contains a local copy of jsdom, possibly for offline development or custom modifications
- Game rules are documented in Russian in README.md
- All game logic runs in the browser (no server-side game state)