235 lines
6.8 KiB
Markdown
235 lines
6.8 KiB
Markdown
# Project Context: hexo
|
||
|
||
## Project Overview
|
||
|
||
**hexo** is an educational game project — a clone of [DiceWars](https://www.gamedesign.jp/games/dicewars/).
|
||
|
||
### Game Concept
|
||
|
||
A strategy dice game played on a hexagonal grid where players command armies of dice and battle to conquer territories.
|
||
|
||
### Features
|
||
|
||
- **2-4 Players**: Support for multiple human and/or AI players
|
||
- **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
|
||
- **Flexible Setup**: Any combination of human/AI players (hotseat, full AI, or mixed)
|
||
|
||
## Directory Structure
|
||
|
||
```
|
||
hexo/
|
||
├── README.md # Game rules and documentation (Russian)
|
||
├── QWEN.md # This file - project context
|
||
├── package.json # NPM configuration
|
||
├── server.js # Simple HTTP server for development
|
||
├── .gitignore # Git ignore rules
|
||
├── jsdom-pkg/ # Local jsdom library copy
|
||
├── public/ # All application files
|
||
│ ├── index.html # Main HTML page with start screen and game UI
|
||
│ ├── styles.css # Game UI styles
|
||
│ ├── 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
|
||
└── ai-bot.test.js # AI bot tests
|
||
```
|
||
|
||
## Technology Stack
|
||
|
||
- **Runtime**: Node.js
|
||
- **Frontend**: Vanilla JavaScript (ES Modules), HTML5 Canvas, CSS3
|
||
- **Backend**: Simple HTTP server (server.js)
|
||
- **Testing**: Node.js built-in test runner (`node --test`)
|
||
|
||
## Building and Running
|
||
|
||
```bash
|
||
# Start web server (http://localhost:8080)
|
||
npm run serve
|
||
|
||
# Run console demo
|
||
npm start
|
||
|
||
# Run tests
|
||
npm test
|
||
```
|
||
|
||
## Development Conventions
|
||
|
||
- ES Modules for browser code (`import`/`export`)
|
||
- CommonJS for Node.js code (`require`/`module.exports`)
|
||
- Map module exports both ES and CommonJS for compatibility
|
||
- Tests use Node.js built-in `node:test` module
|
||
|
||
## Core Game Mechanics
|
||
|
||
### 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
|
||
|
||
### 1. Map Generator (`map.js`)
|
||
|
||
- 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)
|