Sprint 19 - Adam-Poppenheimer/Civ-Clone GitHub Wiki

Goals

  • Carefully divided civ home regions with clear starting city locations, core territory, and hinterlands.
  • Resource distribution that balances different civ home regions without oversaturating regions with bonus resources, lakes, or rivers.
  • Different biomes that provide considerable mechanical and visual variety for different places on the map.
  • A Pangaea map generator, where all players are on a single large continent.
  • An archipelago map generator, where players are scattered in a tangled mass of small and large islands.
  • The notion of ocean regions, which include things like small and large islands and small archipelagos.
  • Cultural borders that run along the edges of rivers when present, rather than meeting in the middle of the river.

Risks and Mitigation

  1. The way in which information is passed between classes in the MapGeneration namespace, as well as the distinction between class responsibilities, remains messy and unclear. This could make it difficult to make substantial modifications to the system, or could make maintaining it costly.
    • I'll need to keep changing the way things are organized. Right now there's several things I ought to do, things I started to do during the last sprint but was too scatterbrained to implement properly. MapGenerator probably needs to be separated into multiple pieces, for instance. Things like creating the Voronoi Partition should really belong in their own class. I'll also need to decide what precisely a MapRegion is, since that's currently in flux. Ideally RegionGenerator should handle all terrain, shape, vegetation, feature, river, and resource placement and everything else should simply call into RegionGenerator with a particular set of cells/MapSections and a template. Having RegionGenerator be agnostic to where the region is located and how the region is configured seems important from an organizational standpoint.
  2. The current implementation of region balancing is a finicky and often unreliable process. It's entirely possible that there are fundamental problems with its design that'll make any success costly and unreliable.
    • The biggest problem right now is the oversaturation of bonus resources, particularly on land cells in regions without many rivers. This happens because there aren't a lot of other reliable means of adding score to a region besides adding new bonus resources. Ostensibly I can correct this in a number of ways. If I add more balance strategies, balancing will choose to place resources less often. If I enforce soft limits on resource saturation (either by changing placement weight or changing the rate at which bonus resource addition is selected as a strategy) I can also get better control over that. I might also consider changing the way in which things are scored. Perhaps it makes sense to add a bit of "artificial" score to sea cells, since they allow civilizations to create naval units and conduct trade more easily. Or perhaps I change the value of forests to account for the flexibility they provide. It's also possible I need to add more selection weight to fish so that bonus resources are more often placed in the sea. That'll reduce clutter by spreading resources across a larger area and increase the strategy's efficacy, since fish are some of the most valuable resources in the game.
  3. It's not clear to me how a civilization's homeland should be separated, nor is it clear that my current region generation system will work well if I start subdividing a civ's homeland into lots of small chunks.
    • I can spend some time studying Civ 5's map generation algorithms again to see how it works. It's entirely possible that there's not much differentiation to speak of. The only thing I'm really concerned about is luxury resource placement and the starting city. So I can start out with two regions: Starting City and Everywhere Else. Starting City can simply be a radius-3 block of cells somewhere in the civ's homeland that I carefully seed with at least two luxuries and some generous sum of resources. Everywhere else I can handle more randomly. I might need to rework how resource selection occurs to distribute copies of a homeland's 3-4 luxuries between Starting City and Everywhere Else. If that doesn't produce good results I can try more sophisticated things, like adding hinterlands. I suspect that won't be necessary, though.
  4. It's not entirely clear how I'll implement biome selection. I have an acceptable way of figuring out temperature, though it's often produces sub-optimal results for the game's needs. And I have no clear way of selecting for precipitation intelligently without running the same sort of water cycle simulation I already ruled out as being too unreliable.
    • I can start out fairly simply. There are several biomes I know I'll need: the temperate biome I'm currently working with, a tropical one, a desert, and a tundra biome. If I want I can build out a full collection of biomes for various temperature and precipitation combinations. I might want to create additional biomes for various shapes (flatland, hills, and mountainous regions) since that's a substantial part of the simulation. Regardless of my collection, I can start out by selecting biomes through temperature, by requiring certain temperature bands for certain biomes and then randomly selecting between all valid biomes. If I want I can create a pseudo-random moisture map (perhaps by sampling Perlin noise) to ensure that neighboring biomes are of similar moisture level, as well (no deserts next to jungles). In order to get that to work properly I might need to subdivide my regions more carefully (particularly my Everything Else region). That way a large region can have a somewhat more gradual transition between different biome types. Regardless, I should start out small and simple with the biomes that I actually need and only build more complex structures when I have a clear need for them.
  5. While my current continent generation system produces natural-looking results, it doesn't always produce a handful of separated continents. It will occasionally produce pangaea-like maps. As it stands, I don't have a way of reliably enforcing continental separation, which could make it impossible to keep the promises certain map types require.
    • I might be able to enforce continent separation using a technique similar to the ocean-growing scheme I used in an earlier algorithm. In order to ensure ocean between a pair of civilizational homelands, I can create a line between the homelands' seeds, find one of its perpendiculars, and then remove a bunch of the sections along that line as valid candidates for continent expansion. If I do that a configurable number of times I could probably vastly increase the likelihood of creating multiple continents. Pangaea maps can have starting locations try to seek the center of the map. I don't think archipelagoes will care much.
  6. Region generation currently assumes a contiguous blotch of land surrounded by that land's coastal region. It's not clear how well it'll work for more water-heavy models, like archipelagoes. And if it doesn't work, I'll need to spend a bunch of time coming up with a similar but distinct system.
    • It's possible that this isn't much of a problem. Region generation with high seed count and carefully-chosen land and water sections might work fine. If it turns out that requiring contiguous patches of terrain is a problem, I can always add configuration options to wave adjacency requirements.
  7. The large number of configuration variables map generation has makes it very difficult to pursue specific results. This might make the generation of specific map templates, like pangaeas and archipelagoes, impractically difficult.
    • I won't know how true this is until I've spent some time trying to get other map types working. I'd imagine there are a fair number of variables that won't need to change much. Resource scoring and minimum food/production yields will apply identically to continents, pangaeas, and archipelagoes. I might consider splitting my various templates into multiple pieces. For instance, I could rather all the biome-based config variables into one template class and all the resource-based variables into another. That way I could select independently for high or low resource concentration and also different biomes. Doing that should make it easier to test and configure each template object, since I'll have less I need to be worrying about at any particular time.

