These past six months or so, I’ve been working on three different projects, or more accurately, on three distinct ideas for projects:
- A structured way of creating stories that doesn’t rely on an act structure, by which I mean that the whole stories are based on the causality of tracking entities, entity statuses, cast members, facts, beliefs, secrets, locations, objects, visible affordances, events, intentions, plans, clocks, obligations, consequences, open threads, relationships, and emotions. As part of this project idea, I also wanted to structure worldbuilding and propagation of canon facts.
- A platform to encode any card/board game relying on a game-agnostic engine, which would help prototype card/board games.
- A maximally-emergent, causality-first simulation that would be able to produce the kind of adventures you get through Dwarf Fortress, Rimworld, Skyrim, etc., without relying on any scripting or game director.
The story-related projects, which ended up being two repositories in Node/Typescript, were the easiest, although they were complicated projects in their own right. But the other two projects deserve their own paragraphs.
That platform to encode any card/board game started as an extremely-ambitious notion: any user would be able to encode every aspect of any game in YAML files. YAML that basically works as programming is a terrible idea, which I realized deeper into the project. I started programming it in Node/Typescript, which was also a terrible idea: it’s far too slow of a combination when it involves AST parsing of the YAML; I had to spend lots of time bytecoding or Rust WASM-fying parts of the Typescript engine to get decent performance, which was never good enough for me, and a lot of possible wins were denied by marshalling issues. But by far, my biggest mistake was proving the project’s ability to accomodate multiple card/board games by implementing two games: Texas Hold ‘Em and Fire in the Lake COIN. Texas Hold ‘Em was mostly fine despite the YAML base: it took like three days.
Merely thinking of Fire in the Lake makes my skin crawl now. Fire in the Lake is an extraordinarily complex board game representing the Vietnam War. Not exactly a traditional wargame, although it’s hard to explain. The point is that back in 2020, before large language models, I attempted to program it in Rust to learn the language. Huge mistake. Having to abandon that project a third of the way in let a splinter stuck in me from which I never fully recovered. So months ago, I decided I would rely on large language models to take the splinter out and properly implement Fire in the Lake. Huge fucking mistake.
The Fire in the Lake map is extremely complex. The adjacencies between provinces and cities are confusing, which involves country borders as well, but much worse, it also features LoCs like roads and the Mekong river. Merely representing it visually without just pasting the map on screen was a fucking nightmare. As if the map graph wasn’t enough of a mess, what the factions can do is much worse: operations and optional special activities, each of which can be as complex as entire regular games. I’m talking sweeping, assaulting, subverting, governing, air striking. Then you have the event deck, which causes stuff to happen on the map and on the markers and tracks, which is easy enough to depict, but the game designers also went out of their way, for which I commend them except for the fact that I tried to program this cursed game, to make almost every card of the 130 its own little exception. Some cards offered grants for actions which may or may not be optional, some of which were taken by different factions other than the one currently playing. Again, makes my skin crawl. I had whole GitHub workflows dedicated to ensuring that the granting system didn’t shit itself.
After I managed to encode the entire game rules and content, which I did manage to do (a fleeting win), I got myself into the issue of encoding competent AI bots. I didn’t want to just copy the flowcharts, given that a computer would run the bots, so I had ChatGPT-Pro deep research what would make a competent human player for each of the factions. My intention was to encode that. I got really deep into AI architecture to figure out what kinds of bots would work well for my requirements, and I finally reached a point in which it seemed like I just had to push through, and keep iteratively improving the bot encoding, to finally get them running. But a few days ago, I found myself not even reading the tickets, not even checking out what was being committed. My subconscious had already understood that this project was a bust. It was crippled from the beginning, and I had done little else than push against enthropy. I would never be happy enough with how Fire in the Lake would be shown on the web app, I would never feel confortable enough with how it was implemented, and worse yet, the engine had taken in too much of Fire in the Lake’s specific shape that disentangling it to implement other games would make me have to fix Fire in the Lake at every step. So I gave up.
The third project was the maximally-emergent, causality-first simulation. From the beginning I had a very clear idea of what I wanted; basically by ideal game which nobody has built yet to my knowledge:
- A simulation able to simulate dozens or hundreds (or thousands) of agents in an area the size of Skyrim, with settlements, roads, points of interest, etc.
- The simulation should be maximally emergent and causality first. By which I mean that there would be no scripting and no game director. The simulation should be able to produce complex chains like this: a big monster gets displaced from a wilderness area due to the activity of some bandits -> the monster ends up hunting around some nearby road -> the monster attacks a caravan -> the caravan survivors reach a town and speak with the authorities about the attack -> the authorities decide to set up a bounty for the monster -> someone creates the bounty and posts it at some board -> some passing adventurers see the bounty and decide to take it -> they gear up and gather supplies for the hunt -> they travel to the area where the monster is supposed to be -> they track it to their den -> they find out some other adventurers casually killed the creature already. This all should happen due to causal chains, no scripting at all.
- You as the player are indistinct to every other AI agent in the simulation. The simulation isn’t even aware that a human player exists. That means that the world continues regardless of what you do, but you can disrupt it.
- Every agent, including the human player if any, acts on their beliefs, which may be truthful, stale, or based on straight lies. People gain beliefs by talking to each other, reading notices, observing the world. This allows chains like someone going home to take money, only to discover that the money is missing because someone has stolen it.
- I should be able to chat through LLMs with any agent in the game, and the LLM would feed into the game which beliefs were actually shared or seeded, which would have gameplay effects.
That’s the main core. Such a simulation would allow any flavor and any kind of gameplay you could imagine. You would just have to build it incrementally. But I underestimated the complexity of such a project, which should be built upon an extremely-robust set of foundational documents of various categories. Mistakes I make during its implementation:
- The foundational docs, while more comprehensive than those of any other repo, just weren’t comprehensive enough. They would have required several iterations of deep research with ChatGPT-Pro.
- I approached it almost as a research project instead of something that would allow me to play it at every stage, even on the terminal.
- I went breadth first: I wanted a significant set of gameplay mechanics in order to prove the emergent nature of the simulation, and found myself programming takeovers of institutions before I had properly proved that people could eat and shit regularly without dying.
- By the time I figured out that even though I had banditry in, AI agents in simulations weren’t able to sustain their basic needs, the project was basically crippled; I just hadn’t accepted it yet. I should have built up step by step, being able to play it to the fullest along the way, and only add features that I missed while playing.
- The AI architecture, while extremely competent in some regards, was crippled as well: I relied too much on GOAP because HTN felt like scripting at first. Then I realized that you could use HTN in a fully emergent way that respected the foundational principles, and relying on GOAP only for the leaf goals.
With this third project, I found myself also disheartened, and feeling that I was fixing mistakes in a crippled project, when likely I would need to build it from the ground up.
So, two days ago I decided to start from zero (a Re:Zero, you could say) both those complex projects: the card/board game one, and the emergent simulation one. It’s amazing how quickly projects progress once you’ve taken the lessons to heart and you’re on the right track. For the card/board game, I’m building it up following a ladder of game complexity. I already have Race to N, Tic-tac-toe, Connect Four, and Othello in. I’ve checked legality issues online, and found out that even if you don’t take money for it, publishing a page that simulates a game with an IP behind it is actually illegal (oops), so I couldn’t have uploaded the project with Fire in the Lake in regardless. While I intend to program in the kinds of games I’m most interested in playing (basically those on my gaming shelves), I won’t be able to upload them to the public repository.

Playing Othello and losing terribly
Regarding the simulation, that third project, it’s shaping up far better. I can play the current state of the simulation at any point through a terminal user interface, which at the moment is mostly rudimentary. The foundational documents are sets of dozens, and extremely comprehensive. I will no longer push for breadth, nor implement mechanics that I don’t miss through playing the simulation.
The important thing is that I’m feeling energized again to work on these projects. I woke up at six in the morning today eager to get back to it. And that’s the best state of being for a wrecked creature such as myself.