City generator
The first generated city
(Originally posted on Tumblr on 2025-02-13)
working on a city generator because sometimes I get bored during character stuff that has nothing to do with me during tabletop.
I’m kind of trying to emulate city generators like the watabou generator and fantasytowngenerator.com type towns.
my first idea was to take a square and slice random lines across it to give me a couple of big polygons, and then filling in the rest of the area with … ??? not sure. that didn’t get very far.
the current setup is very obviously voronoi space. I’m using LLMs to the degree of giving me algorithm ideas, they aren’t very good at writing correct code for the shape/polygon library that I’m using. the really cool thing about partitioning like this is that you can select subsets of the “city” partition and make districts, or make an “inner city” that’s surrounded by walls, or bias a direction to grow the city towards… there’s a lot of levers and pulleys to parameterize what a city looks like.
rendering is done with SVG.
the current algorithm is:
- select the whatever region is the center guy.
- select all neighbors of the center guy, and add that to the “city” group
- repeat #2 a few times (in the image, it’s 4 times = 4 layers) and that’s your city.
I plan on adding more than just this. the whole deal with city generation is that it’s fast(er) than sitting down with pen and paper and making something up yourself. however, making more interesting cities with a computer has a tradeoff with being slower. this prototype is written in python and takes about 1 second to generate (it outputs an SVG file). in my mind, an upper bound for a time limit for a tool like this would be around 5-10 seconds; maybe 30-60 seconds if it promises to be REALLY good and you only need to iterate once or twice to get something you like (= really interesting).
so, some ideas to make a city more interesting, versus computational intensity of generating it:
- adding rivers: interesting+++, computation—. just find a random path between vertices and pretty it up. kinda hard to actually implement if you’re like me and don’t have geometry brain, but it shouldn’t add more than a few milliseconds.
- adding streets and roads/highways: interesting+++, computation–. see above, probably 10-100x more time vs adding a river, but the same idea.
- more realistic districts: interesting++, computation-. make the voronoi space smaller (i.e. bigger districts) and subdivide the districts into streets.
- adding names to everything: interesting+++, computation—. extremely easy way to breathe life into something.
- multiple cities: interesting+++, computation+++. this one is what inspired me to make the list. you can see multiple places that look very natural for a city core. I think it’s cool+natural to have multiple settlements close by e.g. a river. but, selecting N optimal spots is a linear (but not small) growth - there are 1364 locations on this map, multiplied by every polygon face to choose; then you have to choose neighbors for each one for multiple rounds… it’s not a great program for Python to crunch lol
- other: bodies of water, holes in the city, important buildings, walls, farms, there’s so much to add. they’re all going in a todo list.
just a few ideas. I think the main bottleneck is implementation time because I don’t know SHIT about making nice curves and stuff.
as for other work, not by me: one thing I’ve noticed about the watabou generator is that it’s pretty “circular”. a lot of the cities/towns it generates are pretty blobby, and it obviously uses voronoi spaces. but it has a lot of nice features especially for being free, and I am referring to its outputs constantly (not looking at the source code). the fantasytowngenerator link is harder to measure because it generates the same town every time with the “try it out” button. it feels like most of the time is spent downloading assets. but it has a high level of detail, you can click on any building and get a list of people who live there, what their jobs are, the building where their jobs are, etc. it’s also paid-for, while the former is open-source.
idk, I’m mostly looking to make my own thing but also make it good. I’m probably going to drop this before it’s complete but I had a lot of thoughts. this is a nice product for 4 hours of half-programming IMO. I’ll probably port it to a faster language if I actually get that far. but for now I’m sticking with Python, slow as it is.