6.8 KiB
6.8 KiB
Project Context: hexo
Project Overview
hexo is an educational game project — a clone of 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
# 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:testmodule
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:
Where:
F = (cnt - 1) × full_dice + current_dicecnt= number of dice on the fieldfull_dice= maximum die value (6)current_dice= top die current value (1-6)
Game Rules
- Setup: Each player starts with dice on their starting position
- Movement: Can move if strength > 1
- Source cell left with 1, target receives strength-1
- 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)
- Attacker wins: Takes cell with
- 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:
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
- Get all player cells
- Find all possible moves (neighbors that are not own cells)
- Sort moves by priority
- Wait for thinking delay (1000ms)
- Execute best move
- 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 movesgameUI.executeAttack(): Called to perform the actual attackgameUI.endTurn(): Called when AI has no more movesgameUI.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
.gitignorefile appears to be a Python template and may need to be updated for a JavaScript project - The
jsdom-pkgdirectory 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)