How does inflation work in civ 4?
There are two important values we need to calculate the added inflation cost. The inflation rate and the Total cost before inflation.
The Total cost before inflation is rather simple. This is the sum of
There's quiet a lot to unpack here. I will provide the numbers for the example from my screenshot above. So let's start with the first line:
We start by calculating the base turn number. Now getElapsedGameTurns is rather easy, these are the truely elapsed turns. If you start an ancient game and press 'end turn' five times it will be 5 and if you start an medieval game and press 'end turn' five times it will be also be 5.
getGameTurn is a little bit more complicated. This is the turn number as shown in the UI. If you start an ancient game and press 'end turn' five times it will be 5, if you start an medieval game and press 'end turn' five times it will be 130.
Going back to my example. This was an ancient game. So we have this:
int iTurns = ((GC.getGameINLINE().getGameTurn() + GC.getGameINLINE().getElapsedGameTurns()) / 2);
=
(169 + 169) / 2
= 169
What follows next is a safety check, ensuring that the iTurn value doesn't get bigger then the maximum turn.
Now as you can see there is also code from my inflation game option:
I described this in my CtH log. Basically it calculates a turn based on your tech progress and takes whichever value is bigger for iTurn.
The next and also last step for the turn calculation is:
Here we just add the inflation offset from the game speed. This offset guarantees that we have no inflation in during these early turns. On normal game speed this is -90.
In our example we therefore have iTurn at 79 now.
We now enter the second phase of the rate calculation and in here we calculate this omnious iInflationPerTurnTimes10000 value.
As you can see we get iInflationPercent from CIV4GameSpeedInfo.xml and multiplicate it with iInflationPercent from CIV4HandicapInfo.xml before divide by 100.
In our example we are at normal speed and monarch difficulty. Therefore:
iInflationPerTurnTimes10000 = 30 * 100 / 100 = 30
Here we get an inflationModifier. This is a modifier set by an event. In my example this is 0.
Next up the AI gets their bonus modifier calculated. I won't concentrate too much on it. It should be mostly self-explanatory by now. This bonus gets added to iModifier.
Lastly we multiplicate our iModifier with our iInflationPerTurnTimes10000. In our example iModifier is 0 and therefore iInflationPerTurnTimes10000 stays at 30
Now after all this preperation we get to the heart of the calculation: The actual inflationRate. This is basic math, so I just fill in my example numbers for you.
int iRatePercent = (79 * 30) / 100 = 23.7 = 23 because of integer calculation.
23 + (79 * (79 - 1) * 30 * 30) / 2000000 = 25.7729 = 25 because if integer calculation
As you can see we got the 25% we've already seen in the screenshot.
The final formula for the inflation cost is in another method which is just on line of code and boils down to this:
Total cost before inflation * std::max(0, (Inflation rate + 100))) / 100
In our example:
91 * std::max(0, (25 + 100))) / 100 = 113.75 = 113 because of integer calculation.
As you can see we have calculated the Total Expenses at the end. The inflation cost itself is now only the delta between Total Expenses and Total cost before inflation.
Summary
I will try to boil down the calculation to some basic formulas:
Turn = (GameTurn (UI) + elapsedTurns) / 2 + GameSpeed.inflationOffset
InflationPerTurnTimes10000 = GameSpeed.inflationPercent * Handicap.inflationPercent / 100 * (100 + eventModifier) / 100
InflationRate = ((Turn * InflationPerTurnTimes10000) / 100) + (Turn * (Turn - 1) * InflationPerTurnTimes10000 * InflationPerTurnTimes10000) / 2000000
TotalCostBeforeInflation = Unit Cost + Unit Supply + City Maintenance + Civic Upkeep
Total Expenses = (TotalCostBeforeInflation * calculateInflationRate() + 100) / 100;
There are two important values we need to calculate the added inflation cost. The inflation rate and the Total cost before inflation.
The Total cost before inflation is rather simple. This is the sum of
- Unit Cost
- Unit Supply
- City Maintenance
- Civic Upkeep
Code:
int iTurns = ((GC.getGameINLINE().getGameTurn() + GC.getGameINLINE().getElapsedGameTurns()) / 2);
if (GC.getGameINLINE().getMaxTurns() > 0)
{
iTurns = std::min(GC.getGameINLINE().getMaxTurns(), iTurns);
}
//Charriu Inflation Tech Alternative
if (GC.getGame().isOption(GAMEOPTION_INFLATION_TIED_TO_TECH))
{
float techRatio = (float)getTotalTech() / (float)GC.getNumTechInfos();
int techTurn = (int)(techRatio * GC.getGameINLINE().getMaxTurns());
iTurns = std::max(techTurn, iTurns);
}
iTurns += GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getInflationOffset();
if (iTurns <= 0)
{
return 0;
}
int iInflationPerTurnTimes10000 = GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getInflationPercent();
iInflationPerTurnTimes10000 *= GC.getHandicapInfo(getHandicapType()).getInflationPercent();
iInflationPerTurnTimes10000 /= 100;
int iModifier = m_iInflationModifier;
if (!isHuman() && !isBarbarian())
{
int iAIModifier = GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIInflationPercent();
iAIModifier *= std::max(0, ((GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIPerEraModifier() * getCurrentEra()) + 100));
iAIModifier /= 100;
iModifier += iAIModifier - 100;
}
iInflationPerTurnTimes10000 *= std::max(0, 100 + iModifier);
iInflationPerTurnTimes10000 /= 100;
// Keep up to second order terms in binomial series
int iRatePercent = (iTurns * iInflationPerTurnTimes10000) / 100;
iRatePercent += (iTurns * (iTurns - 1) * iInflationPerTurnTimes10000 * iInflationPerTurnTimes10000) / 2000000;
FAssert(iRatePercent >= 0);
return iRatePercent;
There's quiet a lot to unpack here. I will provide the numbers for the example from my screenshot above. So let's start with the first line:
Code:
int iTurns = ((GC.getGameINLINE().getGameTurn() + GC.getGameINLINE().getElapsedGameTurns()) / 2);
We start by calculating the base turn number. Now getElapsedGameTurns is rather easy, these are the truely elapsed turns. If you start an ancient game and press 'end turn' five times it will be 5 and if you start an medieval game and press 'end turn' five times it will be also be 5.
getGameTurn is a little bit more complicated. This is the turn number as shown in the UI. If you start an ancient game and press 'end turn' five times it will be 5, if you start an medieval game and press 'end turn' five times it will be 130.
Going back to my example. This was an ancient game. So we have this:
int iTurns = ((GC.getGameINLINE().getGameTurn() + GC.getGameINLINE().getElapsedGameTurns()) / 2);
=
(169 + 169) / 2
= 169
What follows next is a safety check, ensuring that the iTurn value doesn't get bigger then the maximum turn.
Now as you can see there is also code from my inflation game option:
Code:
//Charriu Inflation Tech Alternative
if (GC.getGame().isOption(GAMEOPTION_INFLATION_TIED_TO_TECH))
{
float techRatio = (float)getTotalTech() / (float)GC.getNumTechInfos();
int techTurn = (int)(techRatio * GC.getGameINLINE().getMaxTurns());
iTurns = std::max(techTurn, iTurns);
}
I described this in my CtH log. Basically it calculates a turn based on your tech progress and takes whichever value is bigger for iTurn.
The next and also last step for the turn calculation is:
Code:
iTurns += GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getInflationOffset();
Here we just add the inflation offset from the game speed. This offset guarantees that we have no inflation in during these early turns. On normal game speed this is -90.
In our example we therefore have iTurn at 79 now.
We now enter the second phase of the rate calculation and in here we calculate this omnious iInflationPerTurnTimes10000 value.
Code:
int iInflationPerTurnTimes10000 = GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getInflationPercent();
iInflationPerTurnTimes10000 *= GC.getHandicapInfo(getHandicapType()).getInflationPercent();
iInflationPerTurnTimes10000 /= 100;
As you can see we get iInflationPercent from CIV4GameSpeedInfo.xml and multiplicate it with iInflationPercent from CIV4HandicapInfo.xml before divide by 100.
In our example we are at normal speed and monarch difficulty. Therefore:
iInflationPerTurnTimes10000 = 30 * 100 / 100 = 30
Code:
int iModifier = m_iInflationModifier;
Here we get an inflationModifier. This is a modifier set by an event. In my example this is 0.
Code:
if (!isHuman() && !isBarbarian())
{
int iAIModifier = GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIInflationPercent();
iAIModifier *= std::max(0, ((GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIPerEraModifier() * getCurrentEra()) + 100));
iAIModifier /= 100;
iModifier += iAIModifier - 100;
}
Next up the AI gets their bonus modifier calculated. I won't concentrate too much on it. It should be mostly self-explanatory by now. This bonus gets added to iModifier.
Code:
iInflationPerTurnTimes10000 *= std::max(0, 100 + iModifier);
iInflationPerTurnTimes10000 /= 100;
Lastly we multiplicate our iModifier with our iInflationPerTurnTimes10000. In our example iModifier is 0 and therefore iInflationPerTurnTimes10000 stays at 30
Code:
// Keep up to second order terms in binomial series
int iRatePercent = (iTurns * iInflationPerTurnTimes10000) / 100;
iRatePercent += (iTurns * (iTurns - 1) * iInflationPerTurnTimes10000 * iInflationPerTurnTimes10000) / 2000000;
Now after all this preperation we get to the heart of the calculation: The actual inflationRate. This is basic math, so I just fill in my example numbers for you.
int iRatePercent = (79 * 30) / 100 = 23.7 = 23 because of integer calculation.
23 + (79 * (79 - 1) * 30 * 30) / 2000000 = 25.7729 = 25 because if integer calculation
As you can see we got the 25% we've already seen in the screenshot.
The final formula for the inflation cost is in another method which is just on line of code and boils down to this:
Total cost before inflation * std::max(0, (Inflation rate + 100))) / 100
In our example:
91 * std::max(0, (25 + 100))) / 100 = 113.75 = 113 because of integer calculation.
As you can see we have calculated the Total Expenses at the end. The inflation cost itself is now only the delta between Total Expenses and Total cost before inflation.
Summary
I will try to boil down the calculation to some basic formulas:
Turn = (GameTurn (UI) + elapsedTurns) / 2 + GameSpeed.inflationOffset
InflationPerTurnTimes10000 = GameSpeed.inflationPercent * Handicap.inflationPercent / 100 * (100 + eventModifier) / 100
InflationRate = ((Turn * InflationPerTurnTimes10000) / 100) + (Turn * (Turn - 1) * InflationPerTurnTimes10000 * InflationPerTurnTimes10000) / 2000000
TotalCostBeforeInflation = Unit Cost + Unit Supply + City Maintenance + Civic Upkeep
Total Expenses = (TotalCostBeforeInflation * calculateInflationRate() + 100) / 100;
Mods: RtR CtH
Pitboss: PB39, PB40, PB52, PB59 Useful Collections: Pickmethods, Mapmaking, Curious Civplayer
Buy me a coffee
Pitboss: PB39, PB40, PB52, PB59 Useful Collections: Pickmethods, Mapmaking, Curious Civplayer
Buy me a coffee