Review

I began the sprint by trying to clean up the MapGeneration namespace. Among other things, I established the notion of a Civ Homeland, which is a collection of regions loosely associated with a particular civilization. This cleanup helped clarify the purpose of a MapRegion and generally made the namespace easier to parse.

After cleaning things up, I started digging into the question of biomes, which seemed the most important issue. At first I addressed particular biomes I thought I might need in isolation (building a desert biome, a jungle biome, a mountainous biome, etc). But this plan had its shortcomings. There wasn't really an issue's worth of work to be done for any particular biome, and the majority of the difficulty of biomes came from their relationships with each-other.

Eventually I started addressing biome creation in a more holistic fashion. I separated my region template into three pieces: the biome (which defines terrain, vegetation, and rivers, and influences balance strategies and resources), the topology (which defines shape and influences balance strategies and resources) and the resources (which defines min food, min production, and average cell score requirements). I then created a number of biomes, a handful of topologies, and a pair of resources templates which could be mixed and matched with each-other.

It took a while to get biomes to work as intended. I ended up breaking luxury distribution and score balancing and had to fix it. During that period I began to weight resources through both my biomes and my topologies, figuring that different regions of the map should have different resource compositions. I also needed to change the way region generation occurred. My original model had assumed fairly large regions, but the more I developed my biome system the more need I had for fairly small regions. I thus removed terrain seeding/crawling from RegionGeneration and replaced it with something simpler.

The new homeland concept got a few responsibilities. They're now responsible for luxury distribution, which gave me a bit of trouble. I also switched river generation from a per-region affair to a per-homeland one, since smaller regions tended to promote smaller rivers in the old paradigm.

Homelands themselves were designed to make starting settler placement easier. I defined a StartingRegion within my homeland, which is the region in which a civ's starting settler will be located. It took a while to get starting regions in a good state, but I did eventually turn them into a fairly consistent and reliable structure. That greatly simplified the process of starting settler placement. All I needed to do was apply my best-location code to a single (and much smaller) region that has stronger guarantees of the sorts of properties I want.

I spent the rest of the sprint resolving bugs and trying to address problems with region balancing. It turns out that the codebase (probably for a while now) has been producing lots of regions with per-cell scores far in excess of their configured maximums. Reducing region score without destroying the features of a particular region is proving quite difficult and will require a lot more work in the future.

Retrospective

What went well?

  1. I came up with a pretty reasonable solution for temperature and moisture that produces fairly good results.
  2. I managed to get a pretty solid collection of biomes, distributed in a fairly sensible way across the map.
  3. I've substantially improved the organization of my map generation system.
  4. Switching rivers from a per-region affair to a per-homeland affair proved incredibly easy. That system was decoupled enough from region generation that I barely needed to change anything.
  5. I think I've finally got an organizational structure in MapGeneration that'll work in the long-run. The idea of regions and homelands seems solid, and the way in which I'm consuming MapSections and converting them into homelands and ocean regions seems fine.
  6. It turns out RegionGenerator can handle regions with lots of water just fine. It is a more robust system than I'd feared.
  7. I developed a fairly consistent way of creating starting locations with certain luxury resources and between-settler separations. That problem was resolved more easily than I'd expected.
  8. I managed to get a decent first-approximation of islands and archipelagoes without much difficulty.

What could be improved?

  1. Tundra regions seem a bit large a lot of the time. I might want to decrease the size of the arctic bands around the poles.
  2. I don't have a clear way of enforcing the existence of multiple continents, nor do I have much control over the precise contours or geography of any particular map. I need to add more tools for creating oceans, for determining how homelands relate to each-other, and for changing the way homelands are carved out of the map.
  3. Balancing the map is proving a very difficult task. I probably need to change the way balancing occurs in order to address the problem. Balancing at the level of the homeland, for instance, might help average out low-score and high-score regions that a civ might have access to. I might also need to drive map generation more by region balance than the requirements of biomes and topologies. Either way, there's much work to be done to balance the maps appropriately.