Showing posts with label Infrastructure. Show all posts
Showing posts with label Infrastructure. Show all posts

April 9, 2021

Detail XIII: A Case Study VII

One full region is now generated:

There's plenty of material here, of course, but I can do better, particularly with the addition of features. Let's zoom in on the capital city here (Hex 25, infrastructure 42).

The first and easiest thing to place is a bridge. Hex 25 has a high enough infrastructure to be able to place bridges (as opposed to ferries or fords). This river has a Strahler number of 4. Therefore, the two hexes where the roads cross the river will have bridges on them, notated by black squares (for now).

I recommend reading through this series of posts to understand where I'm going next. We want to know what features this hex has by virtue of the specific layout. Moreover, it'd be nice if this were a true function: that is, for a single input of hexes, we have a single output set of features. That will allow us to save some storage space, since all we'll need to know is the original layout.

To place these features, we loop through the hexes from highest to lowest infrastructure - not worrying about whether the hex is itself civilized. That is, for a hex and its six neighbors, if there are 4/7 civilized hexes present in that set, then the central hex is of Type 4, quite good. Depending on the exact distribution of those civilized hexes (Type 4 has 8 possible layouts), the possible features could be a large keep with a village, a manor house with a village, an aquifer, or a quarry. Once a feature has been identified, all hexes in the set are removed from the list: this prevents the map from getting too busy.

I've only added a few things to the list given by the Tao above. But there are a lot of configurations which are empty - again, that's fine. Scarcity breeds innovation.

In addition to the bridges, we generate a medium keep with village and church, a toll road, several mines, and a quarry. Additionally, there are several outlying hexes with no specific feature, but which in this case would most likely be farms or other "non-village/city" communities of a few families.

I could also make use of the wilderness and deep country features discussed here; but that would need be on a different layer, not player-facing. Still, could be a useful DM tool.

June 11, 2019

Detail IV: Wilderness Colors

I've just been using a dark and light green to indicate wild and settled terrain. But I need to match that to the actual terrain colors from the 20-hex map.

I really like Welsh Piper's hex generation mechanism so I'll be borrowing some thoughts from here. For now, I'll just define a primary type, a secondary type, and a settled type.

Sometimes, settled will be the same color as unsettled. For example, the halflings, who live in icy terrain, wouldn't be able to grow cropland. In this case, I'll define something like settled = primary, where ice is primary and rock is secondary. So the settled areas are still delineated.

However, most of my test cases right now are in forested areas, so I'll concentrate on those. All those areas turn into grassland type when settled, at least in terms of display. I've also put a pattern over the wild 1-hexes to visually differentiate them if the secondary type is also grassland.

Blitpsy, population 4976, infrastructure 84

I also implemented a condition where the highest infrastructure hex must be on a river. This ensures that a settlement (when I get around to placing them) will always have access to the river.

South of Blitspy, starting to transition into grassland, some of which is settled and some which is not

Speaking of rivers and colors, I'm not sure the river stands out enough. I also kind of want to make the river a bit more fractalized, but I remember that I'm making a representation, a symbolic map, not a literal terrain map.

It does seem that the heightmap (which is shown by lightning the hex the higher you go) is almost invisible. That's fine; it'll mostly be important for determining the rivers and roads.

To do: roads, coastal 20-hexes, and river sources.

June 10, 2019

Detail III: Infrastructure

I have been thinking more about how to generate infrastructure for the detailed hexes. I've floated a few ideas here and there which seem to work well, but I thought of an interesting situation where the current system might give odd results.

To sum up, the infrastructure number of a 20-mile hex will indicate how many of the 400 1-mile hexes will be settled. For ease of experiment, let's assume that the 20-hex is forested, and that the settled 1-hexes are cleared land (whether for grazing animals or for houses, doesn't matter yet).

Previously, I was just using the infrastructure number as the number of settled 1-hexes, up to a maximum of 400, at which point the hex would be totally settled. But after reading this post several more times, I believe I can come up with a more robust system.

