I’ve just gotten the SDK for BtS and so I want to make some use of it both for me and the community.
I’ll post the base code in spoiler tags so people without C++ knowledge don’t have to read it and people with it can correct my analysis.
By “You” and “We” I refer to your player.
By the “Enemy” or “Owner” I refer to owner of the city.
I would like to hear your comments.
[SPOILER]bool CvDLLButtonPopup::launchDoEspionageTargetPopup(CvPopup* pPopup, CvPopupInfo &info)
{
CvUnit* pUnit = gDLL->getInterfaceIFace()->getHeadSelectedUnit();
if (NULL == pUnit)
{
return false;
}
CvPlot* pPlot = pUnit->plot();
CvCity* pCity = pPlot->getPlotCity();
PlayerTypes eTargetPlayer = pPlot->getOwnerINLINE();
CvPlayer& kPlayer = GET_PLAYER(GC.getGameINLINE().getActivePlayer());
[/SPOILER]
[B][SIZE=”5″]General Formula:[/SIZE][/B]
Mission Cost = BaseMissionCost * MissionCostModifier * Number Of Players In Your Team * 0.01
[SPOILER]int CvPlayer::getEspionageMissionCost(EspionageMissionTypes eMission, PlayerTypes eTargetPlayer, const CvPlot* pPlot, int iExtraData, const CvUnit* pSpyUnit) const
{
int iMissionCost = getEspionageMissionBaseCost(eMission, eTargetPlayer, pPlot, iExtraData, pSpyUnit);
if (-1 == iMissionCost)
{
return -1;
}
iMissionCost *= getEspionageMissionCostModifier(eMission, eTargetPlayer, pPlot, iExtraData, pSpyUnit);
iMissionCost /= 100;
// Multiply cost of mission * number of team members
iMissionCost *= GET_TEAM(getTeam()).getNumMembers();
return max(0, iMissionCost);
}[/SPOILER]
[B][SIZE=”5″]Base mission cost:
[/SIZE][/B]
All the variables are taken from file CIV4EspionageMissionInfo.xml (as it is in BtS 3.13):
[B]1.[/B]Stealing gold:
The amount of gold stolen is = (Target’sTotalGold * iStealTreasuryTypes / 100) * CityPopulation / Target’sTotalPopulation
[B]Note: [/B] iStealTreasuryTypes is normally defined as 100
The mission cost is then = iCost * amountOfGoldStolen / 100
[B]Note: [/B]iCost is normally defined as 300
[SPOILER] if (kMission.getStealTreasuryTypes() > 0)
{
// Steal Treasury
int iNumTotalGold = (GET_PLAYER(eTargetPlayer).getGold() * kMission.getStealTreasuryTypes()) / 100;
if (NULL != pCity)
{
iNumTotalGold *= pCity->getPopulation();
iNumTotalGold /= max(1, GET_PLAYER(eTargetPlayer).getTotalPopulation());
}
if (iNumTotalGold > 0)
{
iMissionCost = (iBaseMissionCost * iNumTotalGold) / 100;
}
}[/SPOILER]
[B]2. Steal Tech[/B]
Mission Cost = iCost + ((100 + iBuyTechCostFactor) * TechBaseCost) / 100
[b]Note: [/b]iCost is normally defined as 0 and iBuyTechCostFactor as 25
[SPOILER] else if (kMission.getBuyTechCostFactor() > 0)
{
// Buy (Steal) Tech
TechTypes eTech = (TechTypes)iExtraData;
int iProdCost = MAX_INT;
if (NO_TECH == eTech)
{
for (int iTech = 0; iTech < GC.getNumTechInfos(); ++iTech)
{
if (canStealTech(eTargetPlayer, (TechTypes)iTech))
{
int iCost = GET_TEAM(getTeam()).getResearchCost((TechTypes)iTech);
if (iCost < iProdCost)
{
iProdCost = iCost;
eTech = (TechTypes)iTech;
}
}
}
}
else
{
iProdCost = GET_TEAM(getTeam()).getResearchCost(eTech);
}
if (NO_TECH != eTech)
{
if (canStealTech(eTargetPlayer, eTech))
{
iMissionCost = iBaseMissionCost + ((100 + kMission.getBuyTechCostFactor()) * iProdCost) / 100;
}
}
}[/SPOILER]
[B]3. Forment Unhappiness[/B]
Mission Cost = (iCost * iHurryConscriptAngerPercent (from CIV4GameSpeedInfo.xml)) / 100
[B]Note: [/b]iCost is normally defined as 120
[SPOILER]
else if (kMission.getCityUnhappinessCounter() > 0)
{
FAssert(NULL != pCity);
// Cannot make a city unhappy if you’ve already done it (value is negative when active)
if (NULL != pCity && pCity->getEspionageHappinessCounter() <= 0)
{
iMissionCost = (iBaseMissionCost * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getHurryConscriptAngerPercent()) / 100;
}
}
[/SPOILER]
[B]4. Poison water[/B]
Mission Cost = (iCost * iHurryConscriptAngerPercent (from CIV4GameSpeedInfo.xml)) / 100
[B]Note: [/b]iCost is normally defined as 120
[SPOILER]
else if (kMission.getCityPoisonWaterCounter() > 0)
{
FAssert(NULL != pCity);
// Cannot poison a city’s water supply if it’s already poisoned (value is negative when active)
if (NULL != pCity && pCity->getEspionageHealthCounter() <= 0)
{
iMissionCost = (iBaseMissionCost * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getHurryConscriptAngerPercent()) / 100;
}
}
[/SPOILER]
[B]5. Support city revolt[/B]
Mission Cost = iCost
[B]Note: [/b]iCost is normally defined as 500
[SPOILER]
else if (kMission.getCityRevoltCounter() > 0)
{
FAssert(NULL != pCity);
// Cannot make a city revolt if it’s already revolting
if (NULL != pCity && pCity->getOccupationTimer() == 0)
{
iMissionCost = iBaseMissionCost;
}
}
[/SPOILER]
[B]6. Influence civics[/B]
Mission Cost = iCost + (iSwitchCivicCostFactor * iAnarchyPercent (from CIV4GameSpeedInfo.xml) / 10000
[B]Note: [/b]iCost is normally defined as 0 and iSwitchCivicCostFactor as 60000
[SPOILER] else if (kMission.getSwitchCivicCostFactor() > 0)
{
// Switch Civics
CivicTypes eCivic = (CivicTypes)iExtraData;
if (NO_CIVIC == eCivic)
{
for (int iCivic = 0; iCivic < GC.getNumCivicInfos(); ++iCivic)
{
if (canForceCivics(eTargetPlayer, (CivicTypes)iCivic))
{
eCivic = (CivicTypes)iCivic;
break;
}
}
}
if (NO_CIVIC != eCivic)
{
if (canForceCivics(eTargetPlayer, eCivic))
{
iMissionCost = iBaseMissionCost + (kMission.getSwitchCivicCostFactor() * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getAnarchyPercent()) / 10000;
}
}
}[/SPOILER]
[B]7. Influence religion[/B]
Mission Cost = iCost + (iSwitchReligionCostFactor* iAnarchyPercent (from CIV4GameSpeedInfo.xml) / 10000
[B]Note: [/b]iCost is normally defined as 0 and iSwitchReligionCostFactor as 60000
[SPOILER]
else if (kMission.getSwitchReligionCostFactor() > 0)
{
// Switch Religions
ReligionTypes eReligion = (ReligionTypes)iExtraData;
if (NO_RELIGION == eReligion)
{
for (int iReligion = 0; iReligion < GC.getNumReligionInfos(); ++iReligion)
{
if (canForceReligion(eTargetPlayer, (ReligionTypes)iReligion))
{
eReligion = (ReligionTypes)iReligion;
break;
}
}
}
if (NO_RELIGION != eReligion)
{
if (canForceReligion(eTargetPlayer, eReligion))
{
iMissionCost = iBaseMissionCost + (kMission.getSwitchReligionCostFactor() * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getAnarchyPercent()) / 10000;
}
}
}
[/SPOILER]
[B]8. Destroy Improvement[/B]
Mission Cost = iCost * iBuildPercent (from CIV4GameSpeedInfo.xml) * 0.01
[B]Note: [/B] iCost is normally defined as 75
[SPOILER]
else if (kMission.isDestroyImprovement())
{
if (NULL != pPlot && !pPlot->isCity())
{
if (pPlot->getImprovementType() != NO_IMPROVEMENT || pPlot->getRouteType() != NO_ROUTE)
{
iMissionCost = (iBaseMissionCost * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getBuildPercent()) / 100;
}
}
}
[/SPOILER]
[B][SIZE=”5″]Mission Cost Modifier[/SIZE][/B]
[LIST=1]
[*]We start off with the coefficient equal to 100%
[*]We add ESPIONAGE_CITY_POP_EACH_MOD * (CityPop – 1)
[*]We add ESPIONAGE_CITY_TRADE_ROUTE_MOD if the city has trade routes with us
[*]We add ESPIONAGE_CITY_RELIGION_STATE_MOD if the city has our state religion (and the enemy DOESN’T) but we don’t have holy city, and ESPIONAGE_CITY_HOLY_CITY_MOD if we have the founding location
[*]We multiply by 1 – (YourCultureInTheCity * ESPIONAGE_CULTURE_MULTIPLIER_MOD) / max(1,OwnersCulture + YourCulture)
[*]We add the distance modifier
[*]We subtract ESPIONAGE_EACH_TURN_UNIT_COST_DECREASE * NumOfStationaryTurns (atm capped at 50)
[*]We add (ESPIONAGE_SPENDING_MULTIPLIER * (2 * targetPoints + ourPoints) / max(1,targetPoints + 2 * ourPoints)
[*]If the enemy has an active counterespionage mission against us we add 100%
[/LIST]
Then we round the value down cutting off all further decimal places.
max(x,y) means the greater of x and y
min(x,y) means the lesser of x and y
[B]NOTES: [/B]
Default defines:
ESPIONAGE_CITY_POP_EACH_MOD = 0
ESPIONAGE_CITY_TRADE_ROUTE_MOD = -20
ESPIONAGE_CITY_RELIGION_STATE_MOD = -15
ESPIONAGE_CITY_HOLY_CITY_MOD = -25
ESPIONAGE_CULTURE_MULTIPLIER_MOD = 50
ESPIONAGE_SPENDING_MULTIPLIER = 100
ESPIONAGE_EACH_TURN_UNIT_COST_DECREASE = 10
[SPOILER]
CvEspionageMissionInfo& kMission = GC.getEspionageMissionInfo(eMission);
int iModifier = 100;
CvCity* pCity = NULL;
if (NULL != pPlot)
{
pCity = pPlot->getPlotCity();
}
if (NO_PLAYER == eTargetPlayer)
{
eTargetPlayer = getID();
}
if (pCity != NULL && kMission.isTargetsCity())
{
// City Population
iModifier *= 100 + (GC.getDefineINT(“ESPIONAGE_CITY_POP_EACH_MOD”) * (pCity->getPopulation() – 1));
iModifier /= 100;
// Trade Route
if (pCity->isTradeRoute(getID()))
{
iModifier *= 100 + GC.getDefineINT(“ESPIONAGE_CITY_TRADE_ROUTE_MOD”);
iModifier /= 100;
}
ReligionTypes eReligion = getStateReligion();
if (NO_RELIGION != eReligion)
{
int iReligionModifier = 0;
// City has Your State Religion
if (pCity->isHasReligion(eReligion))
{
if (GET_PLAYER(eTargetPlayer).getStateReligion() != eReligion)
{
iReligionModifier += GC.getDefineINT(“ESPIONAGE_CITY_RELIGION_STATE_MOD”);
}
if (hasHolyCity(eReligion))
{
iReligionModifier += GC.getDefineINT(“ESPIONAGE_CITY_HOLY_CITY_MOD”);;
}
}
iModifier *= 100 + iReligionModifier;
iModifier /= 100;
}
// City’s culture affects cost
iModifier *= 100 – (pCity->getCultureTimes100(getID()) * GC.getDefineINT(“ESPIONAGE_CULTURE_MULTIPLIER_MOD”)) / max(1, pCity->getCultureTimes100(eTargetPlayer) + pCity->getCultureTimes100(getID()));
iModifier /= 100;
iModifier *= 100 + pCity->getEspionageDefenseModifier();
iModifier /= 100;
}
// Distance mod
if (pPlot != NULL)
{
int iDistance = GC.getMap().maxPlotDistance();
CvCity* pOurCapital = getCapitalCity();
if (NULL != pOurCapital)
{
if (kMission.isSelectPlot() || kMission.isTargetsCity())
{
iDistance = plotDistance(pOurCapital->getX_INLINE(), pOurCapital->getY_INLINE(), pPlot->getX_INLINE(), pPlot->getY_INLINE());
}
else
{
CvCity* pTheirCapital = GET_PLAYER(eTargetPlayer).getCapitalCity();
if (NULL != pTheirCapital)
{
iDistance = plotDistance(pOurCapital->getX_INLINE(), pOurCapital->getY_INLINE(), pTheirCapital->getX_INLINE(), pTheirCapital->getY_INLINE());
}
}
}
iModifier *= (iDistance + GC.getMapINLINE().maxPlotDistance()) * GC.getDefineINT(“ESPIONAGE_DISTANCE_MULTIPLIER_MOD”) / GC.getMapINLINE().maxPlotDistance();
iModifier /= 100;
}
// Spy presence mission cost alteration
if (NULL != pSpyUnit)
{
iModifier *= 100 – (pSpyUnit->getFortifyTurns() * GC.getDefineINT(“ESPIONAGE_EACH_TURN_UNIT_COST_DECREASE”));
iModifier /= 100;
}
// My points VS. Your points to mod cost
int iTargetPoints = GET_TEAM(GET_PLAYER(eTargetPlayer).getTeam()).getEspionagePointsEver();
int iOurPoints = GET_TEAM(getTeam()).getEspionagePointsEver();
iModifier *= (GC.getDefineINT(“ESPIONAGE_SPENDING_MULTIPLIER”) * (2 * iTargetPoints + iOurPoints)) / max(1, iTargetPoints + 2 * iOurPoints);
iModifier /= 100;
// Counterespionage Mission Mod
CvTeam& kTargetTeam = GET_TEAM(GET_PLAYER(eTargetPlayer).getTeam());
if (kTargetTeam.getCounterespionageModAgainstTeam(getTeam()) > 0)
{
iModifier *= kTargetTeam.getCounterespionageModAgainstTeam(getTeam());
iModifier /= 100;
}
return iModifier;
[/SPOILER]
[B][SIZE=”5″]City Infiltration Mission[/SIZE][/B]
The thing is extremely simple and is CONSTANT for all civilizations on any given map. It only depends on speed.
PointsGenerated = iEspionagePoints * iUnitGreatWorkPercent * 0.01
iEspionagePoints from CIV4UnitInfos.xml is 3000 by default
iUnitGreatWorkPercent is from CIV4GameSpeedInfo.xml
This yields us following results for game speeds:
Quick: 0.67 * 3000 = 2010
Normal: 1.0 * 3000 = 3000
Epic: 1.5 * 3000 = 4500
Marathon: 3.0 * 3000 = 9000
[B][SIZE=”5″]Steal Tech vs Research[/SIZE][/B]
This is exactly related to tech stealing costs, so I’ll make a comparison.
Before we start, I must say that while research (at a healthy rate) is possible both by cottages and specialists, espionage can’t have unlimited spies assigned and as such is forced to be generated by cottages.
It also wouldn’t hurt the guide if I posted a list of buildings enhancing both (Multiplier buildings):
[B]Note:[/B] UB are not taken into account
[SIZE=”4″][B]1.Comparison of multplier buildings[/B]
[/SIZE]
[B]Summary: Science Wins[/B]
[B]Science:[/B]
[LIST]
[*]Academy (+50%) – Can only be built by a Great Scientist
[*]Monasteries (+10% each) (Meditation) – Requires religion, so I’ll count only one per city
[*]Laboratory (+25%) (Superconductors)
[*]Library (+25%) (Writing)
[*]Observatory (+25%) (Astronomy)
[*]University (+25%) (Education)
[*]Oxford University (+100%) (Education) – Requires 3 Universities, National Wonder
[/LIST]
Sums up to 260%, but with all religions can be made 300%, 2.6 :science: per 1 :commerce: is not bad.
[B]Espionage:[/B]
[LIST]
[*]Castle (25%) (Engineering)
[*]Intelligence Agency (+50%) (Communism)
[*]Scotland Yard (+100%) – Can only be built by a great spy
[*]Jail (+50%) (Constitution)
[/LIST]
Sums up to 225%, still not so bad even when compared to science’s 260%.
Given these values, we can make a simple simulation, here shown results for numbers 1 – 30.
[spoiler]
Commerce: 1,Espionage: 2,Science: 2
Commerce: 2,Espionage: 4,Science: 5
Commerce: 3,Espionage: 6,Science: 7
Commerce: 4,Espionage: 9,Science: 10
Commerce: 5,Espionage: 11,Science: 13
Commerce: 6,Espionage: 13,Science: 15
Commerce: 7,Espionage: 15,Science: 18
Commerce: 8,Espionage: 18,Science: 20
Commerce: 9,Espionage: 20,Science: 23
Commerce: 10,Espionage: 22,Science: 26
Commerce: 11,Espionage: 24,Science: 28
Commerce: 12,Espionage: 27,Science: 31
Commerce: 13,Espionage: 29,Science: 33
Commerce: 14,Espionage: 31,Science: 36
Commerce: 15,Espionage: 33,Science: 39
Commerce: 16,Espionage: 36,Science: 41
Commerce: 17,Espionage: 38,Science: 44
Commerce: 18,Espionage: 40,Science: 46
Commerce: 19,Espionage: 42,Science: 49
Commerce: 20,Espionage: 45,Science: 52
Commerce: 21,Espionage: 47,Science: 54
Commerce: 22,Espionage: 49,Science: 57
Commerce: 23,Espionage: 51,Science: 59
Commerce: 24,Espionage: 54,Science: 62
Commerce: 25,Espionage: 56,Science: 65
Commerce: 26,Espionage: 58,Science: 67
Commerce: 27,Espionage: 60,Science: 70
Commerce: 28,Espionage: 63,Science: 72
Commerce: 29,Espionage: 65,Science: 75
Commerce: 30,Espionage: 67,Science: 78
[/spoiler]
This can easily lead to a conclusion that SCE is more powerful as it generates more :science: from :commerce: than ECE :espionage:.
I, however, want to make sure it’s as optimal as it seems.
[B][SIZE=”4″]2. Comparison of usage
[/SIZE][/B]
[B]Science:[/B]
While bonuses that apply to research seem quite straightforward (according to [URL=”http://forums.civfanatics.com/showthread.php?t=146163″]this [/URL]thread.
These are (+30% * numberOfPlayersThatKnowTheTech/numbersOfPlayersWhoStartedTheMap), so max 30%, and +20% per each additional prerequisite met (max 40%). This is multiplicative with beakers, so it adds a coefficient of 1.7 (note that this is the VERY BEST possible one) in front of raw :science:.
This means that the minimal time of completion is:
t = baseTechCost / (4.42 * baseCommerce)
This is a total of 442% boost, this is huge. :goodjob:
They don’t apply to base tech cost, and so are not beneficial for EE.
[B]Espionage:[/B]
We also assume the very best possible circumstances, still they are much easier to encounter than the science ones.
I’ll assume a near city, with 20% distance penalty.
We have trade routes with it, it has our state religion we founded, our spy’s been standing there for 5 turns. I don’t consider the espionage spending bonus, however.
100% + 20% – 20% – 25% – 50% = 25%
25% = 1/4
Therefore, we get 1/1/4 percentage bonus, which is equal to 400%.
The time needed to generate the points therefore is
t = baseTechCost / (9 * baseCommerce)
Seems good? Hell yeah! 😀
The time is 2.0362 times shorter than if we wanted to research it manually.
[B][SIZE=”4″]3.Example and conclusion[/SIZE][/B]
Say we want to research (or steal) advanced flight. Our city (either research or espionage) produces 30 raw :commerce: per turn. The numbers are of course not realistic but I want to show the concept.
researchTime = 5000 / (4.42 * 30) = 37.70, which in civ terms is 38 turns
espionageTime = 5000 / (9 * 30) = 18.51 => 19 turns
Our gain by stealing the tech is immense. We also have to remember that the expionage points can get +25% civic boost (nationhood), while research only +10% (free religion).
This however is not as great as it seems (slightly less :D). It is very problematic for techs you have to be the first to research in order to get additional benefits (religious techs,physics,economics,liberalism,fission,…) as tech can only be stolen when it’s arleady complete and partial progress can’t be acquired with espionage economy. It also yields problems with techs out of AI’s research path. Additionally, a super science city can easily be transformed from a specialist economy to cottage one (well, 50 turns), while the espionage one has to start cottaged.
It is, however synergistic with intensive tech brokering. And last, but not least, there is deficit espionage, which is more optimal than the deficit research, as average science boost per a building is 37.14%, while average espionage booster is as much as 56.25%. Unfortunately, the very first EE building (except courthouse which I don’t take in account as it’s not a multiplier) comes in the medieval era.
I hope that this analysis has provided you enough insight in espionage vs research that you at least try to play using it and post your results.
[url=http://forums.civfanatics.com/showthread.php?t=252496]Discuss this article on the forum[/url]