Fixed borders idea: uneven spreading of culture

phunny_pharmer

Chieftain
Joined
Jul 10, 2002
Messages
31
Afforess

I want to propose a relatively radical idea to the Civ games, which may or may not have been discussed elsewhere. What if culture spreads unevenly on tiles?

For instance, states historically have had relatively* easy times controlling plains and flatlands. Their controls has been facilitated by rivers, and often easily spreads along coasts. Controlling the highlands tends to be tougher, and peaks can be incredibly tough to crack if even a small hostile civ is established there. I know that I am making sweeping generalizations, but suspend your historical critiques for just a minute and work with me and my ideas.

In Civ4, cities could spread culture. In ROM, forts could spread culture and units could forcibly claim tiles. However, the amount of time necessary to claim land, whether plains near rivers or mountain peaks post mountaineering, was uniform. Your small band of warriors could control either the plot on the river equally as effectively as that mountain peak. If you think that's realistic, ask Alexander the Great why he spent a nontrivial amount of his life trying to do what the British, Russian, and later US armies can't effectively do in Afghanistan. In short, culture spreads at different rates in different areas, almost independently of the size of the army.

To have ROM better reflect this, I'd like to have land tiles be more or less susceptible to the spread of culture. River or coast tiles would be most susceptible to culture; non river plains next; hills following; and deserts, tundra, and peaks least. This reflects approximately how easily most civs have found to control and "civilize"* territory.

The advantages of this would be quite apparent. You'd end up with an ancient Egyptian civ that really did only control the Nile (and little or no desert), as is historically realistic, and a Roman Empire that effectively stops at Scotland's border. Not to mention a whole lot more realistic barbarians and a more complex early game, because then you'd have to choose whether or not to try and found a city in the hills knowing that you can't take control of much of the territory until later, versus a city on the plains that could gradually expand faster. Rivers would become critical, and fights would clearly break out for control of the major waterways.

I don't have any code to support this idea, nor do I have much time to write anything. My guess as to how I would go about this would be to have the city produce X culture a turn as it currently, does, but then have each tile around the city subtract out a constant amount of culture dependent upon the type of tile. For instance, mountains might knock out 20 culture a turn emitted by a particular civ; it would then take a very strong city or a couple of units sitting there to conquer a mountain tile. In contrast, a river-bordering tile would knock out none. I'd then have a small chance that any tile that is being influenced by a city but not owned by the civ could spawn barbarians, to represent hostile forces attacking an established civ.

Thoughts? Comments? Suggestions? I have no idea how hard this would be to implement, but it would be cool to see in game....

* Apologies for the broad generalizations. I am not getting my PhD in history.
 
I believe this is exactly how Civ5's culture will work, and I like it. It, unfortunately, falls in the back of line of big things to change... And I've been getting more and more requests...

Really good idea though. I will add this after Expanded Espionage.
 
I like the sound of this too :) How far down the line is Expanded Espionage?
 
I like the sound of this too :) How far down the line is Expanded Espionage?

1.) Finish up sacking & enslaving (Got them both done, just need to make sure the AI is working)
2.) Inflation
3.) Personalized Maps
4.) Expanded Espionage
5.) Realistic culture spread
 
So, not too far off at all then. Just one per month and you'll be done by July :D
 
So, not too far off at all then. Just one per month and you'll be done by July :D

Redesigned Vassalage should be included, as it currently leads the list in the last QotW thread :)
 
Afforess-

Alright, you're busy. So I'm going to try and make this work on my own :D

My plan for this is to modify the doPlotCulture() function in CvCity, in order to have different culture spread rates to different terrain types. It appears to be relatively simple, if I hardcode in a bunch of numbers for the different terrain types. The general plan is for each terrain type to "subtract" a given amount of culture per turn from the tile. Plains tiles will subtract 0 culture per turn, but hills or forested tiles will subtract enough culture such that it exactly cancels out the growth effect of being at the maximum city culture border.

I'm planning on making mountains, tundra, and ice subtract effectively two cultural expansions. These will give dramatic effects. Again, this is not unrealistic - civs culturally expanded on flat ground.

I do plan to force the game to give the civ access to all eight squares in the city's size-1 radius. This mechanism should only take effect for squares that are not within a stone's throw of the city.

A picture, even an ascii one, is worth a thousand words here. So take the following example, where the city is labelled C. Assume that the city has three levels of cultural expansion, and thus under the current mod has control over all the squares o. The squares X are outside the city's range and no culture is provided there.


XXoooooXX
XoooooooX
ooooooooo
ooooCoooo
ooooooooo
XoooooooX
XXoooooXX

Now, if my changes go through, here's what should happen. Let's have mountains M and hills H in the city at the locations I specify. Assume all other tiles are plains.

XXhhMhhXX
XoohMhooX
ooooMoooo
ooooCoooo
ooooooooo
XoooooooX
XXoooooXX

