jdog what's up with your city distance calc?

phungus420

Deity
Joined
Mar 1, 2003
Messages
6,296
Just think one of the most crucial mods I made with WolfRev was redesigning the whole city distance calculation. I think it's crucial to enjoy revolutions. Hell I never have done . .. .. .. . else but XML modding and simple things like that, but basically taught myself the basics of simple programming to do that, and am now semi comfortable with messing around with Python code cause of it. So it's cool you pushed me to learn this, but I'm wondering why you like your calculation system better. jdog what is your vision for the distance penalty?
 
The next version will have the roll out of the civ stability system which I'm still working on. I haven't figured out exactly how the various city-based effects are going to be updated yet ... the religion system and the city location system are both on the slate to be overhauled.

From what I remember, your changes to the distance calculations revolved around decreases to the strength at various tech levels ... bridge building, astronomy, the internet, etc, so that by the late game large empires could still be pretty stable. Have you made further refinements since then?

The idea behind the distance effects was to make the cities at the fringes of the larger empires in the game less stable so that they were easily tipped over by other effects like religion or culture. With the current system though distance can be it's own cause for a revolt ... in certain circumstances this makes sense, if an empire on the east side of a continent conquers a couple of cities far away on the west side, then those should act like colonies and be more inclined to break free. However, the current system penalizes contiguous empires that are long and slender and that's something I'm planning to remove.

Civ size effects (which modified the strength of distance effects before) are now going to effect the civ-wide stability measure. Empires with low civ-wide stability can suffer from calls for change in government and all-out civil war if things get really bad, but also a low civ stability measure will make restless cities more inclined to rebel (and conversely a high civ stability will make empires hold together better even if a few cities are unhappy).

I'm planning for the city distance effects to split in to two pieces: a detection of cities separated from the rest of the empire (ie, "colonies" on the same continent as the capital) and as a multiplier for other effects in the city. So distance will largely disappear as a direct effect, but instead make cities more sensitive to religious differences, cultural differences, etc. As you've set up currently, this city distance multiplier will decrease as new technologies are discovered.

How does that sound? Does it seem like it will address the issues you have with the current system? Any other things you came up with you think I should consider?
 
That actually sounds about perfect. I was always under the impression that city distance played a multiplying role to other effects, I'm surprised that's not in there already. It seems to be, if I simply increase the city distance penalty, it acts like it multiplies the penalties of other effects already. One thing though, when you rewrite it, please make it so we can see the values of all the causes (as of now some are stealth). I've tried to go through and write in parts so that stealth clauses show, but they usually don't work, not sure why. I also recomend you just remove the need to turn on debugging to see the values, this is a preference of course, but in my oppinion a lack of transparency is rarely a good thing.

Also I haven't changed my alterations to the city distance code since WolfRev v 1.1.1, so no improvements. I'm still a little confused as to why it sometimes takes into account buildings (I have it so the penalty is further reduced by harbors, etc.), and sometimes does not. Since I'm not a coder though, and this is the only true coding I've ever done, I Wouldn't be surprised if I messed something up somewhere. But overall it works really well, I reccomend you give it a try.

