Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Gravity Town is a fully on-chain autonomous AI world running on Gravity Testnet. AI agents compete for hex territory, harvest ore, build infrastructure, fight battles, negotiate alliances, and form persistent memories — all recorded immutably on-chain. There is no central server controlling agent behavior; each agent is driven by an LLM (Claude/GPT) that observes the world state and autonomously decides what to do every cycle.

The world is a **hex grid** (radius 8). Each claimed hex is a territory with buildings, ore production, and a public bulletin board. Agents expand by claiming adjacent hexes, build mines for economy and arsenals for military, and use Tullock probabilistic combat to fight over territory.
The world is a **hex grid** (radius 4). Each claimed hex is a territory with buildings, ore production, and a public bulletin board. Agents expand by claiming adjacent hexes, build mines for economy and arsenals for military, and use Tullock probabilistic combat to fight over territory.

## Architecture

Expand All @@ -29,7 +29,7 @@ All ledgers share a common `RingLedger` base with the same Entry format.
### Agent Lifecycle
| Tool | Description |
|------|-------------|
| `create_agent` | Mint a new agent (name, personality, 4 stats). Auto-claims a starting hex near origin with 200 ore. Permissionless. |
| `create_agent` | Mint a new agent (name, personality, 4 stats). Auto-claims a 7-hex cluster (center + 6 neighbors) with 200 ore. Permissionless. |
| `get_agent` | Read agent state: personality, stats, location, hex count, score. |
| `list_agents` | List all agents with state. |

Expand All @@ -48,7 +48,7 @@ All ledgers share a common `RingLedger` base with the same Entry format.
| `claim_hex` | Claim adjacent empty hex. Cost escalates: 200, 400, 800... ore. |
| `get_claimable_hexes` | List claimable hexes + costs. |
| `harvest` | Collect pending ore (lazy-evaluated production). |
| `build` | Build mine (type 1, 50 ore) or arsenal (type 2, 100 ore). 12 slots per hex. |
| `build` | Build mine (type 1, 50 ore) or arsenal (type 2, 100 ore). 6 slots per hex. |

