Formulas relation to cities.
New City Cost Formula
This formula is cubic.
Next City Cost = 50000*(X-1)^3 + 150000*X + 75000
- Where X is the current number of cities.
Infrastructure Cost Formula
This formula is exponential.
The formula for infrastructure cost is:
Infra Unit Cost = [((Current Infra-10)^2.2) / 710] + 300
Using the above formula to plug in the cost per unit results in the formula for infra cost.
Cost = Infra Unit Cost * Infra to buy
The following PHP function calculates the infra price:
<?php
function infraPrice($amount) {
//old return (pow(abs($amount-10),1.95)*0.01) + 300;
return (pow(abs($amount - 10), 2.2) / 710) + 300;
}
function calcInfraValue($starting_amount = 0, $ending_amount = 100) {
//set some vars
$value = 0;
$cost_of_chunk = 0;
//round values to nearest 2 decimals
$starting_amount = round($starting_amount, 2);
$ending_amount = round($ending_amount, 2);
//check difference between amounts
$difference = $ending_amount - $starting_amount;
//cap out at 10,000 to prevent script running forever
if ($difference > 10000) {
return "Error";
}
//if values are the same, no need to continue
if ($difference == 0) {
$value = 0;
return $value;
}
//if values are not the same, we need to make sure that the starting amount is smaller than the ending amount
if ($difference < 0) {
$infraPrice = 150;
$value = $infraPrice * $difference;
return $value;
}
//break into chunks of 100, and get the price
if ($difference > 100 AND ( $difference % 100 == 0)) {
$cost_of_chunk = round(infraPrice($starting_amount), 2) * 100;
//recursively get value of next chunk
$value += ($cost_of_chunk + calcInfraValue(($starting_amount + 100), $ending_amount));
return $value;
}
//see if the amount left is not divisible by 100 but greater than 100
if ($difference > 100 AND ( $difference % 100 != 0)) {
$cost_of_chunk = round(infraPrice($starting_amount), 2) * ($difference % 100);
//recursively get value of next chunk
$value += ($cost_of_chunk + calcInfraValue(($starting_amount + ($difference % 100)), $ending_amount));
return $value;
}
//if there's less or equal to 100 left, just add that. No need for recursion
if ($difference <= 100) {
$cost_of_chunk = round(infraPrice($starting_amount), 2) * $difference;
$value += $cost_of_chunk;
return $value;
}
}
?>
Google sheets
The following is the app script version for google sheets of the above PHP.
function calculateInfrastructureCost(startRange = "A2:A", endRange = "B2:B", outputRange = "C2:C", outputToSheet = true, calledFromFormula = true) {
var sheet = SpreadsheetApp.getActiveSheet();
var startValues = sheet.getRange(startRange).getValues();
var endValues = sheet.getRange(endRange).getValues();
var costValues = [];
for (var i = 0; i < startValues.length; i++) {
var start = startValues[i][0];
var end = endValues[i][0];
if (start !== "" && end !== "") {
var cost = calcInfraValue(start, end);
costValues.push([cost]);
} else {
costValues.push([""]);
}
}
if (outputToSheet && !calledFromFormula) {
try {
sheet.getRange(outputRange).setValues(costValues);
} catch (error) {
// Handle error
}
}
return costValues;
}
function infraPrice(amount) {
if (amount < 10) {
return 300;
} else {
return Math.pow(Math.abs(amount - 10), 2.2) / 710 + 300;
}
}
function calcInfraValue(startingAmount, endingAmount) {
// round values to nearest 2 decimals
startingAmount = Math.round(startingAmount * 100) / 100;
endingAmount = Math.round(endingAmount * 100) / 100;
// check difference between amounts
const difference = endingAmount - startingAmount;
// cap out at 10,000 to prevent script running forever
if (difference > 10000) {
return "Error";
}
// if values are the same, no need to continue
if (difference === 0) {
return 0;
}
// if values are not the same, we need to make sure that the starting amount is smaller than the ending amount
if (difference < 0) {
const infraPrice = 150;
return infraPrice * difference;
}
// break into chunks of 100, and get the price
if (difference > 100 && difference % 100 === 0) {
const costOfChunk = Math.round(infraPrice(startingAmount) * 100) / 100 * 100;
// recursively get value of next chunk
return costOfChunk + calcInfraValue(startingAmount + 100, endingAmount);
}
// see if the amount left is not divisible by 100 but greater than 100
if (difference > 100 && difference % 100 !== 0) {
const costOfChunk = Math.round(infraPrice(startingAmount) * 100) / 100 * (difference % 100);
// recursively get value of next chunk
return costOfChunk + calcInfraValue(startingAmount + (difference % 100), endingAmount);
}
// if there's less or equal to 100 left, just add that. No need for recursion
if (difference <= 100) {
const costOfChunk = Math.round(infraPrice(startingAmount) * 100) / 100 * difference;
return costOfChunk;
}
}
In the function calculateInfrastructureCost
, there are 5 variables: startRange
, endRange
, outputRange
, outputToSheet
, and calledFromFormula
.
startRange
is the cell or range of cells with the starting infrastructure of the city or cities. endRange
is the cell or range of cells with the desired ending infrastructure of the city or cities. outputRange
is the cell or range of cells where you would like to display the results. outputToSheet
lets you toggle whether to use calculateInfrastructureCost
in this way on or off with true
or false
. In the code above, it is set to use cells A2:A
for the starting infrastructure, B2:B
for the ending infrastructure, C2:C
for the results, and it is turned on (true
). The last variable, calledFromFormula
, indicates whether the function is being called from a formula in a cell or from a script. By default, it is set to true, which means that the function is being called from a formula in a cell. However, when calling the function from a script, you should set calledFromFormula
to false
. This can be done by passing false
as the fifth argument when calling the function. Alternatively, if you are not going to use calls from a cell and only plan to call the function from a script, you can set the calledFromFormula
variable to false in the code above.
If you have set the above values to what you want and have it turned on (outputToSheet = true
), you will need to set up a trigger in Apps Script, in the triggers menu. Alternatively, if you are using the API, add calculateInfrastructureCost("A2:A", "B2:B", "C2:C", true, false);
to the end of your script calling the API so it runs after.
If you prefer not to write to your sheet automatically, you can set outputToSheet = false
to stop it from writing to your sheet and use the following formula: =calculateInfrastructureCost("startValue/s", "endValue/s")
Examples:
=calculateInfrastructureCost("A2","B2")
will display the result in the cell where the formula is entered.
=calculateInfrastructureCost("A2:A","B2:B")
will display the results starting with the cell where the formula is entered and continuing down the column. If your sheet is an older version of Google Sheets, you will need to add an array to the formula to achieve this: =ARRAYFORMULA(calculateInfrastructureCost("A2:A", "B2:B"))
Land Cost Formula
This formula is exponential.
The formula for the cost of one unit of land is the following:
Land Unit Cost = 0.002*(Current Land-20)^2 + 50
Using the above formula to plug in the cost per unit results in the formula for land cost.
Cost = Land Unit Cost * Land to buy
The following PHP function calculates the land price:
<?php
function landPrice($amount) {
return (.002*($amount-20)*($amount-20))+50;
}
function calcLandValue($starting_amount=20, $ending_amount = 500) {
//set some vars
$value = 0;
$cost_of_chunk = 0;
//round values to nearest 2 decimals
$starting_amount = round($starting_amount,2);
$ending_amount = round($ending_amount, 2);
//check difference between amounts
$difference = $ending_amount - $starting_amount;
//cap out at 10,000 to prevent script running forever
if($difference > 10000) {
return "Error";
}
//if values are the same, no need to continue
if($difference == 0) {
$value = 0;
return $value;
}
//if values are not the same, we need to make sure that the starting amount is smaller than the ending amount
if($difference < 0) {
$landPrice = 50;
$value = $landPrice * $difference;
return $value;
}
//break into chunks of 500, and get the price
if($difference > 500 AND ($difference % 500 == 0)) {
$cost_of_chunk = round(landPrice($starting_amount),2) * 500;
//recursively get value of next chunk
$value += ($cost_of_chunk + calcLandValue(($starting_amount + 500), $ending_amount));
return $value;
}
//see if the amount left is not divisible by 500 but greater than 500
if($difference > 500 AND ($difference % 500 != 0)) {
$cost_of_chunk = round(landPrice($starting_amount),2) * ($difference % 500);
//recursively get value of next chunk
$value += ($cost_of_chunk + calcLandValue(($starting_amount + ($difference % 500)), $ending_amount));
return $value;
}
//if there's less or equal to 500 left, just add that. No need for recursion
if($difference <= 500) {
$cost_of_chunk = round(landPrice($starting_amount),2) * $difference;
$value += $cost_of_chunk;
return $value;
}
}
?>
Population Formulas
Before other factors are applied, the formula for population by infrastructure is:
Base Population = Infrastructure * 100
The formula after all everything's been factored in is:
Population = (Base Pop - ((Disease Rate * 100 * Infra)/100) - MAX((Crime Rate / 10) * (100*Infra) - 25, 0) * (1 + ln(CityAgeInDays)/15)
Or simplified
Population = (Base Pop - Disease Deaths - Crime Deaths) * Age Bonus
The age bonus is a function of decreasing returns to city age. The formula is:
Age Bonus = 1 + ln(CityAgeInDays)/15
Population Density Formula
- The formula used for population density when factoring Disease is different than the actual population density. The reason for this, is that Disease (based on Population Density) will kill a percentage of the Base Population, lowering the displayed Population Density. If there was no difference, the formula would feed back on each other.
Equation Specific Formula
Population Density = Base Population / Land Area
Displayed Population Formula
Population Density = Actual Population / Land Area
Crime and Disease Rate Formulas
Note: Both formulas are returned as a percent for use in the population lost formulas.
Crime
Note: 0≤ Crime Rate ≤100
Crime (%) = ((103 - Commerce)^2 + ( Infrastructure * 100))/(111111) - Police Modifier
Where Police Modifier is:
Police Modifier = (# of Police Stations)*(2.5)
Disease
Disease Rate = ((((Population Density^2) * 0.01) - 25)/100) + (Base Population/100000) + Pollution Modifier - Hospital Modifier
- Pop density is based on base population not on displayed population
Pollution Modifier is the increase to disease, from increasing Pollution.
Pollution Modifier = Pollution Index * 0.05
Hospital Modifier is the amount of disease reduced by buying Hospitals.
Hospital Modifier = Hospital Count * 2.5
Population Lost Formulas
Crime
Crime Deaths = (Crime Rate/10)*(Infrastructure*100)-25
Disease
Disease Deaths = Disease Rate * Base Population
Food Production Formula
The basic formula for food production per turn in a city is:
Food Production = Farm Count * (Land Area / 500)
Modifiers to this basic formula include:
- If the Mass Irrigation Nation Project is built the formula is changed to Farms * (Land Area / 400)
- If the season is Summer the production is changed to Food * 1.2
- If the season is Winter the production is changed to Food * .8
Radiation Formula Effect
Final Food Prod = Food Production * (nation+continent+global rad index)/1000
Misc
NOTE: These are things to be moved out but I wanna use somewhere else and need somewhere to store it temporarily.
Land
From the two above formulas, it is made evident that, since the price of new land depends on the level of your current land, it is more profitable to buy land in bulks. In other words, it is more profitable to get land from 500 to 1,000 than from 500 to 750 and then to 1,000.
However, there is one limitation: the game identifies several levels of land, meaning that they are bought in steps. The levels are 500, 1k, 1.5k, 2k land, etc. and each step is 500 Land (except for the first step which is 250, since your city gets 250 land when it is first built). This means that, if you decide to get for example from 250 to 1k land and buy that much land, the game will automatically calculate two transactions instead of one: one from 250 Land to 500 and one from 500 to 1,000. The game calculates the optimized cost for the land you decide to purchase.
Note that the Tutorial will make you buy 500 Land at your first city and as such, your first city will have 750 Land at some point. Going to the next step and buying 250 Land to reach 1,000 will set you back to course of the optimized land purchases.