Sprint 18 - Adam-Poppenheimer/Civ-Clone GitHub Wiki
Goals
- A continents map generator, where players are scattered across 2 or 3 continents.
- The notion of oases, which are essentially small lake cells that only appear on deserts.
- The notion of flood plains, which appear along rivers that run through deserts.
- Procedural distribution of strategic resources.
- Procedural placement of the starting units of civilizations in ideal first-city locations.
- The notion of ocean regions, which include things like small and large islands and small archipelagos.
Risk and Mitigation
- Flood plains in Civ 5 usually have lush green borders along the rivers, but not throughout the entire cell they occupy. As it stands, I don't have a clear way of mixing a flood plains terrain in the middle of a cell without causing it to bleed over into the boundary regions of various neighbors.
- I might consider adding another HexMesh and simply render my flood plain texture on top of the desert, extending it right up to the water perhaps. That way I wouldn't have to change the way I render cell terrain types to the screen.
- My current model for splitting the map into continents seems likely to create very samey maps, all with the same basic structure. That could end up compromising the whole point of procedural generation, which is to create new and interesting maps with unpredictable and unexpected features.
- I can take a look at how Civ 5 does their normal continents generation and go from there. There are some world generation techniques I might be able to make use of. I might be able to get decent results from a Voronoi diagram, whose sections I can aggregate into continents and oceans. How exactly I'll do that remains to be seen, but it's at least a start.
- I have no clear way of guaranteeing sensible starting locations for the initial city, either creating or finding them. This could make starting city locations very imbalanced despite the overall balancing of regions.
- I've been thinking about changing how I reason about regions. Right now I'm representing a civ's starting location as one large region. It might make more sense to subdivide that into additional regions. So I could define a small "first city" region, then a larger "secondary core" region next to that, and maybe a "hinterlands" region opposite. If I do that, I can make my starting location much smaller, which should make it more reliably produce good starting locations. I can then drop the settler right in the middle of this region and have a reasonable guarantee that it'll be in a good place.
- While I know how to create some visual representation of an oasis, it's not at all clear how I'll make something that looks natural. There's a good chance that polygonal oases will look very poor, which'll leave me without a clear solution.
- If hollowing out the center of my cells doesn't work, I can try creating an additional HexMesh and layering the oasis water on top of it. If I'm to do that I'll need some way of creating smooth-edged blotches of water. Most likely I'll accomplish that through a texture I read for transparency data, much like what I did with marshes. To add variety I'll need many patterns of splotches, which I might accomplish by aggregating a bunch of samples into a grid, rendering that grid to a texture, and then picking a random cell within that grid using UV coordinates.
- Adding islands and archipelagos to oceans could result in map clutter and could also make it difficult to ensure consistent separation between continents.
- Islands and archipelagos are a pretty low-priority task right now. And they certainly don't need to be that complicated. I can search for cells sufficiently far from land that changing their terrain won't compromise my ocean boundaries. I'm sure I can use my region-generating system to come up with something reasonable for archipelagos or large islands once I've removed inappropriate cells. If it proves too complex I can always defer it to another time.
- Several of the configuration values I've defined are very sensitive to changes. It's possible their sensitivity makes the whole map generation system brittle, meaning that it'll break every time I make any substantial changes to it.
- I might be able to mitigate this issue by setting better ranges on some of my values. At the very least that'll emphasize the significance to changes of those values. In theory those configurations will only become invalid if I change my region generation code, especially since it's tied to cell count. So if I avoid changing my region generation code I can probably avoid this issue. Though it remains to be seen if this'll even be a problem.
Review
This sprint has substantially improved upon map generation and added several important map elements to the game. A lot of the old problems of map generation have been resolved, though there are a few pernicious issues remaining.
I managed to integrate strategic resources into map generation without very much difficulty. It turns out I was overthinking what they needed to do.
I spend a decent chunk of time adding flood plains to the game. My difficulty estimate for this task was fairly accurate. I ended up adding an additional hex mesh and layered flood plains on top of cells. There was some non-trivial triangulation cases to consider, but overall I think it's produced quite a decent result. Flood plains look decent and stand out on the map, just as they should. They function acceptably in the simulation and in map generation, though I don't like the way CellModificationLogic handles them right now.
I also added oases to the game, which required me to re-introduce the idea of cell features. That forced a lot of changes to the simulation that I dealt with without much difficulty. It seems that my architecture and my test fixtures are amenable to modifications, as was the intent. Visually representing oases (at least in a simple manner) turned out to be fairly easy. I repurposed my flood plains mesh and added a simple polygonal structure in the center of affected desert cells, reusing water logic but with much mellower waves. Right now oases aren't incorporated into map generation, but they are fully functional.
Perhaps the most substantial change I made was a complete overhaul of how maps and continents are formed. Instead of having four continents, one in each corner, continents and player starting regions now appear somewhat randomly across the space. I'm also using an approximation of Voronoi Diagrams and Lloyd's Algorithm to divide the map into groups of cells from which I sample. This has added a lot more variety to map generation and continent contours and has allowed me to clean up the map generation process. There are no longer boundary regions or per-continent generation a la ContinentGenerator, and I no longer have configurable map regions. This system produces much better results than the old paradigm, and I'm quite pleased with what it's creating.
During my map generation overhaul, I ended up removing what little biome determination there was. I began to establish different starting region templates as a way of adding climatic variety to the map but ended up leaving it in a half-finished state. map generation does not currently produce desert, tundra, or snow, nor do different regions of the map behave particularly differently. I'll definitely need to add some notion of biomes (through both moisture and temperature) soon.
After overhauling continent generation, I spent some time trying to improve rivers. I managed to decrease my river saturation issues, making regions containing lots of rivers rarer. I fixed a few bugs that caused rivers to trail off without draining into a body of water. And I helped reduce the variance of rivered cells between different regions operating under the same template, though I was not able to guarantee a specific range of rivered cells.
The last task I attended to was starting unit placement, for which I provided a decent first-approximation that'll need to be replaced with something more controllable. Probably I need to change the way a civ's home territory is generated so that I can more carefully guarantee good starting locations and don't have to scan the entire region looking for something acceptable.
Retrospective
What went well?
- I've substantially improved the way in which continents are generated. Continents now have much better contours, are much more natural and varied, and are generated in a much cleaner manner than they were before.
- I managed to create a pretty good solution for flood plains without much difficulty, one that'll probably stand until the final product.
- My separation of region generation from more general map and continent generation proved very useful. I managed to completely change the way continents were generated without changing region generation much at all.
- I've added several important tools that'll be necessary to make deserts function, and helped move my clone of Civ 5 forward in the process.
- I managed to quickly improve the efficiency of starting unit placement by carefully caching results, to the point where it stopped paralyzing map generation.
- I resolved several important bugs that've been interfering with map generation for a while, I'd imagine.
What could be improved?
- I should probably try to consolidate my Water and Oasis shaders into a single shader with a configurable wave strength. There's no reason to have that much duplicate code.
- I'm still having problems with resource saturation. The map generator continues to produce areas of the map with an absurd saturation of resources. I'll need to add more techniques for balancing maps and work harder to improve and apply my existing solutions.
- Map generation is now completely without biome selection. I'll need to add some way of choosing between different biomes in order to add variety to my maps.
- I'm still not fond of how my map generation code is organized. My attempts to add ocean biomes revealed some problems with how data transfers between classes that I found quite vexing to deal with. I'll probably need to take another pass or two at how all of this is structured (especially MapRegion) before I've got something clean and workable.
- I need more control over home region generation for my civilizations. While I can now effectively build continent and home region contours, what occurs within a particular region remains unstable. I should probably subdivide home regions into smaller units (starting city, secondary core, hinterlands, etc) so that I can more carefully balance yields, determine biomes, and place the starting settler.
- I had work discipline problems the last two days of this sprint, at least partly because the small number of remaining tasks removed my motivation to keep working. I should try overstuffing the next sprint with issues to make sure that I never feel like I'm getting close to completion and thus never feel the urge to slack off.