Back again with another update on Halcyon Reach, my agentically-engineered EVE Online-style MMO. Last devlog I closed by saying I wanted to spend the next stretch on combat and game feel. I took a bit of a break, then sat down to do that, and instead spent my efforts building the world.

A brief detour

As I said, I left off the previous post at an impasse. I feel like I am addicted to building out these core, yet ultimately tertiary systems. Things like... group finder, chat, wallets, login... Just web-app-style nerd stuff that I'm used to. It's my comfort area and honestly these are things that agents can mostly take 100% from start to finish without any human intervention which is why it's so addictive.

That is somewhat the interesting thing about coding with AI -- that there is a very large subset of programming tasks which have now been basically trivialized. If I want to add a mail system to my game, that can be done in 10 minutes. If I want to implement auth, that's 20 minutes. If I want to design compelling combat which engages the user in moment-to-moment battle and keeps them logging in? Well... that ends up being a multi-day long, multi-PR, fine-tuning endeavor with near 100% human intervention required. Binary systems (implemented correctly or not) are trivial, and systems where there is a lot of room for interpretation are still just as complex and winding as they were before AI.

That said, I am acknowledging that I have been putting off the hard work. We have a server and a client. We have unique ships and player ids. Let's get to making something fun!

So, I opened a fresh design doc and started sketching it out. What exactly is the player's journey through a zone in this game? What does a miner do? What does a PvPer do? How about someone that just wants to farm mobs for a few hours, feel a sense of progression, then log off? I love Albion Online and Path of Exile's principle where zones are totally saturated with opportunities for content, so I started writing my design towards that.

I vibed out a decent scaffolding of some basic "space game themey ideas", but then just .. didn't really feel like it was worth implementing them? At least not yet because I wasn't sure if they'd stand the test of time in this world. Why would I waste cycles building out a "shard impact analysis event" when I don't even know what the heck a shard is or why it would be impacting in this world.

Then I took a step back and looked at what I've built so far. I had my agent put together 38 different zones to explore (mostly empty fwiw, but at least I can fly through them). The names were entirely vibe-coded -- just random AI slop like "Lattice," "Conduit," and "Cairn." Instantly forgettable names with absolutely zero lasting meaning.

The people were forgettable too... An entire race of folks whose entire lineage could only be described as "they're space miners lol" which is a degenerate design in a game where mining is a core theme regardless of the player's chosen race.

So I stopped writing content. I had the idea of content that I wanted, but I needed a way to fit it all into the world.

But this presupposes we have a world to put them in.

So I got sidetracked again and built a bit of the world

Robert Kurvitz (Disco Elysium) on worldbuilding at Game Camp France 2024. His argument that a world lives or dies on its names really stuck with me.

I knew that I needed to start to at least do some broad strokes sketching of the game world in order to get inspiration for what I wanted to build, so I spun up 5 Haiku agents and had them do some exploration. I was curious if there were any shared perspectives from the model. LLMs have certainly consumed more sci-fi fantasy tropes than I have, so I'm interested in how it takes all of this information and regurgitates something that might just have resonance within the human mind and our shared culture.

After back and forth we ended up with a real cast of peoples. Five playable races, all intended to be humanoid (I really want to avoid pure alien-types, or Zerg-type bugs). Each race pinned to a Magic: the Gathering color identity so that they have specific temperaments and associated color palettes, ensuring that we have proper diversity without reinventing the wheel.

  • The Halcyte — corporate trade Houses. They run the main trade hub and let anyone dock because they want the business.
  • The Skaral — cautious frontier people who record everything. They keep the Archive of Names.
  • The Aurelim — genetically engineered elites who believe they're superior. That belief is starting to break down.
  • The Keth — nomadic ship-families with no government or leaders. Loyalty runs to family.
  • The Verdan — biocrafters who grow their ships and bodies from living material.
Skaral keepers in charcoal-silver vestments standing in a vast, cold cathedral of ice and dark stone, a shaft of violet light rising from a glowing circular reliquary at the far end.
The Skaral, keepers of the Archive of Names, in the deep-cold halls where they trust the record over the rumor.

Then there are the pirate factions. I gave each one a different reason to attack you. A cyborg hive boxes you in to board your ship and capture the crew. A death-cult ignores your cargo and comes aboard after the kill to take your dead. Radiation-mutants drain your reactor. The point was to make each one want something different from you.