This is the code if you're interested (obviously there is a little more, have to define the techs and such, but this is the core of it)
Code:
           # Distance to capital City Distance modified by communication techs and structures
            cityDistModifier = ( plotDistance( pCity.getX(), pCity.getY(), capital.getX(), capital.getY()) )*0.4
            if( not pCity.isConnectedTo(capital) ) :
                cityDistModifier = (cityDistModifier + 1)*4
            elif( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLAirport)) > 0 ) :
                if( gc.getTeam(pPlayer.getTeam()).isHasTech(self.iJetTech) ) :
                    cityDistModifier = (cityDistModifier - 6)*0.4
                else:
                    cityDistModifier = (cityDistModifier - 5)*0.6
            elif( gc.getTeam(pPlayer.getTeam()).isHasTech(self.iRadioTech) ) :
                cityDistModifier = (cityDistModifier - 4)*0.7
            elif( gc.getTeam(pPlayer.getTeam()).isHasTech(self.iRailRoadTech) ) :
                if( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLHarbor)) > 0 ) :
                    cityDistModifier = (cityDistModifier - 4)*0.7
                elif( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLCothon)) > 0 ) :
                    cityDistModifier = (cityDistModifier - 4)*0.7
                else:
                    cityDistModifier = (cityDistModifier - 3)*1.2
            elif( gc.getTeam(pPlayer.getTeam()).isHasTech(self.iAstronomyTech) ) :
                if( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLHarbor)) > 0 ) :
                    cityDistModifier = (cityDistModifier - 3)*1.2
                elif( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLCothon)) > 0 ) :
                    cityDistModifier = (cityDistModifier - 3)*1.2
                elif( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLDLighthouse)) > 0 ) :
                    cityDistModifier = (cityDistModifier - 2)*1.7
                elif( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLTradePost)) > 0 ) :
                    cityDistModifier = (cityDistModifier - 2)*1.7
                else:
                    cityDistModifier = (cityDistModifier - 2)*2.2
            elif( gc.getTeam(pPlayer.getTeam()).isHasTech(self.iEngineeringTech) and gc.getTeam(pPlayer.getTeam()).isHasTech(self.iHorsebackTech) ) :
                if( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLHarbor)) > 0 ) :
                    cityDistModifier = (cityDistModifier - 2)*2.2
                elif( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLCothon)) > 0 ) :
                    cityDistModifier = (cityDistModifier - 2)*2.2
                else:
                    cityDistModifier = (cityDistModifier - 1)*2.5
            elif( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLHarbor)) > 0 ) :
                cityDistModifier = (cityDistModifier - 1)*2.5
            elif( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLCothon)) > 0 ) :
                cityDistModifier = (cityDistModifier - 1)*2.5
            elif( gc.getTeam(pPlayer.getTeam()).isHasTech(self.iWheelTech) ) :
                if( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLDLighthouse)) > 0 ) :
                    cityDistModifier = (cityDistModifier - 1)*3
                elif( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLTradePost)) > 0 ) :
                    cityDistModifier = (cityDistModifier - 1)*3
                else:
                    cityDistModifier = cityDistModifier*3
            elif( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLDLighthouse)) > 0 ) :
                cityDistModifier = cityDistModifier*3
            elif( pCity.getNumRealBuilding(gc.getInfoTypeForString(RevDefs.sXMLTradePost)) > 0 ) :
                cityDistModifier = cityDistModifier*3
            else:
                cityDistModifier = cityDistModifier*3.6

            #cityDistModifier = adjusted for map size and normalized
            
            cityDistModifier = cityDistModifier - 1
            cityDistModifier = cityDistModifier/((( CyMap().getGridWidth()**2 + CyMap().getGridHeight()**2 )**0.5)*0.013)
            distMod = 1.0 + RevUtils.getCivicsDistanceMod( iPlayer )
            distMod *= self.distToCapModifier
            if( pCity.isGovernmentCenter() ) :
                distMod *= 0.5
            elif( pCity.getMaintenanceModifier() > 0 ) :
                # Decrease effect if city has courthouse
                distMod *= 0.75

            locationRevIdx = 0
This part is particularly important, as it scales the distance penalty to the map size
Code:
 cityDistModifier = cityDistModifier/((( CyMap().getGridWidth()**2 + CyMap().getGridHeight()**2 )**0.5)*0.013)

If you do use something like this, you'll probably want to simplify it. I probably went a little overboard with all the clauses, but I was just pretty stoked I was actually writing code at the time.
 
Been working on improving it, and Am done.

In the last build there was an added function that effected the CityDist calc by era. I've just written some superior code, but I need to disable the era modifier for this code to work right (otherwise it'll scale to extremely in the later eras, destroying they city distance penalty). I thought I had it tracked down, but can't find it, here's where I loose it:
Code:
self.distToCapModifier = config.getfloat("Revolution", "DistanceToCapitalModifier", 1.0)
Where can I find this DistanceToCapModifier? It's not in Revolution.py, this is where i tracked it back to, it's calling form another file now, but I can't find where (looked through all the usual suspects.

Also this is the Code:

