Gladibot System Architecture
Technical overview of Gladibot's persistent AI battle arena. This document covers the game server, engine modules, data flow, database design, and deployment topology.
High-Level Overview
+-------------------------------------------------------------------+
| GLADIBOT SYSTEM |
| |
| +------------------+ +-----------------------------+ |
| | Browser |<--WS-->| Game Server | |
| | (Thin Client) | | (game-server.ts:3849) | |
| | | | | |
| | Canvas renderer | | Tick loop (10/sec) | |
| | Sound engine | | AI engine (FSM) | |
| | Chat UI | | Combat resolver | |
| | Wallet adapter | | Creep/trap spawner | |
| +------------------+ | WebSocket broadcaster | |
| | +-----------------------------+ |
| | | |
| | Phantom/Solflare | Batch save (30s) |
| v v |
| +------------------+ +-----------------------------+ |
| | Solana RPC | | Supabase | |
| | (balance check) | | (gladibot_agents table) | |
| | (sig verify) | | Persistent agent state | |
| +------------------+ +-----------------------------+ |
| |
+-------------------------------------------------------------------+
Core principle: The game server is the single source of truth. The frontend is a thin client that receives state and renders it. Clients never compute game logic.
Game Server
The game server (game-server.ts) is a Node.js process that runs the arena simulation and manages WebSocket connections.
Tick Loop
+------------------------------------------------------------+
| TICK LOOP (every 100ms = 10 ticks/second) |
| |
| 1. Run AI decision for each alive agent |
| +- Perceive: enemies, creeps, traps, items |
| +- Decide: roam/chase/attack/block/dodge/flee/chat |
| '- Execute: move, attack, pick up item |
| |
| 2. Execute movement + collision detection |
| +- Agent-agent proximity |
| +- Agent-trap overlap |
| '- Agent-item pickup range |
| |
| 3. Resolve combat |
| +- Damage calculation (ATK - DEF + weapon bonus) |
| +- Block mitigation (50% if blocking) |
| '- Dodge evasion (miss entirely) |
| |
| 4. Check trap damage |
| +- Fire: 8 DPS while in zone |
| +- Spikes: 15 burst on contact |
| '- Poison: 5 DPS + 40% slow |
| |
| 5. Spawn creeps if arena is quiet (< 3 entities) |
| |
| 6. Spawn traps on timer (every 20 sec) |
| |
| 7. Process XP gains + level ups |
| +- Creep kill: +20 XP |
| +- Agent kill: +50 XP |
| +- 100 XP per level, max 50 |
| '- Stat gains: +5 HP, +0.5 ATK, +0.3 DEF per level |
| |
| 8. Broadcast full arena state to all connected clients |
+------------------------------------------------------------+
Persistence Cycle
Every 30 seconds:
Game Server ---batch upsert---> Supabase (gladibot_agents)
On server boot:
Supabase ---SELECT all agents---> Game Server (restore state)
Agent state survives server restarts. Ephemeral entities (creeps, traps, ground items) are regenerated on boot.
Engine Modules
src/engine/
+-- arena.ts Arena state management, spawn logic, collision
+-- ai.ts AI finite state machine, persona weights, targeting
+-- renderer.ts Canvas 2D rendering (frontend only)
+-- sounds.ts Web Audio API procedural synthesis (frontend only)
+-- db.ts Supabase client, batch save/load
+-- protocol.ts WebSocket message type definitions
+-- types.ts Shared types, constants, persona config
Module Dependency Graph
types.ts
/ | \
/ | \
ai.ts arena.ts protocol.ts
\ | /
\ | /
game-server.ts (imports all)
|
db.ts (Supabase I/O)
Frontend only:
renderer.ts --uses--> types.ts
sounds.ts --uses--> types.ts
page.tsx --uses--> renderer.ts, sounds.ts, protocol.ts
arena.ts -- Arena Engine
Manages the persistent world state:
- Agent registry: Add, remove, update player agents
- Creep spawner: Auto-spawn NPC creeps every 30 seconds when arena has fewer than 3 entities. Max 8 creeps alive.
- Trap spawner: Spawn a random trap (fire/spikes/poison) every 20 seconds. Max 3 active traps. Each lasts 8 seconds.
- Collision detection: Agent-agent (combat range), agent-trap (damage zone), agent-item (pickup range)
- Death handling: Move agent to dead status, drop weapon to ground, start respawn timer (free) or allow instant respawn (holder)
- Weapon ground items: Persist for 60 seconds, any agent can pick up
ai.ts -- AI Combat Brain
Each agent runs a finite state machine every tick:
+------+
+------->| ROAM |<------+
| +------+ |
| | | |
no target enemy trap timeout
| seen detected |
| | | |
| v v |
| +-------+ +------+
| | CHASE | | FLEE |
| +-------+ +------+
| | ^
| in range |
| | low HP
| v |
| +--------+ |
+-----| ATTACK |-----+
+--------+
| |
hit taken kill
| |
v v
+-------+ +------+
| BLOCK | | CHAT |
+-------+ +------+
Persona weights (parsed from user-written persona text):
- Aggression (0.0-1.0): How eagerly the agent seeks combat
- Caution (0.0-1.0): HP threshold for fleeing
- Greed (0.0-1.0): Priority on picking up items vs fighting
- Chattiness (0.0-1.0): Frequency of trash talk emissions
renderer.ts -- Canvas Renderer (Frontend)
Renders the arena state received from WebSocket:
- Geometric chibi gladiators with colored helmets (AgentCraft-inspired)
- Health bars above each agent (green to red gradient)
- Level indicators next to agent names
- Damage numbers floating up on hit (red) or heal (green)
- Speech bubbles for agent trash talk (auto-fade after 3 seconds)
- Trap zones with visual effects (fire glow, spike triangles, poison fog)
- Ground items with rarity-colored glow
- Death animation (fade out + weapon drop effect)
- Deploy animation (spawn flash)
- Level up animation (golden flash + "LEVEL UP!" text)
- Emoji taunts (large floating emoji)
- Camera: auto-follow own agent or free pan with drag
Interpolates positions between server ticks for smooth 60fps rendering.
sounds.ts -- Sound Engine (Frontend)
All sounds are procedurally generated via Web Audio API. Zero audio files.
| Sound | Technique |
|---|---|
| Hit | Short burst, medium frequency oscillator |
| Critical hit | Louder hit + distortion node |
| Kill | Descending tone + low thud |
| Deploy | Ascending sparkle + whoosh noise |
| Level up | Ascending arpeggio + chime |
| Fire trap | Whoosh with noise filter |
| Spike trap | Metallic clang |
| Poison trap | Hissing noise |
| 12 emoji taunts | Unique per emoji (gong, cackle, trumpet, explosion, etc.) |
db.ts -- Database Layer
- Supabase client using service role key (server-side only)
- Save: Batch upsert all alive agents every 30 seconds
- Load: SELECT all agents on server boot to restore state
- Leaderboard: Queries sorted by level DESC or kills DESC
protocol.ts -- WebSocket Protocol
Defines all message types for client-server communication. See API.md for the full protocol reference.
Database Schema
+-------------------------------------------------------------------+
| gladibot_agents |
+-------------------------------------------------------------------+
| id uuid PK, gen_random_uuid() |
| name text UNIQUE, 3-16 chars |
| persona text User-written personality |
| owner_wallet text Solana public key |
| tier text free | bronze | silver | gold |
| level int 1-50, default 1 |
| xp int default 0 |
| hp float Current HP |
| max_hp float Base + level bonus |
| atk float Base + level bonus |
| def float Base + level bonus |
| position_x float Arena X coordinate |
| position_y float Arena Y coordinate |
| weapon text sword|axe|spear|shield|daggers|... |
| weapon_rarity text common|uncommon|rare|epic|legendary |
| kills int Lifetime total, default 0 |
| deaths int Lifetime total, default 0 |
| status text alive | dead | respawning |
| respawn_at timestamptz NULL if alive |
| created_at timestamptz default now() |
| updated_at timestamptz auto-updated |
+-------------------------------------------------------------------+
Indexes:
idx_agents_owner ON owner_wallet
idx_agents_level ON level DESC
idx_agents_kills ON kills DESC
idx_agents_status ON status
What is NOT stored in the database:
- NPC creeps (ephemeral, server-memory only)
- Arena traps (ephemeral, regenerated on spawn timer)
- Ground items / dropped weapons (ephemeral, 60-second TTL)
- Chat messages (transient, WebSocket-only)
Data Flow
+-------------------------------------------------------------------+
| COMPLETE DATA FLOW |
| |
| User opens gladibot.com/arena |
| | |
| v |
| Browser connects WebSocket to ws://server:3849 |
| | |
| v |
| Server sends welcome (full arena state) |
| | |
| v |
| +--- Every 100ms (server tick) ---+ |
| | 1. AI decisions for all agents | |
| | 2. Movement + collision | |
| | 3. Combat resolution | |
| | 4. Trap damage | |
| | 5. Spawning (creeps/traps) | |
| | 6. XP + leveling | |
| | 7. Broadcast state to clients | |
| +----------------------------------+ |
| | |
| v |
| Frontend receives state, renders Canvas, plays sounds |
| | |
| v |
| User sends command (deploy/chat/taunt/respawn) |
| | |
| v |
| Server validates, mutates arena state, broadcasts result |
| |
| +--- Every 30 seconds ---+ |
| | Batch upsert agents | |
| | to Supabase | |
| +-------------------------+ |
| |
+-------------------------------------------------------------------+
Deployment
+-------------------------------------------------------------------+
| DEPLOYMENT TOPOLOGY |
| |
| VPS (Coolify-managed) |
| +-------------------------------------------------------------+ |
| | | |
| | +-------------------+ +-------------------+ | |
| | | Next.js Frontend | | Game Server | | |
| | | (Docker container)| | (Docker container)| | |
| | | Port: 3848 | | Port: 3849 | | |
| | +-------------------+ +-------------------+ | |
| | | | | |
| | +--- Reverse Proxy ------+ | |
| | | (Coolify/Caddy) | |
| | v | |
| | gladibot.com (HTTPS) | |
| | gladibot.com:3849 (WSS) | |
| | | |
| +-------------------------------------------------------------+ |
| | |
| v |
| External: Supabase (managed PostgreSQL) |
| Solana RPC (public endpoint) |
| |
+-------------------------------------------------------------------+
Container Structure
gladibot/
+-- Dockerfile Multi-stage build (frontend + server)
+-- game-server.ts Game server entry point
+-- src/
| +-- app/
| | +-- arena/
| | +-- page.tsx Arena page (thin client)
| +-- engine/
| +-- arena.ts Arena engine
| +-- ai.ts AI engine
| +-- renderer.ts Canvas renderer
| +-- sounds.ts Sound engine
| +-- db.ts Supabase layer
| +-- protocol.ts WebSocket types
| +-- types.ts Shared types
+-- public/ Static assets (logo, favicon)
+-- package.json
+-- tsconfig.json
Scaling Considerations
Current capacity (single server):
- ~200 concurrent WebSocket connections
- ~50 agents in arena simultaneously
- ~2-5 KB per state broadcast (JSON)
- ~10 KB per tick with 50 agents
Future scaling path:
- Arena sharding: multiple arena instances across servers
- State broadcast optimization: delta compression instead of full state
- Message encoding: switch from JSON to MessagePack
- Horizontal scaling: load balancer + multiple game server instances
- Read replicas: Supabase read replicas for leaderboard queries
Last updated: 2026-04-11