The mountain closest to the city will be available for work, because the tile is one of the starting 8. The other two mountains, however, will not be workable due to the culture cancellation mechanism. The farthest set of hills will also not be workable, though the set of hills in the second row will be since the city will produce more culture there.

There are three very cool corollaries to this change

1) Building a fort in the cultural borderland will provide one additional culture point per turn, as per Afforess's mod. Thil will be *just enough* in order to allow the civ to claim the tile, as having even one culture point on the tile claims it. Which, if you think about it, is a not unrealistic approach to conquering and holding rough territory -- putting a fort at your furthest cultural border will help you spread culture, but a fort out in the middle of nowhere won't help you hold the hills.

2) If for some reason your city is captured, I plan to make the penalty on hills or other rough terrain will only affect the *current* owner of the square. Thus, hills will resist the occupying power for longer than the plains will.

3) Forests will slow down the spread of culture growth. If you really want to claim that tile, you'll have to think twice about whether or not you want to keep the forest standing there.

If I manage to get all that working, I'll do the same thing with culture crossing rivers. If you've got a city on one side of the river, spreading culture to the other side won't be a piece of cake. Rivers will then appear to be a more formidable border for civs to cross culturally, and hopefully then we'll see situations where rivers and mountains then become the basis of real borders between civs.

I haven't gotten a working version yet, and don't have a very good ETA. Afforess, I'll need your help (1) getting the AI to recognize that it doesn't necessarily get every square in its BFC very easily and (2) exposing my hard-coded numbers to the XML.

Wish me luck!
 
Interesting; tell me how it goes. If you're successful, I'll be more than happy to add the code to AND, with your permission.
 
Good news, bad news, ugly news, and potentially very interesting news.

Good news: I've got a working prototype. I'll attach screenshots and code if I figure out how to do that, but suffice it to say that I've got something that makes cultural border growth dependent on terrain and feature type. The key function was cultureDistance() in CvCity; previously, it calculated distances using the standard distance function. I have modified it so that hills and such count increase distance by 1, while peaks and things increase distance by 2.

Bad news: Because I focused on using cultureDistance as opposed to the actual culture spread function, it appears that forts are going to act a little weird right now. If forts act as a level 0 city, they're not going to exert cultural control over neighboring hills; you're going to have to put a city there in order to claim the resouce. On a completely different note, one ends up with some rather interesting looking cultural spreads, since it's possible for culture to spread diagonally onto plains through a small gap between hills.

Ugly news: It's going to be very difficult without a recursive structure (or caching information on a per-tile basis) in order to have rivers slow down the spread of cultural borders. The problem isn't that it's difficult to figure out whether or not a tile borders a river. Instead, the problem is figuring out whether a tile borders another tile that borders a river, and so on and so forth. It would be necessary either to come up with a dynamic programming solution or to heavily use recursion. I'm not up for writing either of those approaches this evening; whether or not I ever want to do that, that's another matter. But not tonight.

Potentially fascinating news: It is now very hard to capture all the tiles in the BFC without getting a lot of culture in a city. If this mod is expanded and implemented in AND, it provides a very strong argument for increasing the total number of culture levels to ~10 to achieve legendary culture. Cities would expand rapidly on plains, but less rapidly on other territory; most of the early game would be a fight over plains resources while the medium game might include expansion into hills and more difficult terrain. Hydro's mods that provide a bunch of cultural bonuses might end up being a necessity if we up the amount of culture a city needs to produce.

Alright, for those of you saying screenshots or it didn't happen: screenshots are attached below. Cultural levels go from level 0 (the base at the start) through level 3; I'm just adding culture using the advanced start. Note how terrain dramatically affects which tiles can be worked. This marks the end of the BFC as an "automatic" way to grab territory. From now on, terrain affects your cultural borders.

For those of you asking for the algorithm details, here's what's going on
-- each time a city spreads culture to a tile, it determines the "cultural distance" between the city and the tile. Tiles with a "cultural distance" less than the maximum city culture level (developing = 0, legendary = 5, etc) are given at least one culture per turn. The standard BFC is reached with a culture level of 1.
-- I have added functionality that increases the "cultural distance" of a tile based on the terrain and features on it. For instance, a hill adds one additional point of "cultural distance". Thus, a hill at the edge of the BFC -- a map distance of 2 away from the city -- will act as if it were a map distance of 3 away, meaning that the city must reach a cultural level of 2 in order to work it (previously, it only had to reach culture level 1).
-- I distinguish between terrain types and feature types. A hill will add one cultural distance point, and a forest will add an ADDITIONAL second point. Thus, a forested hill will have a cumulative distance of 2 -- you won't be taking many of those in the early game, or even well into the middle game.

Here is a breakdown of what is currently hardcoded.
terrain that adds an additional distance point over the baseline: hills, tundra, marsh
terrain that adds two additional distance points: peaks, desert, snow
features that add an additional distance point: forest, swamp, jungle