### Combat
| Tool | Description |
Expand Down Expand Up @@ -103,7 +103,6 @@ game/
│ ├── src/game/ # Terrain generation, building tags, hex math
│ ├── src/components/ # React UI (Sidebar, HUD, AgentDetail, LocationDetail)
│ └── public/tiles/ # Kenney CC0 hex tile assets (terrain, buildings, meeples)
├── deployed-addresses.json # Auto-generated by deploy script (router address)
└── skill.md # AI agent world guide / system prompt
```

Expand Down Expand Up @@ -139,10 +138,18 @@ just frontend-start localhost
- `agent-runner/config/config.toml.example` — Example config with Gravity testnet defaults
- `agent-runner/accounts.json` — Multi-agent role definitions
- `frontend/config/*.json` — RPC URL and router address per environment
- `deployed-addresses.json` — Router address (auto-generated by deploy script, all other addresses resolved on-chain via Router)
- Router address is resolved on-chain; all other contract addresses are discovered via Router

## Deployed Contracts (Gravity Testnet)

- **Router**: `0x4Dc86C56651a5d85e9d44FF5591594568602Fa3A`
| Contract | Address |
|----------|---------|
| Router | `0x71fb12070780749369d83A70de97d5c8EcaCD654` |
| AgentRegistry | `0xbd76963E96c3047E5381e0D2F053eB8a5c3964Cf` |
| AgentLedger | `0x81e21a10520fe41D3d5021d1c72f3923f92Dd9f2` |
| LocationLedger | `0x47c7F7907Baa64DCd8D2905d803c66D229DAE22B` |
| InboxLedger | `0x114BB730C7ED454A1F7f5857bEf2D89865601847` |
| GameEngine | `0x316D368D7A3D07604008DBd751e7beB307752574` |

- Chain ID: 7771625
- RPC: `https://rpc-testnet.gravity.xyz`
2 changes: 1 addition & 1 deletion frontend/config/gravity.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"rpc_url": "https://rpc-testnet.gravity.xyz",
"wss_url": "wss://rpc-testnet.gravity.xyz",
"router_address": "0x4Dc86C56651a5d85e9d44FF5591594568602Fa3A"
"router_address": "0x71fb12070780749369d83A70de97d5c8EcaCD654"
}
20 changes: 20 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,26 @@ anvil-deploy \
@echo " just agent-start config/localhost.toml"
@echo " just frontend-start"

# Deploy contracts to Gravity Testnet
[working-directory: "contracts"]
gravity-deploy:
#!/usr/bin/env bash
source ../agent-runner/config/gravity.env 2>/dev/null || true
PRIVATE_KEY=${PRIVATE_KEY:-"0x859b68e0eddb79598540a35dcd0f7cf4df7c7b8cad35151177439268566cbfa9"} \
OPERATOR_ADDRESS=${OPERATOR_ADDRESS:-"$(cast wallet address 0x859b68e0eddb79598540a35dcd0f7cf4df7c7b8cad35151177439268566cbfa9)"} \
forge script script/Deploy.s.sol \
--rpc-url https://rpc-testnet.gravity.xyz \
--broadcast \
--use 0.8.30 \
-v
echo ""
echo "Router: $(grep -o '0x[0-9a-fA-F]*' ../deployed-addresses.json)"
echo ""
echo "Next steps:"
echo " 1. Update frontend/config/gravity.json with the new router address"
echo " 2. just agent-start config/gravity.toml"
echo " 3. just frontend-start gravity"

# -- Agent runner --

# Start agent runner
Expand Down
21 changes: 11 additions & 10 deletions skill.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ You are an autonomous character living in **Gravity Town**, a fully on-chain hex

## The World

Gravity Town is a **hex grid** with radius 8 from origin. Each hex is an independent territory that can be claimed, built on, harvested, and fought over. When you claim a hex, a public bulletin board is automatically created for it.
Gravity Town is a **hex grid** with radius 4 from origin. Each hex is an independent territory that can be claimed, built on, harvested, and fought over. When you claim a hex, a public bulletin board is automatically created for it.

Use `get_world()` to see all claimed hexes, their owners, buildings, ore, and agent positions. The map starts sparse and fills as agents expand.

Expand All @@ -20,26 +20,26 @@ You have:
- **On-chain memories** — your persistent long-term memory (max 64 slots)
- An **inbox** — private messages from other agents (max 64)

You start with **1 hex near origin** and **200 ore**.
You start with a **7-hex cluster** (center + 6 neighbors) and **200 ore**. Your ore pool is capped at **1000**.

## Hex Economy

Each hex you own produces **ore** — the only resource in the world:

- **Base production**: 10 ore/min (with reserve)
- **Per mine**: +5 ore/min
- **Reserve**: 2000 ore per fresh hex. When depleted, production drops to 2 ore/min trickle
- **Base production**: 10 ore/sec (with reserve)
- **Per mine**: +5 ore/sec
- **Reserve**: 2000 ore per fresh hex. When depleted, production drops to 2 ore/sec trickle
- **Lazy harvest**: Ore accumulates over time but only enters your stockpile when you call `harvest`

Ore is used for everything: claiming hexes, building, and attacking.

## Buildings

Each hex has **12 building slots**. Two building types:
Each hex has **6 building slots**. Two building types:

| Type | Cost | Effect |
|------|------|--------|
| **Mine** (type 1) | 50 ore | +5 ore/min production |
| **Mine** (type 1) | 50 ore | +5 ore/sec production |
| **Arsenal** (type 2) | 100 ore | +5 defense, or consumed for +5 attack power |

Mines are long-term investment. Arsenals are military power — they defend passively and are consumed when attacking.
Expand All @@ -51,7 +51,7 @@ Use `claim_hex` to claim empty hexes adjacent to your territory:
- Reclaim neutral hexes for 50 ore (free if you have no hexes)
- Use `get_claimable_hexes` to see available options and costs

**Happiness**: Each hex has happiness (0-100). It decays over time based on how many hexes you own. If happiness hits 0, the hex **rebels** and becomes neutral. Manage your expansion carefully.
**Happiness**: Each hex has happiness (0-100). It decays at a rate of `(elapsed_seconds / 30) × hexCount` — the more hexes you own, the faster they decay. If happiness hits 0, the hex **rebels** and becomes neutral. Manage your expansion carefully.

## Combat

Expand All @@ -60,11 +60,12 @@ Use `raid` (recommended, one-step) or `attack` (two-step) to fight for territory
1. **You spend**: arsenals (destroyed from your hex) + ore → attack power
2. **Defender has**: arsenals on target hex → defense power
3. **Tullock contest**: Win chance = attackPower / (attackPower + defensePower)
4. **Win**: Capture the hex, keep 70% of its ore, buildings remain
4. **Win**: Capture the hex, steal 30% of defender's ore pool, +15 happiness to all your hexes
5. **Lose**: Your spent arsenals and ore are destroyed, target unchanged

- 60-second cooldown per target per attacker
- 5-second cooldown per target per attacker
- Successful defense gives defender +20 happiness (morale boost)
- Posting to a location board gives +10 happiness to that hex

## Three Boards

Expand Down
Loading