The problem is that infrastructure spread stops at the boundaries of a hegemony. This means there is a possibility of a hard edge where there is a totally settled 20-hex ($I\geq 400$) next to a relatively unsettled 20-hex (say, $I=10$). The whole point of the detailed 1-hex view is to give a smooth interpolation between discrete 20-hexes.

So what's the point?
The Tao (Alexis) uses 2-mile or 6-mile hexes, allowing a smoother interpolation because the detail is not as fine. With the 1-hex, there are 400 hexes that must be made to play nice. He gives a chart, however, detailing the behavior of each hex type and group depending on the number of wilderness hexes that surround it. 2-hexes which are completely settled (Type I) contribute 64 points of infrastructure to the total, and so on down the line. Read the links for more info, I won't rehash it here.

Since I'm not dealing with hex groups directly, I need a way to translate or spring-board off this existing system of ideas into my own map. I will define groups of 1-hexes in the following way: counting the 1-hex itself and the surrounding 6 hexes, how many are wild (of the 7 total)? This gives us 8 total types. Furthermore (and here's the distinctive key): these groups are not discrete. Each hex contributes not only to its own group type, but also those of its neighbors. In this way, the combinations are made even more unique...if it works.

TypeAdjacent SettledInfrastructure
I77
II66
III55
IV44
V33
VI22
VII11
VIII00

This has some interesting implications. Observe the minimum situation for a Type I hex:



The very presence of the Type I implies a further 6 Type IVs. That's a total of 31, if the above values are used.

Type II (total 24):