Afforess, feel free to modify these numbers (and please please please add them to the XML schema, as I really didn't want to touch that can of worms)

Code attached. You have my full permission to make changes as well as integrate this into the larger mod.
 

Attachments

  • Civ4ScreenShot0000.JPG
    Civ4ScreenShot0000.JPG
    171.5 KB · Views: 178
  • Civ4ScreenShot0001.JPG
    Civ4ScreenShot0001.JPG
    173.3 KB · Views: 249
  • Civ4ScreenShot0002.JPG
    Civ4ScreenShot0002.JPG
    212.8 KB · Views: 179
  • Civ4ScreenShot0003.JPG
    Civ4ScreenShot0003.JPG
    255.3 KB · Views: 201
  • CvCity.zip
    77.7 KB · Views: 62
Incredible work. I like the idea of adding more culture levels; and it will make 3-radius cities more interesting, and culture more necessary. I'll add XML values for features and terrains for you.
 
Yeah really nice idea & work! I'd like to playtest a bit... :)

Only thing that aesthetically annoys me a bit is the diagonal spread - any ideas how to avoid it?
 
I'm not sure diagonal spread is that big of an issue. It doesn't occur until culture level 4 at least; by then you have multiple cities near the big culture city, which should mask the effect.
 
So I may or may not have much time to touch the code today, but we'll see

I mentioned dynamic programming as a way to deal with the rivers problem. This might actually solve the diagonal spread of culture problem as well. Next time I get to work, I'm going to give that a whirl, caching the culture level and using that cache to determine how far away the plot should be from the city.

The dynamic programming solution would say that the distance D of each square from the city would be

D = min(DE, DW, DN, DS) + (if crossing river 1 else 0) + (if difficult terrain than 1 or 2 else 0)

Where DE is the distance from the city to the square to the east of the current one, DW is the distance to the west, etc. Note that I can be smart and know which way the city is located, so I won't have to test all four directions. If the city is to the west of the plot, I don't have to test any squares to the east. :)

The two difficulties with this approach will be (1) whether or not to save the cache and (2) when to calculate and update it. The memory footprint of the cache shouldn't be much, but I'm hoping to avoid sticking it in the save file since it can be recomputed easily when the city is loaded into memory if it is strictly a function of the culture level. Updating the cache will have to occur each time the city culture is increased, but there may be some funky behavior in various places.
 
I've added your culture spread changes to the SVN, and added XML tags to TerrainInfos and FeatureInfos. The XML is in Modules/Afforess/Required/Culture Spread. Watch out though; I'm in the midst of some large changes; you will need to redownload most of the AND files if you wish to use the latest source code.
 
I do like the idea of uneven culture. I always thought that culture "blossoms" looked a bit odd.
 
Good news: dynamic programming solution implemented. I don't have rivers working yet, but that should be a relatively simple change now that the framework solution is in place. Note that there are no more diagonally linked tiles -- I only check for connections in the NESW directions

Bad news: I have to figure out every time the terrain changes and recompute distances to the city. Right now, I don't see an easy way of doing that, aside from adding calls to cache() everywhere.

Ugly news: There are a couple of CTD bugs that I don't understand. The most easy to reproduce occurs when regenerating any map on the first turn of the game. Still working on a solution.

Note -- in the pictures, it is not possible to see that some of the terrain is marshy / hilly. If culture isn't spreading to a particular tile, that's why. I've penalized marsh terrain the same way I've penalized hills.

After fixing the CTDs and update functions, I'm going to change the culture levels for cities and add a couple more. However, I'm going to decrease the amount of culture necessary to reach each level, which effectively means that there can be more expansions for the same amount of culture. That way, if you're stuck in the forest, you've got a chance of getting out.
 

Attachments

  • Civ4ScreenShot0002.JPG
    Civ4ScreenShot0002.JPG
    294.3 KB · Views: 161
  • Civ4ScreenShot0001.JPG
    Civ4ScreenShot0001.JPG
    274.2 KB · Views: 135
  • Civ4ScreenShot0000.JPG
    Civ4ScreenShot0000.JPG
    263.7 KB · Views: 204
  • Civ4ScreenShot0003.JPG
    Civ4ScreenShot0003.JPG
    309.5 KB · Views: 148
  • Civ4ScreenShot0004.JPG
    Civ4ScreenShot0004.JPG
    325.4 KB · Views: 179
wow, nicely done!

looking at your pictures i think you should give a culture spread penalty to water and ocean tiles similar to forests.
 
Phunny Pharmer, terrain changes very infrequently, but you could invalidate the cache whenever CvPlot::setTerrainType and CvPlot::setFeatureType are called. That wouldn't be very noticable, and the cache is unlikely to be refreshed more than twice per plot, per game.

Regenerating the map, IIRC, actually deletes most (or all, not quite sure) of the map, and constructs a new map, so any plot pointers or plot-specific information would become invalid. You could try a map-wide refresh in CvGame::regenerate().
 
Top Bottom