Code:
            # Distance to capital City Distance modified by communication techs and structures
            cityDistModifier = plotDistance(pCity.getX(), pCity.getY(), capital.getX(), capital.getY())
            cityDistModifier = ( 97*cityDistModifier )/(( CyMap().getGridWidth()**2 + CyMap().getGridHeight()**2 )**0.5)
            cityDistCommBonus = 0
            pTeam = gc.getTeam(pPlayer.getTeam())
            bCanTradeOverCoast = False
            for i in range(gc.getNumTechInfos()):
                    tech = gc.getTechInfo(i)
                    if tech.isTerrainTrade(gc.getInfoTypeForString("TERRAIN_COAST")):
                        if pTeam.isHasTech(i):
                            bCanTradeOverCoast = True
            bCanTradeOverOcean = False
            for i in range(gc.getNumTechInfos()):
                    tech = gc.getTechInfo(i)
                    if tech.isTerrainTrade(gc.getInfoTypeForString("TERRAIN_OCEAN")):
                        if pTeam.isHasTech(i):
                            bCanTradeOverOcean = True
            if bCanTradeOverOcean :
                cityDistCommBonus += 50
            if( pCity.isConnectedTo(capital) ) :
                cityDistCommBonus += 31
                cityDistCommBonus += 100 - (gc.getRouteInfo(pCity.plot().getRouteType()).getFlatMovementCost())*1.67
                if( pCity.isCoastal(-1) ) :
                    if bCanTradeOverOcean :
                        cityDistCommBonus += 66
                    elif bCanTradeOverCoast :
                        cityDistCommBonus += 33
                cityDistCommBonus += pCity.getTradeRouteModifier()
                cityDistCommBonus += pCity.getCommerceRateModifier(CommerceTypes.COMMERCE_CULTURE)*1.1
            if (pCity.getMaxAirlift() > 0 ) :
                cityDistCommBonus += 100
            cityDistModifier = cityDistModifier / ( 1 + ( cityDistCommBonus / 100 ) )

This code is awesome and it will function with other mods. The citydistance penalty is incrementally decreased as various communication effects take place in the civ, and city itself. Please use this code in the next Revolution build. It's all written, and ready to go.

Unfortunately I need to disable the era city distance modifier in order to balance the numbers, though intuitively the numbers here should work. Usually there is some tweaking that needs done in any complex calculation like this though, but this should be pretty near the mark.
 
@Phungus
Where can I find this DistanceToCapModifier?
That line pulls out the modifier from Revolution.ini. Check there. The variable is then used further down in Revolution.py.

Thanks for the code slab! When Jdog get's back, we'll have something to work with for changing the distance calculation.
Cheers.
 
Here are the two files with the code in it. Relevant code tagged with #phungus -start/end comments

Tested this, works great. Tell me what you think. It's tweakable as well. But the numbers I was getting were good. It's a better system then now where city distance penality is tied to era, this ties it to specific effects (like trade routs/bonuses, airlifting) in the city, and in the civilization (road/railroads). This makes specific C++ calls, so it's completely interchangeable with mods, doesn't pull any XML, except for TERRAIN_OCEAN, which, I'd be surprised if any mod got rid of ocean.

Edit: It took a while for this one to show up, thank god for Python Exceptions. Anyway line 1265, CityCommBonus needs to be reverted back to the default code: pPlayer.getCurrentEra()
 
Had a Python Exception in the last code. Plus, the numbers in the code from above were just based off of throwing around cities in random locations with WorldBuilder. Having set up a test game now (watching the AI play), gotten to the Midieval era, and needed to buff things a bit. So this is the updated code. Still doubt the numbers are exactly right (requires more play testing), but this code should be stable, at least it's gotten through 2 eras without any errors. And it is behaving as intended.
 
@Phungus
Thanks for sharing the code. I don't have a feel for how big your citydistmodifier variable changes are yet cause you have made a lot of changes. Would really have to sit down with a calculator and punch numbers. In theory a confidence check is to plant print commands into your code and jdog's "print citydistmodifier" and do a before and after compare on a standard save game by swapping over your revolution.py with jdog's and checking the debug log for the print readout. A calculation like this has to be triple confirmed to be working. It looks like you are not adjusting the tests on the citydistmodifier further down. Maybe they have to be changed as well?

