← All devlog posts

Cairn

A whole character in a URL

Cairn's character workshop can hand a whole character to a friend as a link, with the character carried in the URL fragment and no server involved. Plus the twenty seed gate that asked whether generated characters look different enough.

Cairn is a browser dungeon crawler in the Wizardry lineage, and it is for me and a few friends, not a public release. The whole group draws from one shared roster of characters. A character can be in only one party at a time, and while she is borrowed she is unavailable to everyone, her owner included. With five players, that lock could starve the game. The design's answer is the character creator. If making a character is the part people love, they will make far more characters than they need, and the roster stays full.

That bet has two halves. Making a character has to be quick and fun, and the characters that come out have to look different from each other. Today's work touched both.

The workshop

Phase 1a landed today. It is a page that runs with no build step and no dependencies. You draw a character, recolor her, place marks on her, and save her to a roster kept in the browser. There are no accounts yet, so the workshop asks for your name once and stores it locally. The storage layer is one thin module on purpose, so the later move to a shared server rewrites one file.

The share link is the piece worth describing. One character encodes into the URL fragment, the bit after the #. When the workshop loads with a #c= fragment, it decodes the character and opens the same interface with every control disabled and an "add to my roster" action where save would be.

The measured sizes are small. A sparse character, carrying only the part slots someone set, came to 991 characters of base64url. One with all twelve slots filled came to 1,263. Marks are what grow a record. Each one costs about 66 bytes before encoding, so a veteran with two dozen marks and every identity field at its 64 character limit measured 3,395. Marks have no cap by design, so that growth is intended.

Even the long case is fine. A fragment never reaches a server, so the usual request length limits never apply, and chat apps carry links far longer than that. What the size rules out is putting a whole roster in a link, and roster export to a file covers that. There is no compression and no library. The encoder is about twenty lines of JavaScript over TextEncoder and runs the same in Node and the browser, so the tests cover it directly. The record also carries a version number, so a friend with an old bookmarked link gets a clear message instead of a character missing pieces.

These are Phase 1a's numbers. Phase 1b, later the same day, added race, alignment, class and six attributes to the record, and every share code grew with it.

Twenty seeds

The other half of the bet got a test. A gate page renders twenty characters from twenty fixed seeds, in a grid, at two sizes: full workshop size and the thumbnail size they will have on the tavern board. It asks four questions in writing. Can you tell all twenty apart at full size? How many survive at thumbnail size? Which axis carries the difference, silhouette, color, heraldry or marks? Does any generator look wrong anywhere inside its declared range?

My verdict was GO, and it was two findings in one sentence. I could tell them apart, but they were not very distinct, and that can be fixed later. The art direction itself I am a big fan of. So the way the figures are drawn passes strongly, and how much they differ from one another passes weakly. The weak half lands in content, where the plan said it would if it landed badly at all. Nothing asks for a rig change or a record change. It asks for more to choose from.

Three of the four questions went unanswered, and the record says so. Thumbnail legibility is still untested by eye. Nobody knows yet which axis does the work, which matters because it decides where the next round of content effort goes. Whether every value in every generator's range looks deliberate is still only a claim. None of that blocks the next phase, which is combat, but all three need answers before the next content push.

The exclusive checkout bet is still open. "Not very distinct" does not break it, and it does not confirm it either.

← All devlog posts