Add AI bot tests and update documentation
This commit is contained in:
220
QWEN.md
220
QWEN.md
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user