Wednesday, May 20, 2026

Highlighted Blog Posts Over the Years

Some selected posts


A Developer's Life Stages - a taxonomy of developer growth from under-engineering to over-engineering to mature simplicity.

Underengineering Undead - a candid postmortem of an unfinished Ultima-like RPG whose lack of architecture made it unfinishable.

Some Perfect Hash - a perfect-hash optimization for Cactus Kev’s poker hand evaluator that substantially speeds up five-card evaluation.

NCAA 08's Video Highlights - a behind-the-scenes look at building in-game video highlight capture and upload under tight console constraints for EA's NCAA 08.

Times of Lore Maps - a nostalgic post sharing extracted maps from the PC version of Times of Lore.

Indigo Ocho - a brief App Store note for Indigo Ocho, an eight-ball adventure game set around a dangerous tower.

Sieve of Eratosthenes - an optimized C++ (and assembly) prime-counting sieve written for an EA programming challenge.

Poker Revisited + ESPN - a short update linking the old poker evaluator work to Coding the Wheel’s roundup and mentioning ESPN virtual play-by-play work.

Let Me Count the Ways - a dive into fast enumeration of combinations, moving from brute force to bit-level and recursive/iterative optimizations.

Let Me Count the Ways Part II - a follow-up showing that the optimized combination generator is ultimately bottlenecked by memory bandwidth.

The Relic - a launch/postmortem overview of The Relic, a solo-built 3D iOS action RPG published by Chillingo.

7 - an exploration of fast seven-card poker hand evaluation using compact indexing of 52-bit card sets.

JSON Parser for Objective C - a simple Objective-C JSON parser built on the earlier string code.

C String Library for C and Objective C - a minimal C string utility library adapted for Objective-C and C++ work.

Java-Style Properties Files in C++ - a small utility release for reading Java-style properties files from C++.

A Little 2D Map Matcher

I wrote a small 2D map pattern replacement utility.

It's simple, but solves a problem I keep running into with procedural world generation. You can generate a perfectly valid 2D tile map, but it often has that raw, algorithmic look. Water touches grass. Mountains abruptly become meadow. Rivers stop being rivers in awkward places. The data is fine, but the world needs another pass.

So this tool is that pass.

It is here on Github.  This is currently just a MacOS XCode project, but I'll eventually set it up with CMake for cross-platform building.

The input is a very simple text map format, .m2d, containing tile indices. Right now that is basically the only map format it supports, which is fine. The script file, .m2s, describes patterns to find and what to replace them with. The program reads the map, applies the rules, and writes out a transformed map, along with TypeScript output for the project that consumes it.

The example here uses Ultima V tiles. In the first image, the map is already recognizable as land and water, but the coastlines are harsh. The map is made of legal tiles, but it does not yet have that pleasing old RPG coastline logic where deep water becomes shallow water, shallow water touches a shore tile, and the edge of the land knows which direction the ocean is.

Before the replacement pass, it looks like this:


After the replacement pass, it looks like this:

Much better.

The script starts with named lists:


lists

deep         = 1

shallow      = 2

shoals       = 3

water        = deep|shallow|shoals

swamp        = 4

meadow       = 5

shrub        = 6

grasses      = swamp|meadow|shrub

land         = flatland|mounts

shore_w      = 51

shore_s      = 50

shore_e      = 49

shore_n      = 48


This is mostly to keep the rules readable. I do not want to remember that 1|2|3 means water every time I write a rule. I want to say water.

Then come the rules. A rule is just a little rectangular pattern. Each cell is find:replace. If there is no replacement, it just means find. Wildcards are supported with ? or *.

For example, one early rule turns land next to water into shoals:


water        land

water        land:shoals

water        land:shoals

water        land

There are other rules for removing one-tile islands and promontories, placing the correct directional shore tiles, fixing rivers, and cleaning up mountains. The rules are applied in order, which is important. First you make rough decisions, then later rules refine them. This is the way I tend to think about procedural generation anyway: build a crude version, then gradually make it less ugly.

The implementation goal was also modest but deliberate. I wanted to write it in modern C++, without the old habit of scattering new and delete everywhere. The map is just a small generic map2d<T> backed by std::vector. Files are read into strings. Rules are parsed into objects. Storage owns itself. The code leans on RAII instead of manual cleanup.

That sounds obvious now, but if you have written C++ long enough, you know it was not always the default style. There was a time when every little utility wanted to become a memory-management exercise. This one does not. It reads a file, transforms a map, writes a file, and exits. No ceremony.

I also like that the script format is crude in the right way. It's not JSON or XML. It's not a beautiful general-purpose language. It's a little thing for describing little grids of tile indices.

That said, it already gets surprisingly expressive. The coastline example is the obvious win. The original map has land and water in the right places, but the tile transitions are wrong. The transformed map gets shoals, beaches, shore corners, and more convincing edge behavior without needing the original generator to know about every possible local tile relationship.

That separation is useful. The world generator can think in broad strokes: continents, islands, forests, mountains, rivers. The matcher can think locally: “this water tile has land to the east, so make that land a west-facing shore.” Those are different jobs.

The next obvious improvements would be support for more map formats, better diagnostics when a script rule is malformed, and maybe some way to visualize which rules fired. I could also imagine adding probabilities, so a rule could replace a matched pattern with one of several tiles. That would make it easier to break up repeated edges and add a little controlled noise.

For now, though, it does what I need.  It takes a rough procedural map and gives it one more pass of tile-level intelligence. The result still looks like a map from an old computer RPG, which is exactly the point,