You have also done a /100 change further down which is uncommented but intended to be related?:
connIdx = min([5 + pPlayer.getCurrentEra() / 100 + pCity.getPopulation()/3, 10])
You must have had hell with indentation errors. Single spacing indentation like that is really hard. Your indentations are not consistent all the time but it looks like you have got it going. A good start.

Cheers.
 
That was to make the the effect by era so small, as to have no effect. The numbers will be different then the default code that's the point. Play testing them now to tweak them. Anyway rather then check them against the default #s, play test the changes, and see if you prefer the effect to the default. Though, at this time I still need to tweak the values most likely.

As for single space indentation, for some reason I thought that was required, lol. Anyway Programmers Notepad has these neat little lines in it, so I know exactly where the indentation is.
 
@Phungus
What would be good is if you could collect a set of your save games of the distance scenarios you are using and maybe upload them as zip at some stage. This data would help fine tune things when Jdog get's back. Typical scenarios are good but also edge cases like duel maps and huge maps are good too. Good one.
Cheers.
 
In playtesting I've found that this option in the config file does nothing:

Code:
; Reduce tech given to former barbarians alone on a continent (larger means they're more behind)
; Does not apply when NewWorldPolicy is 0
NewWorldReduction = 1.00
NewWorldErasBehind = 2

Where in the code is this supposed to be read? I'd like to try to fix it, as obviously it's broken. (1.00 has the same effect as 0)


Also the code I have working (it's tweaked a little from what's posted) has been giving me good numbers. I need to see how it handles colonization and such, so need to play it into more advanced eras. But it's definatly balanced for the early, classical and medieval stages. Will keep you posted. Next goal is to get the bonuses to show up in buildings (ie, courthouse will say 50% Revolution Distance Reduction, etc.). glider do you want me to updated the new numbers I have, or just wait until I have the building modifiers being displayed?
 
@Phungus
Keep up the good work on the research and development of Revolutions. There are a lot of scenarios to go through that's an understatement. I would say just concentrate on the bare minimum to get to a point where you think you are happy with the distance modifier algorithm across all maps and eras. All of the detailed stuff like the XML text/definitions etc can be done afterwards. If you make something good, please keep your save games as well. It's so handy to have the distant colony effects ready to test in a corresponding save game and often it's not easy to reproduce a save game like that from scratch.

When I fix the indexer on my Vista computer, I'll do a search and chase up your other question regarding "New World Reduction".

Cheers
 
Tested and done. These seem to work perfectly. Give them a try. Also code optimized according to EF's suggestions. As far as adding text to buildings to note their effect on City Distance, we could do this in one of two ways. Either just use the existing tags, and kind of hack it in via the gametext file, or create new tags in CvGameTextManager.cpp. The former is definatly easier, but adding in the text doesn't create a new bullet, giving it it's own line is easy enough, but it looks a little strange without the bullet. The latter would be much harder to do, but possible.

As usual, altered code is marked with phungus -start and end tags. Though the area of the code I've been writing hasn't changed at all. This code is just tweaked and optimized.
 
Spoiler :
Code:
            # Distance to capital City Distance modified by communication techs and structures
            cityDistModifier = 0
            map = CyMap()
            deltaX = abs(pCity.getX() - capital.getX())
            if map.isWrapX():
                deltaX = min(deltaX, map.getGridWidth() - deltaX)
            deltaY = abs(pCity.getY() - capital.getY())
            if map.isWrapX():
                deltaY = min(deltaY, map.getGridWidth() - deltaY)
            cityDistRaw = ( deltaX**2 + deltaY**2 )**0.5
            cityDistMapModifier = ( map.getGridWidth()**2 + map.getGridHeight()**2 )**0.5
            cityDistCommBonus = 0
            pTeam = gc.getTeam(pPlayer.getTeam())
            bCanTradeOverCoast = False
            bCanTradeOverOcean = False
            iTerrainCoast = gc.getInfoTypeForString("TERRAIN_COAST")
            iTerrainOcean = gc.getInfoTypeForString("TERRAIN_OCEAN")
            for i in range(gc.getNumTechInfos()):
                tech = gc.getTechInfo(i)
                if tech.isTerrainTrade(iTerrainCoast):
                    if pTeam.isHasTech(i):
                        bCanTradeOverCoast = True
                if tech.isTerrainTrade(iTerrainOcean):
                    if pTeam.isHasTech(i):
                        bCanTradeOverOcean = True
            if bCanTradeOverOcean :
                cityDistCommBonus += 50
            iCityTradeRoutes = pCity.getTradeRoutes()
            if(iCityTradeRoutes > 0 ) :
                cityDistCommBonus += (iCityTradeRoutes - 1)*17
            bCityIsConnected = pCity.isConnectedTo(capital)
            if bCityIsConnected :
                bTechRouteModifier = False
                for i in range(gc.getNumTechInfos()):
                    for j in range(gc.getNumRouteInfos()):
                        tech = gc.getTechInfo(i)
                        if(gc.getRouteInfo(j).getTechMovementChange(i) != 0 and pTeam.isHasTech(i)):
                            bTechRouteModifier = True
                            break
                    if bTechRouteModifier:
                        break
                if bTechRouteModifier:
                    cityDistCommBonus += 100 - ( gc.getRouteInfo(pCity.plot().getRouteType()).getFlatMovementCost() + gc.getRouteInfo(pCity.plot().getRouteType()).getTechMovementChange(i) )*1.67
                else:
                    cityDistCommBonus += 100 - ( gc.getRouteInfo(pCity.plot().getRouteType()).getFlatMovementCost() )*1.67
                if( pCity.isCoastal(-1) ) :
                    if bCanTradeOverOcean :
                        cityDistCommBonus += 50
                    elif bCanTradeOverCoast :
                        cityDistCommBonus += 25
                iTradeRouteModifier = pCity.getTradeRouteModifier()
                iCityCulterModifier = pCity.getCommerceRateModifier(CommerceTypes.COMMERCE_CULTURE)
                iCityGoldModifier = pCity.getCommerceRateModifier(CommerceTypes.COMMERCE_GOLD)
                cityDistCommBonus += iTradeRouteModifier
                cityDistCommBonus += iCityCulterModifier
                cityDistCommBonus += iCityGoldModifier / 2            
            iCityMaintenanceModifier = pCity.getMaintenanceModifier()
            cityDistCommBonus -= iCityMaintenanceModifier
            bCityisPower = pCity.isPower()
            if bCityisPower :
                cityDistCommBonus += 150
            iCityAirlift = pCity.getMaxAirlift()            
            cityDistCommBonus += 100*iCityAirlift
            cityDistModifier = ( 307.0*cityDistRaw / cityDistMapModifier ) / ( 1.0 + ( cityDistCommBonus / 100.0 ) )
            cityDistModifier -= int(666 / cityDistMapModifier)
 
Thanks to Tsentom, Now know we can add text to effects like these easily:

They made this really easy in BTS by adding Help tags to the XML. You simply add it under the short description for traits, (for units and buildings and stuff you add it under the strategy text):

Code:
			<ShortDescription>TXT_KEY_TRAIT_AGR_SHORT</ShortDescription>
			[B]<Help>TXT_KEY_AGR_TRAIT_HELP</Help>[/B]
			<iHealth>0</iHealth>

Whatever txt file you put there will show up the same as the standard trait bonuses. To make it look the same just start the new text with [ICON_BULLET].

So for the Reduced City distance penalties caused by techs & buildings, we can add in those effects being displayed easily through the XML.

Also I'm going to buff the Imperialstic Trait by giving it a 100+ CityDistCommBonus (see code in the attachment for how this would work), something to consider for the official mod. Along with a 10% overall reduction to total rev Idx penalties would be a good thing as well.
 
One thing to consider, is to remove the Taxes function. I understand it's intent, but I don't think it really adds to gameplay. It's main gameplay effect is to force out Specialist and some interesting Cash and Buy economy plays. Also in terms of realism I always figured the cIV engine is designed to simulate that the government is collecting optimum taxes anyway, the Civics are really what effect the tax rate. The science slider is the ammount of resources the government is funneling toward development, rather then other types of spending. The government sponsored development of technology still takes money, and this money comes form taxpayers. Anway I'm going to try this code here, and see what happens:

Spoiler :
Code:
        goldPerc = pPlayer.getCommercePercent( CommerceTypes.COMMERCE_GOLD )
        goldPerc = 25 #Remove high taxes penalty
        if( pPlayer.hasTrait(gc.getInfoTypeForString("TRAIT_ORGANIZED")) ):
            goldPerc = 0
        sciPerc = pPlayer.getCommercePercent( CommerceTypes.COMMERCE_RESEARCH )
        cultPerc = pPlayer.getCommercePercent( CommerceTypes.COMMERCE_CULTURE )
        if( pPlayer.hasTrait(gc.getInfoTypeForString("TRAIT_ORGANIZED")) ):
            CultPerc *= 1.5

I didn't really go through and look at the tax code, let me know if this would ruin anything. Also added in a cityDistCommBonus += 100 if pPlayer has the Imperialistic trait. I"m curious to see if these modifications have the desired effect.
 
I think the taxes system is ok, but if you need to make changes to it, I'd make the Culture slider *NOT* count as tax. Though I do agree with your points about Civic costs representing government budgets and taxations. Problem is does Revolutions generate enough unhappiness with the civic choices, to make the Revolutions gameplay occur often enough? Or would you tweak the civics effects on revolution chances?

Another option might be to lower the effect of taxes per city, on a city by city basis of the economic buildings in place. E.g. Having a market might reduce the unhappiness rate of taxes in those specific cities. But again there might be some redundancies (e.g. markets already reduce unhappiness with the right luxuries).
 
Yes buffing civic induced rev effects might be nessesary. Really my main point is from a gameplay perspective. The current taxes penalty eliminates some very creative strategies, and for no real benifit. Revolutionary effects can be induced by other means (Distance, Religion, Civics, War, etc). Also like I said, even from a realism perspective, I think 100% science is the same as 100% gold in terms of taxing the populace, it's just that science means government spending is being alocated differently. Only really culture spending could be considered a drop in taxes.

Edit: Might it be better, for the computer resource wise, to move most of the stuff in Revolution.py to CvCity.cpp?
 
I had another thought to represent the whole taxes, unhappy peasants thing. While eliminating/nerfing the 'tax' slider bar concept, and tweaking civics' affect on the revolution bar is perhaps one part of the equation---a more major part would be simply modeling the standard of living of the populace. I mean while taxation is an issue, it's more of an idealogue issue if the populace is generally satisfied with it's standard of living beyond the luxury resource mechanic, no?

The way to model standard of living dawned on me as already existing in FFH2, in the form of the Dwarf civ. Rather than focus on taxation as implying standard of living, why not go with using a ratio of total treasury to population? E.g. Treasury divided by city equals relative wealth per city, a number applied to each city. Each city then divides that number by population points in it's city. Result is a standard of living metric for that city. Standardize that to a curve to determine if the standard of living loweres/raise the revolt bar.

So rather than a "you're taxing us too hard" it's "we're too poor under your rule".

The problem still remains of how to standardize contentment this way. Yet it'd still maintain some of the fun of Revolution of managing the slider with an eye to the revolt chances, but doesn't punish increasing the treasury rapidly; It'd punish spending the treasury too rapidly. It also has the advantage of making individual citizen's wealth tangible.

On the contement, I think you'd need a sociologist to help out, but I think it could be a relative 'keep up with the jones' type problem. Meaning the civ's with the top rankings in worldwide standard of living (think GNPs per civ) would probably be the happiest, somewhat regardless of the actual standard of living, while ones in the lower tiers might be the most jealous. That would model 'rising expectations' kind of well also.
There could be other fractional modifiers to the standard of living (> 1.0 meaning a positive multiplier, and <1.0 meaning a negative multiplier), such as techs (some techs give a slight positive multiplier to standard of living), a luxury modifier (number of total untraded luxury resources, duplicates counted, the capitol has access to might give a proportionate positive multiplier to the civ's standard of living calculation), and civics (type of civic could represent degree of individual freedom and liberty in the civ---most would give a relatively negative multiplier, if at least one civ in the world has a 'better' civic actively running). Possibly also a bonus given to cities for the hammers : population ratios?

To sum it up, I think the overall model could follow a sort of individual empowerment through wealth and government = people are happy with the status quo = no tendency to revolt; But that is always tempered with what the Jones' have going, as no one likes being left behind. And like the vanilla Civ4, new civics won't always be better in terms of revolt chances.
 
Back
Top Bottom