How it's built
One Durable Object on Cloudflare owns the game. An automation platform runs every turn. Two AI agents make the decisions. Chainlink brings in real ETH, BTC and LINK prices, a weather service brings in a real city's sky, and a smart contract keeps a public, tamper-proof record. Every piece runs on a free tier or a test network, and nothing runs on anyone's own computer.
Architecture
The Generals: AI agents
Each turn the general gets its personality, a rules summary, a situation report (weather, what the markets are doing to both sides, whether it can recruit, castles held, where the enemy was last seen), its journal (memory) and past-season lessons. It calls read-only tools (get_battlefield, which includes the odds of every possible attack, get_enemy_position, get_market) and then exactly one order tool. The server dry-runs every order through the same rules engine the game uses; an illegal order goes back to the model with the reason, and it corrects itself. The model never touches the game state directly.
At the end of a season each general writes one lesson, and it's given its real numbers first (battles won and lost, castles taken, gold left unspent), so the lesson is about what actually happened.
Limits per decision: 5 model calls, 45 seconds, a daily cap below the free quota. If the AI is unavailable, a rule-based bot takes over and the page says so ("standing orders"). Nothing typed by the public ever reaches a general's decision.
Ask a general. Visitors can ask either general a question. It goes to a separate call with no tools: the general's personality, the same situation report and its recent journal, answering in at most three sentences (in business terms when "See it as your business" is on). It can't touch the game, its answer is shown only to the person who asked, and the question is treated as untrusted text. It has its own budget (4 questions per visitor per 10 minutes, 40 a day, and none once the day's AI tokens pass 80%), so the turns always keep the free tier; repeat questions in the same turn come from a cache.
A free plan for your business. A visitor describes their business and the same model, told to think harder (high reasoning), drafts a 2–3 step automation plan as JSON. It gets the builder's real services and projects, notes on healthcare and finance, and strict rules: no prices, no invented numbers, and no blockchain or live data unless they genuinely help. The server checks and trims the JSON before the page shows it. It is the most valuable AI call on the site, so it gets the largest share of the free tier and waits out the per-minute limit instead of failing.
The Automations: n8n
Turn Router (event-driven orchestration). Built only from standard nodes:
- Webhook receives "new turn" from the world and replies at once; an IF node drops anything that doesn't carry the shared secret.
- HTTP Request reads the kingdom's gold and food.
- IF food is below 20%, then HTTP Request reorders food automatically (threshold alert → reorder).
- HTTP Request asks the AI general for an order (60-second timeout).
- HTTP Request delivers the order to the game.
Market Sync (scheduled data sync): every 10 minutes it reads three Chainlink feeds with raw JSON-RPC eth_calls and posts them to the world. Weather Sync: every 15 minutes it asks the world which city each region follows this season, reads all five skies from Open-Meteo in one call and reports back. War Correspondent: the world sends it a report after every round (both moves, the score, the weather in each region) and big moments as they happen (captures, wiped-out armies, battles, season results), and it posts them to Discord.
n8n runs on Render's free tier with its editor switched off. The world pings it every 10 minutes so it never falls asleep; if it's down anyway, the world runs the turn itself, reads prices and weather directly, and logs that it did.
The real world: markets and weather
Emberreach keeps its treasury in ETH and Frostmere in BTC. At the start of every turn, a kingdom gains or loses 100 gold for every 1% its coin moved since its last turn, so an ordinary hour in crypto shows up straight away ("ETH rose 0.31% since Emberreach's last turn, so its treasury gained 31 gold"). The coin's trend over the whole season sets fighting spirit: every 1% is ±20% battle power, capped at ±40%. LINK sets the price of soldiers for both sides: every 1% it rises this season makes them 30% dearer.
The map has five regions (the four corners and the Crownlands in the middle), and each season every region is dealt a real city at random, one from each climate: a hot one (Lahore, Dubai, Cairo…), a cold one (Reykjavík, Moscow, Anchorage…), a wet one (Bergen, London, Seattle…), a tropical one (Mumbai, Singapore, Jakarta…) and a changeable one (New York, Tokyo, Chicago…). Every kind of weather does something you can see, and only on its own ground: clear skies let an army forage 4 extra food, rain makes every step cost one more, snow slows steps and doubles what armies eat, storms slow steps and weaken attacks into them by 30%, wind weakens attacks into it by 20%, fog hides an army from anyone more than one tile away, heat doubles what armies eat and cold adds half again. Chainlink has no weather feed on test networks, so the weather comes from Open-Meteo through n8n, all five cities in one request.
The Oracle and the Ledger: Chainlink + blockchain
The RealmLedger contract reads Chainlink's ETH/USD feed itself on every capture and stamps that price into the permanent record, alongside a hash of the full battle record. Only the game's operator wallet can write; anyone can read.
Loading contract details…
Receipts go through an outbox: one sender, strict order, retries with backoff. If the chain is unreachable, the game keeps going and the receipts are sent when it comes back.
Verify a battle
Every battle is settled by fixed rules and a dice roll seeded from sha256(season:turn:battle), so anyone can recompute it. The hash of the battle record below is the battleHash written on-chain with a capture.
What it costs to run: $0
- Hosting: Cloudflare Workers and Durable Objects on the free plan. The pages are static assets, and the live stream's WebSockets sleep between events.
- AI: free tier of an OpenAI-compatible provider (Groq by default). Any OpenAI-compatible model can be dropped in.
- Automation: n8n Community Edition on Render's free tier (no card needed).
- Data: Chainlink feeds and Open-Meteo are free to read; Discord webhooks are free.
- Chain: Base Sepolia test network, with gas from a free faucet. Only captures and season results are written.
- Pacing: one turn every 30 minutes, around the clock. That's 48 AI decisions a day at about 2,200 tokens each, roughly 105,000 of the 200,000 free daily tokens, with a hard stop at 180,000. The pace also gives real prices and weather time to move between turns.
Tests
- Game rules: map symmetry, deterministic battles, illegal-order rejection, economy and starvation, markets, weather, fog of war, season endings, full simulated seasons, the narrator's plain-English output, and a check that every event type has Tech Lens copy (
npm test). - AI loop: intel → rejected order → corrected order, link and markup stripping, and fallback on API failure (with a scripted fake model).
- Contract (Foundry): price stamping, access control, bad-price rejection, events, and a fork test against the real Chainlink feed.
- End to end: n8n → AI → game → receipt confirmed on a local fork of Base Sepolia, then on Base Sepolia itself, and again after the move to Cloudflare.