Type III (from here on out, I've tried to show the lowest configuration, there are others that could be higher, total 17):


Type IV (total 12):


Type V (total 7):


Type VI (total 4):


Type VII (total 1):



So how do I make this work? I'll start with a brute force approach.

It's very quick to run an algorithm over the 20-hex and get the total infrastructure number based on the 1-hexes. So what I'll do is gradually increase the number of settled 1-hexes and check the number. When I reach the target number, I'm done.

So far, this works pretty well.

$I=113$
Let's try it out for a stark difference. The top hex has $I=1000$, and the bottom two, $I=10$.


Not bad! The edge is still pretty hard...but not as hard. Furthermore, the individual hex groups could be identified for feature placement.

An issue with the infrastructure values for each hex type: The higher the numbers go, the fewer 1-hexes will end up on the final map. Earlier, I had defined 400 as the value of a filled 20-hex: but with the new system, a 20-hex must have $I=2268$. That's pretty high. But it does imply 346 sq. mi. of continuously occupied land (including farmland).

Finally, each iteration is totally random. I want a way to save them so if I come back later, or make a map for a game, I can reproduce it. Each configuration is extremely unique, and so I need a fingerprint. There are a couple of ways I can do it, but here's a very simple one.

First, I sort the hexes by their address, then assign 1 for settled and 0 for wilderness. Then I join all those numbers into a long binary string, padded to 400 zeros. For $I=1000$, that looks like this:
0b0000010000000000000010010011000100000000000000001000000000000000000001000000001001110000000000000101000000010000010000000000100000000010101010000100000010010000010001001000000000001000000011100000000000100000000001000100010010100000001101010000110010000000001000000010000000000000000010000100000000001000000000010000000000000000000010000000000100001000001001000100000000101000001011000100110000010000
But that's super long! So instead, I'll convert that number into hexadecimal. It's still long, but manageable.
0x400093100008000040270005010400802a840904480080e00200444a0350c802020000840080100000801082440282c4c10
I can save this fingerprint for use with this specific hex. When I'm recreating it, I can just pass the seed back to the generator. It's very simple. I think I should try and implement it for the height and river data, but that will require some extra thinking.

June 7, 2019

History XIV: Here I Stand (Summary)

I thought for a bit on how to present a total overview of the system (suggested by Ted), but there are so many moving parts. Still, it's good to sit down and think about it a bit.


This ought to help in keeping things straight. Or perhaps it makes it even more confusing.

It's clear there are several feedback loops: most notably that the city growth rate is affected by the overall tech level of the hegemony. This provides a significant obstacle to small starting cities, but gives a boost to established empires. The loops keep things interesting. In addition, many of these links involve some randomness, which means that things will generally tend in the same direction each time I run the whole simulation, but it's never going to be exactly the same.

Desirability is a value, expressed as a percentage, which describes how desirable a piece of land is for settlement. Each race prefers a different arrangement of terrain and weather. The desirability value will affect how large a settlement can arise in a hex, and also captures the number of resources available there (whether or not they are being totally utilized). Because the resource allotment code adds complexity and time to the history simulation, the desirability is used as an approximation of resources in the battle simulator (since a settlement with access to more physical resources will have an inevitable edge over their adversary). Raw desirability is the desirability in the absence of civilization; it is mixed with infrastructure to obtain a measure of desirability for city expansion, when an existing settlement sends out settlers.

Infrastructure is an integer which describes the effect of settlements on surrounding terrain. Although the Tao only uses elevation to limit the spread of infrastructure, I also include local effects such as forest or desert. I also make infrastructure "flow" downriver easier than upstream. A high enough infrastructure (over 400, for now) changes a forested hex into plains or grassland, depending on the local climate (which is a feedback element encouraging a more efficient infrastructure spread). A higher infrastructure implies a better training mechanism for soldiers. Infrastructure spreads from every settlement in a hegemony and stops at the border.

Hexes with infrastructure but no settlement are the hinterlands; they are prime candidates for future settlements. Since the hinterlands are populated (however sparse), reinforcements can be press-ganged. Generally, however, their population is very low. The rural population of any hex with an infrastructure value is an exponential function of that infrastructure number.

If the effect of a hegemony's capital (measured in % of total infrastructure in a hex) drops too low, and a city's self-generated infrastructure is high enough (100), then a rebellion is possible.

Available resources (which are fed into the market system, not shown) are acquired by cross-referencing the available resources (which is somewhat determined by terrain) with the resource definitions. Certain resources cannot be extracted by low-tech cultures, but may become available as the hegemony grows.

The Long-awaited GitLab. There is no README yet: I've been working on this for two years now, and so the code is a garbled mess in places and cleaner in others. Eventually I'll get around to some housekeeping. Enter at your own risk.

April 30, 2019

Demographics VI: Return of the Urbanites

The equations here are cool, but they start to yield some pretty large numbers when the empire size begins to grow. So I'm going to try an alternative system for a while and see how it feels.

This is just a simple logistic function centered at $I_0 = 400$, with a maximum value of 480 persons per 1hex: a very high rural density indeed for the development we're talking about. \[d(I) = {480 \over 1 + \exp\left(- k \left(I - I_0\right)\right)}\]. $k$ is set to 0.016, so that $d(5) = 1$. The population of a whole 20hex is given as $400 \cdot d(I)$.

Since this doesn't rely on the urbanization rate (which is now derived rather than set) to determine population, we can now get population numbers for hexes with no cities. The hinterlands.

January 30, 2019

Roads III: Across the Wilds

The building of roads must be more dynamic.

Yes, a certain infrastructure must be in place for a road to start. But it is misguided (as I have tried previously) to require that same level of infrastructure for each intermediate hex. Roads will frequently be built across areas of wilderness. How do I capture this?

The road, after all, merely connects two locations. It is not itself a location. So while we might require an infrastructure index of, say, 50 to begin and end a road, it might pass through many areas where the infrastructure index was much lower, like 5 or 10.



A bridge (generalized river crossing) also should not be a static threshold, but should vary based on the size of the river (measured by drainage $d$). \[I_d = 100 \ln(d)\] Bigger rivers require a large infrastructure to be built to maintain their bridges.

Maintained roads are not the only option for travel. Cart trails or other paths can be available as well. So perhaps the "road system" should be primarily for heavy trade, and not necessarily for point to point movement of a player party.

I could also check if two locations can already be connected before placing a new road between them. This would reduce the total number of roads which need to be placed. However, just having a single connection is not enough. We can easily imagine a scenario in which a road between two distant cities is placed among the most optimal route at the time, but 100 years later, a more favorable route (perhaps through a large intermediate city) is possible. We can't expect our people to shrug because there's already a road there! So perhaps this can be tweaked.



That still doesn't improve things a lot. But - maybe they don't need to be "improved." A country with a road system like this could be a military or industrial power.

Limiting the number of roads by population of a city?


This might work. But I still need to tweak it to generate longer networks.

January 17, 2019

Infrastructure II: History I

Time to begin placing cities.

There are a few considerations to make when growing populations/cities organically.
  • Initial populations of villages are set to $P_0 = 150$. The growth equation at time $t$ then becomes \[P(t) = {K \over {1 + {K - P_0 \over P_0} e^{-r t}}}\] In the future, I'll actually progressively modify the population number, but for now I just evaluate this equation using the age of the city.
  • The carrying capacity $K$ is a function of the desirability $D$ of the location. \[K_0 = 5000 \exp\left(10 \left({D \over \textrm{max}(D)} - {1 \over 2}\right)\right)\]
  • $K$ is then modified according to Central Place Theory (CPT). One of the tenets of CPT is that cities are spaced according to the product of their populations and inversely to the distance between them. My method for doing this is as follows: the city in question is assigned a level $\ell = \log_{10} K_0 - 1$. $K_0$ is then reduced by a factor of 10 if $2 ^ i > \delta_c$ for all $i < \ell$, where $\delta_c$ is the distance to the closest city of the same $\ell$. So a city of 9500 people cannot be closer than 4 hexes to another similarly sized city. If it is, then $K_0$ is reduced by a factor of 10. This will hopefully ensure an exponential distribution of city sizes, and prevent a concentration of very large settlements.
  • $r$ will be a random number with a max of $2\% \cdot D \over \textrm{max}(D)$. This sets the maximum growth rate at 2%, but allows for a lot of variation in between. Maybe the different races should have different growth rates?
  • Any given hex which meets all other requirements has only a 5% chance of generating a city. I'll give this a little boost for particularly desirable places.
  • I won't force them to obey Zipf's Law, but I'm wondering how the distribution will shake out. Zipf's Law has been demonstrated to hold most true for "small cities" over 100,000 - for a fantasy low-tech world, that might be a "huge city" instead!
  • Another thing I need is a mechanism to destroy or stagnate a town - many things can affect a city's growth or longevity. Not every city built in 1000 BC still exists. In fact, most don't. Plague, famine, war, resource depletion, etc can all wipe out even large settlements.
  • A dynamic $K$ value might be cool also. That way a settlement might have a bright future, but overcrowding could really hurt long-term. As groups compete for resources, which larger cities need more of, smaller settlements tend to be crowded out. I need to capture that, and that might help my goal of CPT-arranged cities.

Some observations:
  • Since dwarfs (blue cities) are not "constrained" to the coast, their cities are placed much faster. This isn't necessarily a problem, but I want to consider how heavily the coast is weighted vs the inland. As a result, non-dwarfen cities are isolated, and have more difficulty coalescing into an entity.

  • The desirability map takes a dozen seconds or so to populate. This adds up and makes the year-by-year simulation very slow.
  • Similarly, it's expensive to figure out where roads should be placed so that they make sense. I've added some timeout functions to the road placement algorithm to make sure that A* doesn't get stuck somewhere it can't get out, but the constraints need some work. As shown in these images, it's made slower by the fact that eventually, every city gets a full 6 roads coming in and out.
  • Some of the orc cities (purple) behave well with roads, but there are no special road considerations for different races.
  • River crossings are a problem. They would be easier to implement if I used edges instead of tiles, but that would be a big pain to implement with the drainage code.
After 550 years of simulation, the total city populations are as follows (not including rural population, which is expected to be about 5x urban):

elf13,552,065
dwarf5,570,650
halfling11,144,894
orc28,884,984
human14,688,643
Orc growth is much faster because their cities form at great distances from the other, allowing for rapid growth and large carrying capacities from CPT. The opposite is true of the dwarfs: they have many cities, but densely packed, which reduces the maximum carrying capacity.

I could do more analysis of the cities, but I'd like to tackle the road problem first, since it feeds back into the city placement algorithm, and is the current bottleneck for any kind of long-term simulation.

    January 11, 2019

    Desirability IV

    As discussed in previous posts, the presence of cities and infrastructure can make a location more desirable. Shown here for elves:

    without city modifier

    with city modifier
    As with many things, the rich will tend to get richer. Highly desirable locations will only become more so. Can penalties occur naturally? Something to consider.

    Currently, the cities are undifferentiated with respect to race - my end state will be to have more eclectic populations - but for placing initial cities, I may want to change that temporarily.

    The next steps are to put it all together in a coherent whole model.

    January 10, 2019

    Roads II

    With the rough infrastructure map in hand, I wanted to be able to place roads between them. Then both systems could be fed back into the desirability model.

    But as usual, there were some kinks to work out. There are a few constraints on the roads, such as climbing distance (too steep? penalty), altitude (particularly above 8000 ft, where the air is thin for those not acclimated), and of course overall length. Additionally, a hex must have a certain infrastructure threshold to even be considered for a road, and it's even higher for a bridge to cross a river.


    I don't mind the jaggedness of the line - the hexes are huge, after all. It's the overlapping roads I want to avoid. So I fixed it to seek only the closest city for a road. This is similar to a minimum spanning tree, but not exactly. I want a non-optimal layout - the spread of populations shouldn't always make sense.




    These maps also show how the infrastructure (red) is affected by local topography, which constrains it from spreading too far.

    Now, I can feed both of these systems into desirability and start building more organic layouts (the cities I used here are just randomly selected).

    January 4, 2019

    Infrastructure I

    In my discussion on desirability (for population centers), I realized that existing infrastructure is extremely important. Communities can exist in isolation but will inevitably spread themselves out, creating new communities and so on.

    Eventually, I'll split infrastructure out into separate races (at least for the desirability index). Infrastructure, of course, determines what sorts of services and industries could be available in a given hex, so I only need a single (non-racial) number eventually. But as far as settlement placement goes, it would make more sense that an elven village would prefer other elves rather than humans or dwarfs, given the chance. I can also define rough guidelines to racial relations - humans and elves might get along better than humans and dwarfs, and who likes the poor, stereotypically brutal orc?

    However, making this switch is pretty easy, so for now I'll work with a single value. This will make settlements more heterogeneous during these tests.

    To really get an accurate base number for infrastructure, I need a value for the total population in a region (or the whole world, as it may be). This part is tricky when starting from scratch and looking at the entire planet - I don't know how many people there are, and where they live. After all, that's the point of this system in the first place.

    The equation in question is as follows, where $I_{i,0}$ is the base infrastructure index of the $i$th city, $p_i$ is the population of the $i$th city, $p_t$ is the total population (urban and rural), and 346 is the number of square miles in a 20-hex:
    \[I_{i,0} = {p_i \over 346} {\sum_i p_i \over p_t}\]
    Essentially, I am ignoring the ${\sum_i p_i \over p_t}$ term, because I don't (yet) have access to $p_t$. Or I could make up a number. Ignoring it is the more palatable option, but adding a multiplicative factor will make the influence of a settlement "reach" farther.

    Placing a bunch of random cities and applying those rules:

    I'm excited to lay down some roads on this bad boy (and to feed it back into the desirability map).