A grid-based multiplayer territorial strategy game built with TypeScript and Node.js. Players compete to control zones, collect resources, and defend against AI enemies in turn-based tactical gameplay.
- Territorial Control: Claim zones by occupying them for 5 turns with progressive moon phases 🌑🌒🌓🌔🌕
- Shop System: 9x9 interactive shop area with walk-to-buy mechanics and emoji pricing
- Zone-Specific Rewards: Corner zones generate 💎 diamonds (3pts), side zones generate ⚡ energy/💰 gold (2pts)
- Powerup System: ⚡ Sprint, 🧲 Pull, 🛡️ Shield with energy costs and charge mechanics
- Relic System: Passive upgrades available after turn 10 for advanced strategy
- Event System: Real-time feedback on territory control, resource generation, and combat
- AI Enemies: 👻 Scouts and 🤖 destroyers that move toward controlled zones
- Multiplayer: Real-time WebSocket-based multiplayer support
- Offline Mode: Single-player vs AI gameplay
- Node.js 20+
- npm 10+
# Clone and install
git clone <repository>
cd clod
npm install
# Build all packages
npm run build
# Quick commands (recommended)
npm run play # Play offline (human vs AI)
npm run server # Start multiplayer server
npm run create # Create multiplayer game (will prompt for name)
# Advanced commands
npm run dev:cli -- -- --offline # Play offline
npm run dev:cli -- -- --create --name "YourName" # Create game with name
npm run dev:cli -- -- --join GAMEID --name "Name" # Join existing gameThis is a monorepo with separate packages:
clod/
├── packages/
│ ├── game-engine/ # Core game logic & rules
│ ├── game-server/ # WebSocket multiplayer server
│ └── cli-client/ # Terminal game client
├── shared/ # Common types & protocols
└── package.json # Workspace configuration
- Purpose: Core game mechanics, state management, and rule validation
- Key Files:
TerritorialGameEngine.ts- Main game logicConsoleUI.ts- Terminal renderingtypes/game.ts- Game state interfaces
- Features: Turn-based movement, zone control, resource spawning, enemy AI
- Purpose: Multiplayer game coordination via WebSocket
- Key Files:
index.ts- HTTP + WebSocket server setupGameServer.ts- Game session management
- API:
POST /api/games- Create new gameGET /api/games- List active gamesGET /health- Server health check
- Purpose: Terminal-based game interface
- Key Files:
index.ts- CLI argument parsingGameClient.ts- Game state & server communication
- Features: Single-char input, offline/online modes, WebSocket client
- Purpose: Common types and constants
- Contents: WebSocket protocols, game constants, shared interfaces
Control zones to generate resources and accumulate points while defending against AI enemies.
| Symbol | Meaning |
|---|---|
| 🔵 🔴 | Player 1 & 2 |
| 🟫🟪🟨🟩🟧🔲 | Unclaimed zones A-F (color-coded) |
| 🟦 🟥 | Controlled zones (blue/red for each player) |
| 💎 💰 | Diamonds (3pts) & Gold (2pts) resources |
| 👻 🤖 | Scout/Destroyer enemies |
| ⬛ | Empty space |
- WASD: Move player
- Q: Quit game
- Turn Structure: Each player gets 1 move, then time-step processes
- Zone Control: Stay in a zone for 5 turns to claim it with progressive moon phases 🌑🌒🌓🌔🌕
- Guaranteed Resources: Controlled zones generate resources every turn (100% guaranteed!)
- Zone Rewards: 🟫🟩 corners=💎(3pts), 🟪🟧 sides=⚡energy/💰gold(2pts), 🟨🔲 strategic=💰(2pts)
- Shop System: Walk over items or prices in central 9x9 area to buy with gold
- Powerups: Use 1/2/3 keys to activate ⚡Sprint, 🧲Pull, 🛡️Shield abilities
- Enemy Movement: AI enemies move toward controlled zones and steal resources
- Events: ⚡ RECENT EVENTS panel shows all turn actions and results
- Winning: 15 points OR control 4 zones simultaneously
npm run build # Build all packages
npm run build -w <package> # Build specific packagenpm run dev:server # Start game server (port 3001)
npm run dev:engine # Watch game engine changes
npm run dev:cli # Run CLI in development mode# Test offline mode
npm run play
# Test multiplayer (requires server running)
npm run server # Terminal 1: Start server
npm run create # Terminal 2: Create game
npm run dev:cli -- -- --join GAMEID --name "Player2" # Terminal 3: Join game# Create game
POST /api/games
Body: { "playerName": "string" }
Response: { "gameId": "string", "message": "string" }
# List games
GET /api/games
Response: [{ "id": "string", "playerCount": number, "spectatorCount": number, "createdAt": "string" }]{
type: 'join' | 'move' | 'spectate',
gameId?: string,
playerName?: string,
direction?: 'w' | 'a' | 's' | 'd'
}{
type: 'game-state' | 'error' | 'player-joined' | 'player-left',
data?: GameState,
message?: string
}This project evolved through several iterations:
- Initial Concept: Card-based roguelike inspired by Balatro
- Pivot 1: Prisoner's dilemma puzzle mechanics
- Pivot 2: Resource collection with sharing bonuses
- Final Form: Territorial control with strategic zone management
Key design decisions:
- Immutable State: Clean game state management for multiplayer
- Separation of Concerns: Game logic isolated from UI/networking
- Client/Server Architecture: Enables real-time multiplayer
- Monorepo Structure: Shared dependencies while maintaining modularity
- Powerup System: ⚡Sprint, 🧲Pull, 🛡️Shield with energy costs and charges
- Shop System: 9x9 interactive area with walk-to-buy mechanics and auto-refresh
- Win Conditions: Hybrid victory system (15 points OR 4 zones control)
- Relic System: Passive modifiers available after turn 10 (implemented but needs expansion)
- Cooperative Collection: +50% bonus when near teammate
- Enhanced Enemy System: 👻🤖🕷🛡 with specific counters
- Capture Rewards: Powerup/relic shards on zone capture
- Preview Panel: Show projected zone progress and income
- Stage Modifiers: Fog, tremors, tax, resource scaling
- Overcharge System: Bank energy for instant powerup use
- ASCII Rendering: Mono-width mode for alignment reliability
- Fork the repository
- Create a feature branch
- Make changes in appropriate packages
- Build and test locally
- Submit a pull request
ISC License - See package.json for details