Pale Choir celebrants in cream-and-grey robes swinging censers before rows of shrouded bodies hung in a dim starship hold, hundreds of candles burning along the deck below them.
The death-cult in question: the Pale Choir, who ignore your cargo entirely and come aboard after the kill to tend your dead.

The aesthetic as a contract

Naming peoples is the easy half. The hard half is making them look like a coherent set across dozens of generated images, when the generator has no memory between calls.

I created a custom Midjourney Greasemonkey script that I feed a structured JSON batch of prompts.

The Midjourney Prompt Queue userscript running on the
Midjourney web app: a draggable control panel with Start button and delay range (5–10s) sits over
a JSON batch of faction-emblem prompts, each entry carrying an id, race, and text, with a shared d
efaults suffix and Load/Reset controls at the bottom.
The queue userscript mid-run: paste a JSON batch, and it fires each prompt into the textbox on a randomized delay. One shared defaults.suffix carries the style acros s the whole fleet, so each prompt only describes its subject — and ids become the por trait filenames on the way out.

This script was a lifesaver and meant that I could largely offload the responsibility of writing the Midjourney prompts to an AI agent. For those that don't know, Midjourney makes automation deliberately hard. There's no official API, no MCP server, nothing to call programmatically. The only real surface is the web app itself, which is exactly why a browser userscript that fires prompts into the textbox on a randomized, human-paced delay is the pragmatic way in.

I'd scorecard each batch of images to my agent with only a few words. "Yeah that's good," "Wow that one looks terrible," "Hit," "Miss," etc. When mass batching images, this was nice.

After a whole day of doing that, the whole thing converged into what was effectively a design bible for the game. Per-faction portrait, ship, and society entries, hex swatches, and a DO / DON'T model sheet. This includes Midjourney style prompts so the same entities can be generated again and again and can continue to retain its visual identity.

Design bible ship entry for the Halcyte: a Corporate dreadnought rendered as a towering vertical edifice of brushed steel and black glass with cold cyan running lights, alongside hex swatches (steel-black, gunmetal, ice-cyan) and a DO/DON'T model sheet. Design bible portrait entry for the Halcyte: a cropped, regulation-slick officer in a naval admiral uniform with a hard blue rim-light, pinned to MTG Black (Dimir/Orzhov), with clothing, silhouette, and leader notes plus a DO/DON'T model sheet. Design bible society-scene entry for the Halcyte: a crowded trading hall on Halcyon Reach with House officers cutting deals beneath holographic tickers, plus lore about the Long Account ledger and the same hex swatches.
One faction with three separate entries in the design bible. The Halcyte's ship, portrait, and society scene all share a color identity (steel-black / gunmetal / ice-cyan), a signature detail, and a DO / DON'T model sheet, so any agent, or Midjourney itself, regenerates them on-model without relearning the rules.

That's really what the aesthetic rules are: contracts that keep parallel generation consistent. Assigning every faction a color identity and a single signature detail is the same idea as the engineering tooling I've built for this game: a cheap constraint up front that keeps the agents from drifting.

Which is good, because that session didn't survive. It hit the top of its context window, asked to write this very devlog, and died before it could :D.

The rhythm I'm chasing

Here's the thing I'm actually most excited about, and the reason the world had to come first.

There's a design in Guild Wars 2 that I think is wildly underused in the MMO genre: the world event timer. At specific and publicly stated times, players across the whole game get pulled into a single zone for one shared event whether that be a multi-stage fight, a world boss, or a time-locked puzzle.

A Guild Wars 2 event-timer dashboard: a grid of world bosses, meta events, and PvP tournaments laid out against a clock from 10:00 to 12:00, with a red line marking the current time and each event color-coded by how soon it spawns.
The Guild Wars 2 event timer. Every row is a scheduled, public event.

What I love about it is that it directly attacks the oldest problem in MMOs: there are never enough players to make every inch of a world feel alive at once. Density per zone is one knob, but pulling everyone to the same place at the same time is a different and stronger one. And crucially, GW2's events are themed. You're not killing a quest-objective; you're defending the Jade temple against the onslaught. Which is exactly why I couldn't design any of these cute events until the world existed! A raid on the Boneyard salvage fields by a named death-cult means something; a generic "boss spawn" means nothing.

The content wall I hit a while ago is gone. The content now has somewhat of a world to live in with specific peoples, specific places, specific stakes. The encounters can finally be about something. Combat and game feel are still the real frontier, and still mostly ahead of me. But at least now I know what I'm building them inside of.